Add Chromium-only Blender WebEngine parity work
This commit is contained in:
442
blender-5.2.0/extern/mantaflow/helper/util/randomstream.h
vendored
Normal file
442
blender-5.2.0/extern/mantaflow/helper/util/randomstream.h
vendored
Normal file
@@ -0,0 +1,442 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* MantaFlow fluid solver framework
|
||||
* Copyright 2011 Tobias Pfaff, Nils Thuerey
|
||||
*
|
||||
* This program is free software, distributed under the terms of the
|
||||
* Apache License, Version 2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Random numbers
|
||||
*
|
||||
* Based on an example by Makoto Matsumoto, Takuji Nishimura, Shawn Cokus, and Richard J. Wagner
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _RANDOMSTREAM_H
|
||||
#define _RANDOMSTREAM_H
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "vectorbase.h"
|
||||
|
||||
namespace Manta {
|
||||
|
||||
class MTRand {
|
||||
// Data
|
||||
public:
|
||||
typedef unsigned long uint32; // unsigned integer type, at least 32 bits
|
||||
|
||||
static constexpr int N = 624; // length of state vector
|
||||
static constexpr int SAVE = N + 1; // length of array for save()
|
||||
|
||||
protected:
|
||||
static constexpr int M = 397; // period parameter
|
||||
|
||||
uint32 state[N]; // internal state
|
||||
uint32 *pNext; // next value to get from state
|
||||
int left; // number of values left before reload needed
|
||||
|
||||
// Methods
|
||||
public:
|
||||
MTRand(const uint32 &oneSeed); // initialize with a simple uint32
|
||||
MTRand(uint32 *const bigSeed, uint32 const seedLength = N); // or an array
|
||||
MTRand(); // auto-initialize with /dev/urandom or time() and clock()
|
||||
|
||||
// Do NOT use for CRYPTOGRAPHY without securely hashing several returned
|
||||
// values together, otherwise the generator state can be learned after
|
||||
// reading 624 consecutive values.
|
||||
|
||||
// Access to 32-bit random numbers
|
||||
double rand(); // real number in [0,1]
|
||||
double rand(const double &n); // real number in [0,n]
|
||||
double randExc(); // real number in [0,1)
|
||||
double randExc(const double &n); // real number in [0,n)
|
||||
double randDblExc(); // real number in (0,1)
|
||||
double randDblExc(const double &n); // real number in (0,n)
|
||||
uint32 randInt(); // integer in [0,2^32-1]
|
||||
uint32 randInt(const uint32 &n); // integer in [0,n] for n < 2^32
|
||||
double operator()()
|
||||
{
|
||||
return rand();
|
||||
} // same as rand()
|
||||
|
||||
// Access to 53-bit random numbers (capacity of IEEE double precision)
|
||||
double rand53(); // real number in [0,1)
|
||||
|
||||
// Access to nonuniform random number distributions
|
||||
double randNorm(const double &mean = 0.0, const double &variance = 1.0);
|
||||
|
||||
// Re-seeding functions with same behavior as initializers
|
||||
void seed(const uint32 oneSeed);
|
||||
void seed(uint32 *const bigSeed, const uint32 seedLength = N);
|
||||
void seed();
|
||||
|
||||
// Saving and loading generator state
|
||||
void save(uint32 *saveArray) const; // to array of size SAVE
|
||||
void load(uint32 *const loadArray); // from such array
|
||||
friend std::ostream &operator<<(std::ostream &os, const MTRand &mtrand);
|
||||
friend std::istream &operator>>(std::istream &is, MTRand &mtrand);
|
||||
|
||||
protected:
|
||||
void initialize(const uint32 oneSeed);
|
||||
void reload();
|
||||
uint32 hiBit(const uint32 &u) const
|
||||
{
|
||||
return u & 0x80000000UL;
|
||||
}
|
||||
uint32 loBit(const uint32 &u) const
|
||||
{
|
||||
return u & 0x00000001UL;
|
||||
}
|
||||
uint32 loBits(const uint32 &u) const
|
||||
{
|
||||
return u & 0x7fffffffUL;
|
||||
}
|
||||
uint32 mixBits(const uint32 &u, const uint32 &v) const
|
||||
{
|
||||
return hiBit(u) | loBits(v);
|
||||
}
|
||||
uint32 twist(const uint32 &m, const uint32 &s0, const uint32 &s1) const
|
||||
{
|
||||
return m ^ (mixBits(s0, s1) >> 1) ^ (-loBit(s1) & 0x9908b0dfUL);
|
||||
}
|
||||
static uint32 hash(time_t t, clock_t c);
|
||||
};
|
||||
|
||||
inline MTRand::MTRand(const uint32 &oneSeed)
|
||||
{
|
||||
seed(oneSeed);
|
||||
}
|
||||
|
||||
inline MTRand::MTRand(uint32 *const bigSeed, const uint32 seedLength)
|
||||
{
|
||||
seed(bigSeed, seedLength);
|
||||
}
|
||||
|
||||
inline MTRand::MTRand()
|
||||
{
|
||||
seed();
|
||||
}
|
||||
|
||||
inline double MTRand::rand()
|
||||
{
|
||||
return double(randInt()) * (1.0 / 4294967295.0);
|
||||
}
|
||||
|
||||
inline double MTRand::rand(const double &n)
|
||||
{
|
||||
return rand() * n;
|
||||
}
|
||||
|
||||
inline double MTRand::randExc()
|
||||
{
|
||||
return double(randInt()) * (1.0 / 4294967296.0);
|
||||
}
|
||||
|
||||
inline double MTRand::randExc(const double &n)
|
||||
{
|
||||
return randExc() * n;
|
||||
}
|
||||
|
||||
inline double MTRand::randDblExc()
|
||||
{
|
||||
return (double(randInt()) + 0.5) * (1.0 / 4294967296.0);
|
||||
}
|
||||
|
||||
inline double MTRand::randDblExc(const double &n)
|
||||
{
|
||||
return randDblExc() * n;
|
||||
}
|
||||
|
||||
inline double MTRand::rand53()
|
||||
{
|
||||
uint32 a = randInt() >> 5, b = randInt() >> 6;
|
||||
return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0); // by Isaku Wada
|
||||
}
|
||||
|
||||
inline double MTRand::randNorm(const double &mean, const double &variance)
|
||||
{
|
||||
// Return a real number from a normal (Gaussian) distribution with given
|
||||
// mean and variance by Box-Muller method
|
||||
double r = sqrt(-2.0 * log(1.0 - randDblExc())) * variance;
|
||||
double phi = 2.0 * 3.14159265358979323846264338328 * randExc();
|
||||
return mean + r * cos(phi);
|
||||
}
|
||||
|
||||
inline MTRand::uint32 MTRand::randInt()
|
||||
{
|
||||
// Pull a 32-bit integer from the generator state
|
||||
// Every other access function simply transforms the numbers extracted here
|
||||
|
||||
if (left == 0)
|
||||
reload();
|
||||
--left;
|
||||
|
||||
uint32 s1;
|
||||
s1 = *pNext++;
|
||||
s1 ^= (s1 >> 11);
|
||||
s1 ^= (s1 << 7) & 0x9d2c5680UL;
|
||||
s1 ^= (s1 << 15) & 0xefc60000UL;
|
||||
return (s1 ^ (s1 >> 18));
|
||||
}
|
||||
|
||||
inline MTRand::uint32 MTRand::randInt(const uint32 &n)
|
||||
{
|
||||
// Find which bits are used in n
|
||||
// Optimized by Magnus Jonsson (magnus@smartelectronix.com)
|
||||
uint32 used = n;
|
||||
used |= used >> 1;
|
||||
used |= used >> 2;
|
||||
used |= used >> 4;
|
||||
used |= used >> 8;
|
||||
used |= used >> 16;
|
||||
|
||||
// Draw numbers until one is found in [0,n]
|
||||
uint32 i;
|
||||
do
|
||||
i = randInt() & used; // toss unused bits to shorten search
|
||||
while (i > n);
|
||||
return i;
|
||||
}
|
||||
|
||||
inline void MTRand::seed(const uint32 oneSeed)
|
||||
{
|
||||
// Seed the generator with a simple uint32
|
||||
initialize(oneSeed);
|
||||
reload();
|
||||
}
|
||||
|
||||
inline void MTRand::seed(uint32 *const bigSeed, const uint32 seedLength)
|
||||
{
|
||||
// Seed the generator with an array of uint32's
|
||||
// There are 2^19937-1 possible initial states. This function allows
|
||||
// all of those to be accessed by providing at least 19937 bits (with a
|
||||
// default seed length of N = 624 uint32's). Any bits above the lower 32
|
||||
// in each element are discarded.
|
||||
// Just call seed() if you want to get array from /dev/urandom
|
||||
initialize(19650218UL);
|
||||
const unsigned int Nenum = N;
|
||||
int i = 1;
|
||||
uint32 j = 0;
|
||||
int k = (Nenum > seedLength ? Nenum : seedLength);
|
||||
for (; k; --k) {
|
||||
state[i] = state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30)) * 1664525UL);
|
||||
state[i] += (bigSeed[j] & 0xffffffffUL) + j;
|
||||
state[i] &= 0xffffffffUL;
|
||||
++i;
|
||||
++j;
|
||||
if (i >= N) {
|
||||
state[0] = state[N - 1];
|
||||
i = 1;
|
||||
}
|
||||
if (j >= seedLength)
|
||||
j = 0;
|
||||
}
|
||||
for (k = N - 1; k; --k) {
|
||||
state[i] = state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30)) * 1566083941UL);
|
||||
state[i] -= i;
|
||||
state[i] &= 0xffffffffUL;
|
||||
++i;
|
||||
if (i >= N) {
|
||||
state[0] = state[N - 1];
|
||||
i = 1;
|
||||
}
|
||||
}
|
||||
state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array
|
||||
reload();
|
||||
}
|
||||
|
||||
inline void MTRand::seed()
|
||||
{
|
||||
// Seed the generator with an array from /dev/urandom if available
|
||||
// Otherwise use a hash of time() and clock() values
|
||||
|
||||
// First try getting an array from /dev/urandom
|
||||
FILE *urandom = fopen("/dev/urandom", "rb");
|
||||
if (urandom) {
|
||||
uint32 bigSeed[N];
|
||||
uint32 *s = bigSeed;
|
||||
int i = N;
|
||||
bool success = true;
|
||||
while (success && i--)
|
||||
success = fread(s++, sizeof(uint32), 1, urandom);
|
||||
fclose(urandom);
|
||||
if (success) {
|
||||
seed(bigSeed, N);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Was not successful, so use time() and clock() instead
|
||||
seed(hash(time(nullptr), clock()));
|
||||
}
|
||||
|
||||
inline void MTRand::initialize(const uint32 intseed)
|
||||
{
|
||||
// Initialize generator state with seed
|
||||
// See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
|
||||
// In previous versions, most significant bits (MSBs) of the seed affect
|
||||
// only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
|
||||
uint32 *s = state;
|
||||
uint32 *r = state;
|
||||
int i = 1;
|
||||
*s++ = intseed & 0xffffffffUL;
|
||||
for (; i < N; ++i) {
|
||||
*s++ = (1812433253UL * (*r ^ (*r >> 30)) + i) & 0xffffffffUL;
|
||||
r++;
|
||||
}
|
||||
}
|
||||
|
||||
inline void MTRand::reload()
|
||||
{
|
||||
// Generate N new values in state
|
||||
// Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
|
||||
uint32 *p = state;
|
||||
int i;
|
||||
for (i = N - M; i--; ++p)
|
||||
*p = twist(p[M], p[0], p[1]);
|
||||
for (i = M; --i; ++p)
|
||||
*p = twist(p[M - N], p[0], p[1]);
|
||||
*p = twist(p[M - N], p[0], state[0]);
|
||||
|
||||
left = N, pNext = state;
|
||||
}
|
||||
|
||||
inline MTRand::uint32 MTRand::hash(time_t t, clock_t c)
|
||||
{
|
||||
// Get a uint32 from t and c
|
||||
// Better than uint32(x) in case x is floating point in [0,1]
|
||||
// Based on code by Lawrence Kirby (fred@genesis.demon.co.uk)
|
||||
|
||||
static uint32 differ = 0; // guarantee time-based seeds will change
|
||||
|
||||
uint32 h1 = 0;
|
||||
unsigned char *p = (unsigned char *)&t;
|
||||
for (size_t i = 0; i < sizeof(t); ++i) {
|
||||
h1 *= std::numeric_limits<unsigned char>::max() + 2U;
|
||||
h1 += p[i];
|
||||
}
|
||||
uint32 h2 = 0;
|
||||
p = (unsigned char *)&c;
|
||||
for (size_t j = 0; j < sizeof(c); ++j) {
|
||||
h2 *= std::numeric_limits<unsigned char>::max() + 2U;
|
||||
h2 += p[j];
|
||||
}
|
||||
return (h1 + differ++) ^ h2;
|
||||
}
|
||||
|
||||
inline void MTRand::save(uint32 *saveArray) const
|
||||
{
|
||||
uint32 *sa = saveArray;
|
||||
const uint32 *s = state;
|
||||
int i = N;
|
||||
for (; i--; *sa++ = *s++) {
|
||||
}
|
||||
*sa = left;
|
||||
}
|
||||
|
||||
inline void MTRand::load(uint32 *const loadArray)
|
||||
{
|
||||
uint32 *s = state;
|
||||
uint32 *la = loadArray;
|
||||
int i = N;
|
||||
for (; i--; *s++ = *la++) {
|
||||
}
|
||||
left = *la;
|
||||
pNext = &state[N - left];
|
||||
}
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &os, const MTRand &mtrand)
|
||||
{
|
||||
const MTRand::uint32 *s = mtrand.state;
|
||||
int i = mtrand.N;
|
||||
for (; i--; os << *s++ << "\t") {
|
||||
}
|
||||
return os << mtrand.left;
|
||||
}
|
||||
|
||||
inline std::istream &operator>>(std::istream &is, MTRand &mtrand)
|
||||
{
|
||||
MTRand::uint32 *s = mtrand.state;
|
||||
int i = mtrand.N;
|
||||
for (; i--; is >> *s++) {
|
||||
}
|
||||
is >> mtrand.left;
|
||||
mtrand.pNext = &mtrand.state[mtrand.N - mtrand.left];
|
||||
return is;
|
||||
}
|
||||
|
||||
// simple interface to mersenne twister
|
||||
class RandomStream {
|
||||
public:
|
||||
inline RandomStream(long seed) : mtr(seed){};
|
||||
~RandomStream()
|
||||
{
|
||||
}
|
||||
|
||||
/*! get a random number from the stream */
|
||||
inline float getRandNorm(float mean, float var)
|
||||
{
|
||||
return mtr.randNorm(mean, var);
|
||||
};
|
||||
|
||||
#if FLOATINGPOINT_PRECISION == 1
|
||||
inline Real getReal()
|
||||
{
|
||||
return getFloat();
|
||||
}
|
||||
inline Real getReal(float min, float max)
|
||||
{
|
||||
return getFloat(min, max);
|
||||
}
|
||||
|
||||
#else
|
||||
inline Real getReal()
|
||||
{
|
||||
return getDouble();
|
||||
}
|
||||
inline Real getReal(double min, double max)
|
||||
{
|
||||
return getDouble(min, max);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline Vec3 getVec3()
|
||||
{
|
||||
Real a = getReal(), b = getReal(), c = getReal();
|
||||
return Vec3(a, b, c);
|
||||
}
|
||||
inline Vec3 getVec3Norm()
|
||||
{
|
||||
Vec3 a = getVec3();
|
||||
normalize(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
private:
|
||||
MTRand mtr;
|
||||
|
||||
inline double getDouble(void)
|
||||
{
|
||||
return mtr.rand();
|
||||
};
|
||||
inline float getFloat(void)
|
||||
{
|
||||
return (float)mtr.rand();
|
||||
};
|
||||
|
||||
inline double getDouble(double min, double max)
|
||||
{
|
||||
return mtr.rand(max - min) + min;
|
||||
};
|
||||
inline float getFloat(float min, float max)
|
||||
{
|
||||
return (float)(mtr.rand(max - min) + min);
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace Manta
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user