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] */