home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Think Class Libraries / CRandom 1.0 / CRandom.c next >
Encoding:
C/C++ Source or Header  |  1994-11-30  |  4.1 KB  |  160 lines  |  [TEXT/KAHL]

  1. /*
  2.  * CRandom.c
  3.  * A handy little random-number generator.  Just drop it in your project,
  4.  * include the header, and call "x = gRandom->linearShort(low, high)".
  5.  * Version 1.1.1, 14 April 1992
  6.  *
  7.  * by Jamie McCarthy
  8.  * © Copyright 1992 by James R. McCarthy.  All rights reserved.
  9.  * This code can be both distributed and used freely.
  10.  * Internet: k044477@kzoo.edu            AppleLink: j.mccarthy
  11.  * Telephone:  800-421-4157 or US 616-665-7075 (9:00-5:00 Eastern time)
  12.  * I'm releasing this code with the hope that someone will get something
  13.  * out of it.  Feedback of any sort, even just letting me know that you're
  14.  * using it, is greatly appreciated!
  15.  *
  16.  * So far, the only implemented method to get random numbers is
  17.  * linearShort(), which will return a signed 16-bit value between two
  18.  * numbers you specify, with equal probability of each number occurring.
  19.  * I've been meaning to write spinoffs of linearShort(), like
  20.  * poissonShort() and bellCurveShort(), but haven't gotten around to it.
  21.  * If you'd like to see them (or if you make one), drop me a line.
  22.  *
  23.  * Plugging a given value into seed() will always produce the same series.
  24.  * The object is seeded automatically when it's initialized.
  25.  *
  26.  * The algorithm is straight out of Numerical Recipes, translated from
  27.  * the original Fortran version.  I've made it as clear as possible, and
  28.  * kept it reasonably fast without dropping into assembly.
  29.  *
  30.  * I haven't needed a 32-bit routine yet, so I haven't written one.
  31.  * Again, if you want one or have written one, drop me a line.
  32.  *
  33.  * The randomize...Array() methods are spinoffs of linearShort that I
  34.  * threw in for fun.  They scramble up the elements of an array, and
  35.  * should be pretty self-explanatory.  Some people on comp.programming
  36.  * assure me that this algorithm is the proper one.
  37.  *
  38.  * CHANGE HISTORY:
  39.  *
  40.  * From version 1.1 to 1.1.1:
  41.  * Changed a few comments, and added a register declaration.
  42.  *
  43.  * From version 1.0 to 1.1:
  44.  * Added "extern CRandom *gRandom" to the header file.
  45.  *
  46.  */
  47.  
  48.  
  49.  
  50. /******************************/
  51.  
  52. #include "CRandom.h"
  53.  
  54. /******************************/
  55.  
  56. #define MULTIPLICAND (4096)
  57. #define MULTIPLY(x) ((x) << 12)
  58.  
  59. #define ADDEND (150889)
  60. #define ADD(x) ((x) + ADDEND)
  61.  
  62.     /* this probably isn't really a word, but what the hell */
  63. #define MODULEND (NDISTINCTRANDOMVALUES)
  64. #define MODULO(x) ((x) % MODULEND)
  65.  
  66. #define NEXTVAL(x) (MODULO(ADD(MULTIPLY(x))))
  67.  
  68. /******************************/
  69.  
  70. CRandom *gRandom;
  71.  
  72. /******************************/
  73.  
  74.  
  75.  
  76. void CRandom::IRandom(void)
  77. {
  78.     unsigned long theDateTime;
  79.     GetDateTime(&theDateTime);
  80.     seed(theDateTime ^ TickCount());
  81. }
  82.  
  83.  
  84.  
  85. void CRandom::seed(unsigned long seedVal)
  86. {
  87.     register short j;
  88.     
  89.     dummy = MODULO(Abs(ADDEND - seedVal));
  90.     for (j = NRANDOMSLOTS-1; j >= 0; j--) {
  91.         seeds[j] = dummy = NEXTVAL(dummy);
  92.     }
  93.     value = dummy = NEXTVAL(dummy);
  94. }
  95.  
  96.  
  97.  
  98. short CRandom::linearShort(register short lowest, short highest)
  99. {
  100.     register long interval = highest - lowest + 1;
  101.     register long partitionSize;
  102.     register short j;
  103.     
  104.     if (interval <= 0) return lowest;
  105.     partitionSize = (NDISTINCTRANDOMVALUES-1)/interval;
  106.     while (TRUE) {
  107.         j = (NRANDOMSLOTS*value) / NDISTINCTRANDOMVALUES;
  108.         value = seeds[j];
  109.         seeds[j] = dummy = NEXTVAL(dummy);
  110.         if (value < partitionSize * interval) {
  111.             return lowest + value/partitionSize;
  112.         }
  113.     }
  114. }
  115.  
  116.  
  117.  
  118. void CRandom::randomizeArray(register short nElements, register Ptr theArray,
  119.     register short elementSize)
  120. {
  121.     register short i, j;
  122.     register long sourceOffset;
  123.     
  124.     sourceOffset = 0;
  125.     
  126.     for (i = 0; i < nElements-1; i++) {
  127.         short swapWith;
  128.         register char temp;
  129.         register long destOffset;
  130.         
  131.         swapWith = linearShort(i, nElements-1);
  132.         destOffset = swapWith * elementSize;
  133.         
  134.         for (j = 0; j < elementSize; j++) {
  135.             temp = theArray[destOffset + j];
  136.             theArray[destOffset + j] = theArray[sourceOffset + j];
  137.             theArray[sourceOffset + j] = temp;
  138.         }
  139.         
  140.         sourceOffset += elementSize;
  141.     }
  142. }
  143.  
  144.  
  145.  
  146. void CRandom::randomizeShortArray(short nElements, short *theArray)
  147. {
  148.     randomizeArray(nElements, (Ptr) theArray, 2);
  149. }
  150.  
  151.  
  152.  
  153. void CRandom::randomizeLongArray(short nElements, long *theArray)
  154. {
  155.     randomizeArray(nElements, (Ptr) theArray, 4);
  156. }
  157.  
  158.  
  159.  
  160.