Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
points.h
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010-2011 johannes hanika.
4 Copyright (C) 2012 Jean-Sébastien Pédron.
5 Copyright (C) 2012 Richard Wonka.
6 Copyright (C) 2013-2014, 2016 Tobias Ellinghaus.
7 Copyright (C) 2014-2016 Roman Lebedev.
8 Copyright (C) 2017 luzpaz.
9 Copyright (C) 2018 Peter Budai.
10 Copyright (C) 2018 Robert Bridge.
11 Copyright (C) 2019 Andreas Schneider.
12 Copyright (C) 2019, 2025-2026 Aurélien PIERRE.
13 Copyright (C) 2020 Heiko Bauke.
14 Copyright (C) 2020 Pascal Obry.
15 Copyright (C) 2022 Martin Bařinka.
16 Copyright (C) 2024 Alynx Zhou.
17
18 darktable is free software: you can redistribute it and/or modify
19 it under the terms of the GNU General Public License as published by
20 the Free Software Foundation, either version 3 of the License, or
21 (at your option) any later version.
22
23 darktable is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 GNU General Public License for more details.
27
28 You should have received a copy of the GNU General Public License
29 along with darktable. If not, see <http://www.gnu.org/licenses/>.
30*/
31
32#ifndef DT_COMMON_POINTS_H
33#define DT_COMMON_POINTS_H
34
35#include "system/macros.h"
36#include "system/mem_alloc.h"
37#include "common/logging.h"
38#include "system/openmp.h" // dt_get_thread_num()
39
40/* Process-wide singleton with no per-call context to ride on: this accessor is the
41 * intended end state (same category as dt_conf_*), implemented by the orchestrator. */
43
44#ifndef __SSE2__
45
46#if !defined _XOPEN_SOURCE && !defined(__DragonFly__) && !defined(__FreeBSD__) && !defined(__NetBSD__) \
47 && !defined(__OpenBSD__) && !defined(_WIN32)
48#define _XOPEN_SOURCE
49#endif
50
51#include <stdlib.h>
52
53// xorshift128+, period 2^128-1, apparently passes all TestU01 suite tests.
59
60typedef struct dt_points_t
61{
63 unsigned int num; // 0 when initialisation failed; see dt_points_init()
65
66static inline void dt_points_init(dt_points_t *p, const unsigned int num_threads)
67{
68 p->s = (dt_points_state_t *)malloc(sizeof(dt_points_state_t) * num_threads);
69 p->num = num_threads;
70
71 if(IS_NULL_PTR(p->s))
72 {
74 "[points] out of memory allocating the RNG state for %u thread(s)\n", num_threads);
75 p->num = 0;
76 return;
77 }
78
79 for(int k = 0; k < (int)num_threads; k++)
80 {
81 p->s[k].state0 = 1 + k;
82 p->s[k].state1 = 2 + k;
83 }
84}
85
86static inline void dt_points_cleanup(dt_points_t *p)
87{
88 dt_free(p->s);
89 p->s = NULL;
90 p->num = 0;
91}
92
93static inline float dt_points_get_for(dt_points_t *p, const unsigned int thread_num)
94{
95 /* dt_points_init() logs and leaves p->s NULL when it cannot allocate the state, which
96 * only happens if the system is genuinely out of memory. Degrade to a fixed value
97 * rather than dereferencing NULL: callers use this for dithering and noise, where
98 * losing randomness costs a little image quality, whereas crashing costs the session.
99 * The failure is already reported once, at init, instead of per pixel. */
100 if(IS_NULL_PTR(p) || IS_NULL_PTR(p->s) || thread_num >= p->num) return 0.5f;
101
102 uint64_t s1 = p->s[thread_num].state0;
103 uint64_t s0 = p->s[thread_num].state1;
104 p->s[thread_num].state0 = s0;
105 s1 ^= s1 << 23;
106 s1 ^= s1 >> 17;
107 s1 ^= s0;
108 s1 ^= s0 >> 26;
109 p->s[thread_num].state1 = s1;
110 // return (state0 + state1) / ((double)((uint64_t)-1) + 1.0);
111 union {
112 float f;
113 uint32_t u;
114 } v;
115 v.u = 0x3f800000 |
116 ((p->s[thread_num].state0 + p->s[thread_num].state1) >> 41); // faster than double version.
117 return v.f - 1.0f;
118}
119
120static inline float dt_points_get()
121{
123}
124
125#else
126
127#include <inttypes.h>
128
129#define MEXP 19937
130
131#ifndef SFMT_PARAMS_H
132#define SFMT_PARAMS_H
133
134#if !defined(MEXP)
135#ifdef __GNUC__
136#warning "MEXP is not defined. I assume MEXP is 19937."
137#endif
138#define MEXP 19937
139#endif
140/*-----------------
141 BASIC DEFINITIONS
142 -----------------*/
148#define N (MEXP / 128 + 1)
151#define N32 (N * 4)
154#define N64 (N * 2)
155
156/*----------------------
157 the parameters of SFMT
158 following definitions are in paramsXXXX.h file.
159 ----------------------*/
197#if 0
198#if MEXP == 607
199#include "SFMT-params607.h"
200#elif MEXP == 1279
201#include "SFMT-params1279.h"
202#elif MEXP == 2281
203#include "SFMT-params2281.h"
204#elif MEXP == 4253
205#include "SFMT-params4253.h"
206#elif MEXP == 11213
207#include "SFMT-params11213.h"
208#elif MEXP == 19937
209#include "SFMT-params19937.h"
210#elif MEXP == 44497
211#include "SFMT-params44497.h"
212#elif MEXP == 86243
213#include "SFMT-params86243.h"
214#elif MEXP == 132049
215#include "SFMT-params132049.h"
216#elif MEXP == 216091
217#include "SFMT-params216091.h"
218#else
219#ifdef __GNUC__
220#error "MEXP is not valid."
221#undef MEXP
222#else
223#undef MEXP
224#endif
225#endif
226
227#endif
228
229#endif /* SFMT_PARAMS_H */
230
231#ifndef SFMT_PARAMS19937_H
232#define SFMT_PARAMS19937_H
233
234#define POS1 122
235#define SL1 18
236#define SL2 1
237#define SR1 11
238#define SR2 1
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
247
248
249#define ALTI_SL1 \
250 { \
251 SL1, SL1, SL1, SL1 \
252 }
253#define ALTI_SR1 \
254 { \
255 SR1, SR1, SR1, SR1 \
256 }
257#define ALTI_MSK \
258 { \
259 MSK1, MSK2, MSK3, MSK4 \
260 }
261#define ALTI_MSK64 \
262 { \
263 MSK2, MSK1, MSK4, MSK3 \
264 }
265#define ALTI_SL2_PERM \
266 { \
267 1, 2, 3, 23, 5, 6, 7, 0, 9, 10, 11, 4, 13, 14, 15, 8 \
268 }
269#define ALTI_SL2_PERM64 \
270 { \
271 1, 2, 3, 4, 5, 6, 7, 31, 9, 10, 11, 12, 13, 14, 15, 0 \
272 }
273#define ALTI_SR2_PERM \
274 { \
275 7, 0, 1, 2, 11, 4, 5, 6, 15, 8, 9, 10, 17, 12, 13, 14 \
276 }
277#define ALTI_SR2_PERM64 \
278 { \
279 15, 0, 1, 2, 3, 4, 5, 6, 17, 8, 9, 10, 11, 12, 13, 14 \
280 }
281#define IDSTR "SFMT-19937:122-18-1-11-1:dfffffef-ddfecb7f-bffaffff-bffffff6"
282
283#endif /* SFMT_PARAMS19937_H */
284
286typedef union w128_t
287{
288 __m128i si;
289 uint32_t u[4];
290} w128_t;
291
292typedef struct sfmt_state_t
293{
295 w128_t sfmt[N];
297 uint32_t *psfmt32;
298#if !defined(BIG_ENDIAN64) || defined(ONLY64)
300 uint64_t *psfmt64;
301#endif
303 int idx;
306 int initialized;
308 uint32_t parity[4];
309} sfmt_state_t;
310
341#ifndef SFMT_H
342#define SFMT_H
343
344#include <stdio.h>
345
346#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
347#include <inttypes.h>
348#elif defined(_MSC_VER) || defined(__BORLANDC__)
349typedef unsigned int uint32_t;
350typedef unsigned __int64 uint64_t;
351#define inline __inline
352#else
353#include <inttypes.h>
354#if defined(__GNUC__)
355#define inline __inline__
356#endif
357#endif
358
359#ifndef PRIu64
360#if defined(_MSC_VER) || defined(__BORLANDC__)
361#define PRIu64 "I64u"
362#define PRIx64 "I64x"
363#else
364#define PRIu64 "llu"
365#define PRIx64 "llx"
366#endif
367#endif
368
369#if defined(__GNUC__)
370#define ALWAYSINLINE __attribute__((always_inline))
371#else
372#define ALWAYSINLINE
373#endif
374
375#if defined(_MSC_VER)
376#if _MSC_VER >= 1200
377#define PRE_ALWAYS __forceinline
378#else
379#define PRE_ALWAYS inline
380#endif
381#else
382#define PRE_ALWAYS inline
383#endif
384
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)
389 __attribute__((unused));
390static inline const char *get_idstring(void) __attribute__((unused));
392inline static float to_real2f(uint32_t v)
393{
394 union {
395 float f;
396 uint32_t u;
397 } x;
398 x.u = 0x3f800000 | (v >> 9); // faster than double version.
399 return x.f - 1.0f;
400 /* divided by 2^32 */
401}
402inline static float genrand_real2f(struct sfmt_state_t *s)
403{
404 return to_real2f(gen_rand32(s));
405}
406
407#endif
423#ifndef SFMT_SSE2_H
424#define SFMT_SSE2_H
425
426PRE_ALWAYS static __m128i mm_recursion(__m128i *a, __m128i *b, __m128i c, __m128i d,
427 __m128i mask) ALWAYSINLINE;
428
438PRE_ALWAYS static __m128i mm_recursion(__m128i *a, __m128i *b, __m128i c, __m128i d, __m128i mask)
439{
440 __m128i v, x, y, z;
441
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);
452 return z;
453}
454
459inline static void gen_rand_all(struct sfmt_state_t *s)
460{
461 int i;
462 __m128i r, r1, r2, mask;
463 mask = _mm_set_epi32(MSK4, MSK3, MSK2, MSK1);
464
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++)
468 {
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);
471 r1 = r2;
472 r2 = r;
473 }
474 for(; i < N; i++)
475 {
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);
478 r1 = r2;
479 r2 = r;
480 }
481}
482
490inline static void gen_rand_array(struct sfmt_state_t *s, w128_t *array, int size)
491{
492 int i, j;
493 __m128i r, r1, r2, mask;
494 mask = _mm_set_epi32(MSK4, MSK3, MSK2, MSK1);
495
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++)
499 {
500 r = mm_recursion(&(s->sfmt[i].si), &(s->sfmt[i + POS1].si), r1, r2, mask);
501 _mm_store_si128(&array[i].si, r);
502 r1 = r2;
503 r2 = r;
504 }
505 for(; i < N; i++)
506 {
507 r = mm_recursion(&(s->sfmt[i].si), &array[i + POS1 - N].si, r1, r2, mask);
508 _mm_store_si128(&array[i].si, r);
509 r1 = r2;
510 r2 = r;
511 }
512 /* main loop */
513 for(; i < size - N; i++)
514 {
515 r = mm_recursion(&array[i - N].si, &array[i + POS1 - N].si, r1, r2, mask);
516 _mm_store_si128(&array[i].si, r);
517 r1 = r2;
518 r2 = r;
519 }
520 for(j = 0; j < 2 * N - size; j++)
521 {
522 r = _mm_load_si128(&array[j + size - N].si);
523 _mm_store_si128(&(s->sfmt[j].si), r);
524 }
525 for(; i < size; i++)
526 {
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);
530 r1 = r2;
531 r2 = r;
532 }
533}
534
535#endif
548#include <assert.h>
549#include <string.h>
550//#include "SFMT.h"
551//#include "SFMT-params.h"
552
553#if defined(__BIG_ENDIAN__) && !defined(__amd64) && !defined(BIG_ENDIAN64)
554#define BIG_ENDIAN64 1
555#endif
556#if defined(HAVE_ALTIVEC) && !defined(BIG_ENDIAN64)
557#define BIG_ENDIAN64 1
558#endif
559#if defined(ONLY64) && !defined(BIG_ENDIAN64)
560#if defined(__GNUC__)
561#error "-DONLY64 must be specified with -DBIG_ENDIAN64"
562#endif
563#undef ONLY64
564#endif
565
566
567typedef struct dt_points_t
568{
569 sfmt_state_t **s;
570 unsigned int num;
572
573#if 0
574/*--------------------------------------
575 FILE GLOBAL VARIABLES
576 internal state, index counter and flag
577 --------------------------------------*/
579static w128_t sfmt[N];
581static uint32_t *psfmt32 = &sfmt[0].u[0];
582#if !defined(BIG_ENDIAN64) || defined(ONLY64)
584static uint64_t *psfmt64 = (uint64_t *)&sfmt[0].u[0];
585#endif
587static int idx;
590static int initialized = 0;
592static uint32_t parity[4] = {PARITY1, PARITY2, PARITY3, PARITY4};
593#endif
594
595/*----------------
596 STATIC FUNCTIONS
597 ----------------*/
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);
608#endif
609
610/*#if defined(HAVE_ALTIVEC)
611#include "SFMT-alti.h"
612#elif defined(HAVE_SSE2)
613#include "SFMT-sse2.h"
614#endif*/
615
620#ifdef ONLY64
621inline static int idxof(int i)
622{
623 return i ^ 1;
624}
625#else
626inline static int idxof(int i)
627{
628 return i;
629}
630#endif
639#ifdef ONLY64
640inline static void rshift128(w128_t *out, w128_t const *in, int shift)
641{
642 uint64_t th, tl, oh, ol;
643
644 th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]);
645 tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]);
646
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;
654}
655#else
656inline static void rshift128(w128_t *out, w128_t const *in, int shift)
657{
658 uint64_t th, tl, oh, ol;
659
660 th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]);
661 tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]);
662
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;
670}
671#endif
680#ifdef ONLY64
681inline static void lshift128(w128_t *out, w128_t const *in, int shift)
682{
683 uint64_t th, tl, oh, ol;
684
685 th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]);
686 tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]);
687
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;
695}
696#else
697inline static void lshift128(w128_t *out, w128_t const *in, int shift)
698{
699 uint64_t th, tl, oh, ol;
700
701 th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]);
702 tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]);
703
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;
711}
712#endif
713
722#if(!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2))
723#ifdef ONLY64
724inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c, w128_t *d)
725{
726 w128_t x;
727 w128_t y;
728
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);
735}
736#else
737inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c, w128_t *d)
738{
739 w128_t x;
740 w128_t y;
741
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);
748}
749#endif
750#endif
751
752#if defined(BIG_ENDIAN64) && !defined(ONLY64) && !defined(HAVE_ALTIVEC)
753inline static void swap(w128_t *array, int size)
754{
755 for(int i = 0; i < size; i++)
756 {
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];
761 array[i].u[1] = x;
762 array[i].u[3] = y;
763 }
764}
765#endif
772static uint32_t func1(uint32_t x)
773{
774 return (x ^ (x >> 27)) * (uint32_t)1664525UL;
775}
776
783static uint32_t func2(uint32_t x)
784{
785 return (x ^ (x >> 27)) * (uint32_t)1566083941UL;
786}
787
791static void period_certification(sfmt_state_t *s)
792{
793 int inner = 0;
794
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;
797 inner &= 1;
798 /* check OK */
799 if(inner == 1)
800 {
801 return;
802 }
803 /* check NG, and modification */
804 for(int i = 0; i < 4; i++)
805 {
806 uint32_t work = 1;
807 for(int j = 0; j < 32; j++)
808 {
809 if((work & s->parity[i]) != 0)
810 {
811 s->psfmt32[idxof(i)] ^= work;
812 return;
813 }
814 work = work << 1;
815 }
816 }
817}
818
819/*----------------
820 PUBLIC FUNCTIONS
821 ----------------*/
827const char *get_idstring(void)
828{
829 return IDSTR;
830}
831
832#ifndef ONLY64
838uint32_t gen_rand32(sfmt_state_t *s)
839{
840 uint32_t r;
841
842 // assert(s->initialized);
843 if(s->idx >= N32)
844 {
845 gen_rand_all(s);
846 s->idx = 0;
847 }
848 r = s->psfmt32[s->idx++];
849 return r;
850}
851#endif
859uint64_t gen_rand64(sfmt_state_t *s)
860{
861#if defined(BIG_ENDIAN64) && !defined(ONLY64)
862 uint32_t r1, r2;
863#else
864 uint64_t r;
865#endif
866
867 // assert(s->initialized);
868 // assert(s->idx % 2 == 0);
869
870 if(s->idx >= N32)
871 {
872 gen_rand_all(s);
873 s->idx = 0;
874 }
875#if defined(BIG_ENDIAN64) && !defined(ONLY64)
876 r1 = s->psfmt32[s->idx];
877 r2 = s->psfmt32[s->idx + 1];
878 s->idx += 2;
879 return ((uint64_t)r2 << 32) | r1;
880#else
881 r = s->psfmt64[s->idx / 2];
882 s->idx += 2;
883 return r;
884#endif
885}
886
887
894void init_gen_rand(sfmt_state_t *s, uint32_t seed)
895{
896 int i;
897
898 s->psfmt32[idxof(0)] = seed;
899 for(i = 1; i < N32; i++)
900 {
901 s->psfmt32[idxof(i)] = 1812433253UL * (s->psfmt32[idxof(i - 1)] ^ (s->psfmt32[idxof(i - 1)] >> 30)) + i;
902 }
903 s->idx = N32;
904 period_certification(s);
905 s->initialized = 1;
906}
907
914void init_by_array(sfmt_state_t *s, uint32_t *init_key, int key_length)
915{
916 int i, j, count;
917 uint32_t r;
918 int lag;
919 int mid;
920 int size = N * 4;
921
922 if(size >= 623)
923 {
924 lag = 11;
925 }
926 else if(size >= 68)
927 {
928 lag = 7;
929 }
930 else if(size >= 39)
931 {
932 lag = 5;
933 }
934 else
935 {
936 lag = 3;
937 }
938 mid = (size - lag) / 2;
939
940 memset(s->sfmt, 0x8b, sizeof(s->sfmt));
941 if(key_length + 1 > N32)
942 {
943 count = key_length + 1;
944 }
945 else
946 {
947 count = N32;
948 }
949 r = func1(s->psfmt32[idxof(0)] ^ s->psfmt32[idxof(mid)] ^ s->psfmt32[idxof(N32 - 1)]);
950 s->psfmt32[idxof(mid)] += r;
951 r += key_length;
952 s->psfmt32[idxof(mid + lag)] += r;
953 s->psfmt32[idxof(0)] = r;
954
955 count--;
956 for(i = 1, j = 0; (j < count) && (j < key_length); j++)
957 {
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;
964 i = (i + 1) % N32;
965 }
966 for(; j < count; j++)
967 {
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;
971 r += i;
972 s->psfmt32[idxof((i + mid + lag) % N32)] += r;
973 s->psfmt32[idxof(i)] = r;
974 i = (i + 1) % N32;
975 }
976 for(j = 0; j < N32; j++)
977 {
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;
981 r -= i;
982 s->psfmt32[idxof((i + mid + lag) % N32)] ^= r;
983 s->psfmt32[idxof(i)] = r;
984 i = (i + 1) % N32;
985 }
986
987 s->idx = N32;
988 period_certification(s);
989 s->initialized = 1;
990}
991
992
993static inline void dt_points_init(dt_points_t *p, const unsigned int num_threads)
994{
995 /* NOT the pixelpipe cache arena. This is a small (~20 kB), permanent, process-wide
996 * allocation made once during dt_init(), long before any pipeline exists. The cache
997 * arena is LRU-managed and refuses allocations when the system is under memory
998 * pressure -- by design -- so asking it for the RNG state made startup fail on a
999 * machine that was merely low on free RAM:
1000 *
1001 * [pixelpipe_cache] refusing to allocate 0 MiB: the system has only 1638 MiB
1002 * of available RAM left (pressure floor: 5175 MiB)
1003 *
1004 * and the unchecked result then segfaulted in the loop below. A permanent startup
1005 * buffer belongs to the ordinary allocator. */
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;
1009
1010 if(IS_NULL_PTR(states) || IS_NULL_PTR(p->s))
1011 {
1013 "[points] out of memory allocating the RNG state for %u thread(s)\n", num_threads);
1014 dt_free_align(states);
1015 dt_free(p->s);
1016 p->s = NULL;
1017 p->num = 0;
1018 return;
1019 }
1020
1021 int seed = 0xD71337;
1022 for(int i = 0; i < (int)num_threads; i++)
1023 {
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]);
1027#endif
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);
1035 seed ^= seed << 1;
1036 }
1037}
1038
1039static inline void dt_points_cleanup(dt_points_t *p)
1040{
1041 if(IS_NULL_PTR(p->s)) return; // init failed, or already cleaned up
1042 dt_free_align(p->s[0]);
1043 dt_free(p->s);
1044 p->s = NULL;
1045 p->num = 0;
1046}
1047
1048static inline float dt_points_get_for(dt_points_t *p, const unsigned int thread_num)
1049{
1050 /* dt_points_init() logs and leaves p->s NULL when it cannot allocate the state, which
1051 * only happens if the system is genuinely out of memory. Degrade to a fixed value
1052 * rather than dereferencing NULL: callers use this for dithering and noise, where
1053 * losing randomness costs a little image quality, whereas crashing costs the session.
1054 * The failure is already reported once, at init, instead of per pixel. */
1055 if(IS_NULL_PTR(p) || IS_NULL_PTR(p->s) || thread_num >= p->num) return 0.5f;
1056
1057 return genrand_real2f(p->s[thread_num]);
1058}
1059
1060static inline float dt_points_get()
1061{
1063}
1064
1065/* The vendored SFMT generator above defines its parameters as bare macros -- `N`, `POS1`,
1066 * `MSK1`, `inline` -- at file scope, and leaks every one of them into whatever is included
1067 * after this header. `N` is the dangerous one: sqlite3.h declares
1068 * `sqlite3_compileoption_get(int N)`, so any translation unit that reaches sqlite3.h *after*
1069 * points.h fails to compile, with an error pointing at sqlite3.h and no hint as to why.
1070 *
1071 * That was latent for as long as something else happened to include sqlite3.h earlier in
1072 * every affected unit -- which the old gui/gtk.h did, by dragging in history/history.h. Take
1073 * one god-header out of the include graph and a dozen IOPs stop compiling for reasons that
1074 * have nothing to do with the change. Undefine them here so the leak cannot come back.
1075 */
1076#undef N
1077#undef N32
1078#undef N64
1079#undef MEXP
1080#undef POS1
1081#undef SL1
1082#undef SL2
1083#undef SR1
1084#undef SR2
1085#undef MSK1
1086#undef MSK2
1087#undef MSK3
1088#undef MSK4
1089#undef PARITY1
1090#undef PARITY2
1091#undef PARITY3
1092#undef PARITY4
1093#undef IDSTR
1094#undef ALWAYSINLINE
1095#undef PRE_ALWAYS
1096
1097#endif
1098
1099#endif // DT_COMMON_POINTS_H
1100
1101// clang-format off
1102// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
1103// vim: shiftwidth=2 expandtab tabstop=2 cindent
1104// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
1105// clang-format on
static const float x
const float f
const float v
const dt_colormatrix_t dt_aligned_pixel_t out
void * dt_alloc_align(size_t size)
Allocate cacheline-aligned memory.
Definition darktable.c:508
static void swap(float *x, float *y)
Definition lightroom.c:1023
@ DT_DEBUG_ALWAYS
Definition logging.h:49
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...
Definition macros.h:96
#define dt_free_align(ptr)
Release memory from dt_alloc_align() and set ptr to NULL.
Definition mem_alloc.h:214
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
size_t size
Definition mipmap_cache.c:3
#define N
static int dt_get_thread_num()
Index of the calling thread within its parallel region, 0 outside one.
Definition openmp.h:129
static float dt_points_get()
Definition points.h:120
static void dt_points_cleanup(dt_points_t *p)
Definition points.h:86
static void dt_points_init(dt_points_t *p, const unsigned int num_threads)
Definition points.h:66
struct dt_points_t * dt_points_get_global(void)
Definition darktable.c:631
static float dt_points_get_for(dt_points_t *p, const unsigned int thread_num)
Definition points.h:93
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...
Definition simd.h:55
const float r
unsigned __int64 uint64_t
Definition strptime.c:75
uint64_t state1
Definition points.h:57
uint64_t state0
Definition points.h:56
unsigned int num
Definition points.h:63
dt_points_state_t * s
Definition points.h:62