32#ifndef DT_COMMON_POINTS_H
33#define DT_COMMON_POINTS_H
46#if !defined _XOPEN_SOURCE && !defined(__DragonFly__) && !defined(__FreeBSD__) && !defined(__NetBSD__) \
47 && !defined(__OpenBSD__) && !defined(_WIN32)
74 "[points] out of memory allocating the RNG state for %u thread(s)\n", num_threads);
79 for(
int k = 0;
k < (int)num_threads;
k++)
81 p->s[
k].state0 = 1 +
k;
82 p->s[
k].state1 = 2 +
k;
104 p->s[thread_num].state0 = s0;
109 p->s[thread_num].state1 = s1;
116 ((
p->s[thread_num].state0 +
p->s[thread_num].state1) >> 41);
136#warning "MEXP is not defined. I assume MEXP is 19937."
148#define N (MEXP / 128 + 1)
199#include "SFMT-params607.h"
201#include "SFMT-params1279.h"
203#include "SFMT-params2281.h"
205#include "SFMT-params4253.h"
207#include "SFMT-params11213.h"
209#include "SFMT-params19937.h"
211#include "SFMT-params44497.h"
213#include "SFMT-params86243.h"
215#include "SFMT-params132049.h"
217#include "SFMT-params216091.h"
220#error "MEXP is not valid."
231#ifndef SFMT_PARAMS19937_H
232#define SFMT_PARAMS19937_H
239#define MSK1 0xdfffffefU
240#define MSK2 0xddfecb7fU
241#define MSK3 0xbffaffffU
242#define MSK4 0xbffffff6U
243#define PARITY1 0x00000001U
244#define PARITY2 0x00000000U
245#define PARITY3 0x00000000U
246#define PARITY4 0x13c9e684U
259 MSK1, MSK2, MSK3, MSK4 \
263 MSK2, MSK1, MSK4, MSK3 \
265#define ALTI_SL2_PERM \
267 1, 2, 3, 23, 5, 6, 7, 0, 9, 10, 11, 4, 13, 14, 15, 8 \
269#define ALTI_SL2_PERM64 \
271 1, 2, 3, 4, 5, 6, 7, 31, 9, 10, 11, 12, 13, 14, 15, 0 \
273#define ALTI_SR2_PERM \
275 7, 0, 1, 2, 11, 4, 5, 6, 15, 8, 9, 10, 17, 12, 13, 14 \
277#define ALTI_SR2_PERM64 \
279 15, 0, 1, 2, 3, 4, 5, 6, 17, 8, 9, 10, 11, 12, 13, 14 \
281#define IDSTR "SFMT-19937:122-18-1-11-1:dfffffef-ddfecb7f-bffaffff-bffffff6"
292typedef struct sfmt_state_t
298#if !defined(BIG_ENDIAN64) || defined(ONLY64)
346#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
348#elif defined(_MSC_VER) || defined(__BORLANDC__)
349typedef unsigned int uint32_t;
351#define inline __inline
355#define inline __inline__
360#if defined(_MSC_VER) || defined(__BORLANDC__)
370#define ALWAYSINLINE __attribute__((always_inline))
377#define PRE_ALWAYS __forceinline
379#define PRE_ALWAYS inline
382#define PRE_ALWAYS inline
385static inline uint32_t gen_rand32(
struct sfmt_state_t *s);
386static inline uint64_t gen_rand64(
struct sfmt_state_t *s);
387static inline void init_gen_rand(
struct sfmt_state_t *s, uint32_t seed)
__attribute__((unused));
388static inline void init_by_array(
struct sfmt_state_t *s, uint32_t *init_key,
int key_length)
390static inline const char *get_idstring(
void)
__attribute__((unused));
392inline static float to_real2f(uint32_t
v)
398 x.u = 0x3f800000 | (
v >> 9);
402inline static float genrand_real2f(
struct sfmt_state_t *s)
404 return to_real2f(gen_rand32(s));
426PRE_ALWAYS
static __m128i mm_recursion(__m128i *a, __m128i *b, __m128i c, __m128i
d,
427 __m128i mask) ALWAYSINLINE;
438PRE_ALWAYS
static __m128i mm_recursion(__m128i *a, __m128i *b, __m128i c, __m128i
d, __m128i mask)
442 x = _mm_load_si128(a);
443 y = _mm_srli_epi32(*b, SR1);
444 z = _mm_srli_si128(c, SR2);
445 v = _mm_slli_epi32(
d, SL1);
446 z = _mm_xor_si128(z,
x);
447 z = _mm_xor_si128(z,
v);
448 x = _mm_slli_si128(
x, SL2);
449 y = _mm_and_si128(y, mask);
450 z = _mm_xor_si128(z,
x);
451 z = _mm_xor_si128(z, y);
459inline static void gen_rand_all(
struct sfmt_state_t *s)
462 __m128i
r, r1, r2,
mask;
463 mask = _mm_set_epi32(MSK4, MSK3, MSK2, MSK1);
465 r1 = _mm_load_si128(&(s->sfmt[
N - 2].si));
466 r2 = _mm_load_si128(&(s->sfmt[
N - 1].si));
467 for(
i = 0;
i <
N - POS1;
i++)
469 r = mm_recursion(&(s->sfmt[
i].si), &(s->sfmt[
i + POS1].si), r1, r2, mask);
470 _mm_store_si128(&(s->sfmt[
i].si),
r);
476 r = mm_recursion(&(s->sfmt[
i].si), &(s->sfmt[
i + POS1 -
N].si), r1, r2, mask);
477 _mm_store_si128(&(s->sfmt[
i].si),
r);
490inline static void gen_rand_array(
struct sfmt_state_t *s, w128_t *array,
int size)
493 __m128i
r, r1, r2,
mask;
494 mask = _mm_set_epi32(MSK4, MSK3, MSK2, MSK1);
496 r1 = _mm_load_si128(&(s->sfmt[
N - 2].si));
497 r2 = _mm_load_si128(&(s->sfmt[
N - 1].si));
498 for(
i = 0;
i <
N - POS1;
i++)
500 r = mm_recursion(&(s->sfmt[
i].si), &(s->sfmt[
i + POS1].si), r1, r2, mask);
501 _mm_store_si128(&array[
i].si,
r);
507 r = mm_recursion(&(s->sfmt[
i].si), &array[
i + POS1 -
N].si, r1, r2, mask);
508 _mm_store_si128(&array[
i].si,
r);
515 r = mm_recursion(&array[
i -
N].si, &array[
i + POS1 -
N].si, r1, r2, mask);
516 _mm_store_si128(&array[
i].si,
r);
520 for(j = 0; j < 2 *
N -
size; j++)
522 r = _mm_load_si128(&array[j +
size -
N].si);
523 _mm_store_si128(&(s->sfmt[j].si),
r);
527 r = mm_recursion(&array[
i -
N].si, &array[
i + POS1 -
N].si, r1, r2, mask);
528 _mm_store_si128(&array[
i].si,
r);
529 _mm_store_si128(&(s->sfmt[j++].si),
r);
553#if defined(__BIG_ENDIAN__) && !defined(__amd64) && !defined(BIG_ENDIAN64)
554#define BIG_ENDIAN64 1
556#if defined(HAVE_ALTIVEC) && !defined(BIG_ENDIAN64)
557#define BIG_ENDIAN64 1
559#if defined(ONLY64) && !defined(BIG_ENDIAN64)
561#error "-DONLY64 must be specified with -DBIG_ENDIAN64"
579static w128_t sfmt[
N];
581static uint32_t *psfmt32 = &sfmt[0].u[0];
582#if !defined(BIG_ENDIAN64) || defined(ONLY64)
590static int initialized = 0;
592static uint32_t parity[4] = {PARITY1, PARITY2, PARITY3, PARITY4};
598inline static int idxof(
int i);
599inline static void rshift128(w128_t *
out, w128_t
const *in,
int shift);
600inline static void lshift128(w128_t *
out, w128_t
const *in,
int shift);
601inline static void gen_rand_all(sfmt_state_t *s);
602inline static void gen_rand_array(sfmt_state_t *s, w128_t *array,
int size);
603inline static uint32_t func1(uint32_t
x);
604inline static uint32_t func2(uint32_t
x);
605static void period_certification(sfmt_state_t *s);
606#if defined(BIG_ENDIAN64) && !defined(ONLY64)
607inline static void swap(w128_t *array,
int size);
621inline static int idxof(
int i)
626inline static int idxof(
int i)
640inline static void rshift128(w128_t *
out, w128_t
const *in,
int shift)
647 oh = th >> (shift * 8);
648 ol = tl >> (shift * 8);
649 ol |= th << (64 - shift * 8);
650 out->u[0] = (uint32_t)(ol >> 32);
651 out->u[1] = (uint32_t)ol;
652 out->u[2] = (uint32_t)(oh >> 32);
653 out->u[3] = (uint32_t)oh;
656inline static void rshift128(w128_t *
out, w128_t
const *in,
int shift)
663 oh = th >> (shift * 8);
664 ol = tl >> (shift * 8);
665 ol |= th << (64 - shift * 8);
666 out->u[1] = (uint32_t)(ol >> 32);
667 out->u[0] = (uint32_t)ol;
668 out->u[3] = (uint32_t)(oh >> 32);
669 out->u[2] = (uint32_t)oh;
681inline static void lshift128(w128_t *
out, w128_t
const *in,
int shift)
688 oh = th << (shift * 8);
689 ol = tl << (shift * 8);
690 oh |= tl >> (64 - shift * 8);
691 out->u[0] = (uint32_t)(ol >> 32);
692 out->u[1] = (uint32_t)ol;
693 out->u[2] = (uint32_t)(oh >> 32);
694 out->u[3] = (uint32_t)oh;
697inline static void lshift128(w128_t *
out, w128_t
const *in,
int shift)
704 oh = th << (shift * 8);
705 ol = tl << (shift * 8);
706 oh |= tl >> (64 - shift * 8);
707 out->u[1] = (uint32_t)(ol >> 32);
708 out->u[0] = (uint32_t)ol;
709 out->u[3] = (uint32_t)(oh >> 32);
710 out->u[2] = (uint32_t)oh;
722#if(!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2))
724inline static void do_recursion(w128_t *
r, w128_t *a, w128_t *b, w128_t *c, w128_t *
d)
729 lshift128(&
x, a, SL2);
730 rshift128(&y, c, SR2);
731 r->u[0] =
a->u[0] ^
x.u[0] ^ ((
b->u[0] >> SR1) & MSK2) ^ y.u[0] ^ (
d->u[0] << SL1);
732 r->u[1] =
a->u[1] ^
x.u[1] ^ ((
b->u[1] >> SR1) & MSK1) ^ y.u[1] ^ (
d->u[1] << SL1);
733 r->u[2] =
a->u[2] ^
x.u[2] ^ ((
b->u[2] >> SR1) & MSK4) ^ y.u[2] ^ (
d->u[2] << SL1);
734 r->u[3] =
a->u[3] ^
x.u[3] ^ ((
b->u[3] >> SR1) & MSK3) ^ y.u[3] ^ (
d->u[3] << SL1);
737inline static void do_recursion(w128_t *
r, w128_t *a, w128_t *b, w128_t *c, w128_t *
d)
742 lshift128(&
x, a, SL2);
743 rshift128(&y, c, SR2);
744 r->u[0] =
a->u[0] ^
x.u[0] ^ ((
b->u[0] >> SR1) & MSK1) ^ y.u[0] ^ (
d->u[0] << SL1);
745 r->u[1] =
a->u[1] ^
x.u[1] ^ ((
b->u[1] >> SR1) & MSK2) ^ y.u[1] ^ (
d->u[1] << SL1);
746 r->u[2] =
a->u[2] ^
x.u[2] ^ ((
b->u[2] >> SR1) & MSK3) ^ y.u[2] ^ (
d->u[2] << SL1);
747 r->u[3] =
a->u[3] ^
x.u[3] ^ ((
b->u[3] >> SR1) & MSK4) ^ y.u[3] ^ (
d->u[3] << SL1);
752#if defined(BIG_ENDIAN64) && !defined(ONLY64) && !defined(HAVE_ALTIVEC)
753inline static void swap(w128_t *array,
int size)
757 uint32_t
x = array[
i].u[0];
758 uint32_t y = array[
i].u[2];
759 array[
i].u[0] = array[
i].u[1];
760 array[
i].u[2] = array[
i].u[3];
772static uint32_t func1(uint32_t
x)
774 return (
x ^ (
x >> 27)) * (uint32_t)1664525UL;
783static uint32_t func2(uint32_t
x)
785 return (
x ^ (
x >> 27)) * (uint32_t)1566083941UL;
791static void period_certification(sfmt_state_t *s)
795 for(
int i = 0;
i < 4;
i++) inner ^= s->psfmt32[idxof(
i)] & s->parity[
i];
796 for(
int i = 16;
i > 0;
i >>= 1) inner ^= inner >>
i;
804 for(
int i = 0;
i < 4;
i++)
807 for(
int j = 0; j < 32; j++)
809 if((work & s->parity[
i]) != 0)
811 s->psfmt32[idxof(
i)] ^= work;
827const char *get_idstring(
void)
838uint32_t gen_rand32(sfmt_state_t *s)
848 r = s->psfmt32[s->idx++];
861#if defined(BIG_ENDIAN64) && !defined(ONLY64)
875#if defined(BIG_ENDIAN64) && !defined(ONLY64)
876 r1 = s->psfmt32[s->idx];
877 r2 = s->psfmt32[s->idx + 1];
881 r = s->psfmt64[s->idx / 2];
894void init_gen_rand(sfmt_state_t *s, uint32_t seed)
898 s->psfmt32[idxof(0)] = seed;
899 for(
i = 1;
i < N32;
i++)
901 s->psfmt32[idxof(
i)] = 1812433253UL * (s->psfmt32[idxof(
i - 1)] ^ (s->psfmt32[idxof(
i - 1)] >> 30)) +
i;
904 period_certification(s);
914void init_by_array(sfmt_state_t *s, uint32_t *init_key,
int key_length)
938 mid = (
size - lag) / 2;
940 memset(s->sfmt, 0x8b,
sizeof(s->sfmt));
941 if(key_length + 1 > N32)
943 count = key_length + 1;
949 r = func1(s->psfmt32[idxof(0)] ^ s->psfmt32[idxof(mid)] ^ s->psfmt32[idxof(N32 - 1)]);
950 s->psfmt32[idxof(mid)] +=
r;
952 s->psfmt32[idxof(mid + lag)] +=
r;
953 s->psfmt32[idxof(0)] =
r;
956 for(
i = 1, j = 0; (j < count) && (j < key_length); j++)
958 r = func1(s->psfmt32[idxof(
i)] ^ s->psfmt32[idxof((
i + mid) % N32)]
959 ^ s->psfmt32[idxof((
i + N32 - 1) % N32)]);
960 s->psfmt32[idxof((
i + mid) % N32)] +=
r;
961 r += init_key[j] +
i;
962 s->psfmt32[idxof((
i + mid + lag) % N32)] +=
r;
963 s->psfmt32[idxof(
i)] =
r;
966 for(; j < count; j++)
968 r = func1(s->psfmt32[idxof(
i)] ^ s->psfmt32[idxof((
i + mid) % N32)]
969 ^ s->psfmt32[idxof((
i + N32 - 1) % N32)]);
970 s->psfmt32[idxof((
i + mid) % N32)] +=
r;
972 s->psfmt32[idxof((
i + mid + lag) % N32)] +=
r;
973 s->psfmt32[idxof(
i)] =
r;
976 for(j = 0; j < N32; j++)
978 r = func2(s->psfmt32[idxof(
i)] + s->psfmt32[idxof((
i + mid) % N32)]
979 + s->psfmt32[idxof((
i + N32 - 1) % N32)]);
980 s->psfmt32[idxof((
i + mid) % N32)] ^=
r;
982 s->psfmt32[idxof((
i + mid + lag) % N32)] ^=
r;
983 s->psfmt32[idxof(
i)] =
r;
988 period_certification(s);
1006 sfmt_state_t *states = (sfmt_state_t *)
dt_alloc_align(
sizeof(sfmt_state_t) * num_threads);
1007 p->s = (sfmt_state_t **)calloc(num_threads,
sizeof(sfmt_state_t *));
1008 p->num = num_threads;
1013 "[points] out of memory allocating the RNG state for %u thread(s)\n", num_threads);
1021 int seed = 0xD71337;
1022 for(
int i = 0;
i < (int)num_threads;
i++)
1024 p->s[
i] = states +
i;
1025#if !defined(BIG_ENDIAN64) || defined(ONLY64)
1026 p->s[
i]->psfmt64 = (
uint64_t *)&(
p->s[
i]->sfmt[0].u[0]);
1028 p->s[
i]->psfmt32 = &(
p->s[
i]->sfmt[0].u[0]);
1029 p->s[
i]->initialized = 0;
1030 p->s[
i]->parity[0] = PARITY1;
1031 p->s[
i]->parity[1] = PARITY2;
1032 p->s[
i]->parity[2] = PARITY3;
1033 p->s[
i]->parity[3] = PARITY4;
1034 init_gen_rand(
p->s[
i], seed);
1057 return genrand_real2f(
p->s[thread_num]);
const dt_colormatrix_t dt_aligned_pixel_t out
void * dt_alloc_align(size_t size)
Allocate cacheline-aligned memory.
static void swap(float *x, float *y)
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
float *const restrict const size_t k
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
#define dt_free_align(ptr)
Release memory from dt_alloc_align() and set ptr to NULL.
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
static int dt_get_thread_num()
Index of the calling thread within its parallel region, 0 outside one.
static float dt_points_get()
static void dt_points_cleanup(dt_points_t *p)
static void dt_points_init(dt_points_t *p, const unsigned int num_threads)
struct dt_points_t * dt_points_get_global(void)
static float dt_points_get_for(dt_points_t *p, const unsigned int thread_num)
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Apply one channel's tone curve to each of the three colour channels, or pass the channel through unto...
unsigned __int64 uint64_t