Initial version.
This commit is contained in:
commit
fbac6f95d4
|
@ -0,0 +1,82 @@
|
||||||
|
// Copyright (c) 2013, Peter Pettersson
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
// list of conditions and the following disclaimer.
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those
|
||||||
|
// of the authors and should not be interpreted as representing official policies,
|
||||||
|
// either expressed or implied, of the FreeBSD Project.
|
||||||
|
|
||||||
|
#include "RandomWELL512a.h"
|
||||||
|
#include <stdlib.h> // Needed for rand().
|
||||||
|
#include <memory.h> // Needed for memcpy().
|
||||||
|
|
||||||
|
RandomWELL512a::RandomWELL512a(int seed)
|
||||||
|
: index(0)
|
||||||
|
{
|
||||||
|
srand(seed);
|
||||||
|
for (int i = 0; i < 16; ++i)
|
||||||
|
state[i] = rand();
|
||||||
|
}
|
||||||
|
|
||||||
|
RandomWELL512a::RandomWELL512a(unsigned *seed)
|
||||||
|
: index(0)
|
||||||
|
{
|
||||||
|
memcpy(state, seed, 16 * sizeof(unsigned));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned RandomWELL512a::GetUnsigned()
|
||||||
|
{
|
||||||
|
#define MUTATE_LEFT(value, shift) value ^ (value << shift)
|
||||||
|
#define MUTATE_RIGHT(value, shift) value ^ (value >> shift)
|
||||||
|
#define MUTATE_LEFT_MIX(value, shift, mix) value ^ ((value << shift) & mix)
|
||||||
|
|
||||||
|
unsigned index_9 = (index + 9) & 15;
|
||||||
|
unsigned index_13 = (index + 13) & 15;
|
||||||
|
unsigned index_15 = (index + 15) & 15;
|
||||||
|
|
||||||
|
unsigned state_index = state[index];
|
||||||
|
unsigned state_index_9 = state[index_9];
|
||||||
|
unsigned state_index_13 = state[index_13];
|
||||||
|
unsigned state_index_15 = state[index_15];
|
||||||
|
|
||||||
|
unsigned z1 = MUTATE_LEFT(state_index, 16);
|
||||||
|
z1 ^= MUTATE_LEFT(state_index_13, 15);
|
||||||
|
|
||||||
|
unsigned z2 = MUTATE_RIGHT(state_index_9, 11);
|
||||||
|
|
||||||
|
unsigned result0 = z1 ^ z2;
|
||||||
|
state[index] = result0;
|
||||||
|
|
||||||
|
unsigned result1 = MUTATE_LEFT(state_index_15, 2);
|
||||||
|
result1 ^= MUTATE_LEFT(z1, 18);;
|
||||||
|
result1 ^= z2 << 28;
|
||||||
|
|
||||||
|
result1 ^= MUTATE_LEFT_MIX(result0, 5, 0xda442d24U);
|
||||||
|
|
||||||
|
index = index_15;
|
||||||
|
state[index] = result1;
|
||||||
|
return result1;
|
||||||
|
|
||||||
|
#undef MUTATE_LEFT
|
||||||
|
#undef MUTATE_RIGHT
|
||||||
|
#undef MUTATE_LEFT_MIX
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
// Copyright (c) 2013, Peter Pettersson
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
// list of conditions and the following disclaimer.
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those
|
||||||
|
// of the authors and should not be interpreted as representing official policies,
|
||||||
|
// either expressed or implied, of the FreeBSD Project.
|
||||||
|
|
||||||
|
#ifndef RANDOM_WELL512A_H
|
||||||
|
#define RANDOM_WELL512A_H
|
||||||
|
|
||||||
|
class RandomWELL512a
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RandomWELL512a(int seed);
|
||||||
|
RandomWELL512a(unsigned *seed);
|
||||||
|
|
||||||
|
unsigned GetUnsigned();
|
||||||
|
|
||||||
|
double GetDouble()
|
||||||
|
{
|
||||||
|
const double kToFloat = 2.32830643653869628906e-10;
|
||||||
|
return GetUnsigned() * kToFloat;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned state[16];
|
||||||
|
unsigned index;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // RANDOM_WELL512A_H
|
|
@ -0,0 +1,88 @@
|
||||||
|
// Copyright (c) 2013, Peter Pettersson
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
// list of conditions and the following disclaimer.
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those
|
||||||
|
// of the authors and should not be interpreted as representing official policies,
|
||||||
|
// either expressed or implied, of the FreeBSD Project.
|
||||||
|
|
||||||
|
#include "RandomWELL512a_SSE2.h"
|
||||||
|
#include <stdlib.h> // Needed for rand().
|
||||||
|
#include <memory.h> // Needed for memcpy().
|
||||||
|
|
||||||
|
RandomWELL512a_SSE2::RandomWELL512a_SSE2(int seed)
|
||||||
|
: index(0)
|
||||||
|
{
|
||||||
|
srand(seed);
|
||||||
|
for (int i = 0; i < 16; ++i)
|
||||||
|
xmm_state[i] = _mm_set_epi32(rand(), rand(), rand(), rand());
|
||||||
|
}
|
||||||
|
|
||||||
|
RandomWELL512a_SSE2::RandomWELL512a_SSE2(unsigned *seed)
|
||||||
|
: index(0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 16; ++i)
|
||||||
|
xmm_state[i] = _mm_set_epi32(seed[i + 48], seed[i + 32], seed[i + 16], seed[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RandomWELL512a_SSE2::GetUnsigned4(unsigned *result4)
|
||||||
|
{
|
||||||
|
// Calculations.
|
||||||
|
#define MUTATE_LEFT(value, shift) _mm_xor_si128(value, _mm_slli_epi32(value, shift))
|
||||||
|
#define MUTATE_RIGHT(value, shift) _mm_xor_si128(value, _mm_srli_epi32(value, shift))
|
||||||
|
#define MUTATE_LEFT_MIX(value, shift, mix) _mm_xor_si128(value, _mm_and_si128(_mm_slli_epi32(value, shift), mix))
|
||||||
|
|
||||||
|
unsigned index_15 = (index + 15) & 15;
|
||||||
|
__m128i state_index = xmm_state[index];
|
||||||
|
__m128i state_index_9 = xmm_state[(index + 9) & 15];
|
||||||
|
__m128i state_index_13 = xmm_state[(index + 13) & 15];
|
||||||
|
__m128i state_index_15 = xmm_state[index_15];
|
||||||
|
const __m128i kMix = _mm_set1_epi32(0xda442d24);
|
||||||
|
|
||||||
|
__m128i z1 = _mm_xor_si128(MUTATE_LEFT(state_index, 16), MUTATE_LEFT(state_index_13, 15));
|
||||||
|
__m128i z2 = MUTATE_RIGHT(state_index_9, 11);
|
||||||
|
__m128i result0 = _mm_xor_si128(z1, z2);
|
||||||
|
xmm_state[index] = result0;
|
||||||
|
|
||||||
|
__m128i result1 = MUTATE_LEFT(state_index_15, 2);
|
||||||
|
result1 = _mm_xor_si128(result1, MUTATE_LEFT(z1, 18));
|
||||||
|
result1 = _mm_xor_si128(result1, _mm_slli_epi32(z2, 28));
|
||||||
|
result1 = _mm_xor_si128(result1, MUTATE_LEFT_MIX(result0, 5, kMix));
|
||||||
|
index = index_15;
|
||||||
|
xmm_state[index] = result1;
|
||||||
|
|
||||||
|
_mm_storeu_si128((__m128i *)result4, result1);
|
||||||
|
|
||||||
|
#undef MUTATE_LEFT
|
||||||
|
#undef MUTATE_RIGHT
|
||||||
|
#undef MUTATE_LEFT_MIX
|
||||||
|
}
|
||||||
|
|
||||||
|
void RandomWELL512a_SSE2::GetDouble4(double *result4)
|
||||||
|
{
|
||||||
|
unsigned unsignedResult[4];
|
||||||
|
GetUnsigned4(unsignedResult);
|
||||||
|
|
||||||
|
const double kToFloat = 2.32830643653869628906e-10;
|
||||||
|
for (unsigned loop = 0; loop < 4; ++loop)
|
||||||
|
result4[loop] = unsignedResult[loop] * kToFloat;
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
// Copyright (c) 2013, Peter Pettersson
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
// list of conditions and the following disclaimer.
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those
|
||||||
|
// of the authors and should not be interpreted as representing official policies,
|
||||||
|
// either expressed or implied, of the FreeBSD Project.
|
||||||
|
|
||||||
|
#ifndef RANDOM_WELL512A_SSE2_H
|
||||||
|
#define RANDOM_WELL512A_SSE2_H
|
||||||
|
|
||||||
|
#include <emmintrin.h> // SSE2 instrinsics.
|
||||||
|
|
||||||
|
class RandomWELL512a_SSE2
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RandomWELL512a_SSE2(int seed);
|
||||||
|
RandomWELL512a_SSE2(unsigned *seed);
|
||||||
|
|
||||||
|
unsigned GetUnsigned()
|
||||||
|
{
|
||||||
|
if (resultIndex < 4)
|
||||||
|
return result[resultIndex++];
|
||||||
|
|
||||||
|
GetUnsigned4(result);
|
||||||
|
resultIndex = 1;
|
||||||
|
return result[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
double GetDouble()
|
||||||
|
{
|
||||||
|
const double kToFloat = 2.32830643653869628906e-10;
|
||||||
|
return GetUnsigned() * kToFloat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GetUnsigned4(unsigned *result4);
|
||||||
|
void GetDouble4(double *result4);
|
||||||
|
|
||||||
|
private:
|
||||||
|
__m128i xmm_state[16];
|
||||||
|
unsigned index;
|
||||||
|
|
||||||
|
// Helper to allow us to return one number per call.
|
||||||
|
unsigned result[4];
|
||||||
|
unsigned resultIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // RANDOM_WELL512A_SSE2_H
|
|
@ -0,0 +1,55 @@
|
||||||
|
// Copyright (c) 2013, Peter Pettersson
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
// list of conditions and the following disclaimer.
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those
|
||||||
|
// of the authors and should not be interpreted as representing official policies,
|
||||||
|
// either expressed or implied, of the FreeBSD Project.
|
||||||
|
|
||||||
|
#ifndef TIMER_H
|
||||||
|
#define TIMER_H
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class Timer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Timer()
|
||||||
|
{
|
||||||
|
startTime = clock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Report(const char *msg = NULL)
|
||||||
|
{
|
||||||
|
clock_t totalTime = clock() - startTime;
|
||||||
|
float seconds = (float)totalTime / CLOCKS_PER_SEC;
|
||||||
|
if (msg)
|
||||||
|
std::cout << msg << " ";
|
||||||
|
std::cout << "took " << seconds << " seconds." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
clock_t startTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TIMER_H
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*************************************************************************
|
||||||
|
Copyright: Francois Panneton and Pierre L'Ecuyer, Université de Montréal
|
||||||
|
Makoto Matsumoto, Hiroshima University
|
||||||
|
|
||||||
|
Notice: This code can be used freely for personal, academic,
|
||||||
|
or non-commercial purposes. For commercial purposes,
|
||||||
|
please contact P. L'Ecuyer at: lecuyer@iro.UMontreal.ca
|
||||||
|
|
||||||
|
This code can also be used under the terms of the GNU General Public
|
||||||
|
License as published by the Free Software Foundation, either version 3
|
||||||
|
of the License, or any later version. See the GPL licence at URL
|
||||||
|
http://www.gnu.org/licenses
|
||||||
|
|
||||||
|
**************************************************************************/
|
||||||
|
#include "WELL512a.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define W 32
|
||||||
|
#define R 16
|
||||||
|
#define P 0
|
||||||
|
#define M1 13
|
||||||
|
#define M2 9
|
||||||
|
#define M3 5
|
||||||
|
|
||||||
|
#define MAT0POS(t,v) (v^(v>>t))
|
||||||
|
#define MAT0NEG(t,v) (v^(v<<(-(t))))
|
||||||
|
#define MAT3NEG(t,v) (v<<(-(t)))
|
||||||
|
#define MAT4NEG(t,b,v) (v ^ ((v<<(-(t))) & b))
|
||||||
|
|
||||||
|
#define V0 STATE[state_i ]
|
||||||
|
#define VM1 STATE[(state_i+M1) & 0x0000000fU]
|
||||||
|
#define VM2 STATE[(state_i+M2) & 0x0000000fU]
|
||||||
|
#define VM3 STATE[(state_i+M3) & 0x0000000fU]
|
||||||
|
#define VRm1 STATE[(state_i+15) & 0x0000000fU]
|
||||||
|
#define VRm2 STATE[(state_i+14) & 0x0000000fU]
|
||||||
|
#define newV0 STATE[(state_i+15) & 0x0000000fU]
|
||||||
|
#define newV1 STATE[state_i ]
|
||||||
|
#define newVRm1 STATE[(state_i+14) & 0x0000000fU]
|
||||||
|
|
||||||
|
#define FACT 2.32830643653869628906e-10
|
||||||
|
|
||||||
|
static unsigned int state_i = 0;
|
||||||
|
static unsigned int STATE[R];
|
||||||
|
static unsigned int z0, z1, z2;
|
||||||
|
|
||||||
|
void InitWELLRNG512a (unsigned int *init)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
state_i = 0;
|
||||||
|
for (j = 0; j < R; j++)
|
||||||
|
STATE[j] = init[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
double WELLRNG512a (void)
|
||||||
|
{
|
||||||
|
z0 = VRm1;
|
||||||
|
z1 = MAT0NEG(-16, V0) ^ MAT0NEG(-15, VM1);
|
||||||
|
z2 = MAT0POS(11, VM2);
|
||||||
|
newV1 = z1 ^ z2;
|
||||||
|
newV0 = MAT0NEG(-2, z0) ^ MAT0NEG(-18, z1) ^ MAT3NEG(-28, z2) ^ MAT4NEG(-5, 0xda442d24U, newV1);
|
||||||
|
state_i = (state_i + 15) & 0x0000000fU;
|
||||||
|
return ((double) STATE[state_i]) * FACT;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*************************************************************************
|
||||||
|
Copyright: Francois Panneton and Pierre L'Ecuyer, Université de Montréal
|
||||||
|
Makoto Matsumoto, Hiroshima University
|
||||||
|
|
||||||
|
Notice: This code can be used freely for personal, academic,
|
||||||
|
or non-commercial purposes. For commercial purposes,
|
||||||
|
please contact P. L'Ecuyer at: lecuyer@iro.UMontreal.ca
|
||||||
|
|
||||||
|
This code can also be used under the terms of the GNU General Public
|
||||||
|
License as published by the Free Software Foundation, either version 3
|
||||||
|
of the License, or any later version. See the GPL licence at URL
|
||||||
|
http://www.gnu.org/licenses
|
||||||
|
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/* seed is an array of 16 unsigned int's used as seed of the generator */
|
||||||
|
void InitWELLRNG512a (unsigned int *seed);
|
||||||
|
|
||||||
|
double WELLRNG512a (void);
|
|
@ -0,0 +1,26 @@
|
||||||
|
Copyright (c) 2013, Peter Pettersson
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
The views and conclusions contained in the software and documentation are those
|
||||||
|
of the authors and should not be interpreted as representing official policies,
|
||||||
|
either expressed or implied, of the FreeBSD Project.
|
|
@ -0,0 +1,135 @@
|
||||||
|
// Copyright (c) 2013, Peter Pettersson
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
// list of conditions and the following disclaimer.
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those
|
||||||
|
// of the authors and should not be interpreted as representing official policies,
|
||||||
|
// either expressed or implied, of the FreeBSD Project.
|
||||||
|
|
||||||
|
#include "Timer.h"
|
||||||
|
#include "RandomWELL512a.h"
|
||||||
|
#include "RandomWELL512a_SSE2.h"
|
||||||
|
#include "WELL512a.h"
|
||||||
|
|
||||||
|
void Benchmark()
|
||||||
|
{
|
||||||
|
const unsigned kSeed = 123;
|
||||||
|
const unsigned kNumLoops = 5;
|
||||||
|
const unsigned kNumIterations = 40000000;
|
||||||
|
double *result0 = new double [kNumIterations];
|
||||||
|
double *result1 = new double [kNumIterations];
|
||||||
|
double *result2 = new double [kNumIterations];
|
||||||
|
double *result3 = new double [kNumIterations];
|
||||||
|
|
||||||
|
srand(kSeed);
|
||||||
|
unsigned seed[16];
|
||||||
|
for (unsigned i = 0; i < 16; ++i)
|
||||||
|
seed[i] = rand();
|
||||||
|
|
||||||
|
for (unsigned loop = 0; loop < kNumLoops; ++loop)
|
||||||
|
{
|
||||||
|
// RAND implementation.
|
||||||
|
srand(kSeed);
|
||||||
|
Timer timer0;
|
||||||
|
for (unsigned i = 0; i < kNumIterations; ++i)
|
||||||
|
result0[0] = rand() / (double)RAND_MAX;
|
||||||
|
timer0.Report("Rand(): ");
|
||||||
|
|
||||||
|
// WELL512 C++ implementation.
|
||||||
|
RandomWELL512a random(kSeed);
|
||||||
|
Timer timer1;
|
||||||
|
for (unsigned i = 0; i < kNumIterations; ++i)
|
||||||
|
result1[i] = random.GetDouble();
|
||||||
|
timer1.Report("WELL512 C++: ");
|
||||||
|
|
||||||
|
// WELL512 SSE2 implementation.
|
||||||
|
RandomWELL512a_SSE2 randomSSE2(kSeed);
|
||||||
|
Timer timer2;
|
||||||
|
for (unsigned i = 0; i < kNumIterations; i += 4)
|
||||||
|
randomSSE2.GetDouble4(result2 + i);
|
||||||
|
timer2.Report("WELL512 SSE2: ");
|
||||||
|
|
||||||
|
// WELL512 C implementation.
|
||||||
|
InitWELLRNG512a(seed);
|
||||||
|
Timer timer3;
|
||||||
|
for (unsigned i = 0; i < kNumIterations; ++i)
|
||||||
|
result3[i] = WELLRNG512a();
|
||||||
|
timer3.Report("WELL512 C: ");
|
||||||
|
|
||||||
|
std::cout << "---" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] result0;
|
||||||
|
delete [] result1;
|
||||||
|
delete [] result2;
|
||||||
|
delete [] result3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the SIMD implementation returns the same values as the original
|
||||||
|
// algorithm would.
|
||||||
|
void Test()
|
||||||
|
{
|
||||||
|
const int kSeed = 123;
|
||||||
|
const unsigned kNumIterations = 4 * 1024;
|
||||||
|
|
||||||
|
double *result0 = new double [kNumIterations];
|
||||||
|
double *result1 = new double [kNumIterations];
|
||||||
|
|
||||||
|
srand(kSeed);
|
||||||
|
unsigned seed[4 * 16];
|
||||||
|
for (unsigned i = 0; i < 4 * 16; ++i)
|
||||||
|
seed[i] = rand();
|
||||||
|
RandomWELL512a randomWell0(seed + 0 * 16);
|
||||||
|
RandomWELL512a randomWell1(seed + 1 * 16);
|
||||||
|
RandomWELL512a randomWell2(seed + 2 * 16);
|
||||||
|
RandomWELL512a randomWell3(seed + 3 * 16);
|
||||||
|
|
||||||
|
RandomWELL512a_SSE2 randomWellSSE2(seed);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < kNumIterations; i += 4)
|
||||||
|
{
|
||||||
|
result0[i + 0] = randomWell0.GetDouble();
|
||||||
|
result0[i + 1] = randomWell1.GetDouble();
|
||||||
|
result0[i + 2] = randomWell2.GetDouble();
|
||||||
|
result0[i + 3] = randomWell3.GetDouble();
|
||||||
|
|
||||||
|
result1[i + 0] = randomWellSSE2.GetDouble();
|
||||||
|
result1[i + 1] = randomWellSSE2.GetDouble();
|
||||||
|
result1[i + 2] = randomWellSSE2.GetDouble();
|
||||||
|
result1[i + 3] = randomWellSSE2.GetDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(result0, result1, kNumIterations * sizeof(double)))
|
||||||
|
std::cout << "ERROR: C++ vs SSE2: The results don't match!" << std::endl;
|
||||||
|
else
|
||||||
|
std::cout << "C++ vs SSE2: Results match" << std::endl;
|
||||||
|
|
||||||
|
delete [] result0;
|
||||||
|
delete [] result1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
Benchmark();
|
||||||
|
Test();
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
A SIMD optimized version of the WELL512a random algorithm.
|
||||||
|
|
||||||
|
For a detailed description of how the algorithm works, please see the following pages:
|
||||||
|
1) http://en.wikipedia.org/wiki/Well_equidistributed_long-period_linear
|
||||||
|
2) http://www.iro.umontreal.ca/~panneton/WELLRNG.html
|
||||||
|
|
||||||
|
Benchmarking shows that the SSE2 implementation is generally about 2-3 times faster than
|
||||||
|
the C implementation by the original authors.
|
||||||
|
|
||||||
|
It requires a SSE2 capable CPU (i.e. Intel Pentium 4 or newer, AMD Athlon 64 or newer).
|
||||||
|
|
||||||
|
All the source code except WELL512a.cpp|h that contains the original implementation
|
||||||
|
are released under the BSD license which allows you to include this in any open
|
||||||
|
or closed source project.
|
Loading…
Reference in New Issue