Advertisement
Earthcomputer

Untitled

Jul 22nd, 2020
3,445
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.63 KB | None | 0 0
  1. // Copyright (c) The Minecraft Seed Finding Team
  2. //
  3. // MIT License
  4.  
  5. #ifndef LIBSEEDFINDING_LCG_H
  6. #define LIBSEEDFINDING_LCG_H
  7.  
  8. #if __cplusplus < 201402L
  9. #error "lcg.h requires C++ 14"
  10. #endif
  11.  
  12. #include <cinttypes>
  13. #include <type_traits>
  14.  
  15. /**
  16.  * Contains an implementation of the Java LCG and utility functions surrounding it.
  17.  * Many functions here are constexpr, meaning that they can be evaluated at compile-time if their inputs are
  18.  * also statically known. Otherwise, they are usually inlined by the compiler instead.
  19.  */
  20. namespace lcg {
  21.     typedef uint64_t Random;
  22.  
  23.     const uint64_t MULTIPLIER = 0x5deece66dLL;
  24.     const uint64_t ADDEND = 0xbLL;
  25.     const uint64_t MASK = 0xffffffffffffL;
  26.  
  27.     /// The minimum distance that two nextFloat values can be from each other. May be used to iterate over all valid floats.
  28.     const float FLOAT_UNIT = 1.0f / static_cast<float>(1L << 24);
  29.     /// The minimum distance that two nextDouble values can be from each other. May be used to iterate over all valid doubles.
  30.     const double DOUBLE_UNIT = 1.0 / static_cast<double>(1LL << 53);
  31.  
  32.     // Declared here for forward reference
  33.     template<int B>
  34.     constexpr typename std::enable_if_t<(0 <= B && B <= 32), int32_t> next(Random& rand);
  35.  
  36.     /**
  37.      * Contains internal functions. These are unstable, do not use them for any reason!
  38.      * If you think you need something from in here, first look for alternatives, else consider adding something to the public API for it.
  39.      * The internal functions are included in the header file so that the compiler can optimize using their implementations.
  40.      */
  41.     namespace internal {
  42.         // for returning multiple values
  43.         struct LCG {
  44.             uint64_t multiplier;
  45.             uint64_t addend;
  46.         };
  47.  
  48.         constexpr LCG combine(uint64_t calls) {
  49.             uint64_t multiplier = 1;
  50.             uint64_t addend = 0;
  51.  
  52.             uint64_t intermediate_multiplier = MULTIPLIER;
  53.             uint64_t intermediate_addend = ADDEND;
  54.  
  55.             for (uint64_t k = calls; k != 0; k >>= 1) {
  56.                 if ((k & 1) != 0) {
  57.                     multiplier *= intermediate_multiplier;
  58.                     addend = intermediate_multiplier * addend + intermediate_addend;
  59.                 }
  60.  
  61.                 intermediate_addend = (intermediate_multiplier + 1) * intermediate_addend;
  62.                 intermediate_multiplier *= intermediate_multiplier;
  63.             }
  64.  
  65.             multiplier &= MASK;
  66.             addend &= MASK;
  67.  
  68.             return {multiplier, addend};
  69.         }
  70.  
  71.         constexpr LCG combine(int64_t calls) {
  72.             return combine(static_cast<uint64_t>(calls));
  73.         }
  74.  
  75.         constexpr uint64_t gcd(uint64_t a, uint64_t b) {
  76.             if (b == 0) {
  77.                 return a;
  78.             }
  79.             while (true) {
  80.                 a %= b;
  81.                 if (a == 0) {
  82.                     return b;
  83.                 }
  84.                 b %= a;
  85.                 if (b == 0) {
  86.                     return a;
  87.                 }
  88.             }
  89.         }
  90.  
  91.         // Returns modulo inverse of a with
  92.         // respect to m using extended Euclid
  93.         // Algorithm Assumption: a and m are
  94.         // coprimes, i.e., gcd(a, m) = 1
  95.         // stolen code, now handles the case where gcd(a,m) != 1
  96.         constexpr uint64_t euclidean_helper(uint64_t a, uint64_t m) {
  97.             uint64_t m0 = m;
  98.             uint64_t y = 0, x = 1;
  99.             if (m == 1) {
  100.                 return 0;
  101.             }
  102.             uint64_t gcd_ = gcd(a, m);
  103.             while (a > gcd_) {
  104.                 uint64_t q = a / m;
  105.                 uint64_t t = m;
  106.                 m = a % m;
  107.                 a = t;
  108.                 t = y;
  109.                 y = x - q * y;
  110.                 x = t;
  111.             }
  112.             if (x < 0) {
  113.                 x += m0;
  114.             }
  115.             return x;
  116.         }
  117.  
  118.         constexpr uint64_t theta(uint64_t num) {
  119.             if (num % 4 == 3) {
  120.                 num = (1L << 50) - num;
  121.             }
  122.  
  123.             // xhat = num
  124.             uint64_t xhat_lo = num;
  125.             uint64_t xhat_hi = 0;
  126.  
  127.             // raise xhat to the power of 2^49 by squaring it 49 times
  128.             for (int i = 0; i < 49; i++) {
  129.                 xhat_hi = 2 * xhat_hi * xhat_lo;
  130.                 uint64_t xhat_lo_hi = xhat_lo >> 32;
  131.                 uint64_t xhat_lo_lo = xhat_lo & 0xffffffffLL;
  132.                 xhat_hi += xhat_lo_hi * xhat_lo_hi;
  133.                 if (((xhat_lo_hi * xhat_lo_lo) & 0x80000000LL) != 0) {
  134.                     xhat_hi++;
  135.                 }
  136.                 xhat_lo = xhat_lo * xhat_lo;
  137.             }
  138.             xhat_hi &= (1LL << (99 - 64)) - 1;
  139.  
  140.             // xhat--
  141.             if (xhat_lo == 0) xhat_hi--;
  142.             xhat_lo--;
  143.  
  144.             // xhat >>= 51
  145.             xhat_lo = (xhat_lo >> 51) | (xhat_hi << (64 - 51));
  146.  
  147.             // xhat &= MASK
  148.             xhat_lo &= MASK;
  149.             return xhat_lo;
  150.         }
  151.  
  152.         // Computes nextInt(N) for the case where N is a power of 2. Declared to avoid duplicate code.
  153.         // Use the more generic public version, they will compile to the same thing.
  154.         template<int32_t N>
  155.         constexpr std::enable_if_t<(N > 0 && (N & -N) == N), int32_t> next_int_power_of_2(Random& rand) {
  156.             return static_cast<int32_t>((static_cast<uint64_t>(next<31>(rand)) * static_cast<uint64_t>(N)) >> 31);
  157.         }
  158.  
  159.         constexpr int32_t dynamic_next_int_power_of_2(Random& rand, int32_t n) {
  160.             return static_cast<int32_t>((static_cast<uint64_t>(next<31>(rand)) * static_cast<uint64_t>(n)) >> 31);
  161.         }
  162.     }
  163.  
  164.  
  165.     /// Advances the Random by an unsigned N steps, which defaults to 1. Runs in O(1) time because of compile-time optimizations.
  166.     template<uint64_t N = 1>
  167.     constexpr void uadvance(Random& rand) {
  168.         internal::LCG lcg = internal::combine(N);
  169.         rand = (rand * lcg.multiplier + lcg.addend) & MASK;
  170.     }
  171.  
  172.     /// Advances the Random by N steps, which defaults to 1. Runs in O(1) time because of compile-time optimizations.
  173.     template<int64_t N = 1>
  174.     constexpr void advance(Random& rand) {
  175.         uadvance<static_cast<uint64_t>(N)>(rand);
  176.     }
  177.  
  178.     /// Advances the Random by an unsigned n steps. Used when n is not known at compile-time. Runs in O(log(n)) time.
  179.     constexpr void dynamic_advance(Random& rand, uint64_t n) {
  180.         internal::LCG lcg = internal::combine(n);
  181.         rand = (rand * lcg.multiplier + lcg.addend) & MASK;
  182.     }
  183.  
  184.     /// Advances the Random by n steps. Used when n is not known at compile-time. Runs in O(log(n)) time.
  185.     constexpr void dynamic_advance(Random& rand, int64_t n) {
  186.         dynamic_advance(rand, static_cast<uint64_t>(n));
  187.     }
  188.  
  189.     /**
  190.      * Converts a Distance From Zero (DFZ) value to a Random seed.
  191.      * DFZ is a representation of a seed which is the number of LCG calls required to get from seed 0 to that seed.
  192.      * To get Random outputs from a DFZ value it must first be converted to a seed, which is done in O(log(dfz)).
  193.      * In various situations, especially far GPU parallelization, it may be useful to represent seeds this way.
  194.      */
  195.     constexpr Random dfz2seed(uint64_t dfz) {
  196.         Random seed = 0;
  197.         dynamic_advance(seed, dfz);
  198.         return seed;
  199.     }
  200.  
  201.     /**
  202.      * Converts a Random seed to DFZ form. See dfz2seed for a description of DFZ form.
  203.      * This function should be called reservedly, as although it is O(1), it is relatively slow.
  204.      */
  205.     constexpr uint64_t seed2dfz(Random seed) {
  206.         uint64_t a = 25214903917LL;
  207.         uint64_t b = (((seed * (MULTIPLIER - 1)) * 179120439724963LL) + 1) & ((1LL << 50) - 1);
  208.         uint64_t abar = internal::theta(a);
  209.         uint64_t bbar = internal::theta(b);
  210.         uint64_t gcd_ = internal::gcd(abar, (1LL << 48));
  211.         return (bbar * internal::euclidean_helper(abar, (1LL << 48)) & 0x3FFFFFFFFFFFLL) / gcd_; //+ i*(1L << 48)/gcd;
  212.     }
  213.  
  214.     /// Advances the LCG and gets the upper B bits from it.
  215.     template<int B>
  216.     constexpr typename std::enable_if_t<(0 <= B && B <= 32), int32_t> next(Random& rand) {
  217.         advance(rand);
  218.         return static_cast<int32_t>(rand >> (48 - B));
  219.     }
  220.  
  221.     /// Does an unbounded nextInt call and returns the result.
  222.     constexpr int32_t next_int_unbounded(Random& rand) {
  223.         return next<32>(rand);
  224.     }
  225.  
  226.     /// Does a bounded nextInt call with bound N.
  227.     template<int32_t N>
  228.     constexpr typename std::enable_if_t<(N > 0), int32_t> next_int(Random& rand) {
  229.         if ((N & -N) == N) {
  230.             return internal::next_int_power_of_2<N>(rand);
  231.         } else {
  232.             int32_t bits = next<31>(rand);
  233.             int32_t val = bits % N;
  234.             while (bits - val + (N-1) < 0) {
  235.                 bits = next<31>(rand);
  236.                 val = bits % N;
  237.             }
  238.             return val;
  239.         }
  240.     }
  241.  
  242.     /**
  243.      * Does a bounded nextInt call with bound N. If N is not a power of 2, then it makes the assumption that the loop
  244.      * does not iterate more than once. The probability of this being correct depends on N, but for small N this
  245.      * function is extremely likely to have the same effect as next_int.
  246.      */
  247.     template<int32_t N>
  248.     constexpr typename std::enable_if_t<(N > 0), int32_t> next_int_fast(Random& rand) {
  249.         if ((N & -N) == N) {
  250.             return internal::next_int_power_of_2<N>(rand);
  251.         } else {
  252.             return next<31>(rand) % N;
  253.         }
  254.     }
  255.  
  256.     /// Does a bounded nextInt call with bound n, used when n is not known in advance.
  257.     constexpr int32_t dynamic_next_int(Random& rand, int32_t n) {
  258.         if ((n & -n) == n) {
  259.             return internal::dynamic_next_int_power_of_2(rand, n);
  260.         } else {
  261.             int32_t bits = next<31>(rand);
  262.             int32_t val = bits % n;
  263.             while (bits - val + (n-1) < 0) {
  264.                 bits = next<31>(rand);
  265.                 val = bits % n;
  266.             }
  267.             return val;
  268.         }
  269.     }
  270.  
  271.     /**
  272.      * Does a bounded nextInt call with bound n, using the "fast" approach, used when n is not known in advance.
  273.      * See next_int_fast for a description of the fast approach.
  274.      */
  275.     constexpr int32_t dynamic_next_int_fast(Random& rand, int32_t n) {
  276.         if ((n & -n) == n) {
  277.             return internal::dynamic_next_int_power_of_2(rand, n);
  278.         } else {
  279.             return next<31>(rand) % n;
  280.         }
  281.     }
  282.  
  283.     /// Does a nextLong call.
  284.     constexpr int64_t next_long(Random& rand) {
  285.         // separate out calls due to unspecified evaluation order in C++
  286.         int32_t hi = next<32>(rand);
  287.         int32_t lo = next<32>(rand);
  288.         return (static_cast<int64_t>(hi) << 32) + static_cast<int64_t>(lo);
  289.     }
  290.  
  291.     /// Does an unsigned nextLong call.
  292.     constexpr uint64_t next_ulong(Random& rand) {
  293.         return static_cast<uint64_t>(next_long(rand));
  294.     }
  295.  
  296.     /// Does a nextBoolean call.
  297.     constexpr bool next_bool(Random& rand) {
  298.         return next<1>(rand) != 0;
  299.     }
  300.  
  301.     /// Does a nextFloat call.
  302.     float next_float(Random& rand) {
  303.         return static_cast<float>(next<24>(rand)) * FLOAT_UNIT;
  304.     }
  305.  
  306.     /// Does a nextDouble call.
  307.     double next_double(Random& rand) {
  308.         // separate out calls due to unspecified evaluation order in C++
  309.         int32_t hi = next<26>(rand);
  310.         int32_t lo = next<27>(rand);
  311.         return static_cast<double>((static_cast<int64_t>(hi) << 27) + static_cast<int64_t>(lo)) * DOUBLE_UNIT;
  312.     }
  313. }
  314.  
  315. #endif //LIBSEEDFINDING_LCG_H
  316.  
  317. #include <iostream>
  318. int main() {
  319.     lcg::Random seed;
  320.     std::cin >> seed;
  321.     lcg::advance<47>(rand);
  322.     std::cout << seed << std::endl;
  323. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement