diff --git a/src/gnu/CMakeLists.txt b/src/gnu/CMakeLists.txt index 40ba187ab6..d1fa5d12c4 100644 --- a/src/gnu/CMakeLists.txt +++ b/src/gnu/CMakeLists.txt @@ -15,7 +15,6 @@ add_library( Poisson.cpp Rand.cpp Random.cpp - RNG.cpp Uniform.cpp Weibull.cpp) set_property(TARGET nrngnu PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/src/gnu/RNG.cpp b/src/gnu/RNG.cpp deleted file mode 100755 index 40c3057364..0000000000 --- a/src/gnu/RNG.cpp +++ /dev/null @@ -1,132 +0,0 @@ -// This may look like C code, but it is really -*- C++ -*- -/* -Copyright (C) 1989 Free Software Foundation - -This file is part of the GNU C++ Library. This library is free -software; you can redistribute it and/or modify it under the terms of -the GNU Library General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. This library is distributed in the hope -that it will be useful, but WITHOUT ANY WARRANTY; without even the -implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU Library General Public License for more details. -You should have received a copy of the GNU Library General Public -License along with this library; if not, write to the Free Software -Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -#ifdef __GNUG__ -#pragma implementation -#endif -#include -#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(){} - -RNG::RNG() -{ - if (!initialized) - { - - assert (sizeof(double) == 2 * sizeof(uint32_t)); - - // - // 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 || defined(linux) - - 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 ); -} - diff --git a/src/gnu/RNG.h b/src/gnu/RNG.h index 56202c1cec..5f114270d8 100755 --- a/src/gnu/RNG.h +++ b/src/gnu/RNG.h @@ -1,56 +1,28 @@ -// This may look like C code, but it is really -*- C++ -*- -/* -Copyright (C) 1988 Free Software Foundation - written by Dirk Grunwald (grunwald@cs.uiuc.edu) - -This file is part of the GNU C++ Library. This library is free -software; you can redistribute it and/or modify it under the terms of -the GNU Library General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. This library is distributed in the hope -that it will be useful, but WITHOUT ANY WARRANTY; without even the -implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU Library General Public License for more details. -You should have received a copy of the GNU Library General Public -License along with this library; if not, write to the Free Software -Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. -*/ #pragma once -/* - * int32_t and uint32_t have been defined by the configure procedure. Just - * use these in place of the ones that libg++ used to provide. - */ #include -#include -#include - -union PrivateRNGSingleType { // used to access floats as unsigneds - float s; - uint32_t u; -}; - -union PrivateRNGDoubleType { // used to access doubles as unsigneds - double d; - uint32_t u[2]; -}; +#include -// -// Base class for Random Number Generators. -// class RNG { - static PrivateRNGSingleType singleMantissa; // mantissa bit vector - static PrivateRNGDoubleType doubleMantissa; // mantissa bit vector public: - RNG(); - virtual ~RNG(); - // + using result_type = std::uint32_t; + + RNG() = default; + virtual ~RNG() = default; + // Return a long-words word of random bits - // - virtual uint32_t asLong() = 0; + virtual result_type asLong() = 0; virtual void reset() = 0; - // - // Return random bits converted to either a float or a double - // - virtual float asFloat(); - virtual double asDouble(); + + // Return random bits converted to a double + virtual double asDouble() = 0; + + static constexpr result_type min() { + return std::numeric_limits::min(); + } + static constexpr result_type max() { + return std::numeric_limits::max(); + } + result_type operator()() { + return asLong(); + } };