|
22 | 22 | */
|
23 | 23 | #include <math.h>
|
24 | 24 | #include <stdint.h>
|
| 25 | +#ifdef _OPENMP |
| 26 | +#include <omp.h> |
| 27 | +#endif /*_OPENMP*/ |
25 | 28 |
|
26 | 29 | /* initial RNG definitions */
|
27 | 30 | #define AT_RNG_STATE 0x853c49e6748fea9bULL
|
@@ -53,10 +56,14 @@ static uint32_t pcg32_random_r(pcg32_random_t* rng)
|
53 | 56 | {
|
54 | 57 | if (!rng) rng = &pcg32_global;
|
55 | 58 | uint64_t oldstate;
|
56 |
| - #pragma omp atomic read |
57 |
| - oldstate = rng->state; |
58 |
| - #pragma omp atomic write |
59 |
| - rng->state = oldstate * 6364136223846793005ULL + rng->inc; |
| 59 | + uint64_t inc = rng->inc; |
| 60 | + uint64_t *state = &(rng->state); |
| 61 | +// #pragma omp atomic capture |
| 62 | + #pragma omp critical(pgc32) |
| 63 | + { |
| 64 | + oldstate = *state; |
| 65 | + *state = oldstate * 6364136223846793005ULL + inc; |
| 66 | + } |
60 | 67 | uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
|
61 | 68 | uint32_t rot = oldstate >> 59u;
|
62 | 69 | return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
|
@@ -101,23 +108,28 @@ static double atrandn_r(pcg32_random_t* rng, double mean, double stdDev)
|
101 | 108 | {
|
102 | 109 | /* Marsaglia polar method: https://en.wikipedia.org/wiki/Marsaglia_polar_method */
|
103 | 110 |
|
104 |
| - double u, v, s; |
105 |
| - |
106 |
| - if (rng->hasSpare) { |
107 |
| - rng->hasSpare = false; |
108 |
| - return mean + stdDev * rng->spare; |
109 |
| - } |
110 |
| - |
111 |
| - rng->hasSpare = true; |
112 |
| - do { |
113 |
| - u = 2.0 * atrandd_r(rng) - 1.0; |
114 |
| - v = 2.0 * atrandd_r(rng) - 1.0; |
115 |
| - s = u * u + v * v; |
| 111 | + double u, v, s, result; |
| 112 | + |
| 113 | + #pragma omp critical(randn) |
| 114 | + { |
| 115 | + if (rng->hasSpare) { |
| 116 | + rng->hasSpare = false; |
| 117 | + result = mean + stdDev * rng->spare; |
| 118 | + } |
| 119 | + else { |
| 120 | + rng->hasSpare = true; |
| 121 | + do { |
| 122 | + u = 2.0 * atrandd_r(rng) - 1.0; |
| 123 | + v = 2.0 * atrandd_r(rng) - 1.0; |
| 124 | + s = u * u + v * v; |
| 125 | + } |
| 126 | + while ((s >= 1.0) || (s == 0.0)); |
| 127 | + s = sqrt(-2.0 * log(s) / s); |
| 128 | + rng->spare = v * s; |
| 129 | + result = mean + stdDev * u * s; |
| 130 | + } |
116 | 131 | }
|
117 |
| - while ((s >= 1.0) || (s == 0.0)); |
118 |
| - s = sqrt(-2.0 * log(s) / s); |
119 |
| - rng->spare = v * s; |
120 |
| - return mean + stdDev * u * s; |
| 132 | + return result; |
121 | 133 | }
|
122 | 134 |
|
123 | 135 | static int atrandp_r(pcg32_random_t* rng, double lamb)
|
|
0 commit comments