javarnd.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #ifndef JAVARND_H_
  2. #define JAVARND_H_
  3. #include <stdint.h>
  4. /********************** C copy of the Java Random methods **********************
  5. */
  6. static inline void setSeed(int64_t *seed)
  7. {
  8. *seed = (*seed ^ 0x5deece66d) & ((1LL << 48) - 1);
  9. }
  10. static inline int next(int64_t *seed, const int bits)
  11. {
  12. *seed = (*seed * 0x5deece66d + 0xb) & ((1LL << 48) - 1);
  13. return (int) (*seed >> (48 - bits));
  14. }
  15. static inline int nextInt(int64_t *seed, const int n)
  16. {
  17. int bits, val;
  18. const int m = n - 1;
  19. if((m & n) == 0) return (int) ((n * (int64_t)next(seed, 31)) >> 31);
  20. do {
  21. bits = next(seed, 31);
  22. val = bits % n;
  23. }
  24. while (bits - val + m < 0);
  25. return val;
  26. }
  27. static inline int64_t nextLong(int64_t *seed)
  28. {
  29. return ((int64_t) next(seed, 32) << 32) + next(seed, 32);
  30. }
  31. static inline float nextFloat(int64_t *seed)
  32. {
  33. return next(seed, 24) / (float) (1 << 24);
  34. }
  35. static inline double nextDouble(int64_t *seed)
  36. {
  37. return (((int64_t) next(seed, 26) << 27) + next(seed, 27)) / (double) (1LL << 53);
  38. }
  39. /* A macro to generate the ideal assembly for X = nextInt(S, 24)
  40. * This is a macro and not an inline function, as many compilers can make use
  41. * of the additional optimisation passes for the surrounding code.
  42. */
  43. #define JAVA_NEXT_INT24(S,X) \
  44. do { \
  45. int64_t a = (1ULL << 48) - 1; \
  46. int64_t c = 0x5deece66dLL * (S); \
  47. c += 11; a &= c; \
  48. (S) = a; \
  49. a >>= 17; \
  50. c = 0xaaaaaaab * a; \
  51. c >>= 36; \
  52. (X) = (int)a - (int)(c << 3) * 3; \
  53. } while (0)
  54. /* skipNextN
  55. * ---------
  56. * Jumps forwards in the random number sequence by simulating 'n' calls to next.
  57. */
  58. static inline void skipNextN(int64_t *seed, const int n)
  59. {
  60. int i;
  61. for (i = 0; i < n; i++) *seed = (*seed * 0x5deece66d + 0xb);
  62. *seed &= 0xffffffffffff;
  63. }
  64. /* invSeed48
  65. * ---------
  66. * Returns the previous 48-bit seed which will generate 'nseed'.
  67. * The upper 16 bits are ignored, both here and in the generator.
  68. */
  69. static inline int64_t invSeed48(int64_t nseed)
  70. {
  71. const int64_t x = 0x5deece66d;
  72. const int64_t xinv = 0xdfe05bcb1365LL;
  73. const int64_t y = 0xbLL;
  74. const int64_t m48 = 0xffffffffffffLL;
  75. int64_t a = nseed >> 32;
  76. int64_t b = nseed & 0xffffffffLL;
  77. if (b & 0x80000000LL) a++;
  78. int64_t q = ((b << 16) - y - (a << 16)*x) & m48;
  79. int64_t k;
  80. for (k = 0; k <= 5; k++)
  81. {
  82. int64_t d = (x - (q + (k << 48))) % x;
  83. d = (d + x) % x; // force the modulo and keep it positive
  84. if (d < 65536)
  85. {
  86. int64_t c = ((q + d) * xinv) & m48;
  87. if (c < 65536)
  88. {
  89. return ((((a << 16) + c) - y) * xinv) & m48;
  90. }
  91. }
  92. }
  93. return -1;
  94. }
  95. #endif /* JAVARND_H_ */