randomkit.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /* Random kit 1.3 */
  2. /*
  3. * Copyright (c) 2003-2005, Jean-Sebastien Roy ([email protected])
  4. *
  5. * The rk_random and rk_seed functions algorithms and the original design of
  6. * the Mersenne Twister RNG:
  7. *
  8. * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
  9. * All rights reserved.
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions
  13. * are met:
  14. *
  15. * 1. Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. *
  18. * 2. Redistributions in binary form must reproduce the above copyright
  19. * notice, this list of conditions and the following disclaimer in the
  20. * documentation and/or other materials provided with the distribution.
  21. *
  22. * 3. The names of its contributors may not be used to endorse or promote
  23. * products derived from this software without specific prior written
  24. * permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  27. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  28. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  29. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  30. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  31. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  32. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  33. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  34. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  35. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  36. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * Original algorithm for the implementation of rk_interval function from
  39. * Richard J. Wagner's implementation of the Mersenne Twister RNG, optimised by
  40. * Magnus Jonsson.
  41. *
  42. * Constants used in the rk_double implementation by Isaku Wada.
  43. *
  44. * Permission is hereby granted, free of charge, to any person obtaining a
  45. * copy of this software and associated documentation files (the
  46. * "Software"), to deal in the Software without restriction, including
  47. * without limitation the rights to use, copy, modify, merge, publish,
  48. * distribute, sublicense, and/or sell copies of the Software, and to
  49. * permit persons to whom the Software is furnished to do so, subject to
  50. * the following conditions:
  51. *
  52. * The above copyright notice and this permission notice shall be included
  53. * in all copies or substantial portions of the Software.
  54. *
  55. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  56. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  57. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  58. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  59. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  60. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  61. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  62. */
  63. #include <stddef.h>
  64. #include <stdio.h>
  65. #include <stdlib.h>
  66. #include <errno.h>
  67. #include <limits.h>
  68. #include <math.h>
  69. #include <neatogen/randomkit.h>
  70. void
  71. rk_seed(unsigned long seed, rk_state *state)
  72. {
  73. int pos;
  74. seed &= 0xffffffffUL;
  75. /* Knuth's PRNG as used in the Mersenne Twister reference implementation */
  76. for (pos = 0; pos < RK_STATE_LEN; pos++) {
  77. state->key[pos] = seed;
  78. seed = (1812433253UL * (seed ^ (seed >> 30)) + pos + 1) & 0xffffffffUL;
  79. }
  80. state->pos = RK_STATE_LEN;
  81. }
  82. /* Magic Mersenne Twister constants */
  83. #define N 624
  84. #define M 397
  85. #define MATRIX_A 0x9908b0dfUL
  86. #define UPPER_MASK 0x80000000UL
  87. #define LOWER_MASK 0x7fffffffUL
  88. /* Slightly optimised reference implementation of the Mersenne Twister */
  89. unsigned long
  90. rk_random(rk_state *state)
  91. {
  92. unsigned long y;
  93. if (state->pos == RK_STATE_LEN) {
  94. int i;
  95. for (i = 0; i < N - M; i++) {
  96. y = (state->key[i] & UPPER_MASK) | (state->key[i+1] & LOWER_MASK);
  97. state->key[i] = state->key[i+M] ^ (y>>1) ^ (-(y & 1) & MATRIX_A);
  98. }
  99. for (; i < N - 1; i++) {
  100. y = (state->key[i] & UPPER_MASK) | (state->key[i+1] & LOWER_MASK);
  101. state->key[i] = state->key[i+(M-N)] ^ (y>>1) ^ (-(y & 1) & MATRIX_A);
  102. }
  103. y = (state->key[N - 1] & UPPER_MASK) | (state->key[0] & LOWER_MASK);
  104. state->key[N - 1] = state->key[M - 1] ^ (y >> 1) ^ (-(y & 1) & MATRIX_A);
  105. state->pos = 0;
  106. }
  107. y = state->key[state->pos++];
  108. /* Tempering */
  109. y ^= (y >> 11);
  110. y ^= (y << 7) & 0x9d2c5680UL;
  111. y ^= (y << 15) & 0xefc60000UL;
  112. y ^= (y >> 18);
  113. return y;
  114. }
  115. /// returns a random unsigned long between 0 and `ULONG_MAX` inclusive
  116. static unsigned long rk_ulong(rk_state *state) {
  117. #if ULONG_MAX <= 0xffffffffUL
  118. return rk_random(state);
  119. #else
  120. return (rk_random(state) << 32) | (rk_random(state));
  121. #endif
  122. }
  123. unsigned long
  124. rk_interval(unsigned long max, rk_state *state)
  125. {
  126. unsigned long mask = max, value;
  127. if (max == 0) {
  128. return 0;
  129. }
  130. /* Smallest bit mask >= max */
  131. mask |= mask >> 1;
  132. mask |= mask >> 2;
  133. mask |= mask >> 4;
  134. mask |= mask >> 8;
  135. mask |= mask >> 16;
  136. #if ULONG_MAX > 0xffffffffUL
  137. mask |= mask >> 32;
  138. #endif
  139. /* Search a random value in [0..mask] <= max */
  140. #if ULONG_MAX > 0xffffffffUL
  141. if (max <= 0xffffffffUL) {
  142. while ((value = (rk_random(state) & mask)) > max);
  143. }
  144. else {
  145. while ((value = (rk_ulong(state) & mask)) > max);
  146. }
  147. #else
  148. while ((value = (rk_ulong(state) & mask)) > max);
  149. #endif
  150. return value;
  151. }