| 244 | } |
| 245 | |
| 246 | static inline uint64_t pcg_cm_random_r(pcg_state_setseq_128* rng) |
| 247 | { |
| 248 | /* Lots of manual inlining to help out certain compilers to generate |
| 249 | * performant code. */ |
| 250 | uint64_t hi = rng->state.high; |
| 251 | uint64_t lo = rng->state.low; |
| 252 | |
| 253 | /* Run the DXSM output function on the pre-iterated state. */ |
| 254 | lo |= 1; |
| 255 | hi ^= hi >> 32; |
| 256 | hi *= 0xda942042e4dd58b5ULL; |
| 257 | hi ^= hi >> 48; |
| 258 | hi *= lo; |
| 259 | |
| 260 | /* Run the CM step. */ |
| 261 | #if defined _WIN32 && _M_AMD64 |
| 262 | uint64_t h1; |
| 263 | pcg128_t product; |
| 264 | |
| 265 | /* Manually inline the multiplication and addition using intrinsics */ |
| 266 | h1 = rng->state.high * PCG_CHEAP_MULTIPLIER_128; |
| 267 | product.low = |
| 268 | _umul128(rng->state.low, PCG_CHEAP_MULTIPLIER_128, &(product.high)); |
| 269 | product.high += h1; |
| 270 | _addcarry_u64(_addcarry_u64(0, product.low, rng->inc.low, &(rng->state.low)), |
| 271 | product.high, rng->inc.high, &(rng->state.high)); |
| 272 | #else |
| 273 | rng->state = pcg128_add(pcg128_mult_64(rng->state, PCG_CHEAP_MULTIPLIER_128), |
| 274 | rng->inc); |
| 275 | #endif |
| 276 | return hi; |
| 277 | } |
| 278 | #else /* PCG_EMULATED_128BIT_MATH */ |
| 279 | |
| 280 | static inline void pcg_setseq_128_step_r(pcg_state_setseq_128 *rng) { |
no test coverage detected