Blender V4.3
rand.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cmath>
10#include <cstdlib>
11#include <cstring>
12#include <ctime>
13#include <random>
14
15#include "MEM_guardedalloc.h"
16
17#include "BLI_bitmap.h"
18#include "BLI_compiler_compat.h"
19#include "BLI_math_vector.h"
20#include "BLI_rand.h"
21#include "BLI_rand.hh"
22#include "BLI_sys_types.h"
23#include "BLI_threads.h"
24
25#include "BLI_strict_flags.h" /* Keep last. */
26
27extern "C" uchar BLI_noise_hash_uchar_512[512]; /* `noise.cc` */
28#define hash BLI_noise_hash_uchar_512
29
33struct RNG {
35
36 MEM_CXX_CLASS_ALLOC_FUNCS("RNG")
37};
38
40{
41 RNG *rng = new RNG();
42 rng->rng.seed(seed);
43 return rng;
44}
45
47{
48 RNG *rng = new RNG();
49 rng->rng.seed_random(seed);
50 return rng;
51}
52
53RNG *BLI_rng_copy(const RNG *rng)
54{
55 return new RNG(*rng);
56}
57
58void BLI_rng_free(RNG *rng)
59{
60 delete rng;
61}
62
64{
65 rng->rng.seed(seed);
66}
67
69{
70 rng->rng.seed_random(seed);
71}
72
73void BLI_rng_get_char_n(RNG *rng, char *bytes, size_t bytes_len)
74{
75 rng->rng.get_bytes(blender::MutableSpan(bytes, int64_t(bytes_len)));
76}
77
79{
80 return rng->rng.get_int32();
81}
82
84{
85 return rng->rng.get_uint32();
86}
87
89{
90 return rng->rng.get_double();
91}
92
94{
95 return rng->rng.get_float();
96}
97
98void BLI_rng_get_float_unit_v2(RNG *rng, float v[2])
99{
101}
102
103void BLI_rng_get_float_unit_v3(RNG *rng, float v[3])
104{
106}
107
109 RNG *rng, const float v1[2], const float v2[2], const float v3[2], float r_pt[2])
110{
111 copy_v2_v2(r_pt, rng->rng.get_triangle_sample(v1, v2, v3));
112}
113
115 RNG *rng, const float v1[3], const float v2[3], const float v3[3], float r_pt[3])
116{
117 copy_v3_v3(r_pt, rng->rng.get_triangle_sample_3d(v1, v2, v3));
118}
119
120void BLI_rng_shuffle_array(RNG *rng, void *data, uint elem_size_i, uint elem_num)
121{
122 if (elem_num <= 1) {
123 return;
124 }
125
126 const uint elem_size = elem_size_i;
127 uint i = elem_num;
128 void *temp = malloc(elem_size);
129
130 while (i--) {
131 const uint j = BLI_rng_get_uint(rng) % elem_num;
132 if (i != j) {
133 void *iElem = (uchar *)data + i * elem_size_i;
134 void *jElem = (uchar *)data + j * elem_size_i;
135 memcpy(temp, iElem, elem_size);
136 memcpy(iElem, jElem, elem_size);
137 memcpy(jElem, temp, elem_size);
138 }
139 }
140
141 free(temp);
142}
143
144void BLI_rng_shuffle_bitmap(RNG *rng, BLI_bitmap *bitmap, uint bits_num)
145{
146 if (bits_num <= 1) {
147 return;
148 }
149
150 uint i = bits_num;
151 while (i--) {
152 const uint j = BLI_rng_get_uint(rng) % bits_num;
153 if (i != j) {
154 const bool i_bit = BLI_BITMAP_TEST(bitmap, i);
155 const bool j_bit = BLI_BITMAP_TEST(bitmap, j);
156 BLI_BITMAP_SET(bitmap, i, j_bit);
157 BLI_BITMAP_SET(bitmap, j, i_bit);
158 }
159 }
160}
161
162void BLI_rng_skip(RNG *rng, int n)
163{
164 rng->rng.skip(uint(n));
165}
166
167/***/
168
169void BLI_array_frand(float *ar, int count, uint seed)
170{
171 RNG rng;
172
173 BLI_rng_srandom(&rng, seed);
174
175 for (int i = 0; i < count; i++) {
176 ar[i] = BLI_rng_get_float(&rng);
177 }
178}
179
181{
182 RNG rng;
183
184 BLI_rng_srandom(&rng, seed);
185 return BLI_rng_get_float(&rng);
186}
187
188void BLI_array_randomize(void *data, uint elem_size, uint elem_num, uint seed)
189{
190 RNG rng;
191
192 BLI_rng_seed(&rng, seed);
193 BLI_rng_shuffle_array(&rng, data, elem_size, elem_num);
194}
195
197{
198 RNG rng;
199
200 BLI_rng_seed(&rng, seed);
201 BLI_rng_shuffle_bitmap(&rng, bitmap, bits_num);
202}
203
204/* ********* for threaded random ************** */
205
207
220
222{
224}
225
227{
229}
230
234
236{
237 uint i;
239 "random_array");
240
241 for (i = 0; i < BLENDER_MAX_THREADS; i++) {
242 BLI_rng_srandom(&rngarr->rng_tab[i], uint(clock()));
243 }
244
245 return rngarr;
246}
247
249{
250 MEM_freeN(rngarr);
251}
252
254{
255 return BLI_rng_get_int(&rngarr->rng_tab[thread]);
256}
257
258/* ********* Low-discrepancy sequences ************** */
259
260/* incremental halton sequence generator, from:
261 * "Instant Radiosity", Keller A. */
262BLI_INLINE double halton_ex(double invprimes, double *offset)
263{
264 double e = fabs((1.0 - *offset) - 1e-10);
265
266 if (invprimes >= e) {
267 double lasth;
268 double h = invprimes;
269
270 do {
271 lasth = h;
272 h *= invprimes;
273 } while (h >= e);
274
275 *offset += ((lasth + h) - 1.0);
276 }
277 else {
278 *offset += invprimes;
279 }
280
281 return *offset;
282}
283
284void BLI_halton_1d(uint prime, double offset, int n, double *r)
285{
286 const double invprime = 1.0 / double(prime);
287
288 *r = 0.0;
289
290 for (int s = 0; s < n; s++) {
291 *r = halton_ex(invprime, &offset);
292 }
293}
294
295void BLI_halton_2d(const uint prime[2], double offset[2], int n, double *r)
296{
297 const double invprimes[2] = {1.0 / double(prime[0]), 1.0 / double(prime[1])};
298
299 r[0] = r[1] = 0.0;
300
301 for (int s = 0; s < n; s++) {
302 for (int i = 0; i < 2; i++) {
303 r[i] = halton_ex(invprimes[i], &offset[i]);
304 }
305 }
306}
307
308void BLI_halton_3d(const uint prime[3], double offset[3], int n, double *r)
309{
310 const double invprimes[3] = {
311 1.0 / double(prime[0]), 1.0 / double(prime[1]), 1.0 / double(prime[2])};
312
313 r[0] = r[1] = r[2] = 0.0;
314
315 for (int s = 0; s < n; s++) {
316 for (int i = 0; i < 3; i++) {
317 r[i] = halton_ex(invprimes[i], &offset[i]);
318 }
319 }
320}
321
322void BLI_halton_2d_sequence(const uint prime[2], double offset[2], int n, double *r)
323{
324 const double invprimes[2] = {1.0 / double(prime[0]), 1.0 / double(prime[1])};
325
326 for (int s = 0; s < n; s++) {
327 for (int i = 0; i < 2; i++) {
328 r[s * 2 + i] = halton_ex(invprimes[i], &offset[i]);
329 }
330 }
331}
332
333/* From "Sampling with Hammersley and Halton Points" TT Wong
334 * Appendix: Source Code 1 */
336{
337 double u = 0;
338
339 /* This reverse the bit-wise representation
340 * around the decimal point. */
341 for (double p = 0.5; n; p *= 0.5, n >>= 1) {
342 if (n & 1) {
343 u += p;
344 }
345 }
346
347 return u;
348}
349
350void BLI_hammersley_1d(uint n, double *r)
351{
352 *r = radical_inverse(n);
353}
354
356{
357 for (uint s = 0; s < n; s++) {
358 r[s * 2 + 0] = double(s + 0.5) / double(n);
359 r[s * 2 + 1] = radical_inverse(s);
360 }
361}
362
363namespace blender {
364
366{
367 std::random_device rd;
368 std::mt19937 e{rd()};
369 std::uniform_int_distribution<uint32_t> dist;
370 const uint32_t seed = dist(e);
372}
373
375{
376 this->seed(seed + hash[seed & 255]);
377 seed = this->get_uint32();
378 this->seed(seed + hash[seed & 255]);
379 seed = this->get_uint32();
380 this->seed(seed + hash[seed & 255]);
381}
382
384{
385 /* Support for negative values can be added when necessary. */
386 BLI_assert(x >= 0.0f);
387 const float round_up_probability = fractf(x);
388 const bool round_up = round_up_probability > this->get_float();
389 return int(x) + int(round_up);
390}
391
393{
394 float a = float(M_PI * 2.0) * this->get_float();
395 return {cosf(a), sinf(a)};
396}
397
399{
400 float z = (2.0f * this->get_float()) - 1.0f;
401 float r = 1.0f - z * z;
402 if (r > 0.0f) {
403 float a = float(M_PI * 2.0) * this->get_float();
404 r = sqrtf(r);
405 float x = r * cosf(a);
406 float y = r * sinf(a);
407 return {x, y, z};
408 }
409 return {0.0f, 0.0f, 1.0f};
410}
411
413{
414 float u = this->get_float();
415 float v = this->get_float();
416
417 if (u + v > 1.0f) {
418 u = 1.0f - u;
419 v = 1.0f - v;
420 }
421
422 float2 side_u = v2 - v1;
423 float2 side_v = v3 - v1;
424
425 float2 sample = v1;
426 sample += side_u * u;
427 sample += side_v * v;
428 return sample;
429}
430
432{
433 float u = this->get_float();
434 float v = this->get_float();
435
436 if (u + v > 1.0f) {
437 u = 1.0f - u;
438 v = 1.0f - v;
439 }
440
441 float3 side_u = v2 - v1;
442 float3 side_v = v3 - v1;
443
444 float3 sample = v1;
445 sample += side_u * u;
446 sample += side_v * v;
447 return sample;
448}
449
451{
452 constexpr int64_t mask_bytes = 2;
453 constexpr int64_t rand_stride = int64_t(sizeof(x_)) - mask_bytes;
454
455 int64_t last_len = 0;
456 int64_t trim_len = r_bytes.size();
457
458 if (trim_len > rand_stride) {
459 last_len = trim_len % rand_stride;
460 trim_len = trim_len - last_len;
461 }
462 else {
463 trim_len = 0;
464 last_len = r_bytes.size();
465 }
466
467 const char *data_src = (const char *)&x_;
468 int64_t i = 0;
469 while (i != trim_len) {
470 BLI_assert(i < trim_len);
471#ifdef __BIG_ENDIAN__
472 for (int64_t j = (rand_stride + mask_bytes) - 1; j != mask_bytes - 1; j--)
473#else
474 for (int64_t j = 0; j != rand_stride; j++)
475#endif
476 {
477 r_bytes[i++] = data_src[j];
478 }
479 this->step();
480 }
481 if (last_len) {
482 for (int64_t j = 0; j != last_len; j++) {
483 r_bytes[i++] = data_src[j];
484 }
485 }
486}
487
488} // namespace blender
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition BLI_bitmap.h:65
#define BLI_BITMAP_SET(_bitmap, _index, _set)
Definition BLI_bitmap.h:103
unsigned int BLI_bitmap
Definition BLI_bitmap.h:17
#define BLI_INLINE
void BLI_kdtree_nd_ free(KDTree *tree)
#define M_PI
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
Random number functions.
struct RNG RNG
Definition BLI_rand.h:25
unsigned char uchar
unsigned int uint
#define BLENDER_MAX_THREADS
Definition BLI_threads.h:20
typedef double(DMatrix)[4][4]
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
static unsigned long seed
Definition btSoftBody.h:39
constexpr int64_t size() const
Definition BLI_span.hh:494
void get_bytes(MutableSpan< char > r_bytes)
Definition rand.cc:450
int round_probabilistic(float x)
Definition rand.cc:383
RandomNumberGenerator(uint32_t seed=0)
Definition BLI_rand.hh:22
void seed_random(uint32_t seed)
Definition rand.cc:374
float3 get_triangle_sample_3d(float3 v1, float3 v2, float3 v3)
Definition rand.cc:431
float2 get_triangle_sample(float2 v1, float2 v2, float2 v3)
Definition rand.cc:412
void seed(uint32_t seed)
Definition BLI_rand.hh:36
static RandomNumberGenerator from_random_seed()
Definition rand.cc:365
#define sinf(x)
#define cosf(x)
#define sqrtf(x)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
int count
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
MINLINE float fractf(float a)
ccl_device_inline float2 fabs(const float2 a)
#define hash
Definition noise.c:154
void BLI_rng_threaded_free(RNG_THREAD_ARRAY *rngarr)
Definition rand.cc:248
uint BLI_rng_get_uint(RNG *rng)
Definition rand.cc:83
void BLI_thread_srandom(int thread, uint seed)
Definition rand.cc:208
float BLI_rng_get_float(RNG *rng)
Definition rand.cc:93
void BLI_halton_3d(const uint prime[3], double offset[3], int n, double *r)
Definition rand.cc:308
void BLI_rng_free(RNG *rng)
Definition rand.cc:58
void BLI_rng_srandom(RNG *rng, uint seed)
Definition rand.cc:68
float BLI_thread_frand(int thread)
Definition rand.cc:226
void BLI_rng_shuffle_array(RNG *rng, void *data, uint elem_size_i, uint elem_num)
Definition rand.cc:120
void BLI_rng_get_tri_sample_float_v3(RNG *rng, const float v1[3], const float v2[3], const float v3[3], float r_pt[3])
Definition rand.cc:114
RNG * BLI_rng_copy(const RNG *rng)
Definition rand.cc:53
void BLI_rng_shuffle_bitmap(RNG *rng, BLI_bitmap *bitmap, uint bits_num)
Definition rand.cc:144
void BLI_halton_2d(const uint prime[2], double offset[2], int n, double *r)
Definition rand.cc:295
int BLI_rng_get_int(RNG *rng)
Definition rand.cc:78
int BLI_thread_rand(int thread)
Definition rand.cc:221
#define hash
Definition rand.cc:28
void BLI_rng_get_float_unit_v3(RNG *rng, float v[3])
Definition rand.cc:103
uchar BLI_noise_hash_uchar_512[512]
Definition rand.cc:27
BLI_INLINE double radical_inverse(uint n)
Definition rand.cc:335
void BLI_hammersley_1d(uint n, double *r)
Definition rand.cc:350
void BLI_rng_seed(RNG *rng, uint seed)
Definition rand.cc:63
void BLI_hammersley_2d_sequence(uint n, double *r)
Definition rand.cc:355
static RNG rng_tab[BLENDER_MAX_THREADS]
Definition rand.cc:206
int BLI_rng_thread_rand(RNG_THREAD_ARRAY *rngarr, int thread)
Definition rand.cc:253
void BLI_rng_get_char_n(RNG *rng, char *bytes, size_t bytes_len)
Definition rand.cc:73
double BLI_rng_get_double(RNG *rng)
Definition rand.cc:88
void BLI_rng_skip(RNG *rng, int n)
Definition rand.cc:162
RNG * BLI_rng_new_srandom(uint seed)
Definition rand.cc:46
void BLI_halton_1d(uint prime, double offset, int n, double *r)
Definition rand.cc:284
RNG_THREAD_ARRAY * BLI_rng_threaded_new()
Definition rand.cc:235
void BLI_halton_2d_sequence(const uint prime[2], double offset[2], int n, double *r)
Definition rand.cc:322
void BLI_rng_get_float_unit_v2(RNG *rng, float v[2])
Definition rand.cc:98
void BLI_array_randomize(void *data, uint elem_size, uint elem_num, uint seed)
Definition rand.cc:188
BLI_INLINE double halton_ex(double invprimes, double *offset)
Definition rand.cc:262
RNG * BLI_rng_new(uint seed)
Definition rand.cc:39
void BLI_rng_get_tri_sample_float_v2(RNG *rng, const float v1[2], const float v2[2], const float v3[2], float r_pt[2])
Definition rand.cc:108
float BLI_hash_frand(uint seed)
Definition rand.cc:180
void BLI_bitmap_randomize(BLI_bitmap *bitmap, uint bits_num, uint seed)
Definition rand.cc:196
void BLI_array_frand(float *ar, int count, uint seed)
Definition rand.cc:169
unsigned int uint32_t
Definition stdint.h:80
__int64 int64_t
Definition stdint.h:89
RNG rng_tab[BLENDER_MAX_THREADS]
Definition rand.cc:232
Definition rand.cc:33
blender::RandomNumberGenerator rng
Definition rand.cc:34
ccl_device_inline size_t round_up(size_t x, size_t multiple)
Definition util/types.h:58