gsl_rng__slatec.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /* rng/slatec.c
  2. *
  3. * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 James Theiler, Brian Gough
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. */
  19. /**
  20. * ======================================================================
  21. * NIST Guide to Available Math Software.
  22. * Source for module RAND from package CMLIB.
  23. * Retrieved from TIBER on Fri Oct 11 11:43:42 1996.
  24. * ======================================================================
  25. FUNCTION RAND(R)
  26. C***BEGIN PROLOGUE RAND
  27. C***DATE WRITTEN 770401 (YYMMDD)
  28. C***REVISION DATE 820801 (YYMMDD)
  29. C***CATEGORY NO. L6A21
  30. C***KEYWORDS RANDOM NUMBER,SPECIAL FUNCTION,UNIFORM
  31. C***AUTHOR FULLERTON, W., (LANL)
  32. C***PURPOSE Generates a uniformly distributed random number.
  33. C***DESCRIPTION
  34. C
  35. C This pseudo-random number generator is portable among a wide
  36. C variety of computers. RAND(R) undoubtedly is not as good as many
  37. C readily available installation dependent versions, and so this
  38. C routine is not recommended for widespread usage. Its redeeming
  39. C feature is that the exact same random numbers (to within final round-
  40. C off error) can be generated from machine to machine. Thus, programs
  41. C that make use of random numbers can be easily transported to and
  42. C checked in a new environment.
  43. C The random numbers are generated by the linear congruential
  44. C method described, e.g., by Knuth in Seminumerical Methods (p.9),
  45. C Addison-Wesley, 1969. Given the I-th number of a pseudo-random
  46. C sequence, the I+1 -st number is generated from
  47. C X(I+1) = (A*X(I) + C) MOD M,
  48. C where here M = 2**22 = 4194304, C = 1731 and several suitable values
  49. C of the multiplier A are discussed below. Both the multiplier A and
  50. C random number X are represented in double precision as two 11-bit
  51. C words. The constants are chosen so that the period is the maximum
  52. C possible, 4194304.
  53. C In order that the same numbers be generated from machine to
  54. C machine, it is necessary that 23-bit integers be reducible modulo
  55. C 2**11 exactly, that 23-bit integers be added exactly, and that 11-bit
  56. C integers be multiplied exactly. Furthermore, if the restart option
  57. C is used (where R is between 0 and 1), then the product R*2**22 =
  58. C R*4194304 must be correct to the nearest integer.
  59. C The first four random numbers should be .0004127026,
  60. C .6750836372, .1614754200, and .9086198807. The tenth random number
  61. C is .5527787209, and the hundredth is .3600893021 . The thousandth
  62. C number should be .2176990509 .
  63. C In order to generate several effectively independent sequences
  64. C with the same generator, it is necessary to know the random number
  65. C for several widely spaced calls. The I-th random number times 2**22,
  66. C where I=K*P/8 and P is the period of the sequence (P = 2**22), is
  67. C still of the form L*P/8. In particular we find the I-th random
  68. C number multiplied by 2**22 is given by
  69. C I = 0 1*P/8 2*P/8 3*P/8 4*P/8 5*P/8 6*P/8 7*P/8 8*P/8
  70. C RAND= 0 5*P/8 2*P/8 7*P/8 4*P/8 1*P/8 6*P/8 3*P/8 0
  71. C Thus the 4*P/8 = 2097152 random number is 2097152/2**22.
  72. C Several multipliers have been subjected to the spectral test
  73. C (see Knuth, p. 82). Four suitable multipliers roughly in order of
  74. C goodness according to the spectral test are
  75. C 3146757 = 1536*2048 + 1029 = 2**21 + 2**20 + 2**10 + 5
  76. C 2098181 = 1024*2048 + 1029 = 2**21 + 2**10 + 5
  77. C 3146245 = 1536*2048 + 517 = 2**21 + 2**20 + 2**9 + 5
  78. C 2776669 = 1355*2048 + 1629 = 5**9 + 7**7 + 1
  79. C
  80. C In the table below LOG10(NU(I)) gives roughly the number of
  81. C random decimal digits in the random numbers considered I at a time.
  82. C C is the primary measure of goodness. In both cases bigger is better.
  83. C
  84. C LOG10 NU(I) C(I)
  85. C A I=2 I=3 I=4 I=5 I=2 I=3 I=4 I=5
  86. C
  87. C 3146757 3.3 2.0 1.6 1.3 3.1 1.3 4.6 2.6
  88. C 2098181 3.3 2.0 1.6 1.2 3.2 1.3 4.6 1.7
  89. C 3146245 3.3 2.2 1.5 1.1 3.2 4.2 1.1 0.4
  90. C 2776669 3.3 2.1 1.6 1.3 2.5 2.0 1.9 2.6
  91. C Best
  92. C Possible 3.3 2.3 1.7 1.4 3.6 5.9 9.7 14.9
  93. C
  94. C Input Argument --
  95. C R If R=0., the next random number of the sequence is generated.
  96. C If R .LT. 0., the last generated number will be returned for
  97. C possible use in a restart procedure.
  98. C If R .GT. 0., the sequence of random numbers will start with
  99. C the seed R mod 1. This seed is also returned as the value of
  100. C RAND provided the arithmetic is done exactly.
  101. C
  102. C Output Value --
  103. C RAND a pseudo-random number between 0. and 1.
  104. C***REFERENCES (NONE)
  105. C***ROUTINES CALLED (NONE)
  106. C***END PROLOGUE RAND
  107. DATA IA1, IA0, IA1MA0 /1536, 1029, 507/
  108. DATA IC /1731/
  109. DATA IX1, IX0 /0, 0/
  110. C***FIRST EXECUTABLE STATEMENT RAND
  111. IF (R.LT.0.) GO TO 10
  112. IF (R.GT.0.) GO TO 20
  113. C
  114. C A*X = 2**22*IA1*IX1 + 2**11*(IA1*IX1 + (IA1-IA0)*(IX0-IX1)
  115. C + IA0*IX0) + IA0*IX0
  116. C
  117. IY0 = IA0*IX0
  118. IY1 = IA1*IX1 + IA1MA0*(IX0-IX1) + IY0
  119. IY0 = IY0 + IC
  120. IX0 = MOD (IY0, 2048)
  121. IY1 = IY1 + (IY0-IX0)/2048
  122. IX1 = MOD (IY1, 2048)
  123. C
  124. 10 RAND = IX1*2048 + IX0
  125. RAND = RAND / 4194304.
  126. RETURN
  127. C
  128. 20 IX1 = AMOD(R,1.)*4194304. + 0.5
  129. IX0 = MOD (IX1, 2048)
  130. IX1 = (IX1-IX0)/2048
  131. GO TO 10
  132. C
  133. END
  134. **/
  135. #include "gsl__config.h"
  136. #include <stdlib.h>
  137. #include "gsl_rng.h"
  138. static inline unsigned long int slatec_get (void *vstate);
  139. static double slatec_get_double (void *vstate);
  140. static void slatec_set (void *state, unsigned long int s);
  141. typedef struct
  142. {
  143. long int x0, x1;
  144. }
  145. slatec_state_t;
  146. static const long P = 4194304;
  147. static const long a1 = 1536;
  148. static const long a0 = 1029;
  149. static const long a1ma0 = 507;
  150. static const long c = 1731;
  151. static inline unsigned long int
  152. slatec_get (void *vstate)
  153. {
  154. long y0, y1;
  155. slatec_state_t *state = (slatec_state_t *) vstate;
  156. y0 = a0 * state->x0;
  157. y1 = a1 * state->x1 + a1ma0 * (state->x0 - state->x1) + y0;
  158. y0 = y0 + c;
  159. state->x0 = y0 % 2048;
  160. y1 = y1 + (y0 - state->x0) / 2048;
  161. state->x1 = y1 % 2048;
  162. return state->x1 * 2048 + state->x0;
  163. }
  164. static double
  165. slatec_get_double (void *vstate)
  166. {
  167. return slatec_get (vstate) / 4194304.0 ;
  168. }
  169. static void
  170. slatec_set (void *vstate, unsigned long int s)
  171. {
  172. slatec_state_t *state = (slatec_state_t *) vstate;
  173. /* Only eight seeds are permitted. This is pretty limiting, but
  174. at least we are guaranteed that the eight sequences are different */
  175. s = s % 8;
  176. s *= P / 8;
  177. state->x0 = s % 2048;
  178. state->x1 = (s - state->x0) / 2048;
  179. }
  180. static const gsl_rng_type slatec_type =
  181. {"slatec", /* name */
  182. 4194303, /* RAND_MAX */
  183. 0, /* RAND_MIN */
  184. sizeof (slatec_state_t),
  185. &slatec_set,
  186. &slatec_get,
  187. &slatec_get_double};
  188. const gsl_rng_type *gsl_rng_slatec = &slatec_type;