SHARE
TWEET

randomz() reloaded again, update with tests in C

a guest Nov 22nd, 2019 200 in 157 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ///gcc -std=c99 -Wall -Wextra -O3 -march=i686 -o "randomz000" "randomz000.c"
  2. ///best performance compile: gcc -O3 -save-temps -masm=intel -msse -msse2 -msse3 -mfpmath=sse -msse4.1 -std=c99 -Wall -Wextra -march=native -o "%e" "%f" -lm -lrt && ln -fs "%e".i "%e"_cpp.c && ln -fs "%e".s "%e"_cpp.asm
  3. //#include <math.h>
  4. //#include <float.h>    // float min max values
  5. //#include <limits.h>
  6. #include <unistd.h>     //
  7. #include <stdio.h>      //
  8. //#include <stdlib.h>
  9. #include <stdint.h>     //  std int types
  10.  
  11. extern int usleep (__useconds_t __useconds);
  12.  
  13. /// types
  14. // define new standard float types
  15. typedef float       float32_t;
  16. typedef double      float64_t;
  17. typedef long double float80_t;
  18. #define float80_t long double
  19. #define float64_t double
  20. #define float32_t float
  21. // defines make you never actually use the new float types for compatibility
  22.  
  23. //  eval any std type using input size
  24. #define _clone_(to, from)   __typeof__ (from)   (to) = (from)
  25. #define _eval_( anytype )    ( { _clone_( x, (anytype) ); x; } )
  26. #define arraylen( _ary_ ) ( sizeof(_ary_)/sizeof(_ary_[0]) )
  27.  
  28.  
  29. #ifdef __x86_64__
  30.     #define rol64(ui, count) ( ( (ui) << (count) ) | ( (ui) >> ( 64 - (count) ) ) )
  31.     #define ror64(ui, count) ( ( (ui) >> (count) ) | ( (ui) << ( 64 - (count) ) ) )
  32. #else
  33.     #define rol64(ui, count) ( { uint8_t c2 = (count) % 65; uint64_t u2 = ui; ((u2 << c2) | (u2 >> ( 64 - c2 ))); } )
  34.     #define ror64(ui, count) ( { uint8_t c2 = (count) % 65; uint64_t u2 = ui; ((u2 >> c2) | (u2 << ( 64 - c2 ))); } )
  35. #endif
  36.  
  37. // takes <8 cycles (<3.6ns on 2.2GHz amd64) with -O3
  38. #ifdef __x86_64__
  39. #define rdtsc( z )
  40. __asm__ __volatile__ ("\n\
  41.         rdtsc                       \n\
  42.         shl     $32, %%rdx          \n\
  43.         leaq    (%%rax + %%rdx), %0 \n"\
  44.     : "=r" ( *(z) ) \
  45.     : \
  46.     : "%rax", "%rdx", "%cc" \
  47. )
  48. #define rdtsc_or64( z ) \
  49. __asm__ __volatile__ ( \
  50.         "rdtsc\n\t"             /* Returns the time in EDX:EAX. */ \
  51.         "shl $32, %%rdx\n\t"    /* Shift the upper bits left. */ \
  52.         "or %%rdx, %0"          /* 'Or' in the upper bits. */ \
  53.         : "=a" (*(z)) \
  54.         : \
  55.         : "%rax", "%rdx", "%cc" \
  56. )
  57. #else
  58. #define rdtsc( z ) \
  59. __asm__ __volatile__ ("rdtsc" : "=A" (*(z)))
  60. #endif
  61.  
  62.  
  63. #define magic_l32(_cast_)   ((__typeof__(_cast_))0x00000000ffffffff) //01 02 03 04 05 06 07 08
  64. #define magic_h32(_cast_)   ((__typeof__(_cast_))0xffffffff00000000) //05 06 07 08 01 02 03 04
  65. #define magic_l16(_cast_)   ((__typeof__(_cast_))0x0000ffff0000ffff)
  66. #define magic_h16(_cast_)   ((__typeof__(_cast_))0xffff0000ffff0000) //07 08 05 06 03 04 01 02
  67. #define magic_l8(_cast_)    ((__typeof__(_cast_))0x00ff00ff00ff00ff)
  68. #define magic_h8(_cast_)    ((__typeof__(_cast_))0xff00ff00ff00ff00) //08 07 06 05 04 03 02 01
  69. //MOVBE - Move Data After Swapping Bytes
  70. //returns byteswapped value of _v_, upto 64 bits
  71. #define byteSwapped( _v_ ) ({   \
  72.     _clone_(v,(_v_)); __typeof__(v) rv=(_v_);   \
  73.     if (sizeof(rv) >= 8) { rv = ((uint64_t)v            <<  32) |   ((uint64_t)v            >>  32); }  \
  74.     if (sizeof(rv) >= 4) { rv = ((rv & magic_l16(rv))   <<  16) |   ((rv & magic_h16(rv))   >>  16); }  \
  75.     if (sizeof(rv) >= 2) { rv = ((rv & magic_l8(rv))    <<  8 ) |   ((rv & magic_h8(rv))    >>  8 ); }  \
  76.     rv; \
  77. })
  78.  
  79. static inline uint64_t bswap64(uint64_t x)
  80. {   //  randomzz is 1 GB/s with this with ddr400 memory
  81. #ifdef __x86_64__
  82.     __asm__  __volatile__ ("bswap  %0" : "+r" (x));
  83.     return ( x );
  84. #elif       defined __i486__    || defined __pentium__ || defined __pentiumpro__    || defined __pentium4__ \
  85.          || defined __k8__      || defined __athlon__  || defined __k6__            || defined __nocona__   \
  86.          || defined __core2__   || defined __geode__   || defined __amdfam10__
  87.     __asm__  __volatile__ ("bswap  %%eax\n\t"  
  88.                            "bswap  %%edx\n\t"  
  89.                            "xchg   %%eax, %%edx"
  90.                            : "+A" (x));
  91.     return ( x );
  92. #else
  93.     return byteSwapped( x );
  94. #endif
  95. }
  96.  
  97. //Longitudinal Redundancy Check Sum, returns uint8_t LRC of number
  98. #define LRC8sum(_input_) ({ _clone_(z,_input_); uint8_t sum=z; while(z>>=8)sum+=z; sum; })
  99. //International standard ISO 1155 Longitudinal redundancy check, returns uint8_t LRC of number (unnecessary 2's complement)
  100. #define LRC8(_input_) ({ (LRC8sum(_input_)^0xff)+1; })
  101. //Longitudinal Redundancy Check Sum  of Array
  102. #define LRC8Arraysum(_array_) ({ uint8_t sum=0; \
  103.     for (uint32_t i = 0; i<(arraylen(_array_)); i++)sum+=LRC8sum((_array_)[i]); sum; \
  104. })
  105. #define LRC8Array(_array_) ({ (LRC8Arraysum((_array_))^0xff)+1; })
  106.  
  107. //this function is for generating 8x8 bit random numbers,
  108. //good for filling buffers with random-like data fast
  109. //Simplest, fastest, but still adds some entropy each call...
  110. //returns in fix amount of time
  111. uint64_t randomzb(uint64_t range)
  112. {
  113. uint64_t    t,tt;
  114. static uint64_t    randomzb_seed, lasttime;
  115.     rdtsc(&tt); t = tt;
  116. uint8_t        i;
  117.     if (lasttime==0) {usleep(0);rdtsc(&lasttime);}
  118.     i=(uint8_t)(t^lasttime);    t ^= rol64( randomzb_seed, i );
  119.     randomzb_seed = t;
  120.     lasttime = tt;
  121.     return ( (range) > 0 ) ? ( t % range ) : t;
  122. }
  123. //usleep(0); // before rdtscs improves randomness, but makes it insanely slow
  124.  
  125. //this function is for generating 64 bit random numbers
  126. // adds some entropy each call...
  127. // improved distribution, returns in random amount of time
  128. uint64_t randomzx(uint64_t range)
  129. {
  130. static uint64_t    randomzx_seed, lasttime;
  131. uint64_t    tt;
  132. register uint64_t    t, y, s;
  133. register uint8_t        i=0,j;
  134.     rdtsc(&tt); t = tt;
  135.     s = randomzx_seed;
  136.     if (lasttime==0) {usleep(0);rdtsc(&lasttime);}
  137.     y=t^lasttime;  
  138.     while (y) { j=(y&0b11); i=lasttime&(0b111>>(j));    t^=ror64( s, i ); y>>=(4-j);    }
  139.     t-=tt&0b111; t+=(tt>>3)&0b111;  //make it be able to return 0 and -1
  140.     randomzx_seed = t;
  141.     lasttime = tt;
  142.     return ( (range) > 0 ) ? ( t % range ) : t;
  143. }
  144.  
  145. //use this for better performance
  146. ///randomzb_8() should be better than randomzb(0xff) or randomzb(0)&0xff for uint8_t values
  147. //returns random byte if _range_==0, otherwise, returns value in  (uint8_t)range [0,_range_]
  148. #define randomzb_8(_range_) ( (_range_) > 0 ) ? ( LRC8sum(randomzb(0)) % _range_ ) : LRC8sum(randomzb(0))
  149. //use this for better randomness
  150. ///randomzb_8() should be better than randomzb(0xff) or randomzb(0)&0xff for uint8_t values
  151. //returns random byte if _range_==0, otherwise, returns value in  (uint8_t)range [0,_range_]
  152. #define randomzx_8(_range_) ( (_range_) > 0 ) ? ( LRC8sum(randomzx(0)) % _range_ ) : LRC8sum(randomzx(0))
  153.  
  154. //use this for best performance
  155. //returns randomzb floatingpoint value within range [_f1_, _f2_], with type _f1_
  156. #define randomzb_float( _f1_, _f2_ ) ({ \
  157.     (((((_f2_)-(_f1_))*randomzb(0))*((__typeof__(_f1_))1/(__typeof__(_f1_))((uint64_t)~0)))+(_f1_)); \
  158. })
  159. //use this for better randomness and distribution
  160. //returns randomzx floatingpoint value within range [_f1_, _f2_], with type _f1_
  161. #define randomzx_float( _f1_, _f2_ ) ({ \
  162.     (((((_f2_)-(_f1_))*randomzx(0))*((__typeof__(_f1_))1/(__typeof__(_f1_))((uint64_t)~0)))+(_f1_)); \
  163. })
  164.  
  165. int main(){
  166.     uint64_t i,rz;
  167.     for (i = 0; i < 256; i++){  printf("randomzb(0)=%llu\n", randomzb(0));  }  
  168.     for (i = 0; i < 256; i++){  printf("randomzb(0)&0xff=%llu\n", randomzb(0)&0xff);    }  
  169.     for (i = 0; i < 256; i++){  printf("randomzb(0xff)=%llu, randomzb_8()=%u\n", randomzb(0xff), randomzb_8(0));    }  
  170.  
  171.     for (i = 0; i < 256; i++){  printf("randomzx(0)=%llu\n", randomzx(0));  }  
  172.     for (i = 0; i < 256; i++){  printf("randomzx(0)&0xff=%llu\n", randomzx(0)&0xff);    }  
  173.     for (i = 0; i < 256; i++){  printf("randomzx(0xff)=%llu, randomzb_8()=%u\n", randomzx(0xff), randomzb_8(0));    }  
  174.    
  175.     printf("bswap64(%Lx) = %Lx\n", 0x0102030405060708UL, bswap64(0x0102030405060708UL));
  176. uint64_t tsum = randomzb(0);
  177.     printf("LRC8(%llu) = %u\n", tsum, LRC8(tsum));     
  178. uint8_t inputByteArray[13];
  179. printf("array{");
  180. for (i = 0; i < 13; i++){ inputByteArray[i] = randomzb(0xff); printf("%u", inputByteArray[i]); if (i>=12) continue; printf(", ");}
  181.     printf("};\nLRC8Array(array)=%u; LRC8Arraysum(array)=%u\n", LRC8Array(inputByteArray), LRC8Arraysum(inputByteArray));      
  182.    
  183.     printf("randomzb_float(%.7g, %.7g) = %.7g\n", (float32_t)0.0, (float32_t)1.0, randomzb_float((float32_t)0.0,(float32_t)1.0));      
  184.     printf("randomzb_float(%.16g, %.16g) = %.16g\n", (float64_t)1.0, (float64_t)2.0, randomzb_float((float64_t)1.0,(float64_t)2.0));       
  185.     printf("randomzb_float(%.19Lg, %.19Lg) = %.19Lg\n", (float80_t)-1.0, (float80_t)1.0, randomzb_float((float80_t)-1.0,(float80_t)1.0));      
  186.     float80_t trf=1;
  187.     // returns fast even downto 1e-8, <1e-9 in ~ 20s? <1e-10 unpredictable ?10s or more, minutes?
  188.     while ((trf>(float80_t)1e-7)||(trf<(float80_t)-1e-7)) trf=randomzb_float((float80_t)-1.0,(float80_t)1.0);
  189.     printf("randomzb_float(-1, 1) = %.19Lg\n", trf);
  190.     i=0;
  191.    
  192.     printf("wait for randomzx(0) be %Lu...",(uint64_t)~0>>1);           fflush(stdout); while ((rz=randomzx(0))!=(uint64_t)~0>>1) i++;printf("#%llu randomzx(0)=%llu\n", i,rz ); i=0;
  193.     printf("wait for randomzx(0) be 1337...");          fflush(stdout); while ((rz=randomzx(0))!=1337) i++;         printf("#%llu randomzx(0)=%llu\n", i,rz );  i=0;
  194.     printf("wait for randomzx(0) be -1...");            fflush(stdout); while ((rz=randomzx(0))!=(uint64_t)~0) i++; printf("#%llu randomzx(0)=%llu\n", i,rz );  i=0;
  195.     printf("wait for randomzx(0) be less than 127..."); fflush(stdout); while ((rz=randomzx(0))>126) i++;           printf("#%llu randomzx(0)=%llu\n", i,rz ); i=0;
  196.     printf("wait for randomzx(0) be less than 17...");  fflush(stdout); while ((rz=randomzx(0))>16) i++;            printf("#%llu randomzx(0)=%llu\n", i,rz ); i=0;
  197.     printf("wait for randomzx(0) be less than 9...");   fflush(stdout); while ((rz=randomzx(0))>8) i++;             printf("#%llu randomzx(0)=%llu\n", i,rz ); i=0;
  198.     printf("wait for randomzx(0) be less than 4...");   fflush(stdout); while ((rz=randomzx(0))>4) i++;             printf("#%llu randomzx(0)=%llu\n", i,rz ); i=0;
  199.     printf("wait for randomzx(0) be less than 2...");   fflush(stdout); while ((rz=randomzx(0))>1) i++;             printf("#%llu randomzx(0)=%llu\n", i,rz ); i=0;
  200.     printf("wait for randomzx(0) be 0...");             fflush(stdout); while ((rz=randomzx(0))!=0) i++;            printf("#%llu randomzx(0)=%llu\n", i,rz ); i=0;
  201.    
  202.     uint32_t u8distrib[256] = {0};
  203.     printf("randomzb_8(0) distribution test, 100M samples...\n");fflush(stdout);
  204.     for (i = 0; i < 100000000; i++) {   u8distrib[randomzb_8(0)]++; }
  205.     for (i = 0; i < 256; i++)   {   printf("%Lu=#%u\n", i, u8distrib[i]);   }
  206.     for (i = 0; i < 256; i++)   {   u8distrib[i]=0; }
  207.     printf("randomzx_8(0) distribution test, 100M samples...\n");fflush(stdout);
  208.     for (i = 0; i < 100000000; i++) {   u8distrib[randomzx_8(0)]++; }
  209.     for (i = 0; i < 256; i++)   {   printf("%Lu=#%u\n", i, u8distrib[i]);   }
  210.  
  211. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top