rlm@1: /** rlm@1: * @file SFMT-sse2.h rlm@1: * @brief SIMD oriented Fast Mersenne Twister(SFMT) for Intel SSE2 rlm@1: * rlm@1: * @author Mutsuo Saito (Hiroshima University) rlm@1: * @author Makoto Matsumoto (Hiroshima University) rlm@1: * rlm@1: * @note We assume LITTLE ENDIAN in this file rlm@1: * rlm@1: * Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima rlm@1: * University. All rights reserved. rlm@1: * rlm@1: * The new BSD License is applied to this software, see LICENSE.txt rlm@1: */ rlm@1: rlm@1: #ifndef SFMT_SSE2_H rlm@1: #define SFMT_SSE2_H rlm@1: rlm@1: PRE_ALWAYS static __m128i mm_recursion(__m128i *a, __m128i *b, __m128i c, rlm@1: __m128i d, __m128i mask) ALWAYSINLINE; rlm@1: rlm@1: /** rlm@1: * This function represents the recursion formula. rlm@1: * @param a a 128-bit part of the interal state array rlm@1: * @param b a 128-bit part of the interal state array rlm@1: * @param c a 128-bit part of the interal state array rlm@1: * @param d a 128-bit part of the interal state array rlm@1: * @param mask 128-bit mask rlm@1: * @return output rlm@1: */ rlm@1: PRE_ALWAYS static __m128i mm_recursion(__m128i *a, __m128i *b, rlm@1: __m128i c, __m128i d, __m128i mask) { rlm@1: __m128i v, x, y, z; rlm@1: rlm@1: x = _mm_load_si128(a); rlm@1: y = _mm_srli_epi32(*b, SR1); rlm@1: z = _mm_srli_si128(c, SR2); rlm@1: v = _mm_slli_epi32(d, SL1); rlm@1: z = _mm_xor_si128(z, x); rlm@1: z = _mm_xor_si128(z, v); rlm@1: x = _mm_slli_si128(x, SL2); rlm@1: y = _mm_and_si128(y, mask); rlm@1: z = _mm_xor_si128(z, x); rlm@1: z = _mm_xor_si128(z, y); rlm@1: return z; rlm@1: } rlm@1: rlm@1: /** rlm@1: * This function fills the internal state array with pseudorandom rlm@1: * integers. rlm@1: */ rlm@1: inline static void gen_rand_all(void) { rlm@1: int i; rlm@1: __m128i r, r1, r2, mask; rlm@1: mask = _mm_set_epi32(MSK4, MSK3, MSK2, MSK1); rlm@1: rlm@1: r1 = _mm_load_si128(&sfmt[N - 2].si); rlm@1: r2 = _mm_load_si128(&sfmt[N - 1].si); rlm@1: for (i = 0; i < N - POS1; i++) { rlm@1: r = mm_recursion(&sfmt[i].si, &sfmt[i + POS1].si, r1, r2, mask); rlm@1: _mm_store_si128(&sfmt[i].si, r); rlm@1: r1 = r2; rlm@1: r2 = r; rlm@1: } rlm@1: for (; i < N; i++) { rlm@1: r = mm_recursion(&sfmt[i].si, &sfmt[i + POS1 - N].si, r1, r2, mask); rlm@1: _mm_store_si128(&sfmt[i].si, r); rlm@1: r1 = r2; rlm@1: r2 = r; rlm@1: } rlm@1: } rlm@1: rlm@1: /** rlm@1: * This function fills the user-specified array with pseudorandom rlm@1: * integers. rlm@1: * rlm@1: * @param array an 128-bit array to be filled by pseudorandom numbers. rlm@1: * @param size number of 128-bit pesudorandom numbers to be generated. rlm@1: */ rlm@1: inline static void gen_rand_array(w128_t *array, int size) { rlm@1: int i, j; rlm@1: __m128i r, r1, r2, mask; rlm@1: mask = _mm_set_epi32(MSK4, MSK3, MSK2, MSK1); rlm@1: rlm@1: r1 = _mm_load_si128(&sfmt[N - 2].si); rlm@1: r2 = _mm_load_si128(&sfmt[N - 1].si); rlm@1: for (i = 0; i < N - POS1; i++) { rlm@1: r = mm_recursion(&sfmt[i].si, &sfmt[i + POS1].si, r1, r2, mask); rlm@1: _mm_store_si128(&array[i].si, r); rlm@1: r1 = r2; rlm@1: r2 = r; rlm@1: } rlm@1: for (; i < N; i++) { rlm@1: r = mm_recursion(&sfmt[i].si, &array[i + POS1 - N].si, r1, r2, mask); rlm@1: _mm_store_si128(&array[i].si, r); rlm@1: r1 = r2; rlm@1: r2 = r; rlm@1: } rlm@1: /* main loop */ rlm@1: for (; i < size - N; i++) { rlm@1: r = mm_recursion(&array[i - N].si, &array[i + POS1 - N].si, r1, r2, rlm@1: mask); rlm@1: _mm_store_si128(&array[i].si, r); rlm@1: r1 = r2; rlm@1: r2 = r; rlm@1: } rlm@1: for (j = 0; j < 2 * N - size; j++) { rlm@1: r = _mm_load_si128(&array[j + size - N].si); rlm@1: _mm_store_si128(&sfmt[j].si, r); rlm@1: } rlm@1: for (; i < size; i++) { rlm@1: r = mm_recursion(&array[i - N].si, &array[i + POS1 - N].si, r1, r2, rlm@1: mask); rlm@1: _mm_store_si128(&array[i].si, r); rlm@1: _mm_store_si128(&sfmt[j++].si, r); rlm@1: r1 = r2; rlm@1: r2 = r; rlm@1: } rlm@1: } rlm@1: rlm@1: #endif