#include #include #include #include // // The scale constant is 2^-31. It is used to scale a 31 bit // long to a double. // const double randomDoubleScaleConstant = 4.656612873077392578125e-10; const float randomFloatScaleConstant = 4.656612873077392578125e-10; unsigned long RNG::asLong() { (*lib_error_handler)("RNG", "Unimplemented"); } void RNG::reset() { (*lib_error_handler)("RNG", "Unimplemented"); } static char initialized = 0; RNG::RNG() { if (!initialized) { if (sizeof(double) != 2 * sizeof(unsigned long)) { (*lib_error_handler)("RNG", "sizeof(Double) != 2 Sizeof(long)\n"); }; // // The following is a hack that I attribute to // Andres Nowatzyk at CMU. The intent of the loop // is to form the smallest number 0 <= x < 1.0, // which is then used as a mask for two longwords. // this gives us a fast way way to produce double // precision numbers from longwords. // // I know that this works for IEEE and VAX floating // point representations. // // A further complication is that gnu C will blow // the following loop, unless compiled with -ffloat-store, // because it uses extended representations for some of // of the comparisons. Thus, we have the following hack. // If we could specify #pragma optimize, we wouldn't need this. // PrivateRNGDoubleType t; PrivateRNGSingleType s; #if _IEEE == 1 t.d = 1.5; if ( t.u[1] == 0 ) { // sun word order? t.u[0] = 0x3fffffff; t.u[1] = 0xffffffff; } else { t.u[0] = 0xffffffff; // encore word order? t.u[1] = 0x3fffffff; } s.u = 0x3fffffff; #else double x = 1.0; double y = 0.5; do { // find largest fp-number < 2.0 t.d = x; x += y; y *= 0.5; } while (x != t.d && x < 2.0); float xx = 1.0; float yy = 0.5; do { // find largest fp-number < 2.0 s.s = xx; xx += yy; yy *= 0.5; } while (xx != s.s && xx < 2.0); #endif // set doubleMantissa to 1 for each doubleMantissa bit doubleMantissa.d = 1.0; doubleMantissa.u[0] ^= t.u[0]; doubleMantissa.u[1] ^= t.u[1]; // set singleMantissa to 1 for each singleMantissa bit singleMantissa.s = 1.0; singleMantissa.u ^= s.u; initialized = 1; } }