Line data Source code
1 : /************************************************************************* 2 : * 3 : * Project 4 : * _____ _____ __ __ _____ 5 : * / ____| __ \| \/ | __ \ 6 : * ___ _ __ ___ _ __ | | __| |__) | \ / | |__) | 7 : * / _ \| '_ \ / _ \ '_ \| | |_ | ___/| |\/| | ___/ 8 : *| (_) | |_) | __/ | | | |__| | | | | | | | 9 : * \___/| .__/ \___|_| |_|\_____|_| |_| |_|_| 10 : * | | 11 : * |_| 12 : * 13 : * Copyright (C) Akiel Aries, <akiel@akiel.org>, et al. 14 : * 15 : * This software is licensed as described in the file LICENSE, which 16 : * you should have received as part of this distribution. The terms 17 : * among other details are referenced in the official documentation 18 : * seen here : https://akielaries.github.io/openGPMP/ along with 19 : * important files seen in this project. 20 : * 21 : * You may opt to use, copy, modify, merge, publish, distribute 22 : * and/or sell copies of the Software, and permit persons to whom 23 : * the Software is furnished to do so, under the terms of the 24 : * LICENSE file. As this is an Open Source effort, all implementations 25 : * must be of the same methodology. 26 : * 27 : * 28 : * 29 : * This software is distributed on an AS IS basis, WITHOUT 30 : * WARRANTY OF ANY KIND, either express or implied. 31 : * 32 : ************************************************************************/ 33 : #include <chrono> 34 : #include <cstdint> 35 : #include <iostream> 36 : #include <openGPMP/nt/random.hpp> 37 : 38 : // dfault constructor 39 1 : gpmp::core::rndm::LCG::LCG() 40 1 : : state(1), multiplier(6364136223846793005ULL), 41 1 : increment(1442695040888963407ULL) { 42 1 : } 43 : 44 : // constructor 45 1 : gpmp::core::rndm::LCG::LCG(uint64_t seed, uint64_t a, uint64_t c) 46 1 : : state(seed), multiplier(a), increment(c) { 47 1 : } 48 : 49 20 : uint64_t gpmp::core::rndm::LCG::operator()() { 50 : // Ensure the state is non-negative 51 20 : state &= 0x7FFFFFFFFFFFFFFFULL; 52 : 53 : // Linear Congruential Generator algorithm 54 20 : state = multiplier * state + increment; 55 : 56 : // Overflow handling 57 20 : if (state < increment) { 58 : // Overflow occurred, adjust the state 59 3 : state += increment; 60 : } 61 : 62 20 : return state; 63 : } 64 : 65 : // set seed 66 0 : void gpmp::core::rndm::LCG::seed(uint64_t new_seed) { 67 0 : state = new_seed; 68 0 : } 69 : 70 : // methods to retrieve parameters (optional) 71 0 : uint64_t gpmp::core::rndm::LCG::get_multiplier() const { 72 0 : return multiplier; 73 : } 74 : 75 0 : uint64_t gpmp::core::rndm::LCG::get_increment() const { 76 0 : return increment; 77 : } 78 : 79 0 : uint64_t gpmp::core::rndm::LCG::get_seed() const { 80 0 : return state; 81 : } 82 : 83 : /* 84 : uint32_t gpmp::core::rndm::LCG(uint32_t lower, uint32_t upper, uint32_t seed) { 85 : uint32_t mod = __32MAX; 86 : uint32_t mult = 1664525; 87 : uint32_t incr = 1013904223; 88 : 89 : // set seed = current time 90 : uint32_t time_seed = 91 : std::chrono::system_clock::now().time_since_epoch().count(); 92 : 93 : uint32_t final_seed = (seed == 0) ? time_seed : seed; 94 : 95 : // Linear Congruential Generator algorithm 96 : uint32_t res = (mult * final_seed + incr) % mod; 97 : 98 : // trim to range 99 : res = lower + (res % (upper - lower + 1)); 100 : 101 : return res; 102 : } 103 : 104 : uint64_t 105 : gpmp::core::rndm::LCG_64(uint64_t lower, uint64_t upper, uint64_t seed) { 106 : uint64_t mod = __64MAX; 107 : uint64_t mult = 6364136223846793005ULL; // Large multiplier 108 : uint64_t incr = 1442695040888963407ULL; // Large increment 109 : 110 : // set seed = current time 111 : uint64_t time_seed = 112 : std::chrono::system_clock::now().time_since_epoch().count(); 113 : 114 : uint64_t final_seed = (seed == 0) ? time_seed : seed; 115 : 116 : // Linear Congruential Generator algorithm 117 : uint64_t res = (mult * final_seed + incr) % mod; 118 : 119 : // Calculate the range size 120 : uint64_t range_size = upper - lower + 1; 121 : 122 : // Avoid division by zero 123 : if (range_size != 0) { 124 : // Ensure res is non-negative 125 : res = res & ((1ULL << 63) - 1); 126 : 127 : // trim to range 128 : res = lower + (res % range_size); 129 : } 130 : 131 : return res; 132 : }*/ 133 : 134 0 : uint32_t gpmp::core::rndm::rotr32(uint32_t x, unsigned r) { 135 0 : return x >> r | x << (-r & 31); 136 : } 137 : 138 0 : uint32_t gpmp::core::rndm::pcg32(void) { 139 0 : uint64_t x = __PCG_STATE; 140 0 : unsigned count = (unsigned)(x >> 59); // 59 = 64 - 5 141 : 142 0 : __PCG_STATE = x * __PCG_MULTPLR + __PCG_INCR; 143 0 : x ^= x >> 18; // 18 = (64 - 27)/2 144 0 : return rotr32((uint32_t)(x >> 27), count); // 27 = 32 - 5 145 : } 146 : 147 0 : void gpmp::core::rndm::pcg32_init(uint64_t seed) { 148 0 : __PCG_STATE = seed + __PCG_INCR; 149 0 : (void)pcg32(); 150 0 : }