## modules/up/src/Core/gnu/RNG.cc

/* [<][>][^][v][top][bottom][index][help] */

## FUNCTIONS

This source file includes following functions.

1. RNG
2. asFloat
3. asDouble

       1 // This may look like C code, but it is really -*- C++ -*-
       2 /*
       3 Copyright (C) 1989 Free Software Foundation
       4
       5 This file is part of the GNU C++ Library.  This library is free
       6 software; you can redistribute it and/or modify it under the terms of
       7 the GNU Library General Public License as published by the Free
       8 Software Foundation; either version 2 of the License, or (at your
       9 option) any later version.  This library is distributed in the hope
      10 that it will be useful, but WITHOUT ANY WARRANTY; without even the
      11 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
      12 PURPOSE.  See the GNU Library General Public License for more details.
      13 You should have received a copy of the GNU Library General Public
      14 License along with this library; if not, write to the Free Software
      15 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
      16 */
      17 #ifdef __GNUG__
      18 #pragma implementation
      19 #endif
      20 #include <assert.h>
      21 #include "gnu/builtin.h"
      22 #include "gnu/RNG.h"
      23
      24 // These two static fields get initialized by RNG::RNG().
      25 PrivateRNGSingleType RNG::singleMantissa;
      26 PrivateRNGDoubleType RNG::doubleMantissa;
      27
      28 //
      29 //      The scale constant is 2^-31. It is used to scale a 31 bit
      30 //      long to a double.
      31 //
      32
      33 //static const double randomDoubleScaleConstant = 4.656612873077392578125e-10;
      34 //static const float  randomFloatScaleConstant = 4.656612873077392578125e-10;
      35
      36 static char initialized = 0;
      37
      38 RNG::RNG()
         /* [<][>][^][v][top][bottom][index][help] */
      39 {
      40   if (!initialized)
      41   {
      42
      43         assert (sizeof(double) == 2 * sizeof(_G_uint32_t));
      44
      45         //
      46         //      The following is a hack that I attribute to
      47         //      Andres Nowatzyk at CMU. The intent of the loop
      48         //      is to form the smallest number 0 <= x < 1.0,
      49         //      which is then used as a mask for two longwords.
      50         //      this gives us a fast way way to produce double
      51         //      precision numbers from longwords.
      52         //
      53         //      I know that this works for IEEE and VAX floating
      54         //      point representations.
      55         //
      56         //      A further complication is that gnu C will blow
      57         //      the following loop, unless compiled with -ffloat-store,
      58         //      because it uses extended representations for some of
      59         //      of the comparisons. Thus, we have the following hack.
      60         //      If we could specify #pragma optimize, we wouldn't need this.
      61         //
      62
      63         PrivateRNGDoubleType t;
      64         PrivateRNGSingleType s;
      65
      66 #if _IEEE == 1
      67
      68         t.d = 1.5;
      69         if ( t.u[1] == 0 ) {            // sun word order?
      70             t.u[0] = 0x3fffffff;
      71             t.u[1] = 0xffffffff;
      72         }
      73         else {
      74             t.u[0] = 0xffffffff;        // encore word order?
      75             t.u[1] = 0x3fffffff;
      76         }
      77
      78         s.u = 0x3fffffff;
      79 #else
      80         volatile double x = 1.0; // volatile needed when fp hardware used,
      81                              // and has greater precision than memory doubles
      82         double y = 0.5;
      83         do {                        // find largest fp-number < 2.0
      84             t.d = x;
      85             x += y;
      86             y *= 0.5;
      87         } while (x != t.d && x < 2.0);
      88
      89         volatile float xx = 1.0; // volatile needed when fp hardware used,
      90                              // and has greater precision than memory floats
      91         float yy = 0.5;
      92         do {                        // find largest fp-number < 2.0
      93             s.s = xx;
      94             xx += yy;
      95             yy *= 0.5;
      96         } while (xx != s.s && xx < 2.0);
      97 #endif
      98         // set doubleMantissa to 1 for each doubleMantissa bit
      99         doubleMantissa.d = 1.0;
     100         doubleMantissa.u[0] ^= t.u[0];
     101         doubleMantissa.u[1] ^= t.u[1];
     102
     103         // set singleMantissa to 1 for each singleMantissa bit
     104         singleMantissa.s = 1.0;
     105         singleMantissa.u ^= s.u;
     106
     107         initialized = 1;
     108     }
     109 }
     110
     111 float RNG::asFloat()
         /* [<][>][^][v][top][bottom][index][help] */
     112 {
     113     PrivateRNGSingleType result;
     114     result.s = 1.0;
     115     result.u |= (asLong() & singleMantissa.u);
     116     result.s -= 1.0;
     117     assert( result.s < 1.0 && result.s >= 0);
     118     return( result.s );
     119 }
     120
     121 double RNG::asDouble()
         /* [<][>][^][v][top][bottom][index][help] */
     122 {
     123     PrivateRNGDoubleType result;
     124     result.d = 1.0;
     125     result.u[0] |= (asLong() & doubleMantissa.u[0]);
     126     result.u[1] |= (asLong() & doubleMantissa.u[1]);
     127     result.d -= 1.0;
     128     assert( result.d < 1.0 && result.d >= 0);
     129     return( result.d );
     130 }
     131

/* [<][>][^][v][top][bottom][index][help] */