Advertisement
Kaelygon

c++ LCG and hash

Jan 5th, 2024 (edited)
850
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.96 KB | None | 0 0
  1.  
  2. #pragma once
  3. #include <iostream>
  4. #include <vector>
  5. #include <cstdint>
  6. #include <cmath>
  7. #include <cstring>
  8. #include <climits>
  9.  
  10. #include <type_traits>
  11.  
  12. //Simple rorr lcg prng
  13. template <typename InsT = uint64_t> //instance type
  14. class kaelRandom {
  15.     typedef unsigned int uint128_t __attribute__((mode(TI)));
  16.     template <typename... Types>
  17.     void isUint() {
  18.         static_assert(
  19.             ((
  20.             std::is_unsigned<std::remove_pointer_t<Types>>::value ||
  21.             std::is_same< std::remove_pointer_t<Types>, std::remove_pointer_t<uint128_t> >::value
  22.             ) && ...) , "All type must be an unsigned integer type"
  23.         );
  24.     }
  25. public:
  26.     kaelRandom(){ isUint<InsT>(); }
  27.  
  28.     //Store pointers to be used and modified in kaelShfl
  29.     //If no pointer is give, private variables are used
  30.     template <typename X = InsT, typename Y = InsT>
  31.     struct ShufflePair {
  32.         X* seed;
  33.         Y* step;
  34.         ShufflePair(X* seedInit=nullptr, Y* stepInit=nullptr)
  35.             : seed(seedInit), step(stepInit) { 
  36.                 seed = seedInit==nullptr ? &privateSeed : seedInit;
  37.                 step = stepInit==nullptr ? &privateStep : stepInit;
  38.         }
  39.  
  40.         private:
  41.             static constexpr const X defaultSeed = (sizeof(X)==1) ? (X)125 : (X)200 ;
  42.             static constexpr const Y defaultStep = (sizeof(Y)==1) ? (Y)125 : (Y)200 ;  
  43.             X privateSeed = defaultSeed;
  44.             Y privateStep = defaultStep;
  45.     };
  46.  
  47. private:
  48.  
  49.     InsT seed;
  50.     static constexpr const InsT mul= (InsT) (sizeof(InsT) == 1 ? 235 : 913      );
  51.     static constexpr const InsT add= (InsT) (sizeof(InsT) == 1 ? 191 : 13238717 );
  52.     //Generate pseudo random numbers RORR LCG
  53.     template <typename V = InsT>
  54.     inline const InsT kaelLCG(const V n) {  isUint<V>();
  55.         static constexpr const uint bitSize = sizeof(V)*CHAR_BIT;
  56.         static constexpr const uint shift = (sizeof(V)*3)-1;
  57.         static constexpr const uint invShift = bitSize-shift;
  58.  
  59.         V buf = 0;
  60.         buf = ( (n>>shift) | (n<<invShift) ) * mul + add;
  61.         return buf ;
  62.     }
  63.  
  64.     static constexpr const InsT prm35 =(InsT)(mul*add+126U);
  65.     //Evenly distributed hash
  66.     template <typename V = InsT>
  67.     V kaelHash(const char* cstr) {
  68.         static constexpr const uint bitSize = sizeof(V)*CHAR_BIT;
  69.        
  70.         InsT hash=prm35;
  71.         InsT step=(V)14939;
  72.         ShufflePair<InsT,InsT> bufPair = {&hash, &step};
  73.  
  74.         InsT charVal = (uint8_t)cstr[0];
  75.         while(true){ //iterate through every char until null termination
  76.             hash^=charVal;
  77.             shuffle(bufPair); //shuffle hash
  78.             cstr++;
  79.             if(!*cstr){ break; }
  80.             hash = (hash>>CHAR_BIT) | (hash<<(bitSize-CHAR_BIT)) ; //RORR byte
  81.             charVal = (uint8_t)cstr[0];
  82.         }
  83.         hash = kaelLCG(hash); //randomize hash
  84.  
  85.         return (V)hash;
  86.     }
  87.  
  88.     //Bijective shuffle function. Mod 4 is predictable
  89.     template <typename X = InsT, typename Y = InsT>
  90.     ShufflePair<X, Y>& kaelShfl(ShufflePair<X, Y>& shufflePair) {
  91.         constexpr const X a0 = (sizeof(X) == 1) ? 4     : 4     ; //Some values increase periodicity greatly
  92.         constexpr const X a1 = (sizeof(X) == 1) ? 31    : 6619  ;
  93.         constexpr const Y b0 = (sizeof(X) == 1) ? 13    : 3083  ;
  94.         constexpr const Y b1 = (sizeof(X) == 1) ? 7     : 5419  ;
  95.  
  96.         *shufflePair.step &= (~0b1); //has to be even for the next check to work
  97.         *shufflePair.step += ( (*shufflePair.step & 3) == 2) || ((*shufflePair.step & 3) == 3) ? 2 : 0; //skip any step congruent to 2 or 3 of mod 4
  98.        
  99.         *shufflePair.seed = *shufflePair.seed * ( (*shufflePair.step|0b1)+a0 ) + a1; //LCG
  100.         *shufflePair.step = *shufflePair.step * b0+b1; //some values have longer periods of m up to 1 quarter of states available
  101.  
  102.         return shufflePair;
  103.     }
  104.  
  105.  
  106. public:
  107.  
  108.     //iterate instance seed
  109.         //definitely not thread safe
  110.         inline InsT const operator()() {
  111.             seed = kaelLCG(seed);
  112.             return seed;
  113.         }
  114.         inline void setSeed(InsT n) {
  115.             seed = n;
  116.         }
  117.         //potentially not thread safe
  118.         //Seed pointer null check. If input *n is nullptr, return instance seed ptr. Otherwise return *n unchanged
  119.         inline InsT* getSeedPtr(InsT *n){
  120.             if(n==nullptr){
  121.                 return &seed;
  122.             }
  123.             return n;
  124.         }
  125.         //Pointer to instance seed. Not thread safe to modify. No null check.
  126.         inline InsT* getSeedPtr() {
  127.             return &seed;
  128.         }
  129.     //
  130.  
  131.     //thread safe as we are iterating the given argument value or ptr. Unless the pointer is instance seed
  132.         //iterate literal (thread safe)
  133.         template <typename U = InsT, typename = std::enable_if_t<!std::is_pointer<std::remove_reference_t<U>>::value>>
  134.         inline const InsT operator()(const U& n) { isUint<U>();
  135.             return kaelLCG(n);
  136.         }
  137.         //Iterate pointer
  138.         template <typename U = InsT, typename = std::enable_if_t<std::is_pointer<std::remove_reference_t<U>>::value>>
  139.         inline const InsT operator()(U n) { isUint<U>();
  140.             *n = kaelLCG(*n);
  141.             return *n;
  142.         }
  143.     //
  144.  
  145.     //other randomizers
  146.         //hash c string
  147.         inline InsT hashCstr(const std::string& str) {
  148.             return kaelHash<InsT>(str.c_str());
  149.         }
  150.        
  151.         inline InsT hashCstr(const char* str) {
  152.             return kaelHash<InsT>(str);
  153.         }
  154.  
  155.         template <typename X = InsT, typename Y = InsT>
  156.         inline ShufflePair<X, Y>& shuffle(ShufflePair<X, Y>& shflPair) {
  157.             return kaelShfl(shflPair);
  158.         }
  159.     //
  160.  
  161. };
  162. kaelRandom kaelRand;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement