diff options
author | Sven Gothel <[email protected]> | 2015-03-28 01:43:35 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2015-03-28 01:43:35 +0100 |
commit | 4207f9c279e832e3afcb3f5fc6cd8d84cb4cfe4c (patch) | |
tree | cf3671058d55b47ab6cb6f36f369928606137628 /LibOVRKernel/Src/Kernel/OVR_Rand.h | |
parent | c29cd1a2fbff6282bab956ad61661ac9d48c4e6e (diff) |
Bump OculusVR RIFT SDK to 0.5.0.1vanilla_0.5.0.1
Diffstat (limited to 'LibOVRKernel/Src/Kernel/OVR_Rand.h')
-rw-r--r-- | LibOVRKernel/Src/Kernel/OVR_Rand.h | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/LibOVRKernel/Src/Kernel/OVR_Rand.h b/LibOVRKernel/Src/Kernel/OVR_Rand.h new file mode 100644 index 0000000..14897c0 --- /dev/null +++ b/LibOVRKernel/Src/Kernel/OVR_Rand.h @@ -0,0 +1,201 @@ +/************************************************************************************ + +PublicHeader: OVR_Kernel.h +Filename : OVR_Rand.h +Content : Random number generator +Created : Aug 28, 2014 +Author : Chris Taylor + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.2 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#ifndef OVR_Rand_h +#define OVR_Rand_h + +#include "OVR_Types.h" +#include <math.h> + +namespace OVR { + + +/* + This is designed to generate up to 2^^32 numbers per seed. + + Its period is about 2^^126 and passes all BigCrush tests. + It is the fastest simple generator that passes all tests. + + It has a few advantages over the stdlib RNG, including that + all bits of the output are equally good in quality. + Furthermore, the input seeds are hashed to avoid linear + relationships between the input seeds and the low bits of + the first few outputs. +*/ +class RandomNumberGenerator +{ +protected: + uint64_t Rx; + uint64_t Ry; + double NextRandN; + bool Seeded; + bool HaveRandN; + +public: + RandomNumberGenerator() : + Seeded(false), + HaveRandN(false) + // Other members left uninitialized + { + } + + bool IsSeeded() const + { + return Seeded; + } + + // Seed with a random state + void SeedRandom(); + + // Start with a specific seed + void Seed(uint32_t x, uint32_t y); + + // Returns an unsigned uint32_t uniformly distributed in interval [0..2^32-1] + OVR_FORCE_INLINE uint32_t Next() + { + // If it is not Seeded yet, + if (!IsSeeded()) + { + SeedRandom(); + } + + // Sum of two long-period MWC generators + Rx = (uint64_t)0xfffd21a7 * (uint32_t)Rx + (uint32_t)(Rx >> 32); + Ry = (uint64_t)0xfffd1361 * (uint32_t)Ry + (uint32_t)(Ry >> 32); + return (((uint32_t)Rx << 7) | ((uint32_t)Rx >> (32 - 7))) + (uint32_t)Ry; // ROL(x, 7) + y + } + + // The following functions are inspired by the Matlab functions rand(), randi(), and randn() + + // Uniform distribution over open interval (0..2^32) + // (i.e. closed interval [1..2^32-1], not including 0) + OVR_FORCE_INLINE uint32_t NextNonZero() + { + uint32_t n; + do + { + n = Next(); + } while (n == 0); + return n; + } + + // Double uniformly distributed over open interval (0..1) + OVR_FORCE_INLINE double Rand() + { + return NextNonZero() * (1.0 / 4294967296.0); // 2^32 + } + + // Double uniformly distributed over open interval (dmin..dmax) + OVR_FORCE_INLINE double Rand(double dmin, double dmax) + { + return dmin + (dmax - dmin) * (1.0 / 4294967296.0) * NextNonZero(); // 2^32 + } + + // Integer uniformly distributed over closed interval [0..imax-1] + // (NOTE: Matalb randi(imax) returns 1..imax) + OVR_FORCE_INLINE int RandI(int imax) + { + return (int)(Next() % imax); + } + + // Integer uniformly distributed over closed interval [imin..imax-1] + // (NOTE: Matlab randi() returns imin..imax) + OVR_FORCE_INLINE int RandI(int imin, int imax) + { + return imin + (int)(Next() % (imax - imin)); + } + + // Coordinate (x,y) uniformly distributed inside unit circle. + // Returns magnitude squared of (x,y) + OVR_FORCE_INLINE double RandInUnitCircle(double& x, double& y) + { + double r2; + do + { + x = Rand(-1.0, 1.0); + y = Rand(-1.0, 1.0); + r2 = x*x + y*y; + } while (r2 >= 1.0); + return r2; + } + + // Standard normal (gaussian) distribution: mean 0.0, stdev 1.0 + double RandN() + { + if (HaveRandN) + { + HaveRandN = false; + return NextRandN; + } + else + { + double x, y; + double r2 = RandInUnitCircle(x, y); + // Box-Muller transform + double f = sqrt(-2 * log(r2) / r2); + + // Return first, save second for next call + NextRandN = y * f; + HaveRandN = true; + + return x * f; + } + } + + // Uniform coordinate (c,s) ON unit circle. + // This function computes cos(theta), sin(theta) + // of rotation uniform in (0..2*pi). + // [ c s] is a random 2D rotation matrix. + // [-s c] + // Reference: Numerical Recipes in C++, chap. 21 + OVR_FORCE_INLINE void RandOnUnitCircle(double& c, double& s) + { + double r2 = RandInUnitCircle(c, s); + double normalize = 1.0 / sqrt(r2); + c *= normalize; + s *= normalize; + } + + // Uniform coordinate (x,y,z,w) on surface of 4D hypersphere. + // This is a quaternion rotation uniformly distributed across all rotations + // Reference: Numerical Recipes in C++, chap. 21 + OVR_FORCE_INLINE void RandOnUnitSphere4(double& x, double& y, double& z, double& w) + { + double r2xy = RandInUnitCircle(x, y); + + double u, v; + double r2uv = RandInUnitCircle(u, v); + + double f = sqrt((1.0 - r2xy) / r2uv); + z = u * f; + w = v * f; + } +}; + +} // namespace OVR + +#endif // OVR_Rand_h |