Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
data/kernels/noise_generator.h
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2020 Aurélien PIERRE.
4 Copyright (C) 2021 David Koller.
5 Copyright (C) 2023 Luca Zulberti.
6
7 darktable is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 darktable is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with darktable. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21// This is the OpenCL translation of common/noise_generator.h
22
23
25{
26 DT_NOISE_UNIFORM = 0, // $DESCRIPTION: "uniform"
27 DT_NOISE_GAUSSIAN = 1, // $DESCRIPTION: "gaussian"
28 DT_NOISE_POISSONIAN = 2 // $DESCRIPTION: "poissonian"
30
31
32static inline unsigned int splitmix32(const unsigned long seed)
33{
34 // fast random number generator
35 // reference : https://gist.github.com/imneme/6179748664e88ef3c34860f44309fc71
36 unsigned long result = (seed ^ (seed >> 33)) * 0x62a9d9ed799705f5ul;
37 result = (result ^ (result >> 28)) * 0xcb24d0a5c88c35b3ul;
38 return (unsigned int)(result >> 32);
39}
40
41
42
43static inline unsigned rol32(const unsigned int x, const int k)
44{
45 return (x << k) | (x >> (32 - k));
46}
47
48
49static inline float xoshiro128plus(uint state[4])
50{
51 // fast random number generator
52 // reference : http://prng.di.unimi.it/
53 const unsigned int result = state[0] + state[3];
54 const unsigned int t = state[1] << 9;
55
56 state[2] ^= state[0];
57 state[3] ^= state[1];
58 state[1] ^= state[2];
59 state[0] ^= state[3];
60
61 state[2] ^= t;
62 state[3] = rol32(state[3], 11);
63
64 return (float)(result >> 8) * 0x1.0p-24f; // take the first 24 bits and put them in mantissa
65}
66
67
68static inline float4 uniform_noise_simd(const float4 mu, const float4 sigma, uint state[4])
69{
70 const float4 noise = { xoshiro128plus(state), xoshiro128plus(state), xoshiro128plus(state), 0.f };
71 return mu + 2.0f * (noise - 0.5f) * sigma;
72}
73
74
75static inline float4 gaussian_noise_simd(const float4 mu, const float4 sigma, uint state[4])
76{
77 // Create gaussian noise centered in mu of standard deviation sigma
78 // state should be initialized with xoshiro256_init() before calling and private in thread
79 // flip needs to be flipped every next iteration
80 // reference : https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
81
82 float4 u1, u2;
83
84 u1.x = xoshiro128plus(state);
85 u1.y = xoshiro128plus(state);
86 u1.z = xoshiro128plus(state);
87
88 u2.x = xoshiro128plus(state);
89 u2.y = xoshiro128plus(state);
90 u2.z = xoshiro128plus(state);
91
92 u1 = fmax(u1, FLT_MIN);
93
94 const float4 flip = { 1.0f, 0.0f, 1.0f, 0.0f };
95 const float4 flip_comp = { 0.0f, 1.0f, 0.0f, 0.0f };
96
97 // flip is a 4x1 boolean mask
98 const float4 noise = flip * native_sqrt(-2.0f * native_log(u1)) * native_cos(2.f * M_PI_F * u2) +
99 flip_comp * native_sqrt(-2.0f * native_log(u1)) * native_sin(2.f * M_PI_F * u2);
100 return noise * sigma + mu;
101}
102
103
104static inline float4 poisson_noise_simd(const float4 mu, const float4 sigma, uint state[4])
105{
106 // create poissonian noise - It's just gaussian noise with Anscombe transform applied
107 float4 u1, u2;
108
109 // we need to generate the random numbers in this order to match CPU path.
110 u1.x = xoshiro128plus(state);
111 u2.x = xoshiro128plus(state);
112 u1.y = xoshiro128plus(state);
113 u2.y = xoshiro128plus(state);
114 u1.z = xoshiro128plus(state);
115 u2.z = xoshiro128plus(state);
116
117 u1 = fmax(u1, (float4)FLT_MIN);
118
119 const float4 flip = { 1.0f, 0.0f, 1.0f, 0.0f };
120 const float4 flip_comp = { 0.0f, 1.0f, 0.0f, 0.0f };
121
122 // flip is a 4x1 boolean mask
123 const float4 noise = flip * native_sqrt(-2.0f * native_log(u1)) * native_cos(2.f * M_PI_F * u2) +
124 flip_comp * native_sqrt(-2.0f * native_log(u1)) * native_sin(2.f * M_PI_F * u2);
125
126 // now we have gaussian noise, then apply Anscombe transform to get poissonian one
127 const float4 r = noise * sigma + 2.0f * native_sqrt(fmax(mu + (3.f / 8.f), 0.0f));
128 return ((r * r - sigma * sigma) / (4.f)) - (3.f / 8.f);
129}
130
131
132static inline float4 dt_noise_generator_simd(const dt_noise_distribution_t distribution,
133 const float4 mu, const float4 param,
134 uint state[4])
135{
136 // vector version
137
138 switch(distribution)
139 {
140 case(DT_NOISE_UNIFORM):
141 default:
142 {
143 return uniform_noise_simd(mu, param, state);
144 }
145
146 case(DT_NOISE_GAUSSIAN):
147 {
148 return gaussian_noise_simd(mu, param, state);
149 }
150
152 {
153 return poisson_noise_simd(mu, param, state);
154 }
155 }
156}
const float r
Definition colorspaces_inline_conversions.h:1324
#define M_PI_F
Definition data/kernels/common.h:36
dt_noise_distribution_t
Definition data/kernels/noise_generator.h:25
@ DT_NOISE_GAUSSIAN
Definition data/kernels/noise_generator.h:27
@ DT_NOISE_POISSONIAN
Definition data/kernels/noise_generator.h:28
@ DT_NOISE_UNIFORM
Definition data/kernels/noise_generator.h:26
static float4 dt_noise_generator_simd(const dt_noise_distribution_t distribution, const float4 mu, const float4 param, uint state[4])
Definition data/kernels/noise_generator.h:132
static unsigned rol32(const unsigned int x, const int k)
Definition data/kernels/noise_generator.h:43
static unsigned int splitmix32(const unsigned long seed)
Definition data/kernels/noise_generator.h:32
static float4 uniform_noise_simd(const float4 mu, const float4 sigma, uint state[4])
Definition data/kernels/noise_generator.h:68
static float4 poisson_noise_simd(const float4 mu, const float4 sigma, uint state[4])
Definition data/kernels/noise_generator.h:104
static float4 gaussian_noise_simd(const float4 mu, const float4 sigma, uint state[4])
Definition data/kernels/noise_generator.h:75
static float xoshiro128plus(uint state[4])
Definition data/kernels/noise_generator.h:49
static const float x
Definition iop_profile.h:239
const int t
Definition iop_profile.h:227
static void flip(float *x, float *y)
Definition lightroom.c:1015
unsigned int uint
Definition strptime.c:73