Advertisement
Kaelygon

8-bit pcg

Dec 11th, 2024 (edited)
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.70 KB | None | 0 0
  1.  
  2.  
  3. //./include/kaelygon/math/rand.h
  4. #ifndef KAELRAND_H
  5. #define KAELRAND_H
  6. //8-bit permuted congruential generator rorr + LCG
  7.  
  8. //periods, total state bit count is KAELRAND_STATES*8 + 8
  9. //32-bit period: 2^11 * 127^3
  10. //24-bit period: 2^10 * 127^2
  11. //16-bit period: 2^9  * 127^1
  12. //8-bit states 0, since iteration loop requires at least 1 state
  13.  
  14. //More shift,mul,add candidates at ./generated/validRorrLCG.txt
  15.  
  16. #include <stdint.h>
  17. #include <stdlib.h>
  18.  
  19. enum {
  20.     KAELRAND_SHIFT      = 1,
  21.     KAELRAND_MUL        = 37,
  22.     KAELRAND_ADD        = 57,
  23.     KAELRAND_STATES     = 3
  24. };
  25.  
  26. typedef struct {
  27.     uint8_t state[KAELRAND_STATES];
  28.     uint8_t last; //latest output, contributes to period length
  29. }KaelRand;
  30.  
  31. void kaelRand_seed(KaelRand *krand, char *cstr);
  32.  
  33. uint8_t kaelRand(KaelRand *krand);
  34.  
  35. uint16_t kaelRand_u16lcg(uint16_t seed);
  36.  
  37. #endif
  38.  
  39.  
  40. //./include/kaelygon/math/rand.c
  41. #ifndef KAELRAND_C
  42. #define KAELRAND_C
  43. //8-bit permuted congruential generator rorr + LCG
  44.  
  45. #include <stdint.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48.  
  49. #include "kaelygon/math/math.h"
  50. #include "kaelygon/math/rand.h"
  51.  
  52. //Simple cstring to hash
  53. void kaelRand_hash(char* cstr, uint8_t *numArr, uint8_t arrLen){
  54.     if(cstr==NULL || numArr==NULL || arrLen==0){return;}
  55.     const uint8_t ASCII_START = 32;
  56.     const uint8_t ASCII_END = 126;
  57.     const uint8_t ASCII_SCALE = (0xFF) / (ASCII_END - ASCII_START)+1;
  58.  
  59.     //shift and scale ascii range 0 to 0xFF. Sum and wrap to mix  
  60.     uint8_t index = 0;
  61.     uint8_t sum = 0;
  62.     while(cstr[index] && (index!=0xFF)){
  63.         sum += ((uint8_t)(cstr[index])-ASCII_START) * ASCII_SCALE;
  64.         numArr[index%arrLen] = sum;
  65.         index++;
  66.     };
  67. }
  68.  
  69. //Seed from string hash. NULL string = zero
  70. void kaelRand_seed(KaelRand *krand, char *cstr){
  71.     if(krand==NULL){return;}
  72.     memset(&krand->state,0,sizeof(uint8_t)*KAELRAND_STATES);
  73.     if(cstr==NULL){return;}
  74.     krand->last=(uint8_t)cstr[0]*KAELRAND_MUL+KAELRAND_ADD;
  75.     kaelRand_hash( cstr, krand->state, KAELRAND_STATES );
  76. }
  77.  
  78. //Iterate KaelRand states and output a pseudo random number
  79. //No null check as this is run in tight loops, CHECK SEPARATELY
  80. uint8_t kaelRand( KaelRand *krand ){
  81.     for(uint8_t i=0; i<KAELRAND_STATES;i++){ //Cycle all states condotionally
  82.         krand->state[i] = kaelMath_u8rorr(krand->state[i], KAELRAND_SHIFT) * KAELRAND_MUL + KAELRAND_ADD; //rorr LCG
  83.         krand->last+= krand->state[i]; //mix with previous sum
  84.  
  85.         //early exit condition. Only breaking the cycle at 0 is necessary for full period.
  86.         //the part after || results in effective 5/8 chance to skip next bytes
  87.         //trade off for speed at cost off randomness quality
  88.         if( krand->state[i]==0 || ((krand->state[i]&0b11111)!=0) ){
  89.             break;
  90.         }
  91.     }
  92.  
  93.     return krand->last;
  94. }
  95.  
  96. //other 16-bit RLCG parameters
  97. //{1, 95, 975}, // 0.316218
  98. //{2, 83, 89},  // 0.374768
  99. //{2, 61, 394}, // 0.513991
  100. //{1, 49, 112}, // 0.645737
  101.  
  102. //16-bit full period RORR LCG
  103. kmath_t kaelRand_u16lcg(kmath_t seed){
  104.     seed = kaelMath_rorr(seed,2);
  105.     return seed * 83 + 89;
  106. }
  107.  
  108. #endif
  109.  
  110. //main
  111. //./tools/rorLCG-Testing.c
  112. #include <stdio.h>
  113. #include <stdint.h>
  114. #include <stdlib.h>
  115. #include <x86intrin.h>
  116.  
  117. #include "../include/kaelygon/math/rand.h"
  118.  
  119. #include <math.h>
  120.  
  121. int main(){
  122.  
  123.     KaelRand randState;
  124.     kaelRand_seed(&randState,"I am about to become a hash, hihii!");
  125.  
  126.     FILE *fptr;
  127.     fptr = fopen("./generated/audio.pcm","wb");
  128.     if(fptr==NULL){printf("open failed\n"); abort();}
  129.  
  130.     uint8_t num = 0;
  131.  
  132.     uint64_t startTime = __rdtsc();
  133.     for(uint64_t i=0; i<(uint64_t)pow(2,24);i++){
  134.         num = kaelRand(&randState);
  135.         fwrite(&num,sizeof(uint8_t),1,fptr);
  136.     }
  137.     uint64_t endTime = __rdtsc();
  138.     printf("time %.4f \n", (double)(endTime-startTime)/3700000000);
  139.  
  140.     fclose(fptr);
  141.  
  142.     printf("num %u \n", num);
  143.  
  144.    
  145.     return 0;
  146. }
Tags: 8-bit pcg
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement