modules/up/src/Core/gnu/RNG.cc
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- RNG
- asFloat
- 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