This following message was posted to the old ClanLib sourceforge developer mailing list, but it may have been forgotten about (it was not replied to).

It looks good, but I do not have enough knowledge on the subject to make a good judgement:

by Ben Chambers-3 Dec 20, 2006; 10:16pm

This patch implements a PRNG for ClanLib.

Multiple independent and unique RN streams may be created by instancing

the class. Personally, I use this feature for procedural content

generation, where you want the random placement to remain static across

multiple executions despite other uses of the PRNG.

I feel that this is an essential component for a game engine, which

unfortunately few people pay attention to, but which would benefit

ClanLib and its users immensely.

Class use is simple:

CL_Random r( SEED );

will instantiate the class, using a 32bit integer seed (it is possible

to implement this with 64bit integers, but I didn't bother).

unsigned int x=r.rand();

will assign a random value to x in the range of 0x0 .. 0xffffffff (any

32bit unsigned integer value). In addition to this, however, it has

several other functions which are useful for random generation:

even() returns either true or false, with a good distribution between

the two.

normalized() returns a float in the range of 0..1 inclusive, with an

even distribution.

ranged(min, max) returns a float in the range of min..max with an even

distribution.

distributed(mean, deviation) is special :) It returns potentially any

float value. Approximately 50% of all the values return lie within 1

deviation from the mean (note: This is NOT a Standard Deviation, and the

resulting curve is NOT a normal bell curve!). Approximately 75% of all

values lie within 2 deviations from the mean. If you want to know what

percentage P of all values will lie within X deviations from the mean,

it is:

P = 1-1/(2^x)

I don't know a better way to explain this; if someone comes up with one,

I'd appreciate hearing how they put it!

And that's just about it :) The code is not yet thread-safe; if you

will be accessing the same instance from multiple threads, it needs to

be wrapped in a mutex. However, independent instances may be used in

independent threads quite safely.

...Chambers

Index: Sources/API/core.h

================================================== =================

--- Sources/API/core.h (revision 110)

+++ Sources/API/core.h (working copy)

@@ -119,6 +119,7 @@

#include "Core/Math/number_pool.h"

#include "Core/Math/delauney_triangulator.h"

#include "Core/Math/outline_triangulator.h"

+#include "Core/Math/random.h"

#include "Core/XML/xml_token.h"

#include "Core/XML/xml_tokenizer.h"

Index: Sources/API/Core/Math/random.h

================================================== =================

--- Sources/API/Core/Math/random.h (revision 0)

+++ Sources/API/Core/Math/random.h (revision 0)

@@ -0,0 +1,80 @@

+/*

+** ClanLib SDK

+** Copyright (c) 1997-2005 The ClanLib Team

+**

+** This software is provided 'as-is', without any express or implied

+** warranty. In no event will the authors be held liable for any damages

+** arising from the use of this software.

+**

+** Permission is granted to anyone to use this software for any purpose,

+** including commercial applications, and to alter it and redistribute it

+** freely, subject to the following restrictions:

+**

+** 1. The origin of this software must not be misrepresented; you must not

+** claim that you wrote the original software. If you use this software

+** in a product, an acknowledgment in the product documentation would be

+** appreciated but is not required.

+** 2. Altered source versions must be plainly marked as such, and must not be

+** misrepresented as being the original software.

+** 3. This notice may not be removed or altered from any source distribution.

+**

+** Note: Some of the libraries ClanLib may link to may have additional

+** requirements or restrictions.

+**

+** File Author(s):

+**

+** Ben Chambers

+** (if your name is missing here, please add it)

+*/

+

+//! clanCore="Math"

+//! header=core.h

+

+#ifndef header_random

+#define header_random

+

+#if _MSC_VER > 1000

+#pragma once

+#endif

+

+//: Random number stream generator

+//- !group=Core/Math!

+//- !header=core.h!

+class CL_Random

+{

+//! Construction:

+public:

+ //: Creates a unique random number stream.

+ //param SEED: Initial seed for the random number stream.

+ CL_Random( const unsigned int SEED=0 );

+

+//! Operations:

+public:

+ //: Returns an unsigned integer in the range of 0x0 .. 0xffffffff

+ unsigned int rand();

+

+ //: Returns a boolean value, either true or false.

+ bool even();

+

+ //: Returns a floating point value in the range of 0.0 .. 1.0, inclusive.

+ float normalized();

+

+ //: Returns a floating point value in the specified range.

+ //param min: The lower bound of the range

+ //param max: The upper bound of the range

+ float ranged(const float min, const float max);

+

+ //: Returns a floating point value randomly distributed.

+ //param mean: The central data point about which your results will be distributed.

+ //param deviation: 50% of all data will lie within this distance of the mean. 50% of all those outside, will lie within 1 additional deviation, etc.

+ float distributed(const float mean, const float deviation);

+

+//! Implementation:

+private:

+ void randomize();

+ unsigned int state[624];

+

+ unsigned int index;

+};

+

+#endif

Index: Sources/API/Makefile.am

