From d0ae3caca5828675335d3b19ab5dd987e7369b23 Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Wed, 14 Jul 2004 16:21:44 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r1857, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/tb/; revision=1858 --- sc4pd/headers/plugin_interface/SC_RGen.h | 288 +++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100755 sc4pd/headers/plugin_interface/SC_RGen.h (limited to 'sc4pd/headers/plugin_interface/SC_RGen.h') diff --git a/sc4pd/headers/plugin_interface/SC_RGen.h b/sc4pd/headers/plugin_interface/SC_RGen.h new file mode 100755 index 0000000..c82142b --- /dev/null +++ b/sc4pd/headers/plugin_interface/SC_RGen.h @@ -0,0 +1,288 @@ +/* + SuperCollider real time audio synthesis system + Copyright (c) 2002 James McCartney. All rights reserved. + http://www.audiosynth.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +//----------------------------------------------------------------------------// +// Ran088: L'Ecuyer's 1996 three-component Tausworthe generator "taus88" +//----------------------------------------------------------------------------// +// +// Returns an integer random number uniformly distributed within [0,4294967295] +// +// The period length is approximately 2^88 (which is 3*10^26). +// This generator is very fast and passes all standard statistical tests. +// +// Reference: +// (1) P. L'Ecuyer, Maximally equidistributed combined Tausworthe generators, +// Mathematics of Computation, 65, 203-213 (1996), see Figure 4. +// (2) recommended in: +// P. L'Ecuyer, Random number generation, chapter 4 of the +// Handbook on Simulation, Ed. Jerry Banks, Wiley, 1997. +// +//----------------------------------------------------------------------------// + +//----------------------------------------------------------------------------// +// I chose this random number generator for the following reasons: +// fast. +// easier and faster to seed than other high quality rng's such as Mersenne Twister. +// the internal state is only 12 bytes. +// the period is long enough for music/audio. +// possible to code in altivec in future if needed. +// - James McCartney +//----------------------------------------------------------------------------// + +#ifndef _SC_RGen_ +#define _SC_RGen_ + +#include "SC_Endian.h" +#include "SC_Types.h" +#include "SC_BoundsMacros.h" +#include "Hash.h" +#include + +struct RGen +{ + void init(uint32 seed); + + uint32 trand(); + + int32 irand(int32 scale); + int32 irand2(int32 scale); + int32 ilinrand(int32 scale); + int32 ibilinrand(int32 scale); + + float fcoin(); + float frand(); + float frand2(); + float frand0(); + float frand8(); + double drand(); + double drand2(double scale); + double linrand(double scale); + double bilinrand(double scale); + double exprandrng(double lo, double hi); + double exprand(double scale); + double biexprand(double scale); + double sum3rand(double scale); + + uint32 s1, s2, s3; // random generator state +}; + +inline void RGen::init(uint32 seed) +{ + // humans tend to use small seeds - mess up the bits + seed = (uint32)Hash((int)seed); + + // initialize seeds using the given seed value taking care of + // the requirements. The constants below are arbitrary otherwise + s1 = 1243598713U ^ seed; if (s1 < 2) s1 = 1243598713U; + s2 = 3093459404U ^ seed; if (s2 < 8) s2 = 3093459404U; + s3 = 1821928721U ^ seed; if (s3 < 16) s3 = 1821928721U; +} + +inline uint32 trand( uint32& s1, uint32& s2, uint32& s3 ) +{ + // This function is provided for speed in inner loops where the + // state variables are loaded into registers. + // Thus updating the instance variables can + // be postponed until the end of the loop. + s1 = ((s1 & -2) << 12) ^ (((s1 << 13) ^ s1) >> 19); + s2 = ((s2 & -8) << 4) ^ (((s2 << 2) ^ s2) >> 25); + s3 = ((s3 & -16) << 17) ^ (((s3 << 3) ^ s3) >> 11); + return s1 ^ s2 ^ s3; +} + +inline uint32 RGen::trand() +{ + // generate a random 32 bit number + s1 = ((s1 & -2) << 12) ^ (((s1 << 13) ^ s1) >> 19); + s2 = ((s2 & -8) << 4) ^ (((s2 << 2) ^ s2) >> 25); + s3 = ((s3 & -16) << 17) ^ (((s3 << 3) ^ s3) >> 11); + return s1 ^ s2 ^ s3; +} + +inline double RGen::drand() +{ + // return a double from 0.0 to 0.999... +#if BYTE_ORDER == BIG_ENDIAN + union { struct { uint32 hi, lo; } i; double f; } du; +#else + union { struct { uint32 lo, hi; } i; double f; } du; +#endif + du.i.hi = 0x41300000; + du.i.lo = trand(); + return du.f - 1048576.; +} + +inline float RGen::frand() +{ + // return a float from 0.0 to 0.999... + union { uint32 i; float f; } u; // union for floating point conversion of result + u.i = 0x3F800000 | (trand() >> 9); + return u.f - 1.f; +} + +inline float RGen::frand0() +{ + // return a float from +1.0 to +1.999... + union { uint32 i; float f; } u; // union for floating point conversion of result + u.i = 0x3F800000 | (trand() >> 9); + return u.f; +} + +inline float RGen::frand2() +{ + // return a float from -1.0 to +0.999... + union { uint32 i; float f; } u; // union for floating point conversion of result + u.i = 0x40000000 | (trand() >> 9); + return u.f - 3.f; +} + +inline float RGen::frand8() +{ + // return a float from -0.125 to +0.124999... + union { uint32 i; float f; } u; // union for floating point conversion of result + u.i = 0x3E800000 | (trand() >> 9); + return u.f - 0.375f; +} + +inline float RGen::fcoin() +{ + // only return one of the two values -1.0 or +1.0 + union { uint32 i; float f; } u; // union for floating point conversion of result + u.i = 0x3E000000 | (0x80000000 & trand()); + return u.f; +} + +inline int32 RGen::irand(int32 scale) +{ + // return an int from 0 to scale - 1 + return (int32)floor(scale * drand()); +} + +inline int32 RGen::irand2(int32 scale) +{ + // return a int from -scale to +scale + return (int32)floor((2. * scale + 1.) * drand() - scale); +} + +inline int32 RGen::ilinrand(int32 scale) +{ + int32 a = irand(scale); + int32 b = irand(scale); + return sc_min(a,b); +} + +inline double RGen::linrand(double scale) +{ + double a = drand(); + double b = drand(); + return sc_min(a,b) * scale; +} + +inline int32 RGen::ibilinrand(int32 scale) +{ + int32 a = irand(scale); + int32 b = irand(scale); + return a - b; +} + +inline double RGen::bilinrand(double scale) +{ + double a = drand(); + double b = drand(); + return (a - b) * scale; +} + +inline double RGen::exprandrng(double lo, double hi) +{ + return lo * exp(log(hi / lo) * drand()); +} + +inline double RGen::exprand(double scale) +{ + double z; + while ((z = drand()) == 0.0) {} + return -log(z) * scale; +} + +inline double RGen::biexprand(double scale) +{ + double z; + while ((z = drand2(1.)) == 0.0 || z == -1.0) {} + if (z > 0.0) z = log(z); + else z = -log(-z); + return z * scale; +} + +inline double RGen::sum3rand(double scale) +{ + // larry polansky's poor man's gaussian generator + return (drand() + drand() + drand() - 1.5) * 0.666666667 * scale; +} + +inline double drand( uint32& s1, uint32& s2, uint32& s3 ) +{ + union { struct { uint32 hi, lo; } i; double f; } u; + u.i.hi = 0x41300000; + u.i.lo = trand(s1,s2,s3); + return u.f - 1048576.; +} + +inline float frand( uint32& s1, uint32& s2, uint32& s3 ) +{ + // return a float from 0.0 to 0.999... + union { uint32 i; float f; } u; + u.i = 0x3F800000 | (trand(s1,s2,s3) >> 9); + return u.f - 1.f; +} + +inline float frand0( uint32& s1, uint32& s2, uint32& s3 ) +{ + // return a float from +1.0 to +1.999... + union { uint32 i; float f; } u; + u.i = 0x3F800000 | (trand(s1,s2,s3) >> 9); + return u.f; +} + +inline float frand2( uint32& s1, uint32& s2, uint32& s3 ) +{ + // return a float from -1.0 to +0.999... + union { uint32 i; float f; } u; + u.i = 0x40000000 | (trand(s1,s2,s3) >> 9); + return u.f - 3.f; +} + +inline float frand8( uint32& s1, uint32& s2, uint32& s3 ) +{ + // return a float from -0.125 to +0.124999... + union { uint32 i; float f; } u; + u.i = 0x3E800000 | (trand(s1,s2,s3) >> 9); + return u.f - 0.375f; +} + +inline float fcoin( uint32& s1, uint32& s2, uint32& s3 ) +{ + // only return one of the two values -1.0 or +1.0 + union { uint32 i; float f; } u; + u.i = 0x3F800000 | (0x80000000 & trand(s1,s2,s3)); + return u.f; +} + +#endif + -- cgit v1.2.1