📄 rng.cc
字号:
// RNG.cc/* Copyright (C) 1989 Free Software FoundationThis file is part of the GNU C++ Library. This library is freesoftware; you can redistribute it and/or modify it under the terms ofthe GNU Library General Public License as published by the FreeSoftware Foundation; either version 2 of the License, or (at youroption) any later version. This library is distributed in the hopethat it will be useful, but WITHOUT ANY WARRANTY; without even theimplied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULARPURPOSE. See the GNU Library General Public License for more details.You should have received a copy of the GNU Library General PublicLicense along with this library; if not, write to the Free SoftwareFoundation, 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <assert.h>#include "RNG.h"// These two static fields get initialized by RNG::RNG().PrivateRNGSingleType RNG::singleMantissa;PrivateRNGDoubleType RNG::doubleMantissa;//// The scale constant is 2^-31. It is used to scale a 31 bit// long to a double.////static const double randomDoubleScaleConstant = 4.656612873077392578125e-10;//static const float randomFloatScaleConstant = 4.656612873077392578125e-10;static char initialized = 0;RNG::RNG(){ if (!initialized) { assert (sizeof(double) == 2 * sizeof(unsigned int)); // // 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 volatile double x = 1.0; // volatile needed when fp hardware used, // and has greater precision than memory doubles 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); volatile float xx = 1.0; // volatile needed when fp hardware used, // and has greater precision than memory floats 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; }}float RNG::asFloat(){ PrivateRNGSingleType result; result.s = 1.0; result.u |= (asLong() & singleMantissa.u); result.s -= 1.0; assert( result.s < 1.0 && result.s >= 0); return( result.s );} double RNG::asDouble(){ PrivateRNGDoubleType result; result.d = 1.0; result.u[0] |= (asLong() & doubleMantissa.u[0]); result.u[1] |= (asLong() & doubleMantissa.u[1]); result.d -= 1.0; assert( result.d < 1.0 && result.d >= 0); return( result.d );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -