Path: blob/master/3rdparty/openexr/Imath/ImathRandom.cpp
16337 views
1///////////////////////////////////////////////////////////////////////////2//3// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas4// Digital Ltd. LLC5//6// All rights reserved.7//8// Redistribution and use in source and binary forms, with or without9// modification, are permitted provided that the following conditions are10// met:11// * Redistributions of source code must retain the above copyright12// notice, this list of conditions and the following disclaimer.13// * Redistributions in binary form must reproduce the above14// copyright notice, this list of conditions and the following disclaimer15// in the documentation and/or other materials provided with the16// distribution.17// * Neither the name of Industrial Light & Magic nor the names of18// its contributors may be used to endorse or promote products derived19// from this software without specific prior written permission.20//21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS22// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT23// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR24// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT25// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,26// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT27// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,28// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY29// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE31// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.32//33///////////////////////////////////////////////////////////////////////////3435//-----------------------------------------------------------------------------36//37// Routines that generate pseudo-random numbers compatible38// with the standard erand48(), nrand48(), etc. functions.39//40//-----------------------------------------------------------------------------4142#include "ImathRandom.h"43#include "ImathInt64.h"4445namespace Imath {46namespace {4748//49// Static state used by Imath::drand48(), Imath::lrand48() and Imath::srand48()50//5152unsigned short staticState[3] = {0, 0, 0};535455void56rand48Next (unsigned short state[3])57{58//59// drand48() and friends are all based on a linear congruential60// sequence,61//62// x[n+1] = (a * x[n] + c) % m,63//64// where a and c are as specified below, and m == (1 << 48)65//6667static const Int64 a = Int64 (0x5deece66dLL);68static const Int64 c = Int64 (0xbLL);6970//71// Assemble the 48-bit value x[n] from the72// three 16-bit values stored in state.73//7475Int64 x = (Int64 (state[2]) << 32) |76(Int64 (state[1]) << 16) |77Int64 (state[0]);7879//80// Compute x[n+1], except for the "modulo m" part.81//8283x = a * x + c;8485//86// Disassemble the 48 least significant bits of x[n+1] into87// three 16-bit values. Discard the 16 most significant bits;88// this takes care of the "modulo m" operation.89//90// We assume that sizeof (unsigned short) == 2.91//9293state[2] = (unsigned short)(x >> 32);94state[1] = (unsigned short)(x >> 16);95state[0] = (unsigned short)(x);96}9798} // namespace99100101double102erand48 (unsigned short state[3])103{104//105// Generate double-precision floating-point values between 0.0 and 1.0:106//107// The exponent is set to 0x3ff, which indicates a value greater108// than or equal to 1.0, and less than 2.0. The 48 most significant109// bits of the significand (mantissa) are filled with pseudo-random110// bits generated by rand48Next(). The remaining 4 bits are a copy111// of the 4 most significant bits of the significand. This results112// in bit patterns between 0x3ff0000000000000 and 0x3fffffffffffffff,113// which correspond to uniformly distributed floating-point values114// between 1.0 and 1.99999999999999978. Subtracting 1.0 from those115// values produces numbers between 0.0 and 0.99999999999999978, that116// is, between 0.0 and 1.0-DBL_EPSILON.117//118119rand48Next (state);120121union {double d; Int64 i;} u;122123u.i = (Int64 (0x3ff) << 52) | // sign and exponent124(Int64 (state[2]) << 36) | // significand125(Int64 (state[1]) << 20) |126(Int64 (state[0]) << 4) |127(Int64 (state[2]) >> 12);128129return u.d - 1;130}131132133double134drand48 ()135{136return Imath::erand48 (staticState);137}138139140long int141nrand48 (unsigned short state[3])142{143//144// Generate uniformly distributed integers between 0 and 0x7fffffff.145//146147rand48Next (state);148149return ((long int) (state[2]) << 15) |150((long int) (state[1]) >> 1);151}152153154long int155lrand48 ()156{157return Imath::nrand48 (staticState);158}159160161void162srand48 (long int seed)163{164staticState[2] = (unsigned short)(seed >> 16);165staticState[1] = (unsigned short)(seed);166staticState[0] = 0x330e;167}168169170float171Rand32::nextf ()172{173//174// Generate single-precision floating-point values between 0.0 and 1.0:175//176// The exponent is set to 0x7f, which indicates a value greater than177// or equal to 1.0, and less than 2.0. The 23 bits of the significand178// (mantissa) are filled with pseudo-random bits generated by179// Rand32::next(). This results in in bit patterns between 0x3f800000180// and 0x3fffffff, which correspond to uniformly distributed floating-181// point values between 1.0 and 1.99999988. Subtracting 1.0 from182// those values produces numbers between 0.0 and 0.99999988, that is,183// between 0.0 and 1.0-FLT_EPSILON.184//185186next ();187188union {float f; unsigned int i;} u;189190u.i = 0x3f800000 | (_state & 0x7fffff);191return u.f - 1;192}193194} // namespace Imath195196197