home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume28 / mrandom-3.0 / part03 < prev    next >
Text File  |  1994-05-06  |  98KB  |  2,893 lines

  1. Newsgroups: comp.sources.unix
  2. From: cthombor@theory.lcs.mit.edu (Clark D. Thomborson)
  3. Subject: v28i029: mrandom-3.0 - random number generator with persistent state, Part03/06
  4. References: <1.768285901.18944@gw.home.vix.com>
  5. Sender: unix-sources-moderator@gw.home.vix.com
  6. Approved: vixie@gw.home.vix.com
  7.  
  8. Submitted-By: cthombor@theory.lcs.mit.edu (Clark D. Thomborson)
  9. Posting-Number: Volume 28, Issue 29
  10. Archive-Name: mrandom-3.0/part03
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 3 (of 6)."
  19. # Contents:  doc/mrandom.txt src/mrandom.c
  20. # Wrapped by vixie@gw.home.vix.com on Fri May  6 21:42:55 1994
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'doc/mrandom.txt' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'doc/mrandom.txt'\"
  24. else
  25. echo shar: Extracting \"'doc/mrandom.txt'\" \(50066 characters\)
  26. sed "s/^X//" >'doc/mrandom.txt' <<'END_OF_FILE'
  27. X        Massachusetts Institute of Technology
  28. X               77 Massachusetts Avenue
  29. X                Cambridge, MA 02139
  30. X
  31. X
  32. X              mrandom 3.0 User's Manual
  33. X
  34. X
  35. X                by
  36. X
  37. X
  38. X              Robert Plotkin
  39. X
  40. X
  41. X
  42. X    Department of Electrical Engineering and Computer Science
  43. X
  44. X                 May 1993
  45. X
  46. X
  47. X1 Introduction
  48. X--------------
  49. X--------------
  50. X
  51. XThe mrandom package contains a library of routines for using random
  52. Xnumber generators (RNGs) in C in the Unix 4.3bsd environment.  This
  53. XUser's Manual is designed as a guide for programmers who wish to use the
  54. Xmrandom package within their own programs.  The current version of
  55. Xmrandom (version 3.0) is a major rewrite of mrandom version 2.1,
  56. Xreleased by Clark Thomborson in July 1992 (available via anonymous
  57. Xftp from theory.lcs.mit.edu).  The package now provides:
  58. X
  59. X* A standardized interface to many simultaneously-active RNGs,
  60. X* A standardized, and unbiased, method for generating random
  61. Xintegers in the range 0..m-1,
  62. X* A standardized method for generating floating point numbers
  63. Xuniformly distributed in [0.0, 1.0),
  64. X* Two standardized methods for generating pseudorandom bit
  65. Xstreams,
  66. X* Time-efficient vectorized calls, returning multiple uniform
  67. Xvariates,
  68. X* Buffered and unbuffered calls for efficient generation of
  69. Xpseudorandom generates in both large and small quantities,
  70. X* The ability to ``split'' RNGs to produce parallel output streams
  71. Xusing the ``leapfrog'' method,
  72. X* A shorthand notation for completely specifying the
  73. Xalgorithm and current state of an RNG, in an 80-character human-
  74. Xreadable ASCII string,
  75. X* A method for reconstructing an RNG state from its shorthand
  76. Xnotation,
  77. X* A standardized method for adding new RNGs to the package,
  78. Xand
  79. X* A file-I/O interface allowing fast saves and restarts of RNG state
  80. Xvectors.
  81. X
  82. XYou can obtain the complete distribution of mrandom by anonymous ftp
  83. Xfrom theory.lcs.mit.edu.  Take the file `mrandom.tar.Z' from the
  84. Xdirectory /pub/cthombor/Mrandom/V3.0.  The distribution contains all
  85. Xsource code, instructions, and this manual.
  86. X
  87. XIn addition, the mrandom package includes an unsupported set of routines
  88. Xfor testing the statistical properties of the RNGs in the package.  The
  89. Xroutines are packaged in an executable called mrtest.  Information about
  90. Xmrtest is available in the doc/mrtest directory of the distribution.
  91. XAlthough mrtest is included in the current distribution, it is not
  92. Xsupported.
  93. X
  94. XQuestions, comments, bug reports, etc. should be sent to Clark
  95. XThomborson at cthombor@ub.d.umn.edu.
  96. X
  97. X2 Files in the Distribution Directory
  98. X-------------------------------------
  99. X-------------------------------------
  100. X
  101. XThe mrandom source code distribution includes the following
  102. Xfiles:
  103. X
  104. Xmakefile
  105. X    The makefile for creating the mrtest program and the
  106. X    mrandom.a library.
  107. XREADME
  108. X    General information about the mrandom package, including
  109. X    changes to the last version.
  110. Xmrandom.c mrandom.h
  111. X    The source and header files for the main mrandom module.
  112. Xbentley.c bentley.h
  113. X    The source and header files for Bentley's version of the
  114. X    generator described in Knuth Vol 2, Section 3.6.
  115. Xpcrand.c pcrand.h
  116. X    The source and header files for the Portable Combined RNG.
  117. Xran0.c ran0.h ran1.c ran1.h ran2.c ran2.h
  118. X    The source and header files for Press and Teukolsky's ran0,
  119. X    ran1, and ran2.
  120. Xultra.c ultra.h
  121. X    The source and header files for Marsaglia's Ultra generator.
  122. Xmrtest.c
  123. X    The mrtest source file.
  124. Xxsq.c xsq.h
  125. X    Code used by mrtest.
  126. Xrngs.h
  127. X    The header file for the UNIX RNGs and the trivial RNG.
  128. Xnewrng.c newrng.h
  129. X    Source and header file templates for a new RNG.
  130. Xmrandom.3
  131. X    The man pages for mrandom.
  132. Xmrtest.1
  133. X    The man pages for mrtest.
  134. Xscript
  135. X    A test script for mrtest.
  136. Xmrandom.tex
  137. X    The latex source for this manual.
  138. Xlatexinfo.sty
  139. X    The style file needed to latex this manual.
  140. Xmrandom.txt
  141. X    Plain ASCII text version of this manual.
  142. Xmrandom.ps
  143. X    PostScript version of this manual.
  144. X
  145. X3 Installing mrandom
  146. X--------------------
  147. X--------------------
  148. X
  149. XPreparing the mrandom package for use by other programs is
  150. Xsimple.  Merely position yourself in the directory which contains the
  151. Xmrandom files and type:
  152. X
  153. Xmake all
  154. X
  155. XThis will compile all necessary source files and create the mrandom.a
  156. Xlibrary, as well as the mrtest binary executable.
  157. X
  158. XYou can also make either the mrandom.a library or the mrtest executable
  159. Xby typing:
  160. X
  161. Xmake mrandom.a
  162. X
  163. Xor
  164. X
  165. Xmake mrtest
  166. X
  167. Xrespectively.
  168. X
  169. XTo save disk space, various intermediate object files can be removed
  170. Xwith:
  171. X
  172. Xmake clean
  173. X
  174. XThe system can be restored to its original state with:
  175. X
  176. Xmake realclean
  177. X
  178. XThe mrandom package is written in ANSI C, and should be
  179. Xeasily portable to any UNIX-based system supporting a C language
  180. Xcompiler.  However, when compiling on a new system, confirm that
  181. Xthe long type is represented in 32 bits.
  182. X
  183. X4 What is an RNG?
  184. X-----------------
  185. X-----------------
  186. X
  187. XWithin the mrandom package, an RNG is represented by the RNGdata
  188. Xstructure.  An RNG has several abstract characteristics which are
  189. Xdescribed in this section.  For a more detailed description of the
  190. Xrepresentation of the RNGdata structure in C, see
  191. XAppendix A.
  192. X
  193. XAssociated with every RNG is:
  194. X
  195. X* an algorithm number, which determines which algorithm the RNG
  196. Xuses to produce pseudorandom generates.  For descriptions of the
  197. Xalgorithms which are currently installed in the package, see Appendix B.
  198. X* an ``mrandom algorithm number,'' which determines which
  199. Xalgorithm the mrandomrv routine will use to produce
  200. Xrestricted-range integers when called with the RNG.  (See the
  201. Xdescription of mrandomrv in Section 5.4.2 for more
  202. Xinformation.)
  203. X* a state vector, which contains the current state of the RNG.
  204. X* the size of the state vector.
  205. X* a seed vector, which contains the seeds which were used to
  206. Xseed the RNG.
  207. X* the size of the seed vector.
  208. X* a count of the number of times the RNG has been called since
  209. Xit was initialized.
  210. X* two buffers
  211. X    - a bit buffer for bit generates
  212. X    - a main buffer for all other generates.
  213. XSee Section 5.4.2 for a description of how the two buffers work.
  214. X* a split value, which determines how many generates to skip
  215. Xbetween values which are returned from the RNG.  For a detailed
  216. Xdescription of the split value, see Section 5.4.7.
  217. X* a string containing the human-readable name of the RNG.
  218. X* the range of the RNG, such that the RNG is capable of
  219. Xproducing integers with a maximum value of range-1.
  220. X
  221. X5 Using the mrandom package
  222. X---------------------------
  223. X---------------------------
  224. X
  225. X5.1 Overview of the Library
  226. X
  227. XThis section describes the mrandom library.  The procedures
  228. Xin the library are gathered into the following groups:
  229. X
  230. X* functions for initializing and de-initializing (killing) RNGs
  231. X* functions for returning generates from RNGs
  232. X* functions for saving and restarting RNGs
  233. X* a function for seeding RNGs
  234. X* a function for checking the integrity of RNG state vectors
  235. X* a function for producing a human-readable ASCII description
  236. Xof an RNG
  237. X* functions for examining and modifying characteristics of RNGs
  238. X
  239. X5.2 Return codes from mrandom routines
  240. X
  241. XMost mrandom routines follow one of two conventions for return
  242. Xvalues.
  243. X
  244. XFor those routines which return pointers to an RNGdata
  245. Xstructure:
  246. X
  247. X* A valid pointer to an RNGdata structure is returned upon success.
  248. X* A null pointer is returned upon failure.
  249. X
  250. XFor routines which produce vectors of pseudorandom generates:
  251. X
  252. X* The first cell of the vector is returned upon success.
  253. X* The program aborts upon error.
  254. X
  255. XFor all other routines:
  256. X
  257. X* A 0 or -1 is returned upon failure.
  258. X
  259. XDetails are provided in the description of the mrandom library
  260. Xin Section 5.4.
  261. X
  262. X5.3 Linking
  263. X
  264. XIn order to use the mrandom library of routines in your programs
  265. Xyou must:
  266. X
  267. X* Link the mrandom.a library with your program.  This will
  268. Xtypically involve merely including the library on your compiler's
  269. Xcommand line, such as:
  270. X
  271. Xcc myprog.c mrandom.a
  272. X
  273. XSince mrandom uses some UNIX mathematical functions, you may also need
  274. Xto link a math library with your program, as in the following:
  275. X
  276. Xcc myprog.c mrandom.a -lm
  277. X
  278. XCheck the documentation for your C compiler for details.
  279. X* Include the following line at the top of your source file:
  280. X
  281. X#include "mrandom.h"
  282. X
  283. X5.4 The mrandom library
  284. X
  285. X5.4.1 Initialization and De-Initialization
  286. X
  287. XIn order to use an RNG, it must first be initialized.  This is
  288. Xaccomplished by first declaring a pointer to an RNGdata structure, and
  289. Xthen calling init_rng, which allocates memory for the RNG and readies it
  290. Xfor use by the other routines in the package.
  291. X
  292. X    RNGdata *init_rng(alg,mrandom_alg,seed,count1,count2,bufsize)
  293. X    long alg;
  294. X    long mrandom_alg;
  295. X    long *seed;
  296. X    long count1, count2;
  297. X    long bufsize;
  298. X
  299. X    int kill_rng(rng)
  300. X    RNGdata *rng;
  301. X
  302. Xinit_rng returns a pointer to an initialized RNG.  A pointer returned by
  303. Xinit_rng is valid for use by all other mrandom routines.
  304. X
  305. Xalg is the number of the algorithm to be used by the RNG.  (See Appendix
  306. XB.)
  307. X
  308. Xmrandom_alg is the algorithm to be used by mrandomrv when called with
  309. Xthe RNG.  (See Section 5.4.2.)
  310. X
  311. Xseed is a pointer to a seed vector to be used to seed the RNG.
  312. X(See Section 5.4.4.)
  313. X
  314. Xcount1 and count2 determine the number of initial values to be generated
  315. Xby the RNG and then discarded, according to the formula:
  316. X
  317. Xnumber to discard = count1 + BILLION*count2,
  318. X
  319. Xwhere BILLION is defined in 'mrandom.h' as the decimal constant
  320. X1000000000.
  321. X
  322. Xbufsize is the size of the RNG's main buffer.  A non-positive value of
  323. Xbufsize will be interpreted as a value of 1.  (See Section 5.4.2 for
  324. Xmore information on buffering.)
  325. X
  326. Xkill_rng destroys the RNG, making it invalid for use.  This procedure
  327. Xde-allocates the space used by the RNG, and should therefore be used to
  328. Xkill RNGs which will no longer be used.
  329. X
  330. XDo *not* use an RNGdata pointer which points to an active RNG
  331. Xto store the return value of init_rng.  In order to initialize an
  332. XRNG, you should either:
  333. X
  334. X* Declare a new RNGdata pointer, and then use it to store the
  335. Xreturn value of init_rng, as shown in Figure 1.
  336. X
  337. X-----------------------------------------------
  338. XRNGdata *rng;
  339. Xlong seed[1];
  340. X
  341. Xrng=init_rng(2, 0, seed, 10000, 0, 8192);
  342. X
  343. XFigure 1: Proper initialization of an RNG
  344. X-----------------------------------------------
  345. X
  346. X* Use kill_rng to de-initialize an RNGdata pointer which points to an
  347. Xactive RNG, and then use that pointer to store to the return value of
  348. Xinit_rng, as shown in Figure 2.  Figure 3 shows how an RNG should *not
  349. Xbe re-initialized.
  350. X
  351. X-----------------------------------------------
  352. XRNGdata *myrng;
  353. Xlong seed[1];
  354. X
  355. Xseed[0]=12345;
  356. Xmyrng=init_rng(2, 0, seed, 10000, 0, 8192);
  357. Xkill_rng(myrng);
  358. Xmyrng=init_rng(3, 0, seed, 5000, 0, 2048);
  359. X
  360. XFigure 2: Proper re-initialization of an RNG
  361. X-----------------------------------------------
  362. X
  363. X-----------------------------------------------
  364. XRNGdata *myrng;
  365. Xlong seed[1];
  366. X
  367. Xseed[0]=12345;
  368. Xmyrng=init_rng(2, 0, seed, 10000, 0, 8192);
  369. Xmyrng=init_rng(3, 0, seed, 5000, 0, 2048);
  370. X
  371. XFigure 3: Improper re-initialization of an RNG
  372. X-----------------------------------------------
  373. X
  374. X5.4.2 Procedures for Generating Pseudorandom Numbers
  375. X
  376. XAn initialized RNG can be used to generate pseudorandom numbers by using
  377. Xa variety of routines described in this section.
  378. X
  379. XRoutines are provided for producing generates of four types:
  380. X
  381. X* double precision floating point generates in the range [0,1)
  382. X* single precision floating point generates in the range [0,1)
  383. X* long integer generates in the range 0..r-1, where r is the range of
  384. Xthe RNG being used to produce generates
  385. X* long integer generates in the range 0..m-1, for any
  386. X1 <= m < range_rng(rng)
  387. X
  388. XNote that although both single and double precision floats can be
  389. Xreturned by the generate-producing routines, the actual precision of the
  390. Xgenerates produced is determined by the precision of the underlying
  391. Xgenerator being used.  In other words, the difference between routines
  392. Xwhich return generates of type double and those which return generates
  393. Xof type float is merely in the ``packaging'' of the generates, not in
  394. Xthe precision they provide.  Information about the precision of the RNGs
  395. Xcurrently installed in the package is in Appendix B; such information
  396. Xcan also be obtained at run-time through the range_rng routine (see
  397. XSection 5.4.7).  The current version of the package only supports RNGs
  398. Xwith precisions of no more than 32 bits.
  399. X
  400. XBoth buffered and unbuffered routines are provided.  Unbuffered routines
  401. Xcall the underlying RNG only as many times as are needed to produce the
  402. Xrequested number of generates, while buffered routines maintain buffers
  403. Xof generates, so that generates may be produced efficiently even when
  404. Xrequested in small quantities.  Roughly, buffered routines are
  405. Xpreferable when generates are requested one at a time or in small
  406. Xquantities, while unbuffered routines are preferable when generates are
  407. Xrequested in large quantities.  Some other differences between buffered
  408. Xand unbuffered routines are discussed later in this section.  The size
  409. Xof the buffer used by an RNG is determined at the time of the RNG's
  410. Xinitialization; effective buffer sizes will vary from application to
  411. Xapplication.
  412. X
  413. XThe name of a routine denotes the type of the value which the routine
  414. Xreturns and whether the routine is buffered or unbuffered. The first
  415. Xletter of a routine denotes the type of value which it returns: ``d''
  416. Xfor double precision and ``f'' for single precision floating point in
  417. Xthe range [0,1); ``l'' for long integer in the range
  418. X0..(range_rng(rng)-1), and ``b'' for bit (either a 0 or a 1).  If the
  419. Xsecond letter of the routine's name is an ``x'', then the routine is
  420. Xunbuffered.  Otherwise, the routine is buffered.
  421. X
  422. XFor convenience in user programming, we also provide a number of macros
  423. Xthat supply default parameter values.  The last two letters of all our
  424. Xfundamental routines is ``rv''.  This means that they must be provided
  425. Xwith both a pointer to an RNGdata structure and a vector to fill with
  426. Xgenerates from the RNG.  Macros whose names do not contain an ``r'' have
  427. Xthe RNGdata pointer omitted from their parameter list; they use the
  428. Xmost-recently initialized or restarted RNG to produce generates.  Macros
  429. Xwhose names do not contain a ``v'' have the vector and number of
  430. Xgenerates omitted from their parameter list; they produce and return a
  431. Xsingle generate.
  432. X
  433. XAll generating routines abort with a message to stderr if called with an
  434. Xinvalid RNGdata pointer.
  435. X
  436. XBuffering
  437. X
  438. XThe operation of the buffered routines and their interaction with the
  439. Xunbuffered routines requires some elaboration.  Each RNG maintains two
  440. Xseparate buffers: one for buffering bit values (the ``bit buffer''), and
  441. Xone for buffering all other values (the ``main buffer'').  The size of
  442. Xthe main buffer of an RNG is determined at the time of the RNG's
  443. Xinitialization, while the size of the bit buffer is currently fixed at
  444. X32 bits.
  445. X
  446. XConsider a freshly-initialized RNG with a main buffer size of 1000.  A
  447. Xrequest is made for a single generate of type long.  The RNG's buffer
  448. Xgets filled with 1000 generates, and the first such generate is returned
  449. Xto the user.  So the buffer now contains 999 generates.  If another
  450. Xgenerate of type long, double, or float, is requested, a generate will
  451. Xbe pulled from the buffer and returned to the user after being converted
  452. Xto the proper type.  If the user continues to request generates in this
  453. Xway and the main buffer becomes depleted, it will be filled again with
  454. X1000 generates, and so on.
  455. X
  456. XThe unbuffered routines do not interfere with either of the RNG's
  457. Xbuffers.  Again, consider our RNG, with its buffer filled with 1000
  458. Xgenerates.  The user now makes a request for a single unbuffered
  459. Xgenerate.  The underlying RNG will then be called once, returning a
  460. Xsingle generate, leaving our buffer of 1000 generates untouched, and
  461. Xstill ready to be accessed by the buffered routines.  If, in a
  462. Xparticular application, it is necessary to always use consecutive
  463. Xgenerates from an RNG, then that RNG should always be called *either*
  464. Xwith buffered or unbuffered routines, but not with a combination of
  465. Xboth.
  466. X
  467. XThe bit buffer of an RNG operates similarly to the main buffer, with one
  468. Xkey difference: the bit buffer is filled by sequentially retrieving
  469. Xgenerates from the main buffer.  Once again, consider our RNG, with its
  470. Xbuffer filled with 1000 generates, and with its bit buffer empty.  A
  471. Xsingle bit is then requested.  Thirty-two generates will be pulled from
  472. Xthe main buffer, transformed into thirty-two one-bit 0-1 values, then
  473. Xstored in the bit buffer.  (For users who are more concerned with speed
  474. Xthan accuracy, we also provide a ``fast'' bit-buffer call, in which a
  475. Xsingle 32-bit generate from the main buffer is transformed into
  476. Xthirty-two 0-1 variates.  See the descriptions of bxrandom_f and
  477. Xbrandom_f, below.)
  478. X
  479. XUnbuffered and buffered calling procedures
  480. X
  481. X    double dxrandomrv(rng, n, v)
  482. X    double drandomrv(rng, n, v)
  483. X    RNGdata *rng;
  484. X    long n;
  485. X    double v[];
  486. X
  487. X    float fxrandomrv(rng, n, v)
  488. X    float frandomrv(rng, n, v)
  489. X    RNGdata *rng;
  490. X    long n;
  491. X    float v[];
  492. X
  493. X    long lxrandomrv(rng, n, v)
  494. X    long lrandomrv(rng, n, v)
  495. X    RNGdata *rng;
  496. X    long n;
  497. X    long v[];
  498. X
  499. X    int bxrandomrv(rng, n, v)
  500. X    int brandomrv(rng, n, v)
  501. X    RNGdata *rng;
  502. X    long n;
  503. X    int v[];
  504. X
  505. X    int bxrandomrv_f(rng, n, v)
  506. X    int brandomrv_f(rng, n, v)
  507. X    RNGdata *rng;
  508. X    long n;
  509. X    double v[];
  510. X
  511. XThese routines fill the vector v with n generates from rng, and return
  512. Xthe first generate produced (i.e. v[0]).
  513. X
  514. XIf rng is a null pointer, then the most-recently initialized or
  515. Xrestarted RNG is used to produce generates.  If n is 0, then the v
  516. Xparameter need not be provided, and a single generate is produced and
  517. Xreturned.
  518. X
  519. Xbxrandomrv uses one generate from rng to generate each bit.  This
  520. Xroutine is slower than bxrandomrv_f, but returns bits of higher quality.
  521. X
  522. Xbxrandomrv_f uses each generate from rng to produce 32 bits.  Therefore,
  523. Xrequests for bits in other than multiples of 32 will result in bits from
  524. Xthe stream being ``lost'' between calls.  The routine returns -1 if it
  525. Xis called with an RNG whose range is not 2^32.  This routine is faster
  526. Xthan bxrandomrv, but we do not recommend its use, since we know of no
  527. Xone who has rigorously tested such a bit stream.  We gain confidence in
  528. Xour slower bxrandomrv bit stream, in comparison, every time the
  529. Xunderlying generator passes a test sensitive to correlations in the
  530. Xleading digit of its floating point output, or to the most significant
  531. Xbit of its fixed point output.
  532. X
  533. Xbrandomrv_f, the buffered version of bxrandomrv_f, does not exhibit the
  534. Xsame property of ``losing bits'' as does bxrandomrv_f, since bits which
  535. Xare not used in one call to brandomrv_f are stored in the bit buffer and
  536. Xare available for use upon future calls.
  537. X
  538. X    int flush_rng(rng)
  539. X    RNGdata *rng;
  540. X
  541. X    Flushes both of the RNG's buffers.
  542. X
  543. XProcedure for generating integers in a restricted range
  544. X
  545. X    long mrandomrv(rng, m, n, v)
  546. X    RNGdata *rng;
  547. X    long m,n,v[];
  548. X
  549. Xmrandomrv fills the vector v with n generates in the range 0..m-1 using
  550. Xrng, where 1 <= m <= range_rng(rng).  If range_rng(rng) < m, the program
  551. Xaborts with an error.
  552. X
  553. XThe algorithm used by mrandomrv to fill v is set by init_rng or by
  554. Xmralg_rng.  (See Section 5.4.1 and Section 5.4.7.)
  555. X
  556. XAlgorithm 0 is Thomborson's unbiased method, which produces unbiased
  557. Xlong integers in the range [0..m).  The algorithm discards any outputs
  558. Xfrom rng which are larger than r-(r mod m), where r is equal to
  559. Xrange_rng(rng).  At worst, this code will discard (on long-term average)
  560. Xat most one value of r for every one that is useful.  This worst case is
  561. Xonly encountered for extremely large m; for fixed and moderate m, this
  562. Xcode will rarely discard a value, and thus will run essentially as fast
  563. Xas algorithm 1.  When the value of m changes on each call to mrandom,
  564. Xhowever, this code is slower than algorithm 1, due to the necessity of
  565. Xrecomputing r-(r mod m).
  566. X
  567. XThe program aborts with an error message to stderr if rng is behaving so
  568. Xnon-randomly that Algorithm 0 must make an excessive number of calls to
  569. Xrng in order to produce the requested number of generates.
  570. X
  571. XThe program aborts with an error to stderr if mrandomrv is asked to use
  572. XAlgorithm 0 with a value of m for which m > range_rng(rng).
  573. X
  574. X
  575. XAlgorithm 1 is the standard (long)(m*dxrandomr(rng)).  This algorithm
  576. Xmay be biased: for large m, some results may be be more likely than
  577. Xothers.  The bias is (r mod m)/m, which is upper-bounded by 0.1% if m is
  578. Xless than a million and the range r of rng is at least a billion.
  579. X
  580. XWe do not support, and indeed we actively discourage, generating
  581. Xrestricted-range integers with lrandomr(rng)%m.  Many RNGs have poor
  582. Xbehavior under this transformation, most noticeably when m is a power of
  583. X2.  When m is not a power of 2, fixed-point division required by an
  584. X``%'' operation is time-consuming on many workstations.
  585. X
  586. XNOTES
  587. XThe mrandomrv procedure is capable of generating long integers in the
  588. Xfull range of any RNG for which 1 <= range_rng(rng) <= 2^32.  In order
  589. Xto accomplish this, with the parameter m a signed long integer, the
  590. Xfollowing mapping is used:
  591. X
  592. XRange(mrandom(m)) = 0..m-1        if 1 <= m < 2^31
  593. X            0.. 2^32-1      if m=0
  594. X            0..(2^31-m-1)    if -2^31 <= m < 0
  595. X
  596. XMacros are defined for easy calling of mrandomrv with various default
  597. Xparameters.  See Section 5.4.2 for the naming conventions followed by
  598. Xthe macros.
  599. X
  600. X5.4.3 Saving and restarting RNGs
  601. X
  602. XRNGs may be saved to disk files in a human-readable ASCII format and
  603. Xlater restarted.  RNG buffers are not saved, and therefore all restarted
  604. XRNGs have empty buffers, and any data remaining in an RNG's buffer at
  605. Xthe time of its state-save will *not* be reconstructed.
  606. X
  607. X    int save_rng(rng, filename)
  608. X    RNGdata *rng;
  609. X    char *filename;
  610. X
  611. X    RNGdata *restart_rng(filename)
  612. X    char *filename;
  613. X
  614. Xsave_rng saves rng to the ASCII file named filename.
  615. X
  616. Xrestart_rng restarts an RNG from a previously saved statefile.  The
  617. Xrestarted RNG will begin where the saved RNG ``left off.''  As with
  618. Xinit_rng, the RNGdata pointer used to store the restarted RNG *must* be
  619. Xeither a freshly declared pointer or a pointer to a freshly killed RNG
  620. X(see Section 5.4.1).
  621. X
  622. XRNGs may store their state and seed vectors in any of a number of
  623. Xformats, and this is reflected in the format of the state file.
  624. XFigure 4 shows a sample state file of an RNG using the Knuth/Bentley
  625. Xlagged-Fibonnacci generator prand (see Appendix B), which stores its
  626. Xstate and seeds as 32-bit long ints.  Figure 5 shows a sample state
  627. Xfile of an RNG using 4.3bsd nrand48, which stores its state and seeds
  628. Xas 16-bit ints.
  629. X
  630. X--------------------------------------
  631. XRNG statefile for algorithm 2, (Knuth/Bentley prand: lagged Fibbonacci)
  632. XBuffer size = 1024 bytes
  633. XInitial seed table =
  634. X   00000927
  635. XNumber of calls to underlying RNG after seeding = 0 billion + 2000
  636. XNext value in this pseudorandom sequence = 0b64d0ea
  637. XThis RNG returns every 1 generates
  638. XThis RNG uses mrandom algorithm 0
  639. XRNG state table =
  640. X   0911c27a 10641ca0 2ba00807 1aabed0a
  641. X   273ff367 1ab88564 2ae76a9e 2a7e6bc0
  642. X   35c7568e 201b6b04 3ad90695 303208b2
  643. X   1e718896 054c9886 00e8c93f 130a41cb
  644. X   11de97bf 0da54e15 2f4fcca0 0ebb1f70
  645. X   01c195c3 3283980e 37dee108 0893a89b
  646. X   326849b0 167bb45e 19cc9765 33d97b51
  647. X   36b425d1 35704e34 29a638ca 280a086f
  648. X   11dfa5d6 14dcbcc4 2610bdf4 02534109
  649. X   2817daf4 0bcf76ab 19b0a07d 0eebf7f6
  650. X   113c003e 31b996b0 12bab234 05eddb36
  651. X   1ed71381 377742a3 3878e079 2668c922
  652. X   22cc8033 22368c85 18e960ea 2002b06f
  653. X   22ff23e8 251187dc 340c3dcd 00000023
  654. X   00000004
  655. X
  656. XFigure 4: A sample RNG state file for the Knuth/Bentley prand().
  657. X--------------------------------------
  658. X
  659. X--------------------------------------
  660. XRNG statefile for algorithm 4, (4.3bsd nrand48.c: 48-bit multiplicative)
  661. XBuffer size = 8192 bytes
  662. XInitial seed table =
  663. X   0096   b43f   0034   bf15
  664. X
  665. XNumber of calls to underlying RNG after seeding = 0 billion + 11000
  666. XNext value in this pseudorandom sequence = 04a3689e
  667. XThis RNG returns every 1 generates
  668. XThis RNG uses mrandom algorithm 0
  669. XRNG state table =
  670. X   07c5   8f2d   0000   a7d6
  671. X
  672. XFigure 5: A sample RNG state table for nrand48
  673. X--------------------------------------
  674. X
  675. XA few examples of how to save and restart RNGs are displayed in Figure
  676. X6.
  677. X
  678. X--------------------------------------
  679. X/* Proper way to re-initialize an active RNG */
  680. Xmrandom(rng,10,n,v);
  681. Xkill_rng(rng);
  682. Xrng=restart_rng("mystatefile");
  683. X
  684. X/* Proper way to restart an inactive RNG */
  685. XRNGdata *rng;
  686. Xrng=restart_rng("mystatefile");
  687. X
  688. X/* Improper way to restart an active RNG */
  689. Xmrandom(rng,10,n,v);
  690. Xrng=restart_rng("mystatefile");
  691. X
  692. XFigure 6: Examples of saving and restarting RNGs
  693. X--------------------------------------
  694. X
  695. X5.4.4 Seeding
  696. X
  697. XEach RNG is initially seeded during initialization by init_rng.  An RNG
  698. Xmay also be reseeded at any time after initialization.
  699. X
  700. X    void seed_rng(rng,seed)
  701. X     RNGdata *rng;
  702. X     long *seed;
  703. X
  704. Xseed_rng seeds rng with the seed table pointed to by seed.  The RNG's
  705. Xcounter is reset to 0 and its buffers are flushed.
  706. X
  707. X5.4.5 Checking RNG integrity
  708. X
  709. XAn RNG can be checked to see if it has been corrupted or is otherwise
  710. Xnot in proper condition for use.
  711. X
  712. X    int check_rng(rng);
  713. X    RNGdata *rng;
  714. X
  715. Xcheck_rng checks the integrity of the RNG, in order to determine whether
  716. Xit can be used by the other mrandom library routines.
  717. X
  718. X5.4.6 Obtaining a human-readable description of the RNG
  719. X
  720. X    char *describe_rng(rng,rngid)
  721. X    RNGdata *rng;
  722. X    char rngid[RNGIDSTRLEN];
  723. X
  724. Xdescribe_rng places a human-readable description of rng in
  725. Xthe string rngid.  The string has the following format:
  726. X
  727. XRNG state identifier is (alg, mralg: seed1, seed2; count1,count2;
  728. Xbufsize, split)
  729. X
  730. Xwhere
  731. X
  732. X* alg is the number of the algorithm used by rng to generate
  733. Xpseudorandom numbers.  (See Appendix B.)
  734. X* mralg is the number of the algorithm used by
  735. Xmrandomrv when called with rng.  (See Section 5.4.2.)
  736. X* seed1 and seed2 are the first and second entries in trng's seed table.
  737. XIf rng's seed table has more than two entries, only the first two are
  738. Xincluded in its description.  (See Section 5.4.4.)
  739. X* count1 and count2 represent rng's counter.  (See Section 5.4.1.)
  740. X* bufsize is the number of entries in rng's buffer.  (See Section
  741. X5.4.2.)
  742. X* split is rng's current split value.  (See Section 5.4.7.)
  743. X
  744. Xdescribe_rng exits with a message to stderr if called with an invalid
  745. XRNGdata pointer.
  746. X
  747. X5.4.7 Procedures for examining and modifying RNG parameters
  748. X
  749. XProcedures are available for examining and modifying an RNG's parameters
  750. Xonce it has been initialized.
  751. X
  752. X    int mralg_rng(rng, new_value)
  753. X    RNGdata *rng;
  754. X    long new_value;
  755. X
  756. X    int split_rng(rng, new_value)
  757. X    RNGdata *rng;
  758. X    long new_value;
  759. X
  760. X    double range_rng(rng)
  761. X    RNGdata *rng;
  762. X
  763. Xmralg_rng sets rng's mrandom algorithm number (See Section 5.4.2 for
  764. Xinformation on mrandom algorithm numbers).  It returns 0 if new_value is
  765. Xan invalid value.
  766. X
  767. Xsplit_rng sets the split value of rng.  It returns 0 if new_value < 0.
  768. XAn RNG's split value is set to SPLIT_DEF upon initialization.  SPLIT_DEF
  769. Xis #defined in 'mrandom.h', and currently has a value of 0.
  770. X
  771. XThe function of the split value is to simulate one ``branch'' of a
  772. Xgenerator which has been ``split'' into two or more generators.  This is
  773. Xbest illustrated with an example.  Consider an (apparently non-random)
  774. XRNG which returns the raw sequence:
  775. X
  776. X0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ...
  777. X
  778. XThe split value indicates how many elements of the sequence to skip
  779. Xbetween generates.  For example, if our sample RNG were given a split
  780. Xvalue of 1 immediately after initialization, it would then return the following
  781. Xsequence:
  782. X
  783. X0 2 4 6 8 10 ...
  784. X
  785. XA split value of 2 after initialization would produce:
  786. X
  787. X0 3 6 9 12 15 ...
  788. X
  789. XAn RNG may be split at any time after its initialization.  So, for
  790. Xexample, our sample RNG might be initialized and then made to generate
  791. Xthe following values:
  792. X
  793. X0 1 2 3 4 5
  794. X
  795. Xbefore being split with a split value of 3, producing the following
  796. Xgenerates:
  797. X
  798. X6 10 14 18 22 ...
  799. X
  800. XSplitting can be used to create several ``leapfrogged'' RNGs from one
  801. XRNG, as shown in Figure 7.
  802. X
  803. X------------------------------------
  804. XRNGdata *rngs[10];
  805. Xlong seed;
  806. Xint i;
  807. X
  808. Xseed=12345;
  809. Xfor (i=0; i<10; i++) {
  810. X  /* RNG #i gets cycled i times */
  811. X  rng[i]=init_rng(2,0,&seed,i,0,1024);
  812. X  split(rng[i],9);
  813. X}
  814. X
  815. XFigure 7: Creating ``leapfrogged'' RNGs.
  816. X------------------------------------
  817. X
  818. XThis operation may be useful in parallel codes, as in testing an RNG for
  819. Xlong-range correlations.  Unfortunately, our current implementation is
  820. Xinefficient for leapfrogging large numbers of RNGs.  A more efficient
  821. Xmethod may be included in a future version of mrandom.
  822. X
  823. XThe split value affects all of the pseudorandom number generating
  824. Xroutines (See Section 5.4.2).
  825. X
  826. Xrange_rng returns the range of rng.
  827. X
  828. XNOTES
  829. XThese procedures exit with a message to stderr if rng does not
  830. Xpoint to a valid RNGdata structure.
  831. X
  832. X6 Adding new RNGs to the Package
  833. X--------------------------------
  834. X--------------------------------
  835. X
  836. XThis section is designed for the programmer who wishes to add new RNGs
  837. Xto the mrandom package.  The section first describes the routines which
  838. Xmust be provided by the programmer to serve as an interface between the
  839. XRNG and the mrandom package.  It then describes the RNG parameters which
  840. Xmust be defined in a header file for the RNG, and how these parameters
  841. Xare to be incorporated into the code for mrandom itself.  Finally, it
  842. Xdescribes how to remake the mrandom package after adding or modifying
  843. XRNGs.  Appendix B contains descriptions of the ten RNGs installed in the
  844. Xcurrent version of the package.
  845. X
  846. X6.1 Routines Provided by the Programmer
  847. X
  848. XThis section describes routines which must be provided by each RNG in
  849. Xthe package.
  850. X
  851. XThe routines provided by the programmer must manipulate an
  852. XRNGdata structure.  In order to facilitate this, two macros are
  853. Xavailable for accessing an RNG's state and seed vectors:
  854. X
  855. X* RNGstate refers to the RNG's state vector.
  856. X* RNGseed refers to the RNG's seed vector.
  857. X
  858. XThese vectors are one-dimensional C arrays, e.g.  RNGstate[0] is the
  859. Xfirst element in the RNG's state vector, RNGstate[1] is the second
  860. Xelement, etc.  In order to make use of these macros, the name of the
  861. XRNGdata pointer in your routines' parameter lists *must be rng, as shown
  862. Xin the examples in this section.
  863. X
  864. XThe names used as examples in this section begin with ``myrng'';
  865. Xhowever, there are no restrictions on naming of routines provided by an
  866. XRNG.  However, for ease of readability and consistency, we suggest that
  867. Xthe naming conventions used in this section be followed.
  868. X
  869. XThe routines described in this section should be included in a single .c
  870. Xfile.  A template for such a source file, called `newrng.c', is included
  871. Xin the distribution and displayed in Figure 8.
  872. X
  873. XRemember that all RNG state information must be included in the RNGstate
  874. Xfield of the RNGdata structure.  In particular, do *not use global or
  875. Xstatic variables to hold RNG state information.  Doing so will make it
  876. Ximpossible to run several instantiations of your RNG simulataneously.
  877. X
  878. X------------------------------------
  879. X/* newrng.c */
  880. X/* RNG source file template */
  881. X/* Robert Plotkin
  882. X/* 5/3/93 */
  883. X
  884. X#include "newrng.h"
  885. X
  886. X/* Generating procedure */
  887. X/* Only one of the following two procedures should be */
  888. X/* defined, depending on the kind of value that */
  889. X/* your RNG returns */
  890. X
  891. Xlong newrng_lgen(rng)
  892. XRNGdata *rng;
  893. X{
  894. X/* Your generating procedure goes here */
  895. X}
  896. X
  897. Xdouble newrng_dgen(rng)
  898. XRNGdata *rng;
  899. X{
  900. X/* Your generating procedure goes here */
  901. X}
  902. X
  903. X/* Seeding procedure */
  904. Xvoid newrng_seed(rng,seed)
  905. XRNGdata *rng;
  906. Xlong *seed;
  907. X{
  908. X/* Your seeding procedure goes here */
  909. X}
  910. X
  911. X/* Checking procedure */
  912. Xint newrng_check(rng)
  913. XRNGdata *rng;
  914. X{
  915. X/* Your checking procedure goes here */
  916. X}
  917. X
  918. XFigure 8: RNG source file template
  919. X------------------------------------
  920. X
  921. X6.1.3 Seeding Routine
  922. X
  923. Xvoid myrng_seed(rng, seed)
  924. XRNGdata *rng;
  925. Xlong *seed;
  926. X
  927. XThis procedure is used for seeding the RNG.  The interpretation of the
  928. Xseed parameter is left entirely to the programmer.  It may, for example,
  929. Xpoint to a single integer or to an array of 5,000 integers.  One of the
  930. XRNGs currently installed in the package interprets the seed parameter as
  931. Xpointing to three 16-bit integers.  Obviously, RNGs which are capable of
  932. Xbeing seeded with a variable number of seeds need to be passed a seed
  933. Xpointer which contains adequate information about the number of seeds to
  934. Xwhich it points.
  935. X
  936. XAlthough the seeding procedure is passed an entire RNGdata
  937. Xstructure as a parameter, it should only manipulate the RNGstate
  938. Xfield of that structure.  (See Appendix A for information
  939. Xon the RNGdata structure.)  Many RNG seeding procedures will simply
  940. Xcopy the seed parameter into RNGstate, as shown in Figure 9.
  941. X
  942. X------------------------------------
  943. Xvoid myrng_seed(rng, seed)
  944. XRNGdata *rng;
  945. Xlong *seed;
  946. X{
  947. XRNGstate[0]=seed[0];
  948. XRNGstate[1]=seed[1]; /* This RNG uses two long seeds */
  949. X}
  950. X
  951. XFigure 9: A sample seeding procedure
  952. X------------------------------------
  953. X
  954. XOther seeding procedures may fill RNGstate with the results
  955. Xof some complicated function performed on the initial seed table.
  956. X
  957. X6.1.3 Pseudorandom Number Generating Procedure
  958. X
  959. Xlong myrng_lgen(rng)
  960. XRNGdata *rng;
  961. X
  962. Xdouble myrng_dgen(rng)
  963. XRNGdata *rng;
  964. X
  965. XThe programmer must provide *one* procedure, matching one of the two
  966. Xprototypes given above, which returns a single generate from the RNG.
  967. XThe routine may return either:
  968. X
  969. X* a double precision floating point number in the range [0,1), or
  970. X* a long (32-bit) integer in the range 0..range_rng(rng)-1
  971. X
  972. XIt is pointless for the programmer to provide procedures of both types.
  973. XIf this is done, only one of them will be accessible by any user code,
  974. Xdepending on the value given to RNGreturns, RNGdgen, and RNGlgen (see
  975. XSection 6.2).
  976. X
  977. XAlthough the generating procedure is passed an entire RNGdata
  978. Xstructure, it should only manipulate the RNGstate field of the
  979. Xstructure.  A sample generating procedure is displayed in Figure 10.
  980. X
  981. X------------------------------------
  982. Xlong myrng_lgen(rng)
  983. XRNGdata *rng;
  984. X{
  985. XRNGstate[0]*=12345+6789;
  986. Xreturn(RNGstate[0]);
  987. X}
  988. X
  989. XFigure 10: A sample generating procedure
  990. X------------------------------------
  991. X
  992. X6.1.4 RNG Checking Procedure
  993. X
  994. Xint myrng_check(rng)
  995. XRNGdata *rng;
  996. X
  997. XThe programmer must provide a procedure to check the integrity of the
  998. XRNGdata structure.  The procedure returns a value of 1 if the RNG is fit
  999. Xfor use, and returns 0 otherwise.  The coding of the procedure is
  1000. Xentirely RNG-specific, and may be extremely simple or extremely
  1001. Xcomplicated, depending on the nature of the RNG and the extent of
  1002. Xintegrity desired.  On one extreme is the procedure which always
  1003. Xdeclares success, and on the other extreme is the perfect (and slow)
  1004. Xprocedure which creates a new RNG, seeds it with the seeds of the RNG to
  1005. Xbe checked, cycles it through the number of generates which were
  1006. Xproduced by the RNG to be checked, and compares the state tables of the
  1007. Xtwo RNGs.  Clearly, the procedure should not modify the RNG in any way.
  1008. XWhen writing a checking procedure it might be useful to examine those
  1009. Xincluded in the existing package.
  1010. X
  1011. X6.2 RNG Header Files
  1012. X
  1013. XFor each RNG included in the package, there must be a corresponding
  1014. Xheader file.  The header file contains information about the RNG which
  1015. Xis used by the mrandom library routines.  This section describes the
  1016. Xinformation contained in RNG header files, and describes how to use such
  1017. Xheader files to incorporate new RNGs into the mrandom package.  A
  1018. Xtemplate for such a header file, called `newrng.h', is included in
  1019. Xthe distribution and displayed in Figure 11.
  1020. X
  1021. X------------------------------------
  1022. X/* newrng.h */
  1023. X/* RNG header file template */
  1024. X/* Robert Plotkin
  1025. X/* 5/3/93 */
  1026. X
  1027. X#include "mrandom.h"
  1028. X
  1029. X/* Information for mrandom */
  1030. X#define RNGstatesize_n    
  1031. X#define RNGseedsize_2
  1032. X#define RNGrange_2
  1033. X#define RNGname_2
  1034. X#define RNGreturns_2
  1035. X#define RNGstatetype_2
  1036. X#define RNGdgen_2
  1037. X#define RNGlgen_2
  1038. X#define RNGseed_2
  1039. X#define RNGcheck_2
  1040. X
  1041. X/* mrandom interface routines */
  1042. Xlong newrng_gen(/* RNGdata * */);
  1043. Xvoid newrng_seed(/* RNGdata *, long * */);
  1044. Xint newrng_check(/* RNGdata * */);
  1045. X
  1046. XFigure 11: RNG header file template
  1047. X------------------------------------
  1048. X
  1049. X6.2.1 Information in Header Files
  1050. X
  1051. XEach header file should begin with the following directives:
  1052. X
  1053. X#ifndef MRANDOM
  1054. X#include "mrandom.h"
  1055. X#endif
  1056. X
  1057. XDefinition of RNG parameters
  1058. X
  1059. XThe next set of lines in the file should contain #define statements
  1060. Xwhich assign values to the RNG's parameters.  The names used in the
  1061. X#define statements must contain the RNG's number.  There are currently
  1062. Xten RNGs included in the package, labeled 0 through 9.  The next RNG
  1063. Xincluded in the package should be labeled number 10, and so on.  The
  1064. X``n'' in each parameter name in the following list should be interpreted
  1065. Xas the RNG's number.
  1066. X
  1067. XRNGname_n
  1068. X    A string constant containing the name of the RNG, terminated
  1069. X    with a newline character.
  1070. XRNGstatesize_n
  1071. X    The number of entries in the RNG's state table.  Each entry is a
  1072. X    (32-bit) long.  If the RNG is capable of using state tables of
  1073. X    varying sizes, RNGstatesize_n should be defined as the maximum
  1074. X    possible size.
  1075. XRNGseedsize_n
  1076. X    The number of entries in the RNG's seed table.  Each entry is a
  1077. X    (32-bit) long.  If the RNG is capable of using seed tables of
  1078. X    varying sizes, RNGseedsize_n should be defined as the maximum
  1079. X    possible size.
  1080. XRNGrange_n
  1081. X    The range of the RNG, expressed as a double precision floating
  1082. X    point number.  The range of the RNG is one more than the maximum
  1083. X    value the RNG is capable of generating.  For RNGs which produce
  1084. X    double precision generates with a precision of p (i.e. in the
  1085. X    range [0,(RNGrange-1.0)/(1<<p)), RNGrange should be defined as
  1086. X    2^p.  For example, an RNG which produces 8-byte IEEE
  1087. X    floating-point generates using single-precision IEEE arithmetic
  1088. X    (24-bit mantissas) has a range of 16777216.0.
  1089. X
  1090. XRNGreturns_n
  1091. X    A number signifying the type of the generate returned by the
  1092. X    RNG.  An RNG can return a value of one of two types:
  1093. X        * a long in the range 0..RNGrange-1
  1094. X        * a double in the range [0,1)
  1095. X    RNGs which return values of type long and double return
  1096. X    types RET_LONG and RET_DOUBLE, respectively, as defined in
  1097. X    mrandom.h.
  1098. XRNGstatetype
  1099. X    A number signifying the interpretation of the values stored in
  1100. X    the RNG's state and seed vectors.  This value is used by the
  1101. X    routines that read and write the ASCII state files, thereby
  1102. X    allowing portability of state files across machines with
  1103. X    different byte orderings (see Section 5.4.3).  The following
  1104. X    values are currently supported:
  1105. X
  1106. X            Value        Type
  1107. X            ---------------------------
  1108. X            STATE_CHAR    8-bit character
  1109. X            STATE_INT    16-bit integer
  1110. X            STATE_LONG    32-bit long integer
  1111. X
  1112. X    The values of STATE_FLOAT (IEEE-standard 32-bit float) and
  1113. X    STATE_DOUBLE (IEEE-standard 64-bit float) are not currently
  1114. X    supported and are reserved for future use.
  1115. XRNGdgen_n and RNGlgen_n
  1116. X    The label of the procedure to be used for generating
  1117. X    pseudorandom numbers.  If the RNG returns doubles, then RNG_dgen
  1118. X    should be defined as the label of the RNG generating procedure,
  1119. X    and RNG_lgen should be defined as 0.  If the RNG returns longs,
  1120. X    then RNG_lgen should be defined as the label of the RNG
  1121. X    generating procedure, and RNG_dgen should be defined as 0.
  1122. XRNGseed_n
  1123. X    The label of the procedure to be used for seeding the RNG.
  1124. XRNGcheck_n
  1125. X    The label of the procedure to be used for checking the integrity
  1126. Xof the RNG.
  1127. X
  1128. XProcedure prototypes
  1129. X
  1130. XFinally, the header file must contain function prototypes for
  1131. Xthe three procedures provided by the RNG, so that the procedures
  1132. Xcan be accessed by the main mrandom code.  For example:
  1133. X
  1134. Xlong myrng_gen();
  1135. Xvoid myrng_seed();
  1136. Xint myrng_check();
  1137. X
  1138. X6.3 Modifying the mrandom code
  1139. X
  1140. XOnly a few lines of mrandom.h and mrandom.c need to be modified when
  1141. Xadding a new RNG to the package.
  1142. X
  1143. X* The number of RNGs currently installed in the package is defined as
  1144. XNUM_RNGS in `mrandom.h'.  The current value is 10.  This value should be
  1145. Xincremented when a new RNG is added to the package.
  1146. X* The header file for the new RNG needs to be #included in mrandom.c.
  1147. XThe #include directive should be included in the section marked by the
  1148. Xcomment ``Header files for RNGs currently included in package.''
  1149. X* Several additions need to be made in mrandom.c in the section marked
  1150. Xby the comment ``Arrays to hold information about RNGs.''  This section
  1151. Xof the code declares and initializes several arrays which hold
  1152. Xinformation about the RNGs included in the package.  When installing a
  1153. Xnew RNG, the appropriate #defined values need to be inserted at the end
  1154. Xof each initialization list.  For example, the declaration of RNGname_a
  1155. Xcurrently reads:
  1156. X
  1157. Xchar RNGname_a[NUM_RNGS][RNGIDSTRLEN]={RNGname_0, RNGname_1,
  1158. X      RNGname_2, RNGname_3, RNGname_4, RNGname_5, RNGname_6,
  1159. X      RNGname_7, RNGname_8, RNGname_9};
  1160. X
  1161. XAfter adding a new RNG to the package, this declaration would read:
  1162. X
  1163. Xchar RNGname_a[NUM_RNGS][RNGIDSTRLEN]={RNGname_0, RNGname_1,
  1164. X      RNGname_2, RNGname_3, RNGname_4, RNGname_5, RNGname_6,
  1165. X      RNGname_7, RNGname_8, RNGname_9,
  1166. X      /* RNG #10 added -> */ RNGname_10};
  1167. X
  1168. XThe arrays statesize_a, seedsize_a, range_a, returns_a, statetype_a,
  1169. Xseed_a, dgen_a, lgen_a, and check_a need to be similarly modified.
  1170. X
  1171. X6.4 Remaking the mrandom Package
  1172. X
  1173. XOnce you have added an RNG to the package as described in the
  1174. Xprevious sections, you will need to remake the mrandom package.  To do
  1175. Xthis:
  1176. X
  1177. X
  1178. X* Make sure that all of the files for the mrandom package, include the
  1179. Xsource and header files for your new RNG, are in the same directory.
  1180. X* Include the names of your header, source, and object files in makefile
  1181. Xon the lines labeled INCS, SRCS, and OBJS, respectively, as show in
  1182. XFigure 12.
  1183. X* Follow the instructions for making the mrandom package, as
  1184. Xdescribed in Section 3.
  1185. XOnce the package has been remade it will be ready for use, with your new
  1186. XRNG, by other programs.
  1187. X
  1188. X--------------------------------
  1189. XINCS = mrandom.h bentley.h pcrand.h ran0.h ran1.h ran2.h ultra.h xsq.h myrng.h
  1190. XSRCS = mrtest.c mrandom.c bentley.c pcrand.c ran0.c ran1.c ran2.c ultra.c xsq.c myrng.c
  1191. XOBJS = mrandom.o bentley.o pcrand.o ran0.o ran1.o ran2.o ultra.o xsq.o myrng.o
  1192. X
  1193. XFigure 12: Addition of myrng to makefile
  1194. X--------------------------------
  1195. X
  1196. X
  1197. XA The RNGdata Structure
  1198. X-----------------------
  1199. X-----------------------
  1200. X
  1201. XA.1 Introduction
  1202. X
  1203. XThis section describes the representation in C of the RNGdata structure
  1204. Xwhich is used by the mrandom package to represent RNGs.  This structure
  1205. Xneed never be manipulated by the programmer, except as described in
  1206. XSection 6.1.  This section, therefore, is intended for those who are
  1207. Xinterested in learning a little more about the inner workings of the
  1208. Xmrandom package.
  1209. X
  1210. XIn order to generate random numbers, the user must first declare a
  1211. Xpointer to an RNGdata structure, and use init_rng to allocate space for
  1212. Xthe RNG and perform various initialization functions.  The user uses the
  1213. XRNG entirely through calls provided by the interface described in
  1214. XSection 5.4; i.e. the user should not directly manipulate the RNGdata
  1215. Xstructure.
  1216. X
  1217. XA.2 Inside the Structure
  1218. X    The definition of the RNGdata structure is displayed in
  1219. XFigure 13.
  1220. X
  1221. X--------------------------------
  1222. Xstruct rngdata {
  1223. X    long rngalg;
  1224. X    long mrandom_alg;
  1225. X    long *rngstate;
  1226. X    long *rngseed;
  1227. X    long rngcount1;
  1228. X    long rngcount2;
  1229. X    struct {
  1230. X        long size;
  1231. X        long nleft;
  1232. X        long nbleft;
  1233. X        double *dbuf,*dbufp;
  1234. X        long *lbuf,*lbufp;
  1235. X        int *bbuf,*bbufp;
  1236. X    } buffer;
  1237. X    long rngnextval;
  1238. X    long rngsplit;
  1239. X    char rngname[];
  1240. X    long rngstatesize;
  1241. X    long rngseedsize;
  1242. X    long rngrangem1;
  1243. X    double rngrange;
  1244. X    signed int rngreturns;
  1245. X}; 
  1246. Xtypedef struct rngdata RNGdata;
  1247. X
  1248. XFigure 13: The RNGdata structure
  1249. X--------------------------------
  1250. X
  1251. XDescriptions of its fields are as follows:
  1252. X
  1253. Xrngalg
  1254. X    A number identifying the algorithm to be used by the RNG to
  1255. X    produce pseudorandom generates.  Algorithms in the package are
  1256. X    numbered sequentially starting with 0; currently there are 10
  1257. X    algorithms installed, numbered 0 through 9.  A table of RNGs
  1258. X    which are currently installed in the mrandom package, with their
  1259. X    corresponding algorithm numbers, is in Appendix B.
  1260. Xmrandom_alg
  1261. X    The algorithm use by mrandomrv when called with this RNG.
  1262. X    See Section 5.4.2 for more on mrandomrv.
  1263. Xrngstate
  1264. X    A pointer to the RNG's state vector, used to store the current
  1265. X    state of the RNG.  See Sections 5.4.3, 6.1, and 6.2.1 for more
  1266. X    information on RNG state vectors.
  1267. Xrngseed
  1268. X    A pointer to the RNG's seed vector.  See Section 5.4.4
  1269. X    for more information on RNG seed vectors.
  1270. Xrngcount1, rngcount2
  1271. X    These two values represent the number of generates the RNG has
  1272. X    produced since initialization, according to the formula:
  1273. X        rngcount1+rngcount2*BILLION
  1274. X
  1275. X    where BILLION is defined in `mrandom.h'.  Please note that the
  1276. X    value represented by rngcount1 and rngcount2 is the *total*
  1277. X    number of generates produced by the RNG since initialization,
  1278. X    including those discarded due to splitting of the RNG.  (See
  1279. X    Section 5.4.7 for more information about splitting RNGs.)
  1280. Xrngnextval
  1281. X    The next value to be output from the RNG.  This
  1282. X    value is used internally by the mrandom library and is not
  1283. X    guaranteed to be accurate.
  1284. Xrngsplit
  1285. X    Every (split+1)-th generate of the underlying RNG will be
  1286. X    returned by the RNG calling procedures.  rngsplit is set to
  1287. X    DEF_SPLIT upon initialization of the RNG, as defined in
  1288. X    `mrandom.h'.  See Section 5.4.7 for more information about
  1289. X    splitting RNGs.
  1290. Xbuffer
  1291. X    This structure contains information about the RNG's buffer and
  1292. X    its bit buffer.  (See Section 5.4.2 for more information on RNG
  1293. X    buffers.)  It contains several fields:
  1294. X
  1295. X    size
  1296. X        The number of entries in the RNG's buffer.
  1297. X    nleft
  1298. X        The number of values left in the RNG's buffer.
  1299. X    nbleft
  1300. X        The number of values left in the RNG's bit buffer.
  1301. X    dbuf, dbufp
  1302. X        A pointer to the first entry in the double
  1303. X        buffer, and a pointer to the next entry to be retrieved
  1304. X        from the double buffer.
  1305. X    lbuf, lbufp
  1306. X        Same for the long buffer.
  1307. X    bbuf, bbufp
  1308. X        Same for the bit buffer.
  1309. X
  1310. XThe remaining values in the RNGdata structure are derived
  1311. Xfrom the RNG's header file upon initialization.  For more information on
  1312. Xthe values of these fields, see Section 6.2.1.
  1313. X
  1314. X
  1315. XB RNGs Currently Installed in the Package
  1316. X-----------------------------------------
  1317. X-----------------------------------------
  1318. X
  1319. XThere are currently ten RNGs installed in the mrandom package.  This
  1320. Xappendix provides brief descriptions of each of them.  References are
  1321. Xprovided for those who are interested in finding out about the RNGs in
  1322. Xmore detail.
  1323. X
  1324. XRNG algorithm 0: A trivial RNG
  1325. X    A trivial RNG is included in the package, primarily for testing
  1326. X    purposes.  The generates it produces are not ``random'' in
  1327. X    virtually any sense of the word; it simply produces generates
  1328. X    from an arithmetical progression determined by its initial
  1329. X    seeds.  For example, if it is seeded with 5 and 7, respectively,
  1330. X    it will produce the sequence 5, 12, 19, 26, etc.
  1331. X
  1332. X    This RNG takes two longs as seeds.  It returns generates of type
  1333. X    long.
  1334. X
  1335. XRNG algorithm 1: 4.3bsd random
  1336. X    This is UNIX 4.3bsd random.  It is a 31-bit nonlinear
  1337. X    additive feedback generator with a range of 2^31 and a period of
  1338. X    approximately 16*2^31-1.  It is nominally able to save and
  1339. X    restore state, but its state-saving code is buggy.  Therefore,
  1340. X    when using random with the mrandom package, no more than one RNG
  1341. X    should use random at a time.
  1342. X
  1343. X    This RNG takes a single long as a seed.  It returns generates of
  1344. X    type long.
  1345. X
  1346. XRNG algorithm 2: the Knuth/Bentley prand
  1347. X    This lagged-Fibonacci RNG was introduced by Jon Bentley in his
  1348. X    ``Software Exploratorium'' column in Unix Review, Vol. 10, No.
  1349. X    6, June 1992, and is based on one first presented in Donald E.
  1350. X    Knuth's The Art of Computer Programming , Vol. 2,
  1351. X    Addison-Wesley, Reading, Mass., 1981.  It has a range of
  1352. X    1,000,000,000.
  1353. X
  1354. X    This RNG takes a single long as a seed.  It returns generates of
  1355. X    type long.
  1356. X
  1357. XRNG algorithm 3: The Portable Combined RNG
  1358. X    This combined prime multiplicative congruential RNG was
  1359. X    developed based on algorithms and selections of prime numbers
  1360. X    presented in ``Efficient and Portable Combined Random Number
  1361. X    Generators,'' Pierre L'Ecuyer, Communications of the ACM, Vol.
  1362. X    10, No.  6, June 1992, and ``Random Number Generators: Good Ones
  1363. X    are Hard to Find,'' Stephen Park and Keith Miller,
  1364. X    Communications of the ACM, Vol.  31, No. 10, October 1992.  It
  1365. X    has a range of 2147483561.
  1366. X
  1367. X    This RNG takes two longs as seeds.  It returns generates of type
  1368. X    long.
  1369. X
  1370. XRNG algorithm 4: 4.3bsd nrand48
  1371. X    This is UNIX 4.3bsd nrand48.  It produces generates using a
  1372. X    linear congruential algorithm and 48-bit integer arithmetic.  It
  1373. X    has a range of 2^31.
  1374. X
  1375. X    This RNG takes three unsigned shorts as seeds.  They are passed
  1376. X    to the seeding procedure as two longs, and are interpreted in
  1377. X    the following way:
  1378. X
  1379. X        * The 16 least significant bits of the second long is
  1380. X        the first seed.
  1381. X        * The 16 least significant bits of the first long is the
  1382. X        second seed.
  1383. X        * The 16 most significant bits of the first long is the
  1384. X        third seed.
  1385. X        * The 16 most significant bits of the second long is
  1386. X        ignored.
  1387. X
  1388. X    This RNG returns generates of type long.
  1389. X
  1390. XRNG algorithm 5: 4.3bsd rand
  1391. X    This is UNIX 4.3bsd rand.  It uses a multiplicative congruential
  1392. X    algorithm.  It has a period of 2^32 and a range of 2^31.
  1393. X
  1394. X    This RNG takes a single long as a seed.  It returns generates of
  1395. X    type long.
  1396. X
  1397. XRNG algorithm 6, 7, and 8: Press and Teukolsky's ran0, ran1, and ran2
  1398. X    These three multiplicative congruential RNGs are adapted from
  1399. X    those presented in ``Portable Random Number Generators,''
  1400. X    William H.  Press and Saul A. Teukolsky, Computers in Physics,
  1401. X    Vol. 6, No. 5, Sep/Oct 1992.  They all have a period of
  1402. X    2^31-2 and a range of 2^31-1.
  1403. X
  1404. X    These RNGs take a single long as a seed.  They return generates
  1405. X    of type double.
  1406. XRNG algorithm 9: Marsaglia's Ultra RNG
  1407. X
  1408. X    We obtained the source code for this generator by anonymous ftp
  1409. X    from nic.funit.fi (take the file fsultra.zip from the directory
  1410. X    /pub/msdos/science/math/fsultra).  A note in the readme file
  1411. X    says: ``To obtain permission to incorporate this program into
  1412. X    any commercial product, please contact the authors at the e-mail
  1413. X    address given above [afir@stat.fsu.edu or geo@stat.fsu.edu] or
  1414. X    at Department of Statistics and Supercomputer Computations
  1415. X    Research Institute, Florida State University, Tallahassee, FL
  1416. X    32306.''  This RNG is one of those originally presented in ``A
  1417. X    New Class of Random Number Generators,'' George Marsaglia and
  1418. X    Arif Zaman, The Annals of Applied Probability, Vol.  1, No. 3,
  1419. X    1991.  It is a ``subtract-with-borrow'' generator with a range
  1420. X    of 2^32 and a staggering period of 10^354.
  1421. X
  1422. X    This RNG takes two unsigned longs as seeds.  It returns
  1423. X    generates of type double.
  1424. END_OF_FILE
  1425. if test 50066 -ne `wc -c <'doc/mrandom.txt'`; then
  1426.     echo shar: \"'doc/mrandom.txt'\" unpacked with wrong size!
  1427. fi
  1428. # end of 'doc/mrandom.txt'
  1429. fi
  1430. if test -f 'src/mrandom.c' -a "${1}" != "-c" ; then 
  1431.   echo shar: Will not clobber existing file \"'src/mrandom.c'\"
  1432. else
  1433. echo shar: Extracting \"'src/mrandom.c'\" \(42469 characters\)
  1434. sed "s/^X//" >'src/mrandom.c' <<'END_OF_FILE'
  1435. X/* mrandom.c 3.1 5/28/93 */
  1436. X/*
  1437. X *        mrandom.c
  1438. X *
  1439. X *      An interface for random number generators (RNGs)
  1440. X *
  1441. X *    Original Implementation:
  1442. X *        Clark Thomborson, September 1991
  1443. X *    Modifications:
  1444. X *       - give uniform interface to other rngs
  1445. X *       - remove bias from integer generator
  1446. X *       - avoid possible infinite loop in mrandom(m)
  1447. X *       - allow access to multiple simultaneous rngs
  1448. X *       - add interface to nrand48()
  1449. X *       - add interface to rand()
  1450. X *       - tuned for speed
  1451. X *        Clark Thomborson, May 1992
  1452. X *    
  1453. X *      Version 3.0:
  1454. X *              Robert Plotkin, May 1993
  1455. X *      Modifications include:
  1456. X *         - Standardized interface to underlying RNGs
  1457. X *         - Added buffered generating routines
  1458. X *         - Added interfaces to ran0, ran1, ran2, Ultra RNGs
  1459. X *         - Added routines for generating bits
  1460. X *         - Added split feature
  1461. X *         - Allow choice of algorithms in mrandomrv
  1462. X *         - Dynamic allocation of RNGs
  1463. X *
  1464. X *    This material is based upon work supported by the National
  1465. X *    Science Foundation under grant number MIP-9023238.  The
  1466. X *    Government has certain rights in this material.
  1467. X *
  1468. X *    Any opinions, findings, and conclusions or recommendations
  1469. X *    expressed in this material are those of the author and do
  1470. X *    not necessarily reflect the view of the National Science
  1471. X *    Foundation.
  1472. X *
  1473. X *    This code is neither copyrighted nor patented, although we are
  1474. X *    not sure about the status of some of the routines it calls.
  1475. X */
  1476. X
  1477. X#ifndef MRANDOM
  1478. X#include "mrandom.h"
  1479. X#endif
  1480. X
  1481. X/*****************/
  1482. X/* Include files */
  1483. X/*****************/
  1484. X#include <malloc.h> /* To allocate space for RNGs*/
  1485. X#include <math.h>   /* we need floor() */
  1486. X#include <stdio.h>  /* We need FILE */
  1487. X#include <strings.h>
  1488. X#include <values.h> /* We need MAXLONG */
  1489. X
  1490. X/*******************************************************/
  1491. X/* Header files for RNGs currently included in package */
  1492. X/*******************************************************/
  1493. X#include "rngs.h"    /* "Built-in" rngs:
  1494. X            Trivial RNG:               Algorithm #0
  1495. X            4.3bsd random:             Algorithm #1
  1496. X            4.3bsd nrand48:            Algorithm #4
  1497. X            4.3bsd rand:               Algorithm #5 */
  1498. X#include "bentley.h" /* Knuth/Bentley prand:       Algorithm #2 */
  1499. X#include "pcrand.h"  /* The portable combined RNG: Algorithm #3 */
  1500. X#include "ran0.h"    /* Press & Teukolsky's ran0:  Algorithm #6 */
  1501. X#include "ran1.h"    /* Press & Teukolsky's ran1:  Algorithm #7 */
  1502. X#include "ran2.h"    /* Press & Teukolsky's ran2:  Algorithm #8 */
  1503. X#include "ultra.h"   /* Marsaglia's Ultra RNG:     Algorithm #9 */
  1504. X
  1505. X/*****************************************/
  1506. X/* Arrays to hold information about RNGs */
  1507. X/*****************************************/
  1508. Xchar RNGname_a[NUM_RNGS][RNGIDSTRLEN]={RNGname_0, RNGname_1,
  1509. X                     RNGname_2, RNGname_3,
  1510. X                     RNGname_4, RNGname_5,
  1511. X                     RNGname_6, RNGname_7,
  1512. X                     RNGname_8, RNGname_9};
  1513. Xlong statesize_a[NUM_RNGS]={RNGstatesize_0, RNGstatesize_1,
  1514. X                  RNGstatesize_2, RNGstatesize_3,
  1515. X                  RNGstatesize_4, RNGstatesize_5,
  1516. X                  RNGstatesize_6, RNGstatesize_7,
  1517. X                  RNGstatesize_8, RNGstatesize_9},
  1518. X  seedsize_a[NUM_RNGS]={RNGseedsize_0, RNGseedsize_1, RNGseedsize_2,
  1519. X              RNGseedsize_3, RNGseedsize_4, RNGseedsize_5,
  1520. X              RNGseedsize_6, RNGseedsize_7, RNGseedsize_8,
  1521. X              RNGseedsize_9};
  1522. Xdouble range_a[NUM_RNGS]={RNGrange_0, RNGrange_1, RNGrange_2,
  1523. X                RNGrange_3, RNGrange_4, RNGrange_5,
  1524. X                RNGrange_6, RNGrange_7, RNGrange_8,
  1525. X                RNGrange_9};
  1526. Xsigned int returns_a[NUM_RNGS]={RNGreturns_0, RNGreturns_1,
  1527. X                  RNGreturns_2, RNGreturns_3,
  1528. X                  RNGreturns_4, RNGreturns_5,
  1529. X                  RNGreturns_6, RNGreturns_7,
  1530. X                  RNGreturns_8, RNGreturns_9};
  1531. X  int statetype_a[NUM_RNGS]={RNGstatetype_0, RNGstatetype_1,
  1532. X                 RNGstatetype_2, RNGstatetype_3,
  1533. X                 RNGstatetype_4, RNGstatetype_5,
  1534. X                 RNGstatetype_6, RNGstatetype_7,
  1535. X                 RNGstatetype_8, RNGstatetype_9};
  1536. X
  1537. X
  1538. Xtypedef void (*SP)(RNGdata *, long *);
  1539. Xtypedef double (*DPP)(RNGdata *);
  1540. Xtypedef long (*LPP)(RNGdata *);
  1541. Xtypedef int (*CP)(RNGdata *);
  1542. XSP seed_a[NUM_RNGS] = {RNGseed_0, RNGseed_1, RNGseed_2, RNGseed_3,
  1543. X             RNGseed_4, RNGseed_5, RNGseed_6, RNGseed_7,
  1544. X             RNGseed_8, RNGseed_9};
  1545. XDPP dgen_a[NUM_RNGS] = {RNGdgen_0, RNGdgen_1, RNGdgen_2,
  1546. X               RNGdgen_3, RNGdgen_4, RNGdgen_5,
  1547. X               RNGdgen_6, RNGdgen_7,  RNGdgen_8,
  1548. X               RNGdgen_9};
  1549. XLPP lgen_a[NUM_RNGS] = {RNGlgen_0, RNGlgen_1, RNGlgen_2, RNGlgen_3,
  1550. X               RNGlgen_4, RNGlgen_5, RNGlgen_6,
  1551. X               RNGlgen_7, RNGlgen_8, RNGlgen_9};
  1552. XCP check_a[NUM_RNGS] = {RNGcheck_0, RNGcheck_1, RNGcheck_2,
  1553. X              RNGcheck_3, RNGcheck_4, RNGcheck_5,
  1554. X              RNGcheck_6, RNGcheck_7, RNGcheck_8, RNGcheck_9};
  1555. X/* The most-recently initialized or restarted RNG */
  1556. XRNGdata *mru_rng = 0;
  1557. X
  1558. X/* Format of the RNG statefile */
  1559. X#define RNGfileLINE0   "RNG statefile for algorithm %ld, "
  1560. X#define RNGfileLINE1   "Buffer size = %ld bytes\n"
  1561. X#define RNGfileLINE2   "Initial seed table =\n"
  1562. X#define RNGfileLINE3   \
  1563. X "Number of calls to underlying RNG after seeding = %ld billion + %ld\n"
  1564. X#define RNGfileLINE4   "Next value in this pseudorandom sequence = \
  1565. X%08lx\n"
  1566. X#define RNGfileLINE5   "This RNG returns every %ld generates\n"
  1567. X#define RNGfileLINE6   "This RNG uses mrandom algorithm %ld\n"
  1568. X#define RNGfileLINE7   "RNG state table =\n"
  1569. Xchar *RNGfileLINEn[]={"",
  1570. X            "   %02lx %02lx %02lx %02lx\n",
  1571. X            "   %04lx %04lx %04lx %04lx\n",
  1572. X            "",
  1573. X            "   %08lx %08lx %08lx %08lx\n"},
  1574. X  *RNGfileLINEnn[]={"", "   %02lx", "   %04lx", "", "   %08lx"};
  1575. X
  1576. X/* Error message for invalid RNGs */
  1577. X#define BADRNG_ERR \
  1578. X fprintf(stderr, "RNG must be initialized or restarted before use!\n"); \
  1579. X fflush(stderr);\
  1580. X exit(1)
  1581. X
  1582. X/**************************************************/
  1583. X/* Auxiliary macros for RNG generating procedures */
  1584. X/**************************************************/
  1585. X/*************************************/
  1586. X/* set_rng                           */
  1587. X/* Sets rng to point to a valid      */
  1588. X/*  RNGdata structure, if any        */
  1589. X/*  can be found.                    */
  1590. X/* Otherwise it calls                */
  1591. X/*  the error routine no_rng().      */
  1592. X/*************************************/
  1593. X#define set_rng(rng)   if (rng == 0) { \
  1594. X                if (mru_rng) { \
  1595. X                    rng = mru_rng; \
  1596. X                } else { \
  1597. X                    BADRNG_ERR; \
  1598. X                } \
  1599. X            }
  1600. X
  1601. X/*************************************/
  1602. X/* inc_counts                        */
  1603. X/* Increment an RNG counter n times  */
  1604. X/*************************************/
  1605. X/* Using two while loops is necessary.  If RNGcount1 is added to n
  1606. X *  before n is reduced to a number less than BILLION, it is
  1607. X *  possible that RNGcount1+n will overflow.
  1608. X * Possible overflow of count2 is not handled, because on today's
  1609. X *  computers it will not occur.
  1610. X */
  1611. X#define inc_counts(rng,n) \
  1612. X  while (n >= BILLION) { \
  1613. X    n -= BILLION; \
  1614. X    RNGcount2 += 1; \
  1615. X  } \
  1616. X  RNGcount1 += n; \
  1617. X  while (RNGcount1 >= BILLION) { \
  1618. X    RNGcount1 -= BILLION; \
  1619. X    RNGcount2 += 1; \
  1620. X  }
  1621. X
  1622. X/*************************************/
  1623. X/* fill_buffer                       */
  1624. X/* Fill an RNG buffer                */
  1625. X/*************************************/
  1626. Xvoid fill_buffer(rng)
  1627. X     RNGdata *rng;
  1628. X{
  1629. X  long i,j; /* Loop variables */
  1630. X  
  1631. X  inc_counts(rng,RNGbuffer.size);
  1632. X  
  1633. X  if (RNGreturns == RET_LONG) { /* Underlying RNG returns longs */
  1634. X    LPP proc;
  1635. X    long *temp_l; /* Temporary pointer for efficiency */
  1636. X    proc=lgen_a[RNGalg];
  1637. X    RNGbuffer.lbufp=temp_l=RNGbuffer.lbuf;
  1638. X    
  1639. X    for (i=0; i<RNGbuffer.size; i++) { /* Fill the buffer */
  1640. X      *temp_l++  = proc(rng);
  1641. X      for (j=0;j<RNGsplit;j++) /* Handle split */
  1642. X    proc(rng);
  1643. X    }
  1644. X  }
  1645. X  else if (RNGreturns == RET_DOUBLE) { /* Underlying RNG returns */
  1646. X                                       /* doubles */
  1647. X    DPP proc;
  1648. X    double *temp_d; /* Temporary pointer for efficiency */
  1649. X    proc=dgen_a[RNGalg];
  1650. X    RNGbuffer.dbufp=temp_d=RNGbuffer.dbuf;
  1651. X    
  1652. X    for (i=0; i<RNGbuffer.size; i++) { /* Fill the buffer */
  1653. X      *temp_d++ = proc(rng);
  1654. X      for (j=0;j<RNGsplit;j++) /* Handle split */
  1655. X    proc(rng);
  1656. X    }
  1657. X  }
  1658. X  RNGbuffer.nleft=RNGbuffer.size-1; /* Buffer is full */
  1659. X}
  1660. X
  1661. X/*************************************/
  1662. X/* bfill_vector                      */
  1663. X/* Fill a vector, with buffering,    */
  1664. X/*  with a function of               *
  1665. X/*  the underlying RNG               */
  1666. X/*************************************/
  1667. X#define bfill_vector(function) \
  1668. X  while (n--) { \
  1669. X         if (RNGbuffer.nleft-- == 0) \
  1670. X           fill_buffer(rng); \
  1671. X         *v++ = function; \
  1672. X         }
  1673. X
  1674. X/*************************************/
  1675. X/* random_setup                      */
  1676. X/* Handle special case of n == 0     */
  1677. X/*************************************/
  1678. X#define random_setup()\
  1679. X  set_rng(rng); \
  1680. X  if (n == 0) { \
  1681. X    n=1; \
  1682. X    v=vdef; \
  1683. X  } \
  1684. X  vreturn=v
  1685. X
  1686. X/*************************************/
  1687. X/* randomrv                          */
  1688. X/* Kernel of buffered routines       */
  1689. X/*************************************/
  1690. X/* The order of the cases is important for maximum efficiency.
  1691. X * The order is optimized for the case in which a request is made for
  1692. X *  the same type as the value returned by the underlying RNG
  1693. X */
  1694. X#define randomrv(case1, function1, case2, function2)\
  1695. X  random_setup(); \
  1696. X  if (RNGreturns == case1) \
  1697. X    bfill_vector(function1) \
  1698. X  else if (RNGreturns == case2) \
  1699. X    bfill_vector(function2) \
  1700. X  else \
  1701. X    while (n--) \
  1702. X      *v++ = 0; \
  1703. X  return(*vreturn)
  1704. X
  1705. X/*************************************/
  1706. X/* fill_vector                       */
  1707. X/* Fill a vector, without buffering, */
  1708. X/*  with a function of               */
  1709. X/*  the underlying RNG               */
  1710. X/*************************************/
  1711. X#define fill_vector(function) \
  1712. X  while (n--) { \
  1713. X         *v++ = function; \
  1714. X         for(j=0;j<RNGsplit;j++) \
  1715. X           proc(rng); \
  1716. X         }
  1717. X
  1718. X/*************************************/
  1719. X/* xrandom_setup                     */
  1720. X/* Setup common to all xrandoms      */
  1721. X/*************************************/
  1722. X#define xrandom_setup() \
  1723. X  random_setup(); \
  1724. X  inc_counts(rng,n)
  1725. X
  1726. X/* Auxiliary routines for 32-bit generators */
  1727. Xdouble longtodouble(l)
  1728. X     long l;
  1729. X{
  1730. X  if (l > 0)
  1731. X    return((double)l);
  1732. X  else if (l < 0)
  1733. X    return((double)(l & 0x7fffffff) + 2147483648.0); /* 2^31 */
  1734. X  else
  1735. X    return(4294967296.0); /* 2^32 */
  1736. X}
  1737. X
  1738. X/* Coded as a macro for efficiency */
  1739. X#define doubletolong(d) ((long)((unsigned long)(d)))
  1740. X
  1741. X/*******************************************************************/
  1742. X/* Procedures for generating pseudorandom numbers                  */
  1743. X/* These procedures write a vector v of length n, by repeating the */
  1744. X/* following two steps n times:                                    */
  1745. X/*      - place the next generate in v                             */
  1746. X/*      - discard the next k generates, where k is the split value */
  1747. X/*         of the RNG                                              */
  1748. X/*                                                                 */
  1749. X/* Special cases:                                                  */
  1750. X/*  Argument  Value  Meaning                                       */
  1751. X/*  --------  -----  -------                                       */
  1752. X/*  rng         0    Use most recently used or initialized rng.    */
  1753. X/*  n           0    Return  a single generate.                    */
  1754. X/*                   The value of v is ignored(it may be set to 0).*/
  1755. X/*                                                                 */  
  1756. X/* All procedures return the first entry in the vector v.          */
  1757. X/*******************************************************************/
  1758. X
  1759. X/***********************************************/
  1760. X/* Buffered calling procedures.                */
  1761. X/***********************************************/
  1762. X/*******************/
  1763. X/* drandomrv       */
  1764. X/* Returns doubles */
  1765. X/*******************/
  1766. Xdouble drandomrv(rng,n,v)
  1767. X     RNGdata *rng;
  1768. X     long n;
  1769. X     double v[];
  1770. X{
  1771. X  long i;
  1772. X  double vdef[1],*vreturn;
  1773. X  
  1774. X  if (RNGrange > MAXLONG + 1.0) {
  1775. X    randomrv(RET_DOUBLE, *RNGbuffer.dbufp++,
  1776. X         RET_LONG, longtodouble(*RNGbuffer.lbufp++)/RNGrange);
  1777. X  }
  1778. X  else {
  1779. X    randomrv(RET_DOUBLE, *RNGbuffer.dbufp++,
  1780. X         RET_LONG, *RNGbuffer.lbufp++/RNGrange);
  1781. X  }
  1782. X}
  1783. X
  1784. X/******************/
  1785. X/* frandomrv      */
  1786. X/* Returns floats */
  1787. X/******************/
  1788. Xfloat frandomrv(rng,n,v)
  1789. X     RNGdata *rng;
  1790. X     long n;
  1791. X     float v[];
  1792. X{
  1793. X  long i;
  1794. X  float vdef[1],*vreturn;
  1795. X  
  1796. X  if (RNGrange > MAXLONG + 1.0) {
  1797. X    randomrv(RET_DOUBLE, *RNGbuffer.dbufp++,
  1798. X         RET_LONG, longtodouble(*RNGbuffer.lbufp++)/RNGrange);
  1799. X  }
  1800. X  else {
  1801. X    randomrv(RET_DOUBLE, *RNGbuffer.dbufp++,
  1802. X         RET_LONG, *RNGbuffer.lbufp++/RNGrange);
  1803. X  }
  1804. X}
  1805. X
  1806. X/*****************/
  1807. X/* lrandomrv     */
  1808. X/* Returns longs */
  1809. X/*****************/
  1810. Xlong lrandomrv(rng,n,v)
  1811. X     RNGdata *rng;
  1812. X     long n;
  1813. X     long v[];
  1814. X{
  1815. X  long vdef[1],*vreturn;
  1816. X
  1817. X  if (RNGrange > MAXLONG + 1.0) {
  1818. X    randomrv(RET_LONG, *RNGbuffer.lbufp++,
  1819. X         RET_DOUBLE, doubletolong(*RNGbuffer.dbufp++ * RNGrange));
  1820. X  }
  1821. X  else {
  1822. X    randomrv(RET_LONG, *RNGbuffer.lbufp++,
  1823. X         RET_DOUBLE, *RNGbuffer.dbufp++ * RNGrange);
  1824. X  }
  1825. X}
  1826. X
  1827. X/******************************************/
  1828. X/* brandomrv                              */
  1829. X/* Returns "high quality" bits,           */
  1830. X/*  i.e. each generate from the underlying*/
  1831. X/*  RNG is used to generate one bit.      */
  1832. X/******************************************/
  1833. Xint brandomrv(rng,n,v)
  1834. X     RNGdata *rng;
  1835. X     long n;
  1836. X     int v[];
  1837. X{
  1838. X  long i,j;
  1839. X  int vdef[1],*vreturn;
  1840. X  
  1841. X  random_setup();
  1842. X
  1843. X  for (i=0;i<n;i++) {
  1844. X    if (RNGbuffer.nbleft-- == 0) { /* Bit buffer is empty, */
  1845. X      /* so fill it */
  1846. X      for (j=0;j<BBUF_SIZE;j++)
  1847. X    RNGbuffer.bbuf[j]=drandomr(rng)*2.0;
  1848. X      RNGbuffer.bbufp=RNGbuffer.bbuf;
  1849. X      RNGbuffer.nbleft=BBUF_SIZE-1; /* Bit buffer is full */
  1850. X    }
  1851. X    *v++ = *RNGbuffer.bbufp++;
  1852. X  }
  1853. X  return(*vreturn);
  1854. X}
  1855. X
  1856. X/******************************************/
  1857. X/* brandomrv_f                            */
  1858. X/* Returns "low quality" fast bits,       */
  1859. X/*  i.e. each generate from the underlying*/
  1860. X/*  RNG is used to generate 32 bits.      */
  1861. X/* Return -1 if the range of the RNG      */
  1862. X/*  is not 2^32.                          */
  1863. X/******************************************/
  1864. X/* Splitting of this fast bit stream is not currently supported. */
  1865. Xint brandomrv_f(rng,n,v)
  1866. X     RNGdata *rng;
  1867. X     long n;
  1868. X     int v[];
  1869. X{
  1870. X  long i,j,r;
  1871. X  int vdef[1],*vreturn;
  1872. X  
  1873. X  random_setup();
  1874. X  
  1875. X  for (i=0;i<n;i++) {
  1876. X    if (RNGbuffer.nbleft-- == 0) { /* Bit buffer is empty, */
  1877. X      /* so fill it */
  1878. X      r=lrandomr(rng);
  1879. X      for (j=0;j<BBUF_SIZE;j++) {
  1880. X    RNGbuffer.bbuf[j] = r & 1;
  1881. X    r = r >> 1;
  1882. X      }
  1883. X      RNGbuffer.bbufp=RNGbuffer.bbuf;
  1884. X      RNGbuffer.nbleft=BBUF_SIZE-1; /* Bit buffer is full */
  1885. X    }
  1886. X    *v++ = *RNGbuffer.bbufp++;
  1887. X  }
  1888. X  return(RNGrange == 4294967296.0 ? *vreturn: -1);
  1889. X}
  1890. X
  1891. X/***********************************************/
  1892. X/* Unbuffered calling procedures               */
  1893. X/***********************************************/
  1894. X/*******************/
  1895. X/* dxrandomrv      */
  1896. X/* Returns doubles */
  1897. X/*******************/
  1898. Xdouble dxrandomrv(rng,n,v)
  1899. X     RNGdata *rng;
  1900. X     long n;
  1901. X     double v[];
  1902. X{
  1903. X  long i,j;
  1904. X  double vdef[1],*vreturn;
  1905. X  double d;
  1906. X
  1907. X  xrandom_setup();
  1908. X  if (RNGreturns == RET_DOUBLE) {
  1909. X    DPP proc;
  1910. X    proc=dgen_a[RNGalg];
  1911. X    fill_vector(proc(rng));
  1912. X  }
  1913. X  else if (RNGreturns == RET_LONG) {
  1914. X    LPP proc;
  1915. X    proc=lgen_a[RNGalg];
  1916. X    if (RNGrange > MAXLONG + 1.0) /* 32-bit generator */
  1917. X      { fill_vector(longtodouble(lgen_a[RNGalg](rng))/RNGrange); }
  1918. X    else
  1919. X      { fill_vector((double)lgen_a[RNGalg](rng)/RNGrange); }
  1920. X  }
  1921. X  else
  1922. X    while (n--)
  1923. X      *v++ = 0;
  1924. X  return(*vreturn);
  1925. X}
  1926. X
  1927. X/******************/
  1928. X/* fxrandomrv     */
  1929. X/* Returns floats */
  1930. X/******************/
  1931. Xfloat fxrandomrv(rng,n,v)
  1932. X     RNGdata *rng;
  1933. X     long n;
  1934. X     float v[];
  1935. X{
  1936. X  long i,j;
  1937. X  float vdef[1],*vreturn;
  1938. X  
  1939. X  xrandom_setup();
  1940. X  if (RNGreturns == RET_DOUBLE) {
  1941. X    DPP proc;
  1942. X    proc=dgen_a[RNGalg];
  1943. X    fill_vector(proc(rng));
  1944. X  }
  1945. X  else if (RNGreturns == RET_LONG) {
  1946. X    LPP proc;
  1947. X    proc=lgen_a[RNGalg];
  1948. X    if (RNGrange > MAXLONG + 1.0) /* 32-bit generator */
  1949. X      { fill_vector(longtodouble(lgen_a[RNGalg](rng))/RNGrange); }
  1950. X    else
  1951. X      { fill_vector((double)lgen_a[RNGalg](rng)/RNGrange); }
  1952. X  }
  1953. X  else
  1954. X    while (n--)
  1955. X      *v++ = 0;
  1956. X  return(*vreturn);
  1957. X}
  1958. X
  1959. X/*****************/
  1960. X/* lxrandomrv    */
  1961. X/* Returns longs */
  1962. X/*****************/
  1963. Xlong lxrandomrv(rng,n,v)
  1964. X     RNGdata *rng;
  1965. X     long n;
  1966. X     long v[];
  1967. X{
  1968. X  long i,j;
  1969. X  long vdef[1],*vreturn;
  1970. X  
  1971. X  xrandom_setup();
  1972. X  if (RNGreturns == RET_LONG) {
  1973. X    LPP proc;
  1974. X    proc=lgen_a[RNGalg];
  1975. X    fill_vector(proc(rng));
  1976. X  }
  1977. X  else if (RNGreturns == RET_DOUBLE) {
  1978. X    DPP proc;
  1979. X    proc=dgen_a[RNGalg];
  1980. X    if (RNGrange > MAXLONG + 1.0) /* 32-bit generator */
  1981. X      { fill_vector(doubletolong(dgen_a[RNGalg](rng)*RNGrange)); }
  1982. X    else
  1983. X      { fill_vector(dgen_a[RNGalg](rng)*RNGrange); }
  1984. X  }
  1985. X  else
  1986. X    while (n--)
  1987. X      *v++ = 0;
  1988. X  return(*vreturn);
  1989. X}
  1990. X
  1991. X/*******************************/
  1992. X/* bxrandomrv                  */
  1993. X/* Return "high quality" bits. */
  1994. X/*******************************/
  1995. Xint bxrandomrv(rng,n,v)
  1996. X     RNGdata *rng;
  1997. X     long n;
  1998. X     int v[];
  1999. X{
  2000. X  long i,j;
  2001. X  int vdef[1],*vreturn;
  2002. X  
  2003. X  xrandom_setup();
  2004. X  if (RNGreturns == RET_LONG) {
  2005. X    LPP proc;
  2006. X    proc=lgen_a[RNGalg];
  2007. X    fill_vector(((double)proc(rng)/RNGrange)*2.0);
  2008. X  }
  2009. X  else if (RNGreturns == RET_DOUBLE) {
  2010. X    DPP proc;
  2011. X    proc=dgen_a[RNGalg];
  2012. X    fill_vector(proc(rng)*2.0);
  2013. X    }
  2014. X  else
  2015. X    while (n--)
  2016. X      *v++ = 0;
  2017. X  return(*vreturn);
  2018. X}
  2019. X
  2020. X/*******************************/
  2021. X/* bxrandomrv_f                */
  2022. X/* Return "low quality" bits.  */
  2023. X/* Return -1 if range of RNG   */
  2024. X/*  is not 2^32                */
  2025. X/*******************************/
  2026. X/* This routine will "lose" random bits if they are not requested in
  2027. X *  multiples of (RNGsplit+1)*BBUF_SIZE, since bits are returned by
  2028. X *  pulling them off the random stream sequentially, using up exactly
  2029. X *  as many as are needed in order to generate the requested number
  2030. X *  of bits.
  2031. X * Splitting of this fast bit stream is not currently supported.
  2032. X */
  2033. Xint bxrandomrv_f(rng,n,v)
  2034. X     RNGdata *rng;
  2035. X     long n;
  2036. X     int v[];
  2037. X{
  2038. X  long i,j;
  2039. X  int vdef[1],*vreturn;
  2040. X  long value;
  2041. X  long index;
  2042. X  
  2043. X  inc_counts(rng,n);
  2044. X  set_rng(rng);
  2045. X  random_setup();
  2046. X  
  2047. X  index=0;
  2048. X  
  2049. X  for (i=0;i<n;i++) {
  2050. X    if (index-- == 0) {
  2051. X      value=lxrandomr(rng);;
  2052. X      index=31;
  2053. X    }
  2054. X    v[i] = value & 1;
  2055. X    value = value >> 1;
  2056. X  }
  2057. X  return(RNGrange == 4294967296.0 ? *vreturn: -1);
  2058. X}
  2059. X
  2060. X/*************************************/
  2061. X/* seed_rng                          */
  2062. X/* Seeds the underlying RNG          */
  2063. X/*************************************/
  2064. Xvoid seed_rng(rng, seed)
  2065. X     RNGdata *rng;
  2066. X     long *seed;
  2067. X{
  2068. X  long i;
  2069. X  
  2070. X  /* Keep a record of the seeds */
  2071. X  for (i=0;i<RNGseedsize;i++)
  2072. X    RNGseed[i]=seed[i];
  2073. X  RNGcount1 = 0;             /* Reset counter */
  2074. X  RNGcount2 = 0;
  2075. X  flush_rng(rng);            /* Flush the RNG's buffers */
  2076. X  seed_a[RNGalg](rng, seed); /* Seed the underlying RNG */
  2077. X  mru_rng = rng;             /* This RNG is now the most recently */
  2078. X                             /* initialized or restarted */
  2079. X}
  2080. X
  2081. X/*************************************/
  2082. X/* setRNGparams                      */
  2083. X/* Set RNGalg to alg, and set all    */
  2084. X/*  information which can be derived */
  2085. X/*  from RNGalg.                     */
  2086. X/* Return 0 and print message to     */
  2087. X/*  stderr if alg is out of range    */
  2088. X/* Return 1 otherwise                */
  2089. X/*************************************/
  2090. Xint setRNGparams(rng,alg)
  2091. X     RNGdata *rng;
  2092. X     long alg;
  2093. X{
  2094. X  if (alg<0 || alg>NUM_RNGS-1) /* alg is out of range */
  2095. X    return(0);
  2096. X  else { /* Set RNG parameters */
  2097. X    RNGalg = alg;
  2098. X    RNGstatesize = statesize_a[alg];
  2099. X    RNGseedsize = seedsize_a[alg];
  2100. X    RNGrange = range_a[alg];
  2101. X    strcpy(RNGname,RNGname_a[alg]);
  2102. X    RNGreturns = returns_a[alg];
  2103. X    RNGstatetype = statetype_a[alg];
  2104. X    return(1);
  2105. X  }
  2106. X}
  2107. X
  2108. X/*************************************/
  2109. X/* check_rng                         */
  2110. X/* Check the integrity of the RNG.   */
  2111. X/* Return 1 if ok, 0 if not.         */
  2112. X/*************************************/
  2113. Xint check_rng(rng)
  2114. X     RNGdata *rng;
  2115. X{
  2116. X  /* Temporary variables */
  2117. X  long statesize, seedsize;
  2118. X  double range;
  2119. X  signed int returns;
  2120. X  char name[RNGIDSTRLEN];
  2121. X  int statetype;
  2122. X
  2123. X  if (rng == 0)
  2124. X    return(0);
  2125. X  
  2126. X  /* Have derived RNG values been overwritten? */
  2127. X  statesize = RNGstatesize;
  2128. X  seedsize = RNGseedsize;
  2129. X  range = RNGrange;
  2130. X  strcpy(name,RNGname);
  2131. X  returns = RNGreturns;
  2132. X  statetype = RNGstatetype;
  2133. X
  2134. X  if (!setRNGparams(rng,RNGalg))
  2135. X    return(0);
  2136. X
  2137. X  if (statesize != RNGstatesize || seedsize != RNGseedsize ||
  2138. X      range != RNGrange || strcmp(name,RNGname) || returns !=
  2139. X      RNGreturns || statetype != RNGstatetype)
  2140. X    return(0);
  2141. X
  2142. X  /* Now look at RNGstate (algorithm-specific tests) */
  2143. X  return(check_a[RNGalg](rng));
  2144. X}
  2145. X
  2146. X/*************************************/
  2147. X/* describe_rng                      */
  2148. X/* Write a short ASCII description   */
  2149. X/*  of the RNG to the user-supplied  */
  2150. X/*  string rngid, which must be of   */
  2151. X/*  length at least RNGIDSTRLEN.     */
  2152. X/* If the user has not initialized   */
  2153. X/*  the rng with init_rng() or       */
  2154. X/*  restart_rng(), abort with an     */
  2155. X/*  error message to stderr.         */
  2156. X/* Otherwise return rngid.           */
  2157. X/* Currently only supports RNGs with */
  2158. X/*  at most two seeds.               */
  2159. X/*************************************/
  2160. Xchar *describe_rng (rng,rngid)
  2161. X     RNGdata *rng;
  2162. X     char rngid[RNGIDSTRLEN];
  2163. X{
  2164. X  if (!check_rng(rng)) {
  2165. X    BADRNG_ERR;
  2166. X  }
  2167. X  sprintf(rngid, "RNG state identifier is (%ld, %ld: %ld, %ld; %ld,\
  2168. X%ld; %ld, %ld)\n",
  2169. X      RNGalg, RNGmrandom_alg, RNGseed[0], RNGseed[1],
  2170. X      RNGcount1, RNGcount2, RNGbuffer.size, RNGsplit);
  2171. X  return(rngid);
  2172. X}
  2173. X
  2174. X/*************************************/
  2175. X/* split_rng                         */
  2176. X/* Modify rng to "leapfrog" a number */
  2177. X/*  of generates determined by the   */
  2178. X/*  value of new_value               */
  2179. X/*  (new_value == 0 returns          */
  2180. X/*     every generate)               */
  2181. X/* Returns 0 if new_value < 0        */
  2182. X/* Returns 1 otherwise               */
  2183. X/* Exits on error if rng has not     */
  2184. X/*  been initialized                 */
  2185. X/*************************************/
  2186. Xint split_rng(rng,new_value)
  2187. X     RNGdata *rng;
  2188. X     long new_value;
  2189. X{
  2190. X  if (check_rng(rng)) {
  2191. X    if (new_value < 0)
  2192. X      return(0);
  2193. X    else {
  2194. X      RNGsplit=new_value;
  2195. X      return(1);
  2196. X    }
  2197. X  }
  2198. X  else {
  2199. X    BADRNG_ERR;
  2200. X  }
  2201. X}
  2202. X
  2203. X/*************************************/
  2204. X/* mralg_rng                         */
  2205. X/* Modify rng to use a different     */
  2206. X/*  algorithm for mrandom()          */
  2207. X/* Returns 0 if mralg is out of range*/
  2208. X/* Returns 1 otherwise               */
  2209. X/* Exits on error if rng has not     */
  2210. X/*  been initialized                 */
  2211. X/*************************************/
  2212. Xint mralg_rng(rng,new_value)
  2213. X     RNGdata *rng;
  2214. X     long new_value;
  2215. X{
  2216. X  if (check_rng(rng)) {
  2217. X    if (new_value == 0 || new_value == 1) {
  2218. X      RNGmrandom_alg=new_value;
  2219. X      return(1);
  2220. X    }
  2221. X    else
  2222. X      return(0);
  2223. X  }
  2224. X  else {
  2225. X    BADRNG_ERR;
  2226. X  }
  2227. X}
  2228. X
  2229. X/*************************************/
  2230. X/* range_rng                         */
  2231. X/* Return the range of the RNG       */
  2232. X/*  (i.e. rng is capable of producing*/
  2233. X/*  generates in the range           */
  2234. X/*  0...(range_rng(rng)-1)           */
  2235. X/* Exits on error if rng has not     */
  2236. X/*  been initialized                 */
  2237. X/*************************************/
  2238. Xdouble range_rng(rng)
  2239. X     RNGdata *rng;
  2240. X{
  2241. X  if (check_rng(rng))
  2242. X    return(RNGrange);
  2243. X  else {
  2244. X    BADRNG_ERR;
  2245. X  }
  2246. X}
  2247. X
  2248. X/* Auxiliary routine for allocating memory for an RNG */
  2249. XRNGdata *allocate_rng(rng, alg, bufsize)
  2250. X     RNGdata *rng;
  2251. X     long alg, bufsize;
  2252. X{
  2253. X  if (bufsize <= 0)
  2254. X    bufsize=1;
  2255. X  if ((rng = (RNGdata *)malloc(sizeof(RNGdata))) == 0)
  2256. X    return(0);
  2257. X  if (!setRNGparams(rng,alg))
  2258. X    return(0);
  2259. X  if ((RNGstate=(long *)calloc(RNGstatesize,sizeof(long))) == 0)
  2260. X    return(0);
  2261. X  /* Allocate and clear at least two elements for describe_rng */
  2262. X  if ((RNGseed=(long *)calloc(RNGseedsize > 2 ?
  2263. X                RNGseedsize:2,sizeof(long))) == 0)
  2264. X    return(0);
  2265. X  if (RNGreturns == RET_LONG) {
  2266. X    if ((RNGbuffer.lbuf=RNGbuffer.lbufp =
  2267. X     (long *) calloc(bufsize,sizeof(long))) == 0)
  2268. X      return(0);
  2269. X    RNGbuffer.dbuf=RNGbuffer.dbufp=0;
  2270. X  }
  2271. X  else if (RNGreturns == RET_DOUBLE) {
  2272. X    if ((RNGbuffer.dbuf=RNGbuffer.dbufp =
  2273. X     (double *) calloc(bufsize,sizeof(double))) == 0)
  2274. X      return(0);
  2275. X    RNGbuffer.lbuf=RNGbuffer.lbufp=0;
  2276. X  }
  2277. X  if ((RNGbuffer.bbuf=RNGbuffer.bbufp =
  2278. X       (int *) calloc(BBUF_SIZE,sizeof(int))) == 0)
  2279. X    return(0);
  2280. X  RNGbuffer.size=bufsize;
  2281. X  RNGbuffer.nleft=0;
  2282. X  RNGbuffer.nbleft=0;
  2283. X  return(rng);
  2284. X}
  2285. X
  2286. X/************/
  2287. X/* init_rng */
  2288. X/************/
  2289. X/* Initialize the general-purpose rng data area so that it holds the
  2290. X * state and other data required for the selected algorithm "alg", where
  2291. X *    alg = 0 is a trivial generator that returns state += seed2,
  2292. X *      where state is initially set to seed1.  Use for debugging only!
  2293. X *    alg = 1 is 4.3bsd random.c (non-linear additive feedback)
  2294. X *    alg = 2 is the Knuth/Bentley prand (lagged Fibonnacci)
  2295. X *    alg = 3 is the portable combined (multiplicative) RNG
  2296. X *    alg = 4 is 4.3bsd nrand48.c,
  2297. X *      alg = 5 is 4.3bsd rand
  2298. X *      alg = 6 is Press and Teukolsky's ran0
  2299. X *      alg = 7 is Press and Teukolsky's ran1
  2300. X *      alg = 8 is Press and Teukolsky's ran2
  2301. X *      alg = 9 is Marsaglia's Ultra RNG
  2302. X *
  2303. X * Note: Memory for rng is allocated by this routine.  Before calling
  2304. X *  this routine the user need only declare a pointer to the generator,
  2305. X *  for example
  2306. X *        RNGdata *myrng;
  2307. X *
  2308. X * The mrandom_alg parameter determines which algorithm will be used
  2309. X *  by mrandom when call with this RNG:
  2310. X *      0 = Thomborson's unbiased conversion
  2311. X *      1 = (int) (m * drandomr(rng))
  2312. X *
  2313. X * The bufsize parameter determines the number of entries in the
  2314. X *  buffer.  Buffer space is allocated dynamically during
  2315. X *  initialization.  Thirty-two entries are allocated for the bit
  2316. X *  buffer.
  2317. X *
  2318. X * The count1 parameter indicates how many times the selected RNG algorithm
  2319. X *  should be called prior to returning control to the calling routine.
  2320. X *  We recommend a high value, at least 10000, for this parameter, to minimize
  2321. X *  the ill effects of seeding.  The count2 parameter can be given a non-zero
  2322. X *  value if you wish to "cycle" the generator a huge number of times: it 
  2323. X *  will be called (count2*1e9 + count1) times.  Probably count2 should always
  2324. X *  be 0 until computers become much, much faster than today.
  2325. X *
  2326. X * init_rng() returns a pointer to the initialized RNG unless an
  2327. X *  out-of-range argument is detected (rngalg >9 or < 0; count1 >1e9 or <0;
  2328. X *  or count2 <0), or if memory cannot be allocated for the RNG,
  2329. X *  in which case it returns a null pointer.
  2330. X *
  2331. X * Note: a single program may call init_rng() any number of times, to set up
  2332. X * multiple generators (possibly using more than one RNG algorithm), e.g with 
  2333. X *        RNGdata *myrngs[8];
  2334. X *        long i,sum=0,seed[2];
  2335. X *              seed[1]=0;
  2336. X *        for (i=0; i<7; i++) {
  2337. X *          /* generator #i gets seed1 = i
  2338. X *                seed[0]=i;
  2339. X *          myrngs[i]=init_rng(2,0,seed,100000,0,1024);
  2340. X *        }
  2341. X *        /* our eighth RNG uses algorithm #3
  2342. X *              seed[7]=7;
  2343. X *        myrngs[7]=init_rng(3,0,seed,100000,0,1024);
  2344. X *        /* add 1-bit numbers, one from each generator
  2345. X *        for (i=0; i<7; i++) {
  2346. X *          sum += mrandom(&myrngs[i],2);
  2347. X *        }
  2348. X *
  2349. X * Warning: do not attempt to use multiple RNGdata areas for algorithm #1.
  2350. X *  The 4.3bsd random.c code has internal state that will not be modified
  2351. X *  correctly when you switch generators (this was a bug in the original
  2352. X *  implementation and it would be very difficult to fix here).
  2353. X * 
  2354. X * Warning: Do NOT override previously-initialized RNGs with the results
  2355. X *  of this procedure.  If you have a pointer to a valid RNG and wish to
  2356. X *  initialize a new RNG using the same pointer, you should call
  2357. X *  kill_rng() before calling init_rng().  For example:
  2358. X *              ...
  2359. X *              i=lrandomr(rng); /* This RNG is in use
  2360. X *              kill_rng(rng);   /* Kill the RNG, and THEN
  2361. X *              rng=init_rng(3,1,seed,1000,0,256); /* init a new one
  2362. X *
  2363. X * We recommend that init_rng() be used very sparingly.  Except when
  2364. X * replicating experiments or debugging, it is better to restart an
  2365. X * existing generator (stored in a statefile) than to initialize a new one.
  2366. X */
  2367. XRNGdata *init_rng(alg, mrandom_alg, seed, count1, count2, bufsize)
  2368. X     long alg;         /* The RNG algorithm to use */
  2369. X     long mrandom_alg; /* Algorithm to use for mrandom:
  2370. X              0 = Thomborson's slow but unbasied conversion
  2371. X              1 = (int) (m*drandom()) */
  2372. X     long *seed;          /* Seed */
  2373. X     long count1, count2; /* Initial counts */
  2374. X     long bufsize;        /* Size of buffer */
  2375. X{
  2376. X  RNGdata *rng;
  2377. X  double x[64]; /* Temporary vector */
  2378. X  long i;       /* Loop variable    */
  2379. X  
  2380. X  /* Are count1 and count2 in range? */
  2381. X  if (count1 >= BILLION || count1 < 0 || count2 < 0) {
  2382. X    return(0);
  2383. X  }
  2384. X  /* Is count2 nonzero? */
  2385. X  if (count2 != 0) {
  2386. X    fprintf(stderr, "Warning: this initialization will take a LONG time!\n");
  2387. X    fflush(stderr);
  2388. X  }
  2389. X  if ((rng=allocate_rng(rng,alg,bufsize))==0)
  2390. X    return(0); /* Allocate space for the RNG */
  2391. X  seed_rng(rng, seed);       /* Seed the RNG */
  2392. X  if (mralg_rng(rng, mrandom_alg) == 0)
  2393. X    return(0); /* Set default algorithm for mrandom */
  2394. X  if (split_rng(rng, SPLIT_DEF) == 0)
  2395. X    return(0); /* Set default split */
  2396. X  /* Cycle the generator, in blocks of 64 (for speed) */
  2397. X  for ( ; RNGcount2 < count2; ) { /* Get to the right BILLION count */
  2398. X    dxrandomrv(rng,64,x);
  2399. X  }
  2400. X  for ( ; RNGcount1+64 < count1; ) { /* Get close to the right count1 */
  2401. X    dxrandomrv(rng,64,x);
  2402. X  }
  2403. X  for ( ; RNGcount1 != count1; ) { /* and, finally, do the last few */
  2404. X    dxrandomrv(rng,1,x);
  2405. X  }
  2406. X  return(rng); /* normal exit */
  2407. X  
  2408. X}
  2409. X
  2410. X/*******************************/
  2411. X/* kill_rng                    */
  2412. X/* Frees memory used by an RNG */
  2413. X/* Returns 0 if kill failed    */
  2414. X/* Returns 1 otherwise         */
  2415. X/*******************************/
  2416. Xint kill_rng(rng)
  2417. X     RNGdata *rng;
  2418. X{
  2419. X  if (check_rng(rng)) {
  2420. X    free(RNGstate);
  2421. X    free(RNGseed);
  2422. X    free(RNGbuffer.lbuf);
  2423. X    free(RNGbuffer.dbuf);
  2424. X    free(RNGbuffer.bbuf);
  2425. X    free(rng);
  2426. X    return(1);
  2427. X  }
  2428. X  else
  2429. X    return(0);
  2430. X}
  2431. X
  2432. X/***************************************/
  2433. X/* nextval                             */
  2434. X/* Return the next lxrandomrv() output */
  2435. X/*  without disturbing the RNG state.  */
  2436. X/***************************************/
  2437. Xlong nextval(rng)
  2438. X     RNGdata *rng;
  2439. X{
  2440. X  static long *state=0;
  2441. X  long i, r, tcount1, tcount2, retval;
  2442. X  
  2443. X  if (state != 0)
  2444. X    free(state);
  2445. X  state = (long *)calloc(RNGstatesize,sizeof(long));
  2446. X  /* Check that this only allocates the first time */
  2447. X  
  2448. X  /* Preserve old RNG state */
  2449. X  tcount1 = RNGcount1;
  2450. X  tcount2 = RNGcount2;
  2451. X  for (i=0; i<RNGstatesize; i++) {
  2452. X    state[i] = RNGstate[i];
  2453. X  }
  2454. X  
  2455. X  /* Find the next value in this pseudorandom sequence */
  2456. X  retval=lxrandomr(rng);
  2457. X  
  2458. X  /* Restore the RNG state */
  2459. X  RNGcount1 = tcount1;
  2460. X  RNGcount2 = tcount2;
  2461. X  /* Special fixup for 4.3bsd random()'s hidden state variables */
  2462. X  if (RNGalg == 1) for (i=1; i<31; i++) {
  2463. X    r = random();
  2464. X  }
  2465. X  for (i=0; i<RNGstatesize; i++) {
  2466. X    RNGstate[i] = state[i];
  2467. X  }
  2468. X  
  2469. X  return(retval);
  2470. X}
  2471. X
  2472. X/* printvector */
  2473. X/* auxiliary routine for save_rng */
  2474. Xvoid printvector(fp,size,vector,type)
  2475. X     FILE *fp;
  2476. X     long size;
  2477. X     long *vector;
  2478. X     int type;
  2479. X{
  2480. X  long i,j,printval;
  2481. X  long windex,bindex;
  2482. X  long mask;
  2483. X
  2484. X  mask=0;
  2485. X  for(j=0;j < (type << 3); j++)
  2486. X    mask = (mask << 1) | 1;
  2487. X  
  2488. X  windex=0;
  2489. X  bindex=31;
  2490. X  i=0;
  2491. X
  2492. X  while (windex<size) {
  2493. X    printval = 0;
  2494. X    for (j=0; j < (type << 3); j++) {
  2495. X      printval |= (vector[windex] & (1 << bindex));
  2496. X      if (bindex-- == 0) {
  2497. X    bindex = 31;
  2498. X    windex++;
  2499. X      }
  2500. X    }
  2501. X    fprintf(fp, RNGfileLINEnn[type],
  2502. X        (printval >> ((bindex+1)%32)) & mask);
  2503. X    if (++i == 4) {
  2504. X      fprintf(fp,"\n");
  2505. X      i = 0;
  2506. X    }
  2507. X  }
  2508. X  fprintf(fp,"\n");
  2509. X}
  2510. X
  2511. X/* scanvector */
  2512. X/* auxiliary routine for restart_rng */
  2513. Xvoid scanvector(fp,size,vector,type)
  2514. X     FILE *fp;
  2515. X     long size;
  2516. X     long *vector;
  2517. X     int type;
  2518. X{
  2519. X  long i,j,scanval;
  2520. X  long windex,bindex;
  2521. X
  2522. X  windex=-1;
  2523. X  bindex=0;
  2524. X  i=0;
  2525. X
  2526. X  while (windex<size) {
  2527. X    fscanf(fp,RNGfileLINEnn[type],&scanval);
  2528. X    for (j=0; j < (type << 3); j++) {
  2529. X      if (bindex-- == 0) {
  2530. X    bindex=31;
  2531. X    windex++;
  2532. X    vector[windex]=0;
  2533. X      }
  2534. X    }
  2535. X    vector[windex] |= (scanval << bindex);
  2536. X    if (++i == 4) {
  2537. X      fscanf(fp,"\n");
  2538. X      i = 0;
  2539. X    }
  2540. X  }
  2541. X  fscanf(fp,"\n");
  2542. X}
  2543. X
  2544. X/*********************************************/
  2545. X/* save_rng                                  */
  2546. X/* Save the RNG state to a statefile.        */
  2547. X/* Return 0 if RNG couldn't be saved.        */
  2548. X/* Returns 1 otherwise.                      */
  2549. X/*********************************************/
  2550. Xint save_rng(rng,filename)
  2551. X     RNGdata *rng;
  2552. X     char *filename;
  2553. X{
  2554. X  FILE *fp;
  2555. X  long i;
  2556. X  unsigned short *sarray;
  2557. X  RNGdata *temp_rng;
  2558. X
  2559. X  if (!check_rng(rng))
  2560. X    return(0);
  2561. X
  2562. X  /* Write the statefile */
  2563. X  fp = fopen(filename, "w");
  2564. X  if (!fp) /* Couldn't open file for writing */
  2565. X    return(0);
  2566. X  
  2567. X  fprintf(fp, RNGfileLINE0, RNGalg);
  2568. X  fprintf(fp,RNGname_a[RNGalg]);
  2569. X  fprintf(fp, RNGfileLINE1,RNGbuffer.size);
  2570. X  fprintf(fp, RNGfileLINE2);
  2571. X  printvector(fp,RNGseedsize,RNGseed,RNGstatetype);
  2572. X  fprintf(fp, RNGfileLINE3, RNGcount2, RNGcount1);
  2573. X  fprintf(fp, RNGfileLINE4, nextval(rng));
  2574. X  fprintf(fp, RNGfileLINE5, RNGsplit+1);
  2575. X  fprintf(fp, RNGfileLINE6, RNGmrandom_alg);
  2576. X  fprintf(fp, RNGfileLINE7);
  2577. X  printvector(fp,RNGstatesize,RNGstate,RNGstatetype);
  2578. X  fclose(fp);
  2579. X
  2580. X  temp_rng=restart_rng(filename); /* Verify save */
  2581. X  if (temp_rng == 0)
  2582. X    return(0);
  2583. X  else {
  2584. X    kill_rng(temp_rng);
  2585. X    return(1);
  2586. X  }
  2587. X}
  2588. X
  2589. X/****************************************************************/
  2590. X/* restart_rng                                                  */
  2591. X/* Restart a generator from a statefile.                        */
  2592. X/* Return a null pointer if the restart failed due to a garbled */
  2593. X/*  or nonexistent statefile.                                   */
  2594. X/* Otherwise return a pointer to the restarted RNG.             */
  2595. X/* WARNING: An RNG which has been previously initialized using  */
  2596. X/*  init_rng() should NOT be overwritten with the return value  */
  2597. X/*  of this procedure.  In order to provide a "fresh" RNG for   */
  2598. X/*  this procedure, do one of the following:                    */
  2599. X/*     - Declare a new RNG                                      */
  2600. X/*     - Kill a previously initialized RNG using kill_rng()     */
  2601. X/****************************************************************/
  2602. XRNGdata *restart_rng(filename)
  2603. X     char *filename;
  2604. X{
  2605. X  FILE *fp;
  2606. X  unsigned short *sarray; /* for reading alg #4's statefile */
  2607. X  long i, m, r; /* temps */
  2608. X  long alg, bufsize;
  2609. X  int errflag; /* initially 0, becomes 1 if a problem is discovered */
  2610. X  RNGdata *rng;
  2611. X  
  2612. X  /* If mru_rng == 0, we assume random() hasn't been called yet,
  2613. X   * so its internal state is at its startup values.
  2614. X   * If mru_rng != 0 and alg=1, then we've used random() already, so we
  2615. X   * must reset its internal state to its startup values.
  2616. X   */
  2617. X  if (mru_rng != 0 && mru_rng->rngalg == 1) {
  2618. X    m = (mru_rng->rngcount1%31) + mru_rng->rngcount2*(BILLION%31);
  2619. X    /* note: the hidden state variables are counters mod 31 */
  2620. X    for ( ; (m%31) != 0; m++) {
  2621. X      r = random();
  2622. X    }
  2623. X  }
  2624. X  
  2625. X  /* Restore counter values, retrieve original RNG seeds and current state */
  2626. X  fp = fopen(filename, "r");
  2627. X  if (!fp)
  2628. X    return(0);
  2629. X  /* Read statefile */
  2630. X  fscanf(fp, RNGfileLINE0, &alg);
  2631. X  fscanf(fp,RNGname_a[alg]);
  2632. X  fscanf(fp, RNGfileLINE1, &bufsize);
  2633. X  if ((rng=allocate_rng(rng, alg, bufsize))==0)
  2634. X    return(0);
  2635. X  fscanf(fp, RNGfileLINE2);
  2636. X  scanvector(fp,RNGseedsize,RNGseed,RNGstatetype);
  2637. X  fscanf(fp, RNGfileLINE3, &RNGcount2, &RNGcount1);
  2638. X  fscanf(fp, RNGfileLINE4, &RNGnextval);
  2639. X  fscanf(fp, RNGfileLINE5, &RNGsplit);
  2640. X  RNGsplit--;
  2641. X  fscanf(fp, RNGfileLINE6, &RNGmrandom_alg);
  2642. X  fscanf(fp, RNGfileLINE7);
  2643. X  scanvector(fp,RNGstatesize,RNGstate,RNGstatetype);
  2644. X  fclose(fp);
  2645. X
  2646. X  errflag = 0; /* no errors detected yet */
  2647. X
  2648. X  /* If reconstruction will be rapid, do it as an error check. */ 
  2649. X  if (RNGcount1 < 1000 && RNGcount2 == 0) {
  2650. X    RNGdata *test_rng;
  2651. X    test_rng = init_rng(RNGalg, RNGmrandom_alg, RNGseed,
  2652. X            RNGcount1, RNGcount2, RNGbuffer.size);
  2653. X    /* See if we got to the same state */
  2654. X    for (i=0; i<RNGstatesize; i++) {
  2655. X      if ((test_rng->rngstate)[i] != RNGstate[i]) {
  2656. X        errflag = 1;
  2657. X      }
  2658. X    }
  2659. X    kill_rng(test_rng);
  2660. X  } else { /* Just update mru_rng */
  2661. X    /* first, some special hacks for alg 1 */
  2662. X    if (RNGalg == 1) {
  2663. X      /* tell random() we've got a 31-word statefile */
  2664. X      RNGstate[0] = MRNGSTATE0;
  2665. X      setstate(RNGstate);
  2666. X      /* and modify random()'s hidden state to correspond to the RNGcount */
  2667. X      m = RNGcount1%31 + RNGcount2*(BILLION%31);
  2668. X      for (i=0 ; i<(m%31); i++) {
  2669. X        r = random();
  2670. X      }
  2671. X    }
  2672. X    mru_rng = rng; /* remember this rng, for use by mrandom() and frandom() */
  2673. X  }
  2674. X  
  2675. X  /* see if RNG state looks ok */
  2676. X  errflag = errflag || !check_rng(rng);
  2677. X
  2678. X  /* Check nextval() operation */
  2679. X  if (nextval(rng) != nextval(rng)) {
  2680. X    errflag = 1;
  2681. X  }
  2682. X
  2683. X  if (errflag) {
  2684. X    kill_rng(rng);
  2685. X    return(0);
  2686. X  }
  2687. X  return(rng);
  2688. X}
  2689. X
  2690. X/*********************************************/
  2691. X/* flush_rng                                 */
  2692. X/* Flush the contents of the RNG's buffers   */
  2693. X/* Returns 1 upon success, 0 upon failure    */
  2694. X/*********************************************/
  2695. Xint flush_rng(rng)
  2696. X     RNGdata *rng;
  2697. X{
  2698. X  if (check_rng(rng)) {
  2699. X    if (RNGreturns == RET_LONG) {
  2700. X      RNGbuffer.lbufp=RNGbuffer.lbuf;
  2701. X      RNGbuffer.dbuf=RNGbuffer.dbufp=0;
  2702. X    }
  2703. X    else if (RNGreturns == RET_DOUBLE) {
  2704. X      RNGbuffer.dbufp=RNGbuffer.dbuf;
  2705. X      RNGbuffer.lbuf=RNGbuffer.lbufp=0;
  2706. X    }
  2707. X    RNGbuffer.nleft=0;
  2708. X    RNGbuffer.bbufp=RNGbuffer.bbuf;
  2709. X    RNGbuffer.nbleft=0;
  2710. X    return(1);
  2711. X  }
  2712. X  else
  2713. X    return(0);
  2714. X}
  2715. X
  2716. X/*************/
  2717. X/* mrandomrv */
  2718. X/*************/
  2719. X/* Generate a length-n vector v of random longs, uniformly distributed
  2720. X * in the range 0..m-1, using the indicated rng.  Return a copy of the
  2721. X * first random variate, v[0].
  2722. X *
  2723. X * Special-case parameter values: if rng==0, use the RNG that was
  2724. X * the most-recently initialized or restarted; if n==0, return one
  2725. X * random variate and don't write into v[]. 
  2726. X *
  2727. X * Our code does not have a deterministic bias for any m, unlike the
  2728. X * typical "good" code
  2729. X *        (int) floor( drandom() * (double) m )
  2730. X * or the commonly-used, but hazardous (because it exposes the flaws
  2731. X * in many RNGs) code 
  2732. X *        random()%m
  2733. X * We remove the bias by making multiple calls (on rare occasions)
  2734. X * to the underlying generator.  The expected number of RNG calls
  2735. X * is upper-bounded by n/(1 - (RNGrange%m)/RNGrange) < 2n.
  2736. X *
  2737. X * The program is aborted, with an error message, if
  2738. X *  m exceeds the range of the RNG.
  2739. X *
  2740. X * The program will also abort, again with an error message to stderr,
  2741. X * if the generator is behaving so non-randomly that our multiple-call
  2742. X * bias-removal algorithm makes an excessive number of calls to the
  2743. X * underlying generator.
  2744. X */
  2745. Xlong mrandomrv(rng,m,n,v)
  2746. X     RNGdata *rng;
  2747. X     long m,n,v[];
  2748. X{
  2749. X  long i,yield; /* temps */
  2750. X  long ncalls; /* counts number of RNG calls during this mrandomrv call */
  2751. X  long vdef[1],*vreturn; /* default value for v */
  2752. X  char rngdesc[RNGIDSTRLEN]; /* for a describe_rng() call */
  2753. X  double d; /* temporary variable */
  2754. X
  2755. X  /* we can avoid some calcs&tests if m and rng range are unchanged */ 
  2756. X  static long lastm=0,lastrangem1=0; /* m on last call */
  2757. X  static double lastrange=0;         /* range on last call */
  2758. X  static double maxv;  /* largest "useful" RNG output for this m */
  2759. X  static double ifreq; /* multiplicity of RNG -> mrandomr() mapping */
  2760. X  static double dm;    /* floated value of m */
  2761. X  static int is32bit;  /* is rng is 32-bit generator? */
  2762. X
  2763. X  set_rng(rng);
  2764. X
  2765. X  random_setup();
  2766. X
  2767. X  if (m != lastm) {
  2768. X    dm=longtodouble(m);
  2769. X    lastm=m;
  2770. X    if (dm > RNGrange) { /* Is m in range? */
  2771. X      fprintf(stderr,
  2772. X          "Error: mrandom() argument value, %ld, is out of range.\n", m);
  2773. X      fprintf(stderr,
  2774. X          "The range of this RNG is %.0f.\n", RNGrange);
  2775. X      fflush(stderr);
  2776. X      exit(1);
  2777. X    }
  2778. X  }
  2779. X  switch (RNGmrandom_alg) {
  2780. X  case 0: /* Thomborson's unbiased conversion */
  2781. X    /* see if RNGrange has changed recently */
  2782. X    if (RNGrange != lastrange) {
  2783. X      /* yes, save current RNGrange ... */
  2784. X      lastrange = RNGrange;
  2785. X
  2786. X      /* ... and recalculate ifreq and maxv */      
  2787. X      /* Compute ifreq = multiplicity of RNG -> mrandom(m) mapping,
  2788. X       * and maxv = the largest "useful" RNG output for this m.
  2789. X       *
  2790. X       * You might want to rewrite this code if you don't have FP hardware.
  2791. X       */
  2792. X      ifreq = floor(RNGrange/dm);
  2793. X      maxv = RNGrange - (int)(RNGrange - ifreq*dm);
  2794. X      is32bit = (RNGrange > MAXLONG + 1.0);
  2795. X    }
  2796. X    
  2797. X    /* the expected # of calls to underlying RNG is */
  2798. X    /* n/(1-xdiscard/range) < 2n */
  2799. X    
  2800. X    ncalls = 0; /* number of RNG calls so far */
  2801. X    for (yield=0; yield<n;  ) {
  2802. X      
  2803. X      /* fill (or re-fill) v[] */
  2804. X      lxrandomrv(rng,n-yield,&v[yield]);
  2805. X      /* make sure ncalls doesn't get ridiculously large */
  2806. X      ncalls += n-yield;
  2807. X      if (ncalls > 3*n+300) {
  2808. X    /* For yield ==n, mean(ncalls) < 2*n; std dev < sqrt(2*n);
  2809. X     * If ncalls > 3*n + 300, we are dozens of stddevs away from mean!
  2810. X     */
  2811. X    fprintf(stderr, "Trouble in mrandomrv, m = %ld\n",m);
  2812. X    fprintf(stderr, "Aborting program: this RNG is apparently stuck!\n");
  2813. X    fprintf(stderr, describe_rng(rng,rngdesc));
  2814. X    exit(1);
  2815. X      }
  2816. X      
  2817. X      /* the following steps are coded for 32-bit and non-32-bit RNGs */
  2818. X      /* for reasons of efficiency (32-bit RNGs will be slower)       */
  2819. X      /* first, for all generators except 32-bit generators */
  2820. X      if (!is32bit) {
  2821. X    for (  ; yield<n; yield++) {
  2822. X      if (v[yield] > maxv) {
  2823. X        break;
  2824. X      }
  2825. X    }
  2826. X    for (i=yield+1; i<n; i++) {
  2827. X      if (v[i] <= maxv) {
  2828. X        v[yield] = v[i];
  2829. X        yield++;
  2830. X      }
  2831. X    }
  2832. X    for (i=0; i<n; i++) {
  2833. X      v[i] = (long) ((double)v[i] / ifreq);
  2834. X    }
  2835. X      }
  2836. X      else { /* for 32-bit generators */
  2837. X    /* find first out-of-range v[], if any, */
  2838. X    for (  ; yield<n; yield++) {
  2839. X      if (longtodouble(v[yield]) > maxv) {
  2840. X        break;
  2841. X      }
  2842. X    }
  2843. X    /* and move in-range values to front of v[] */
  2844. X    for (i=yield+1; i<n; i++) {
  2845. X      if (longtodouble(v[i]) <= maxv) {
  2846. X        v[yield] = v[i];
  2847. X        yield++;
  2848. X      }
  2849. X    }
  2850. X    /* map v[] values, with ifreq:1 multiplicity, */
  2851. X    /* into the range 0..m-1 */
  2852. X    for (i=0; i<n; i++) {
  2853. X      v[i] = (long) (longtodouble(v[i]) / ifreq);
  2854. X    }
  2855. X      }
  2856. X    }
  2857. X    return (*vreturn);
  2858. X    break;
  2859. X  case 1: /* (long) m*dxrandomr() */
  2860. X    for (i=0;i<n;i++)
  2861. X      v[i]= (long) (dm*dxrandomr(rng));
  2862. X    return(*vreturn);
  2863. X    break;
  2864. X  default:
  2865. X    break;
  2866. X  }
  2867. X}
  2868. END_OF_FILE
  2869. if test 42469 -ne `wc -c <'src/mrandom.c'`; then
  2870.     echo shar: \"'src/mrandom.c'\" unpacked with wrong size!
  2871. fi
  2872. # end of 'src/mrandom.c'
  2873. fi
  2874. echo shar: End of archive 3 \(of 6\).
  2875. cp /dev/null ark3isdone
  2876. MISSING=""
  2877. for I in 1 2 3 4 5 6 ; do
  2878.     if test ! -f ark${I}isdone ; then
  2879.     MISSING="${MISSING} ${I}"
  2880.     fi
  2881. done
  2882. if test "${MISSING}" = "" ; then
  2883.     echo You have unpacked all 6 archives.
  2884.     rm -f ark[1-9]isdone
  2885. else
  2886.     echo You still need to unpack the following archives:
  2887.     echo "        " ${MISSING}
  2888. fi
  2889. ##  End of shell archive.
  2890. exit 0
  2891.