libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

random.h (2800B)


      1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style
      4 // license that can be found in the LICENSE file.
      5 
      6 #ifndef LIB_JXL_BASE_RANDOM_
      7 #define LIB_JXL_BASE_RANDOM_
      8 
      9 // Random number generator + distributions.
     10 // We don't use <random> because the implementation (and thus results) differs
     11 // between libstdc++ and libc++.
     12 
     13 #include <stdint.h>
     14 #include <string.h>
     15 
     16 #include <algorithm>
     17 #include <cmath>
     18 
     19 #include "lib/jxl/base/status.h"
     20 
     21 namespace jxl {
     22 struct Rng {
     23   explicit Rng(size_t seed)
     24       : s{static_cast<uint64_t>(0x94D049BB133111EBull),
     25           static_cast<uint64_t>(0xBF58476D1CE4E5B9ull) + seed} {}
     26 
     27   // Xorshift128+ adapted from xorshift128+-inl.h
     28   uint64_t operator()() {
     29     uint64_t s1 = s[0];
     30     const uint64_t s0 = s[1];
     31     const uint64_t bits = s1 + s0;  // b, c
     32     s[0] = s0;
     33     s1 ^= s1 << 23;
     34     s1 ^= s0 ^ (s1 >> 18) ^ (s0 >> 5);
     35     s[1] = s1;
     36     return bits;
     37   }
     38 
     39   // Uniformly distributed int64_t in [begin, end), under the assumption that
     40   // `end-begin` is significantly smaller than 1<<64, otherwise there is some
     41   // bias.
     42   int64_t UniformI(int64_t begin, int64_t end) {
     43     JXL_DASSERT(end > begin);
     44     return static_cast<int64_t>((*this)() %
     45                                 static_cast<uint64_t>(end - begin)) +
     46            begin;
     47   }
     48 
     49   // Same as UniformI, but for uint64_t.
     50   uint64_t UniformU(uint64_t begin, uint64_t end) {
     51     JXL_DASSERT(end > begin);
     52     return (*this)() % (end - begin) + begin;
     53   }
     54 
     55   // Uniformly distributed float in [begin, end) range. Note: only 23 bits of
     56   // randomness.
     57   float UniformF(float begin, float end) {
     58     float f;
     59     // Bits of a random [1, 2) float.
     60     uint32_t u = ((*this)() >> (64 - 23)) | 0x3F800000;
     61     static_assert(sizeof(f) == sizeof(u),
     62                   "Float and U32 must have the same size");
     63     memcpy(&f, &u, sizeof(f));
     64     // Note: (end-begin) * f + (2*begin-end) may fail to return a number >=
     65     // begin.
     66     return (end - begin) * (f - 1.0f) + begin;
     67   }
     68 
     69   // Bernoulli trial
     70   bool Bernoulli(float p) { return UniformF(0, 1) < p; }
     71 
     72   // State for geometric distributions.
     73   // The stored value is inv_log_1mp
     74   using GeometricDistribution = float;
     75   static GeometricDistribution MakeGeometric(float p) {
     76     return 1.0 / std::log(1 - p);
     77   }
     78 
     79   uint32_t Geometric(const GeometricDistribution& dist) {
     80     float f = UniformF(0, 1);
     81     float inv_log_1mp = dist;
     82     float log = std::log(1 - f) * inv_log_1mp;
     83     return static_cast<uint32_t>(log);
     84   }
     85 
     86   template <typename T>
     87   void Shuffle(T* t, size_t n) {
     88     for (size_t i = 0; i + 1 < n; i++) {
     89       size_t a = UniformU(i, n);
     90       std::swap(t[a], t[i]);
     91     }
     92   }
     93 
     94  private:
     95   uint64_t s[2];
     96 };
     97 
     98 }  // namespace jxl
     99 #endif  // LIB_JXL_BASE_RANDOM_