2014-07-08 03:11:14 -04:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "EmberDefines.h"
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// C++ TEMPLATE VERSION OF Robert J. Jenkins Jr.'s
|
|
|
|
/// ISAAC Random Number Generator.
|
2014-09-10 01:41:26 -04:00
|
|
|
///
|
2014-07-08 03:11:14 -04:00
|
|
|
/// Ported from vanilla C to to template C++ class
|
|
|
|
/// by Quinn Tyler Jackson on 16-23 July 1998.
|
2014-09-10 01:41:26 -04:00
|
|
|
///
|
2014-07-08 03:11:14 -04:00
|
|
|
/// quinn@qtj.net
|
2014-09-10 01:41:26 -04:00
|
|
|
///
|
2014-07-08 03:11:14 -04:00
|
|
|
/// The function for the expected period of this
|
|
|
|
/// random number generator, according to Jenkins is:
|
2014-09-10 01:41:26 -04:00
|
|
|
///
|
2014-07-08 03:11:14 -04:00
|
|
|
/// f(a,b) = 2**((a+b*(3+2^^a)-1)
|
2014-09-10 01:41:26 -04:00
|
|
|
///
|
2014-07-08 03:11:14 -04:00
|
|
|
/// (where a is ALPHA and b is bitwidth)
|
2014-09-10 01:41:26 -04:00
|
|
|
///
|
2014-07-08 03:11:14 -04:00
|
|
|
/// So, for a bitwidth of 32 and an ALPHA of 8,
|
|
|
|
/// the expected period of ISAAC is:
|
2014-09-10 01:41:26 -04:00
|
|
|
///
|
2014-07-08 03:11:14 -04:00
|
|
|
/// 2^^(8+32*(3+2^^8)-1) = 2^^8295
|
2014-09-10 01:41:26 -04:00
|
|
|
///
|
2014-07-08 03:11:14 -04:00
|
|
|
/// Jackson has been able to run implementations
|
|
|
|
/// with an ALPHA as high as 16, or
|
2014-09-10 01:41:26 -04:00
|
|
|
///
|
2014-07-08 03:11:14 -04:00
|
|
|
/// 2^^2097263
|
2014-09-10 01:41:26 -04:00
|
|
|
///
|
2014-07-08 03:11:14 -04:00
|
|
|
/// -Modified by Matt Feemster to eliminate needless dynamic memory allocation and virtual functions and bring inline with Ember coding style.
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
#ifndef __ISAAC64
|
2014-12-06 00:05:09 -05:00
|
|
|
typedef uint ISAAC_INT;
|
2014-07-08 03:11:14 -04:00
|
|
|
const ISAAC_INT GOLDEN_RATIO = ISAAC_INT(0x9e3779b9);
|
|
|
|
#else
|
2014-10-14 11:53:15 -04:00
|
|
|
typedef size_t ISAAC_INT;
|
2014-07-08 03:11:14 -04:00
|
|
|
const ISAAC_INT GOLDEN_RATIO = ISAAC_INT(0x9e3779b97f4a7c13);
|
|
|
|
#endif
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
namespace EmberNs
|
|
|
|
{
|
|
|
|
/// <summary>
|
|
|
|
/// QTIsaac class which allows using ISAAC in an OOP manner.
|
|
|
|
/// </summary>
|
2014-09-10 01:41:26 -04:00
|
|
|
template <int ALPHA = 4, class T = ISAAC_INT>
|
2014-07-08 03:11:14 -04:00
|
|
|
class EMBER_API QTIsaac
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum { N = (1 << ALPHA) };
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Global ISAAC RNG to be used from anywhere. This is not thread safe, so take caution to only
|
|
|
|
/// use it when no other threads are.
|
|
|
|
/// </summary>
|
2015-01-14 05:37:40 -05:00
|
|
|
static unique_ptr<QTIsaac<ALPHA, ISAAC_INT> > GlobalRand;
|
2014-07-08 03:11:14 -04:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The structure which holds all of the random information.
|
|
|
|
/// </summary>
|
|
|
|
struct EMBER_API randctx
|
|
|
|
{
|
|
|
|
T randcnt;
|
|
|
|
T randrsl[N];
|
|
|
|
T randmem[N];
|
|
|
|
T randa;
|
|
|
|
T randb;
|
|
|
|
T randc;
|
|
|
|
};
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
/// <summary>
|
|
|
|
/// Constructor which initialized the random context using the values passed in.
|
|
|
|
/// Leaving these as their defaults is fine, and will still give different
|
|
|
|
/// results because time is internally used if they are default.
|
|
|
|
/// However, specifying specific values is useful if you want to duplicate
|
|
|
|
/// a sequence of random numbers.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="a">First random seed. Default: 0.</param>
|
|
|
|
/// <param name="b">Second random seed. Default: 0.</param>
|
|
|
|
/// <param name="c">Third random seed. Default: 0.</param>
|
2014-09-10 01:41:26 -04:00
|
|
|
/// <param name="s">Pointer to a buffer of 256 random integer seeds. Default: nullptr.</param>
|
|
|
|
QTIsaac(T a = 0, T b = 0, T c = 0, T* s = nullptr)
|
2014-07-08 03:11:14 -04:00
|
|
|
{
|
|
|
|
Srand(a, b, c, s);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Return the next random integer.
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>The next random integer</returns>
|
|
|
|
inline T Rand()
|
|
|
|
{
|
Numerous fixes
0.4.0.5 Beta 07/18/2014
--User Changes
Allow for vibrancy values > 1.
Add flatten and unflatten menu items.
Automatically flatten like Apophysis does.
Add plugin and new_linear tags to Xml to be compatible with Apophysis.
--Bug Fixes
Fix blur, blur3d, bubble, cropn, cross, curl, curl3d, epispiral, ho,
julia3d, julia3dz, loonie, mirror_x, mirror_y, mirror_z, rotate_x,
sinusoidal, spherical, spherical3d, stripes.
Unique filename on final render was completely broken.
Two severe OpenCL bugs. Random seeds were biased and fusing was being
reset too often leading to results that differ from the CPU.
Subtle, but sometimes severe bug in the setup of the xaos weights.
Use properly defined epsilon by getting the value from
std::numeric_limits, rather than hard coding 1e-6 or 1e-10.
Omit incorrect usage of epsilon everywhere. It should not be
automatically added to denominators. Rather, it should only be used if
the denominator is zero.
Force final render progress bars to 100 on completion. Sometimes they
didn't seem to make it there.
Make variation name and params comparisons be case insensitive.
--Code Changes
Make ForEach and FindIf wrappers around std::for_each and std::find_if.
2014-07-19 02:33:18 -04:00
|
|
|
#ifdef ISAAC_FLAM3_DEBUG
|
|
|
|
return (!m_Rc.randcnt-- ? (Isaac(&m_Rc), m_Rc.randcnt=N-1, m_Rc.randrsl[m_Rc.randcnt]) : m_Rc.randrsl[m_Rc.randcnt]);
|
|
|
|
#else
|
2014-07-08 03:11:14 -04:00
|
|
|
return (m_Rc.randcnt++ == N ? (Isaac(&m_Rc), m_Rc.randcnt=0, m_Rc.randrsl[m_Rc.randcnt]) : m_Rc.randrsl[m_Rc.randcnt]);
|
Numerous fixes
0.4.0.5 Beta 07/18/2014
--User Changes
Allow for vibrancy values > 1.
Add flatten and unflatten menu items.
Automatically flatten like Apophysis does.
Add plugin and new_linear tags to Xml to be compatible with Apophysis.
--Bug Fixes
Fix blur, blur3d, bubble, cropn, cross, curl, curl3d, epispiral, ho,
julia3d, julia3dz, loonie, mirror_x, mirror_y, mirror_z, rotate_x,
sinusoidal, spherical, spherical3d, stripes.
Unique filename on final render was completely broken.
Two severe OpenCL bugs. Random seeds were biased and fusing was being
reset too often leading to results that differ from the CPU.
Subtle, but sometimes severe bug in the setup of the xaos weights.
Use properly defined epsilon by getting the value from
std::numeric_limits, rather than hard coding 1e-6 or 1e-10.
Omit incorrect usage of epsilon everywhere. It should not be
automatically added to denominators. Rather, it should only be used if
the denominator is zero.
Force final render progress bars to 100 on completion. Sometimes they
didn't seem to make it there.
Make variation name and params comparisons be case insensitive.
--Code Changes
Make ForEach and FindIf wrappers around std::for_each and std::find_if.
2014-07-19 02:33:18 -04:00
|
|
|
#endif
|
2014-07-08 03:11:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
2014-10-27 17:21:06 -04:00
|
|
|
/// Return the next random integer between 0 and the value passed in minus 1.
|
2014-07-08 03:11:14 -04:00
|
|
|
/// </summary>
|
2014-10-27 17:21:06 -04:00
|
|
|
/// <param name="upper">A value one greater than the maximum value that will be returned</param>
|
|
|
|
/// <returns>A value between 0 and the value passed in minus 1</returns>
|
2014-07-08 03:11:14 -04:00
|
|
|
inline T Rand(T upper)
|
|
|
|
{
|
|
|
|
return (upper == 0) ? Rand() : Rand() % upper;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Returns a random floating point value between the specified minimum and maximum.
|
|
|
|
/// Template argument expected to be float or double.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="fMin">The minimum value allowed, inclusive.</param>
|
|
|
|
/// <param name="fMax">The maximum value allowed, inclusive.</param>
|
|
|
|
/// <returns>A new random floating point value within the specified range, inclusive.</returns>
|
|
|
|
template<typename floatType>
|
|
|
|
inline floatType Frand(floatType fMin, floatType fMax)
|
|
|
|
{
|
2014-12-07 02:51:44 -05:00
|
|
|
floatType f = static_cast<floatType>(Rand()) / static_cast<floatType>(std::numeric_limits<T>::max());
|
2014-07-08 03:11:14 -04:00
|
|
|
return fMin + (f * (fMax - fMin));
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Thin wrapper around a call to Frand() with a range of 0-1.
|
|
|
|
/// Template argument expected to be float or double.
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>A new random number in the range of 0-1, inclusive.</returns>
|
|
|
|
template<typename floatType>
|
|
|
|
inline floatType Frand01()
|
|
|
|
{
|
Numerous fixes
0.4.0.5 Beta 07/18/2014
--User Changes
Allow for vibrancy values > 1.
Add flatten and unflatten menu items.
Automatically flatten like Apophysis does.
Add plugin and new_linear tags to Xml to be compatible with Apophysis.
--Bug Fixes
Fix blur, blur3d, bubble, cropn, cross, curl, curl3d, epispiral, ho,
julia3d, julia3dz, loonie, mirror_x, mirror_y, mirror_z, rotate_x,
sinusoidal, spherical, spherical3d, stripes.
Unique filename on final render was completely broken.
Two severe OpenCL bugs. Random seeds were biased and fusing was being
reset too often leading to results that differ from the CPU.
Subtle, but sometimes severe bug in the setup of the xaos weights.
Use properly defined epsilon by getting the value from
std::numeric_limits, rather than hard coding 1e-6 or 1e-10.
Omit incorrect usage of epsilon everywhere. It should not be
automatically added to denominators. Rather, it should only be used if
the denominator is zero.
Force final render progress bars to 100 on completion. Sometimes they
didn't seem to make it there.
Make variation name and params comparisons be case insensitive.
--Code Changes
Make ForEach and FindIf wrappers around std::for_each and std::find_if.
2014-07-19 02:33:18 -04:00
|
|
|
#ifdef ISAAC_FLAM3_DEBUG
|
|
|
|
return (Rand() & 0xfffffff) / (floatType)0xfffffff;
|
|
|
|
#else
|
2014-07-08 03:11:14 -04:00
|
|
|
return Frand<floatType>(floatType(0), floatType(1));
|
Numerous fixes
0.4.0.5 Beta 07/18/2014
--User Changes
Allow for vibrancy values > 1.
Add flatten and unflatten menu items.
Automatically flatten like Apophysis does.
Add plugin and new_linear tags to Xml to be compatible with Apophysis.
--Bug Fixes
Fix blur, blur3d, bubble, cropn, cross, curl, curl3d, epispiral, ho,
julia3d, julia3dz, loonie, mirror_x, mirror_y, mirror_z, rotate_x,
sinusoidal, spherical, spherical3d, stripes.
Unique filename on final render was completely broken.
Two severe OpenCL bugs. Random seeds were biased and fusing was being
reset too often leading to results that differ from the CPU.
Subtle, but sometimes severe bug in the setup of the xaos weights.
Use properly defined epsilon by getting the value from
std::numeric_limits, rather than hard coding 1e-6 or 1e-10.
Omit incorrect usage of epsilon everywhere. It should not be
automatically added to denominators. Rather, it should only be used if
the denominator is zero.
Force final render progress bars to 100 on completion. Sometimes they
didn't seem to make it there.
Make variation name and params comparisons be case insensitive.
--Code Changes
Make ForEach and FindIf wrappers around std::for_each and std::find_if.
2014-07-19 02:33:18 -04:00
|
|
|
#endif
|
2014-07-08 03:11:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Thin wrapper around a call to Frand() with a range of -1-1.
|
|
|
|
/// Template argument expected to be float or double.
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>A new random number in the range of -1-1, inclusive.</returns>
|
|
|
|
template<typename floatType>
|
|
|
|
inline floatType Frand11()
|
|
|
|
{
|
Numerous fixes
0.4.0.5 Beta 07/18/2014
--User Changes
Allow for vibrancy values > 1.
Add flatten and unflatten menu items.
Automatically flatten like Apophysis does.
Add plugin and new_linear tags to Xml to be compatible with Apophysis.
--Bug Fixes
Fix blur, blur3d, bubble, cropn, cross, curl, curl3d, epispiral, ho,
julia3d, julia3dz, loonie, mirror_x, mirror_y, mirror_z, rotate_x,
sinusoidal, spherical, spherical3d, stripes.
Unique filename on final render was completely broken.
Two severe OpenCL bugs. Random seeds were biased and fusing was being
reset too often leading to results that differ from the CPU.
Subtle, but sometimes severe bug in the setup of the xaos weights.
Use properly defined epsilon by getting the value from
std::numeric_limits, rather than hard coding 1e-6 or 1e-10.
Omit incorrect usage of epsilon everywhere. It should not be
automatically added to denominators. Rather, it should only be used if
the denominator is zero.
Force final render progress bars to 100 on completion. Sometimes they
didn't seem to make it there.
Make variation name and params comparisons be case insensitive.
--Code Changes
Make ForEach and FindIf wrappers around std::for_each and std::find_if.
2014-07-19 02:33:18 -04:00
|
|
|
#ifdef ISAAC_FLAM3_DEBUG
|
|
|
|
return ((Rand() & 0xfffffff) - 0x7ffffff) / (floatType)0x7ffffff;
|
|
|
|
#else
|
2014-07-08 03:11:14 -04:00
|
|
|
return Frand<floatType>(floatType(-1), floatType(1));
|
Numerous fixes
0.4.0.5 Beta 07/18/2014
--User Changes
Allow for vibrancy values > 1.
Add flatten and unflatten menu items.
Automatically flatten like Apophysis does.
Add plugin and new_linear tags to Xml to be compatible with Apophysis.
--Bug Fixes
Fix blur, blur3d, bubble, cropn, cross, curl, curl3d, epispiral, ho,
julia3d, julia3dz, loonie, mirror_x, mirror_y, mirror_z, rotate_x,
sinusoidal, spherical, spherical3d, stripes.
Unique filename on final render was completely broken.
Two severe OpenCL bugs. Random seeds were biased and fusing was being
reset too often leading to results that differ from the CPU.
Subtle, but sometimes severe bug in the setup of the xaos weights.
Use properly defined epsilon by getting the value from
std::numeric_limits, rather than hard coding 1e-6 or 1e-10.
Omit incorrect usage of epsilon everywhere. It should not be
automatically added to denominators. Rather, it should only be used if
the denominator is zero.
Force final render progress bars to 100 on completion. Sometimes they
didn't seem to make it there.
Make variation name and params comparisons be case insensitive.
--Code Changes
Make ForEach and FindIf wrappers around std::for_each and std::find_if.
2014-07-19 02:33:18 -04:00
|
|
|
#endif
|
2014-07-08 03:11:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Not sure what this does.
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>Something that is golden</returns>
|
|
|
|
template<typename floatType>
|
|
|
|
inline floatType GoldenBit()
|
|
|
|
{
|
|
|
|
return RandBit() ? floatType(0.38196) : floatType(0.61804);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Returns a random 0 or 1.
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>A random 0 or 1</returns>
|
2014-12-06 00:05:09 -05:00
|
|
|
inline uint RandBit()
|
2014-07-08 03:11:14 -04:00
|
|
|
{
|
|
|
|
return Rand() & 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// A different way of getting a floating point rand in the range -1-1.
|
|
|
|
/// Flam3 used this but it seems unnecessary now, keep around if it's ever needed.
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>A new random number in the range of -1-1, inclusive.</returns>
|
|
|
|
//double drand11()
|
|
|
|
//{
|
|
|
|
// return (((int)Rand() & 0xfffffff) - 0x7ffffff) / (double) 0x7ffffff;
|
|
|
|
//}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a random context.
|
|
|
|
/// Unsure exacly how this works, but it does.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="ctx">The random context to initialize</param>
|
|
|
|
/// <param name="useSeed">Whether to use the seeds passed in to the constructor, else zero.</param>
|
|
|
|
void RandInit(randctx* ctx, bool useSeed)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
T a, b, c, d, e, f, g, h;
|
|
|
|
T* m = ctx->randmem;
|
|
|
|
T* r = ctx->randrsl;
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
a = b = c = d = e = f = g = h = GOLDEN_RATIO;
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
if (!useSeed)
|
|
|
|
{
|
|
|
|
ctx->randa = 0;
|
|
|
|
ctx->randb = 0;
|
|
|
|
ctx->randc = 0;
|
|
|
|
}
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
//Scramble it.
|
2014-09-10 01:41:26 -04:00
|
|
|
for (i = 0; i < 4; ++i)
|
2014-07-08 03:11:14 -04:00
|
|
|
{
|
|
|
|
Shuffle(a, b, c, d, e, f, g, h);
|
|
|
|
}
|
2014-09-10 01:41:26 -04:00
|
|
|
|
|
|
|
if (useSeed)
|
2014-07-08 03:11:14 -04:00
|
|
|
{
|
|
|
|
//Initialize using the contents of r[] as the seed.
|
|
|
|
for (i = 0; i < N; i += 8)
|
|
|
|
{
|
|
|
|
a += r[i ]; b += r[i + 1]; c += r[i + 2]; d += r[i + 3];
|
|
|
|
e += r[i + 4]; f += r[i + 5]; g += r[i + 6]; h += r[i + 7];
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
Shuffle(a, b, c, d, e, f, g, h);
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d;
|
|
|
|
m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h;
|
2014-09-10 01:41:26 -04:00
|
|
|
}
|
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
//Do a second pass to make all of the seed affect all of m.
|
|
|
|
for (i = 0; i < N; i += 8)
|
|
|
|
{
|
|
|
|
a += m[i ]; b += m[i + 1]; c += m[i + 2]; d += m[i + 3];
|
|
|
|
e += m[i + 4]; f += m[i + 5]; g += m[i + 6]; h += m[i + 7];
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
Shuffle(a, b, c, d, e, f, g, h);
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d;
|
|
|
|
m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//Fill in mm[] with messy stuff.
|
|
|
|
Shuffle(a, b, c, d, e, f, g, h);
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d;
|
|
|
|
m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h;
|
|
|
|
}
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
Isaac(ctx); //Fill in the first set of results.
|
Numerous fixes
0.4.0.5 Beta 07/18/2014
--User Changes
Allow for vibrancy values > 1.
Add flatten and unflatten menu items.
Automatically flatten like Apophysis does.
Add plugin and new_linear tags to Xml to be compatible with Apophysis.
--Bug Fixes
Fix blur, blur3d, bubble, cropn, cross, curl, curl3d, epispiral, ho,
julia3d, julia3dz, loonie, mirror_x, mirror_y, mirror_z, rotate_x,
sinusoidal, spherical, spherical3d, stripes.
Unique filename on final render was completely broken.
Two severe OpenCL bugs. Random seeds were biased and fusing was being
reset too often leading to results that differ from the CPU.
Subtle, but sometimes severe bug in the setup of the xaos weights.
Use properly defined epsilon by getting the value from
std::numeric_limits, rather than hard coding 1e-6 or 1e-10.
Omit incorrect usage of epsilon everywhere. It should not be
automatically added to denominators. Rather, it should only be used if
the denominator is zero.
Force final render progress bars to 100 on completion. Sometimes they
didn't seem to make it there.
Make variation name and params comparisons be case insensitive.
--Code Changes
Make ForEach and FindIf wrappers around std::for_each and std::find_if.
2014-07-19 02:33:18 -04:00
|
|
|
ctx->randcnt = N;//TODO//0;//Prepare to use the first set of results.
|
2014-07-08 03:11:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initialize the seeds of the member random context using the specified seeds.
|
|
|
|
/// If s is null, time plus index up to 256 is used for the random buffer.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="a">First random seed. Default: 0.</param>
|
|
|
|
/// <param name="b">Second random seed. Default: 0.</param>
|
|
|
|
/// <param name="c">Third random seed. Default: 0.</param>
|
2014-09-10 01:41:26 -04:00
|
|
|
/// <param name="s">Pointer to a buffer of 256 random integer seeds. Default: nullptr.</param>
|
|
|
|
void Srand(T a = 0, T b = 0, T c = 0, T* s = nullptr)
|
2014-07-08 03:11:14 -04:00
|
|
|
{
|
2014-09-10 01:41:26 -04:00
|
|
|
if (s == nullptr)//Default to using time plus index as the seed if s was nullptr.
|
2014-07-08 03:11:14 -04:00
|
|
|
{
|
|
|
|
for (int i = 0; i < N; i++)
|
2014-12-07 02:51:44 -05:00
|
|
|
m_Rc.randrsl[i] = static_cast<T>(time(nullptr)) + i;
|
2014-07-08 03:11:14 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (int i = 0; i < N; i++)
|
|
|
|
m_Rc.randrsl[i] = s[i];
|
|
|
|
}
|
|
|
|
|
Numerous fixes
0.4.0.5 Beta 07/18/2014
--User Changes
Allow for vibrancy values > 1.
Add flatten and unflatten menu items.
Automatically flatten like Apophysis does.
Add plugin and new_linear tags to Xml to be compatible with Apophysis.
--Bug Fixes
Fix blur, blur3d, bubble, cropn, cross, curl, curl3d, epispiral, ho,
julia3d, julia3dz, loonie, mirror_x, mirror_y, mirror_z, rotate_x,
sinusoidal, spherical, spherical3d, stripes.
Unique filename on final render was completely broken.
Two severe OpenCL bugs. Random seeds were biased and fusing was being
reset too often leading to results that differ from the CPU.
Subtle, but sometimes severe bug in the setup of the xaos weights.
Use properly defined epsilon by getting the value from
std::numeric_limits, rather than hard coding 1e-6 or 1e-10.
Omit incorrect usage of epsilon everywhere. It should not be
automatically added to denominators. Rather, it should only be used if
the denominator is zero.
Force final render progress bars to 100 on completion. Sometimes they
didn't seem to make it there.
Make variation name and params comparisons be case insensitive.
--Code Changes
Make ForEach and FindIf wrappers around std::for_each and std::find_if.
2014-07-19 02:33:18 -04:00
|
|
|
#ifndef ISAAC_FLAM3_DEBUG
|
2014-07-08 03:11:14 -04:00
|
|
|
if (a == 0 && b == 0 && c == 0)
|
|
|
|
{
|
2014-12-07 02:51:44 -05:00
|
|
|
m_Rc.randa = static_cast<T>(time(nullptr));
|
|
|
|
m_Rc.randb = static_cast<T>(time(nullptr)) * static_cast<T>(time(nullptr));
|
|
|
|
m_Rc.randc = static_cast<T>(time(nullptr)) * static_cast<T>(time(nullptr)) * static_cast<T>(time(nullptr));
|
2014-07-08 03:11:14 -04:00
|
|
|
}
|
|
|
|
else
|
Numerous fixes
0.4.0.5 Beta 07/18/2014
--User Changes
Allow for vibrancy values > 1.
Add flatten and unflatten menu items.
Automatically flatten like Apophysis does.
Add plugin and new_linear tags to Xml to be compatible with Apophysis.
--Bug Fixes
Fix blur, blur3d, bubble, cropn, cross, curl, curl3d, epispiral, ho,
julia3d, julia3dz, loonie, mirror_x, mirror_y, mirror_z, rotate_x,
sinusoidal, spherical, spherical3d, stripes.
Unique filename on final render was completely broken.
Two severe OpenCL bugs. Random seeds were biased and fusing was being
reset too often leading to results that differ from the CPU.
Subtle, but sometimes severe bug in the setup of the xaos weights.
Use properly defined epsilon by getting the value from
std::numeric_limits, rather than hard coding 1e-6 or 1e-10.
Omit incorrect usage of epsilon everywhere. It should not be
automatically added to denominators. Rather, it should only be used if
the denominator is zero.
Force final render progress bars to 100 on completion. Sometimes they
didn't seem to make it there.
Make variation name and params comparisons be case insensitive.
--Code Changes
Make ForEach and FindIf wrappers around std::for_each and std::find_if.
2014-07-19 02:33:18 -04:00
|
|
|
#endif
|
2014-07-08 03:11:14 -04:00
|
|
|
{
|
|
|
|
m_Rc.randa = a;
|
|
|
|
m_Rc.randb = b;
|
|
|
|
m_Rc.randc = c;
|
|
|
|
}
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
RandInit(&m_Rc, true);
|
|
|
|
}
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
protected:
|
|
|
|
/// <summary>
|
|
|
|
/// Compute the next batch of random numbers for a random context.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="ctx">The context to populate.</param>
|
|
|
|
void Isaac(randctx* ctx)
|
|
|
|
{
|
|
|
|
T x,y;
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
T* mm = ctx->randmem;
|
|
|
|
T* r = ctx->randrsl;
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
T a = (ctx->randa);
|
|
|
|
T b = (ctx->randb + (++ctx->randc));
|
2014-09-10 01:41:26 -04:00
|
|
|
|
|
|
|
T* m = mm;
|
2014-07-08 03:11:14 -04:00
|
|
|
T* m2 = (m + (N / 2));
|
|
|
|
T* mend = m2;
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
for(; m < mend; )
|
|
|
|
{
|
|
|
|
#ifndef __ISAAC64
|
|
|
|
RngStep((a << 13), a, b, mm, m, m2, r, x, y);
|
|
|
|
RngStep((a >> 6) , a, b, mm, m, m2, r, x, y);
|
|
|
|
RngStep((a << 2) , a, b, mm, m, m2, r, x, y);
|
|
|
|
RngStep((a >> 16), a, b, mm, m, m2, r, x, y);
|
|
|
|
#else // __ISAAC64
|
|
|
|
RngStep(~(a ^ (a << 21)), a, b, mm, m, m2, r, x, y);
|
|
|
|
RngStep( a ^ (a >> 5) , a, b, mm, m, m2, r, x, y);
|
|
|
|
RngStep( a ^ (a << 12) , a, b, mm, m, m2, r, x, y);
|
|
|
|
RngStep( a ^ (a >> 33) , a, b, mm, m, m2, r, x, y);
|
|
|
|
#endif // __ISAAC64
|
|
|
|
}
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
m2 = mm;
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
for(; m2<mend;)
|
|
|
|
{
|
|
|
|
#ifndef __ISAAC64
|
|
|
|
RngStep((a << 13), a, b, mm, m, m2, r, x, y);
|
|
|
|
RngStep((a >> 6) , a, b, mm, m, m2, r, x, y);
|
|
|
|
RngStep((a << 2) , a, b, mm, m, m2, r, x, y);
|
|
|
|
RngStep((a >> 16), a, b, mm, m, m2, r, x, y);
|
|
|
|
#else // __ISAAC64
|
|
|
|
RngStep(~(a ^ (a << 21)), a, b, mm, m, m2, r, x, y);
|
|
|
|
RngStep( a ^ (a >> 5) , a, b, mm, m, m2, r, x, y);
|
|
|
|
RngStep( a ^ (a << 12) , a, b, mm, m, m2, r, x, y);
|
|
|
|
RngStep( a ^ (a >> 33) , a, b, mm, m, m2, r, x, y);
|
|
|
|
#endif // __ISAAC64
|
|
|
|
}
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
ctx->randb = b;
|
|
|
|
ctx->randa = a;
|
|
|
|
}
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
/// <summary>
|
|
|
|
/// Retrieves a value using indirection.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="mm">The buffer.</param>
|
|
|
|
/// <param name="x">The offset.</param>
|
|
|
|
/// <returns>A new value</returns>
|
|
|
|
inline T Ind(T* mm, T x)
|
|
|
|
{
|
|
|
|
#ifndef __ISAAC64
|
2014-12-07 02:51:44 -05:00
|
|
|
return (*reinterpret_cast<T*>(reinterpret_cast<byte*>(mm) + ((x) & ((N - 1) << 2))));
|
2014-07-08 03:11:14 -04:00
|
|
|
#else // __ISAAC64
|
2014-12-07 02:51:44 -05:00
|
|
|
return (*reinterpret_cast<T*>(reinterpret_cast<byte*>(mm) + ((x) & ((N - 1) << 3))));
|
2014-07-08 03:11:14 -04:00
|
|
|
#endif // __ISAAC64
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Unsure what this does.
|
|
|
|
/// </summary>
|
|
|
|
void RngStep(T mix, T& a, T& b, T*& mm, T*& m, T*& m2, T*& r, T& x, T& y)
|
|
|
|
{
|
2014-09-10 01:41:26 -04:00
|
|
|
x = *m;
|
|
|
|
a = (a ^ (mix)) + *(m2++);
|
|
|
|
*(m++) = y = Ind(mm, x) + a + b;
|
|
|
|
*(r++) = b = Ind(mm, y >> ALPHA) + x;
|
2014-07-08 03:11:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Unsure what this does.
|
|
|
|
/// </summary>
|
|
|
|
void Shuffle(T& a, T& b, T& c, T& d, T& e, T& f, T& g, T& h)
|
2014-09-10 01:41:26 -04:00
|
|
|
{
|
2014-07-08 03:11:14 -04:00
|
|
|
#ifndef __ISAAC64
|
2014-09-10 01:41:26 -04:00
|
|
|
a ^= b << 11; d += a; b += c;
|
|
|
|
b ^= c >> 2; e += b; c += d;
|
|
|
|
c ^= d << 8; f += c; d += e;
|
|
|
|
d ^= e >> 16; g += d; e += f;
|
|
|
|
e ^= f << 10; h += e; f += g;
|
|
|
|
f ^= g >> 4; a += f; g += h;
|
|
|
|
g ^= h << 8; b += g; h += a;
|
|
|
|
h ^= a >> 9; c += h; a += b;
|
2014-07-08 03:11:14 -04:00
|
|
|
#else // __ISAAC64
|
|
|
|
a -= e; f ^= h >> 9; h += a;
|
|
|
|
b -= f; g ^= a << 9; a += b;
|
|
|
|
c -= g; h ^= b >> 23; b += c;
|
|
|
|
d -= h; a ^= c << 15; c += d;
|
|
|
|
e -= a; b ^= d >> 14; d += e;
|
|
|
|
f -= b; c ^= e << 20; e += f;
|
|
|
|
g -= c; d ^= f >> 17; f += g;
|
|
|
|
h -= d; e ^= g << 14; g += h;
|
|
|
|
#endif // __ISAAC64
|
|
|
|
}
|
2014-09-10 01:41:26 -04:00
|
|
|
|
2014-07-08 03:11:14 -04:00
|
|
|
private:
|
|
|
|
randctx m_Rc;//The random context which holds all of the seed and state information as well as the random number values.
|
|
|
|
};
|
2014-09-10 01:41:26 -04:00
|
|
|
}
|