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