================================================== =================

--- Sources/API/Makefile.am (revision 110)

+++ Sources/API/Makefile.am (working copy)

@@ -194,7 +194,8 @@

Core/Math/triangle_math.h \

Core/Math/pointset_math.h \

Core/Math/rect.h \

- Core/Math/quad.h \

+ Core/Math/quad.h \

+ Core/Math/random.h \

Core/Math/size.h \

Core/Math/vector2.h \

Core/Math/point.h \

Index: Sources/Core/Math/random.cpp

================================================== =================

--- Sources/Core/Math/random.cpp (revision 0)

+++ Sources/Core/Math/random.cpp (revision 0)

@@ -0,0 +1,147 @@

+/*

+** ClanLib SDK

+** Copyright (c) 1997-2005 The ClanLib Team

+**

+** This software is provided 'as-is', without any express or implied

+** warranty. In no event will the authors be held liable for any damages

+** arising from the use of this software.

+**

+** Permission is granted to anyone to use this software for any purpose,

+** including commercial applications, and to alter it and redistribute it

+** freely, subject to the following restrictions:

+**

+** 1. The origin of this software must not be misrepresented; you must not

+** claim that you wrote the original software. If you use this software

+** in a product, an acknowledgment in the product documentation would be

+** appreciated but is not required.

+** 2. Altered source versions must be plainly marked as such, and must not be

+** misrepresented as being the original software.

+** 3. This notice may not be removed or altered from any source distribution.

+**

+** Note: Some of the libraries ClanLib may link to may have additional

+** requirements or restrictions.

+**

+** File Author(s):

+**

+** Ben Chambers

+** (if your name is missing here, please add it)

+*/

+

+// Note: This file implements the Mersenne Twist algorithm to generate a pseudorandom number stream.

+

+#include "Core/precomp.h"

+#include "API/Core/Math/random.h"

+

+/////////////////////////////////////////////////////////////////////////////

+// CL_Random constants needed:

+const double PI = 3.141592653589793238462643383279502884197169399375 10;

+const double sqrt2pi = sqrt(2*PI);

+const float inverse_log_2 = 1.0f/float(log(2.0));

+

+/////////////////////////////////////////////////////////////////////////////

+// CL_Random construction:

+

+CL_Random::CL_Random( const unsigned int SEED )

+{

+ state[0] = SEED;

+

+ for (int i=1; i<624; i++)

+ {

+ // Multiply the previous value, add 1 in case of 0, and use the lower

+ // 32 bits.

+ state[i] = (0x10dcd * state[i-1] +1)&0xffffffff;

+ }

+ randomize();

+ index=0;

+}

+

+/////////////////////////////////////////////////////////////////////////////

+// CL_Random operations:

+

+unsigned int CL_Random::rand()

+{

+ unsigned int q=state[index];

+ index++;

+ if (index > 623)

+ {

+ index=0;

+ randomize();

+ }

+ return q;

+}

+

+bool CL_Random::even()

+{

+ unsigned int q=rand();

+ if ((rand()&0x1) == 1)

+ {

+ return true;

+ }

+ else

+ {

+ return false;

+ }

+}

+

+float CL_Random::normalized()

+{

+ return float(rand())/float(0xffffffff);

+}

+

+float CL_Random::ranged(const float min, const float max)

+{

+ float range = max-min;

+ return min+range*normalized();

+}

+

+float CL_Random::distributed(const float mean, const float deviation)

+{

+ // The function is simple... for X deviations, and a probability P that the

+ // result will lie X deviations from the mean, P=1-(1/2^x)

+ // Solving this for X, we have X=log(1/(1-P))/log(2)

+ // Of course, since P lies between 0..1, we can just use X=log(1/P)/log(2)

+

+ float x=log(1/normalized())*inverse_log_2;

+

+ if (even())

+ {

+ return mean + x*deviation;

+ }

+ return mean - x*deviation;

+}

+

+/////////////////////////////////////////////////////////////////////////////

+// CL_Random implementation:

+

+void CL_Random::randomize()

+{

+ for (int i=0; i<623; i++)

+ {

+ // The highest bit of state[i] + the lower 31 bits of state[i+1]

+ unsigned int q = state[i]&0x80000000 + state[i+1]&0x7fffffff;

+

+ // The state is the state of i + the offset (397), bitwise

+ // xor'd with (y right shifted by 1 bit)

+ unsigned int w = state[(i+397)%624]^(q>>1);

+ if ((q&0x1) == 0)

+ {

+ // If q is even

+ state[i] = w;

+ }

+ else

+ {

+ // q is odd

+ state[i] = w^0x9908b0df;

+ }

+ }

+ unsigned int q = state[623]&0x80000000 + state[0]&0x7fffffff;

+ unsigned int w = state[396]^(q >> 1);

+ if ((q&0x1) == 0)

+ {

+ state[623]=w;

+ }

+ else

+ {

+ state[623]=w^0x9908b0df;

+ }

+}

## Bookmarks