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