/* * PCG Random Number Generation for C. * * Copyright 2014-2019 Melissa O'Neill , * and the PCG Project contributors. * * SPDX-License-Identifier: (Apache-2.0 OR MIT) * * Licensed under the Apache License, Version 2.0 (provided in * LICENSE-APACHE.txt and at http://www.apache.org/licenses/LICENSE-2.0) * or under the MIT license (provided in LICENSE-MIT.txt and at * http://opensource.org/licenses/MIT), at your option. This file may not * be copied, modified, or distributed except according to those terms. * * Distributed on an "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, either * express or implied. See your chosen license for details. * * For additional information about the PCG random number generation scheme, * visit http://www.pcg-random.org/. */ /* * This code is derived from the canonical C++ PCG implementation, which * has many additional features and is preferable if you can use C++ in * your project. * * Repetative C code is derived using C preprocessor metaprogramming * techniques. */ #include "pcg_variants.h" /* Multi-step advance functions (jump-ahead, jump-back) * * The method used here is based on Brown, "Random Number Generation * with Arbitrary Stride,", Transactions of the American Nuclear * Society (Nov. 1994). The algorithm is very similar to fast * exponentiation. * * Even though delta is an unsigned integer, we can pass a * signed integer to go backwards, it just goes "the long way round". */ uint64_t pcg_advance_lcg_64(uint64_t state, uint64_t delta, uint64_t cur_mult, uint64_t cur_plus) { uint64_t acc_mult = 1u; uint64_t acc_plus = 0u; while (delta > 0) { if (delta & 1) { acc_mult *= cur_mult; acc_plus = acc_plus * cur_mult + cur_plus; } cur_plus = (cur_mult + 1) * cur_plus; cur_mult *= cur_mult; delta /= 2; } return acc_mult * state + acc_plus; }