/****************************************************************************** * This program implements the ACORN pseudo-random number generator. * * Copyright © 2021 Richard Lesh. All rights reserved. *****************************************************************************/ #undef NDEBUG #include "Utils.hpp" #include #include #include #include #include #include using namespace Utils; using namespace std; class AcornPrng { private: long modulus; int order; vector seeds = {}; public: AcornPrng(int order) noexcept { this->modulus = 4294967295L; this->order = order; for (auto m = 0; m <= order; ++m) { long s(modulus * rand()/(RAND_MAX + 1.0)); if (s % 2 == 0) { ++s; } Utils::push(seeds, s); } } long next_int() noexcept { for (auto m = 1; m <= order; ++m) { seeds[m] = (m == 1 ? seeds[0] : seeds[m - 1]) + seeds[m]; seeds[m] &= modulus; } return seeds[order]; } double next_float() noexcept { return next_int() / (modulus + 1.0); } }; int main(int argc, char **argv) { if (argc == 2 && string(argv[1]) == "-h") { cout << "Syntax: " << argv[0] << " [num_random] [int|float]" << endl; cout << "If no arguments are provided a random stream of bytes" << endl; cout << "are output." << endl; exit(1); } int num = argc >= 2 ? Utils::stoiWithDefault(string(argv[1]), 10) : -1; string type = argc == 3 ? string(argv[2]) : "int"; cout << "type: " << (type == "int" ? "d" : "f") << endl; cout << "count: " << num << endl; cout << "numbit: 32" << endl; shared_ptr generator(new AcornPrng(10)); if (type == "int") { if (num < 1) { while (true) { int randint = int(generator->next_int()); unsigned char b = (unsigned char)(randint & 0xFF); cout.put(b); randint >>= 8; b = (unsigned char)(randint & 0xFF); cout.put(b); randint >>= 8; b = (unsigned char)(randint & 0xFF); cout.put(b); randint >>= 8; b = (unsigned char)(randint & 0xFF); cout.put(b); } } else { for (auto i = 0; i < num; ++i) { cout << generator->next_int() << endl; } } } else { for (auto i = 0; i < num; ++i) { cout << fmt::format("{0:.10f}", generator->next_float()) << endl; } } return 0; }