fork download
  1. // Ranlux24 PRNG. (2.01)
  2. // Chaotic with long period but slow due to discard.
  3.  
  4. #include <stdlib.h>
  5. #include <limits.h>
  6. #include <assert.h>
  7. #include <stdio.h>
  8. #include <time.h>
  9.  
  10. // Utility.
  11.  
  12. #define BITS(x) \
  13.   (sizeof(x) * CHAR_BIT)
  14.  
  15. #define UNLIKELY(cond) \
  16.   __builtin_expect(!!(cond), 0)
  17.  
  18. #define NEW_T(T, n) \
  19.   ((T *) allocate(n * sizeof(T)))
  20.  
  21. void *allocate(size_t n)
  22. {
  23. void *r = malloc(n);
  24. assert(r != 0 || n == 0);
  25. return r;
  26. }
  27.  
  28. // Ranlux24.
  29.  
  30. typedef struct {
  31. int *x, c, i, j;
  32. } Ranlux24;
  33.  
  34. static inline int next(int *x, int i_s, int i_r, int *carry)
  35. {
  36. int y = x[i_s] - x[i_r] - *carry;
  37. *carry = -(y >> (BITS(int) - 1));
  38. return y & 0xFFFFFF;
  39. }
  40.  
  41. static int subtract_with_carry_next(Ranlux24 *self)
  42. {
  43. self->i += 1;
  44. int *x = self->x, i = self->i;
  45.  
  46. if (UNLIKELY(i >= 24))
  47. {
  48. int c = self->c;
  49. for (i = 0; i < 10; i++)
  50. x[i] = next(x, i + 14, i, &c);
  51. for (i = 10; i < 24; i++)
  52. x[i] = next(x, i - 10, i, &c);
  53. self->c = c;
  54. self->i = i = 0;
  55. }
  56. return x[i];
  57. }
  58.  
  59. static void subtract_with_carry_discard(Ranlux24 *self, int n)
  60. {
  61. for (int i = 0; i < n; i++)
  62. subtract_with_carry_next(self);
  63. }
  64.  
  65. int ranlux24_next(Ranlux24 *self)
  66. {
  67. if (self->j == 0)
  68. {
  69. subtract_with_carry_discard(self, 223 - 23);
  70. self->j = 23;
  71. }
  72. self->j -= 1;
  73. return subtract_with_carry_next(self);
  74. }
  75.  
  76. void ranlux24_discard(Ranlux24 *self, int n)
  77. {
  78. for (int i = 0; i < n; i++)
  79. ranlux24_next(self);
  80. }
  81.  
  82. void ranlux24_delete(Ranlux24 *self)
  83. {
  84. if (self != 0)
  85. {
  86. free(self->x);
  87. free(self);
  88. }
  89. }
  90.  
  91. Ranlux24 *ranlux24_new(unsigned int seed)
  92. {
  93. Ranlux24 *self = NEW_T(Ranlux24, 1);
  94. self->x = NEW_T(int, 24);
  95. self->c = 0;
  96. self->i = 24-1;
  97. self->j = 23;
  98.  
  99. unsigned short rs[] = {0x330E, seed, seed>>16};
  100. for (int i = 0; i < 24; i++)
  101. self->x[i] = nrand48(rs) & 0xFFFFFF;
  102. return self;
  103. }
  104.  
  105. // Main.
  106.  
  107. double clock_now(void)
  108. {
  109. struct timespec now;
  110. clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &now);
  111. return now.tv_sec + now.tv_nsec / 1.0E+09;
  112. }
  113.  
  114. int main(void)
  115. {
  116. unsigned int seed = time(0);
  117. Ranlux24 *engine = ranlux24_new(seed);
  118.  
  119. for (int i = 0; i < 24; i++)
  120. {
  121. int r = ranlux24_next(engine);
  122. printf("%d\n", r);
  123. }
  124.  
  125. int n = 10000000;
  126. double t = clock_now();
  127. ranlux24_discard(engine, n);
  128. printf("Elapsed: %.9fs\n", clock_now() - t);
  129.  
  130. ranlux24_delete(engine);
  131. return 0;
  132. }
Success #stdin #stdout 0.31s 5288KB
stdin
Standard input is empty
stdout
12179220
5173598
13775569
1073511
13529616
13304922
2045120
12491779
16628999
6749568
3109715
10244510
3457060
2366590
16412
13737503
9253003
7897636
6031014
182086
9037632
14262199
12379601
1966982
Elapsed: 0.305485274s