rng.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. #include "config.h"
  2. #include "rng.h"
  3. #include <math.h>
  4. #include "mcell_structs.h"
  5. extern struct volume *world;
  6. /*************************************************************************
  7. * Ziggurat Gaussian generator
  8. *
  9. * The Ziggurat algorithm works, loosely speaking, by dividing the
  10. * probability space under the Gaussian pdf into 128 rectangular
  11. * regions of equal probability. Obviously, since the regions are
  12. * rectangular, each region will intersect the pdf, and part of the
  13. * region will lie outside.
  14. *
  15. * With a single random integer selection, we choose a region under the
  16. * curve and an x position within the bounds of the region. Using
  17. * table "K" below, it quickly determines whether the column of the
  18. * region with the chosen X position lies entirely under the pdf. If
  19. * so, the value is chosen. If not, it will choose an independent Y
  20. * coordinate, and test whether the X,Y point lies under the pdf.
  21. * Essentially, this weights values based on the fraction of the cross
  22. * section of the box which lies inside the curve at the chosen X
  23. * coordinate.
  24. *
  25. * Now, the bottom-most region, encompassing the tails, is dealt with
  26. * as a special case, using a more expensive formula to choose an X and
  27. * Y within the region, and applying the same rejection test.
  28. *
  29. * For a full description, see
  30. * The Ziggurat method for generating random variables -
  31. * Marsaglia, Tsang - 2000
  32. *************************************************************************/
  33. #define R_VALUE (3.442619855899)
  34. static const double SCALE_FACTOR = R_VALUE;
  35. static const double RECIP_SCALE_FACTOR = 1.0 / R_VALUE;
  36. /* Tabulated PDF at ends of strips */
  37. static const double YTAB[128] =
  38. {
  39. 1.0000000000000, 0.96359862301100, 0.93628081335300, 0.91304110425300,
  40. 0.8922785066960, 0.87323935691900, 0.85549640763400, 0.83877892834900,
  41. 0.8229020836990, 0.80773273823400, 0.79317104551900, 0.77913972650500,
  42. 0.7655774360820, 0.75243445624800, 0.73966978767700, 0.72724912028500,
  43. 0.7151433774130, 0.70332764645500, 0.69178037703500, 0.68048276891000,
  44. 0.6694182972330, 0.65857233912000, 0.64793187618900, 0.63748525489600,
  45. 0.6272219914500, 0.61713261153200, 0.60720851746700, 0.59744187729600,
  46. 0.5878255314650, 0.57835291380300, 0.56901798419800, 0.55981517091100,
  47. 0.5507393208770, 0.54178565668200, 0.53294973914500, 0.52422743462800,
  48. 0.5156148863730, 0.50710848925300, 0.49870486747800, 0.49040085481200,
  49. 0.4821934769860, 0.47407993601000, 0.46605759612500, 0.45812397121400,
  50. 0.4502767134670, 0.44251360317100, 0.43483253947300, 0.42723153202200,
  51. 0.4197086933790, 0.41226223212000, 0.40489044654800, 0.39759171895500,
  52. 0.3903645103820, 0.38320735581600, 0.37611885978800, 0.36909769233400,
  53. 0.3621425852820, 0.35525232883400, 0.34842576841500, 0.34166180177600,
  54. 0.3349593763110, 0.32831748658800, 0.32173517206300, 0.31521151497000,
  55. 0.3087456383670, 0.30233670433800, 0.29598391232000, 0.28968649757100,
  56. 0.2834437297390, 0.27725491156000, 0.27111937764900, 0.26503649338700,
  57. 0.2590056539120, 0.25302628318300, 0.24709783313900, 0.24121978293200,
  58. 0.2353916382390, 0.22961293064900, 0.22388321712200, 0.21820207951800,
  59. 0.2125691242010, 0.20698398170900, 0.20144630649600, 0.19595577674500,
  60. 0.1905120942560, 0.18511498440600, 0.17976419618500, 0.17445950232400,
  61. 0.1692006994920, 0.16398760860000, 0.15882007519500, 0.15369796996400,
  62. 0.1486211893480, 0.14358965629500, 0.13860332114300, 0.13366216266900,
  63. 0.1287661893090, 0.12391544058200, 0.11910998874500, 0.11434994070300,
  64. 0.1096354402300, 0.10496667053300, 0.10034385723200, 0.09576727182660,
  65. 0.0912372357329, 0.08675412501270, 0.08231837593200, 0.07793049152950,
  66. 0.0735910494266, 0.06930071117420, 0.06506023352900, 0.06087048217450,
  67. 0.0567324485840, 0.05264727098000, 0.04861626071630, 0.04464093597690,
  68. 0.0407230655415, 0.03686472673860, 0.03306838393780, 0.02933699774110,
  69. 0.0256741818288, 0.02208443726340, 0.01857352005770, 0.01514905528540,
  70. 0.0118216532614, 0.00860719483079, 0.00553245272614, 0.00265435214565
  71. };
  72. /* Tabulated 'K' for quick out on strips (strip #0 at bottom, strips
  73. * 1...127 counting down from the top */
  74. static const unsigned long KTAB[128] = {
  75. 3961069056u, 0u, 3223204864u, 3653799168u,
  76. 3837168384u, 3938453504u, 4002562304u, 4046735616u,
  77. 4078995712u, 4103576064u, 4122919680u, 4138533632u,
  78. 4151398144u, 4162178048u, 4171339520u, 4179219968u,
  79. 4186068736u, 4192074496u, 4197382656u, 4202106624u,
  80. 4206336512u, 4210145280u, 4213591808u, 4216723968u,
  81. 4219582464u, 4222200320u, 4224606208u, 4226823936u,
  82. 4228873984u, 4230773504u, 4232538112u, 4234180864u,
  83. 4235713280u, 4237145088u, 4238485504u, 4239742208u,
  84. 4240921856u, 4242030848u, 4243074816u, 4244058368u,
  85. 4244986112u, 4245861888u, 4246689024u, 4247471360u,
  86. 4248211200u, 4248911616u, 4249574656u, 4250202624u,
  87. 4250797824u, 4251361536u, 4251895808u, 4252401920u,
  88. 4252881408u, 4253335552u, 4253765632u, 4254172416u,
  89. 4254556928u, 4254920192u, 4255262976u, 4255586048u,
  90. 4255889920u, 4256175360u, 4256442880u, 4256693248u,
  91. 4256926464u, 4257143040u, 4257343488u, 4257528064u,
  92. 4257696768u, 4257850368u, 4257988608u, 4258111488u,
  93. 4258219776u, 4258312704u, 4258391040u, 4258454016u,
  94. 4258502144u, 4258535168u, 4258552832u, 4258554880u,
  95. 4258541056u, 4258511360u, 4258464768u, 4258401536u,
  96. 4258320896u, 4258222080u, 4258104832u, 4257968128u,
  97. 4257811200u, 4257633280u, 4257433088u, 4257209856u,
  98. 4256961792u, 4256687616u, 4256385792u, 4256054272u,
  99. 4255691264u, 4255294208u, 4254860288u, 4254386688u,
  100. 4253869824u, 4253305856u, 4252690176u, 4252017664u,
  101. 4251282176u, 4250476800u, 4249593088u, 4248621568u,
  102. 4247550720u, 4246366464u, 4245052672u, 4243589120u,
  103. 4241950720u, 4240106752u, 4238018048u, 4235635200u,
  104. 4232893184u, 4229705472u, 4225955328u, 4221478912u,
  105. 4216040192u, 4209284608u, 4200653824u, 4189208320u,
  106. 4173230848u, 4149180928u, 4108286464u, 4020287488u,
  107. };
  108. /* Tabulated 'W' - scale for output values which aren't in the tails.
  109. */
  110. static const double WTAB[128] = {
  111. 8.6953453083203121e-10, 6.3405591725390621e-11, 8.4488869224218753e-11, 9.9314962924609369e-11,
  112. 1.1116387731953125e-10, 1.2122657128203126e-10, 1.3008270556367187e-10, 1.3806213294726563e-10,
  113. 1.4537213775703125e-10, 1.5215230301562501e-10, 1.5850154873593751e-10, 1.6449279254492188e-10,
  114. 1.7018149410312499e-10, 1.7561092513125e-10, 1.8081557188632812e-10, 1.8582341630273437e-10,
  115. 1.9065751455351563e-10, 1.9533711929062499e-10, 1.9987849626093751e-10, 2.04295530709375e-10,
  116. 2.08600185790625e-10, 2.1280285463710938e-10, 2.1691263460195312e-10, 2.2093754361679686e-10,
  117. 2.2488469284960938e-10, 2.2876042594218749e-10, 2.3257043236796876e-10, 2.3631984053750003e-10,
  118. 2.4001329488320311e-10, 2.4365502016640626e-10, 2.4724887549179688e-10, 2.5079839997539061e-10,
  119. 2.5430685159257813e-10, 2.5777724040898438e-10, 2.6121235716445313e-10, 2.6461479798749998e-10,
  120. 2.6798698586328124e-10, 2.7133118937656251e-10, 2.7464953914179685e-10, 2.7794404227695312e-10,
  121. 2.8121659520312502e-10, 2.8446899501171874e-10, 2.8770294960624999e-10, 2.9092008678046877e-10,
  122. 2.9412196238398437e-10, 2.973100676984375e-10, 3.0048583611992187e-10, 3.0365064925234374e-10,
  123. 3.0680584247773435e-10, 3.0995271007539061e-10, 3.1309250994960936e-10, 3.1622646801875002e-10,
  124. 3.1935578230429687e-10, 3.2248162677148437e-10, 3.2560515494570314e-10, 3.2872750334726564e-10,
  125. 3.3184979476601564e-10, 3.3497314140859373e-10, 3.3809864793867189e-10, 3.4122741443554687e-10,
  126. 3.4436053929296873e-10, 3.4749912207851561e-10, 3.5064426637031249e-10, 3.537970825980469e-10,
  127. 3.569586908984375e-10, 3.6013022401210936e-10, 3.6331283023710936e-10, 3.6650767646015627e-10,
  128. 3.6971595128828127e-10, 3.7293886829960937e-10, 3.7617766944101564e-10, 3.7943362859414062e-10,
  129. 3.8270805533945314e-10, 3.8600229894414062e-10, 3.8931775261445313e-10, 3.9265585803906251e-10,
  130. 3.9601811027343748e-10, 3.9940606299218751e-10, 4.0282133419531251e-10, 4.0626561237890627e-10,
  131. 4.0974066326171876e-10, 4.1324833716015624e-10, 4.1679057705078127e-10, 4.2036942743359373e-10,
  132. 4.2398704412499999e-10, 4.27645705109375e-10, 4.313478225390625e-10, 4.3509595613671873e-10,
  133. 4.3889282815234374e-10, 4.4274134012109375e-10, 4.4664459169921876e-10, 4.5060590190234376e-10,
  134. 4.5462883316796875e-10, 4.5871721866015623e-10, 4.6287519341406249e-10, 4.6710722996874996e-10,
  135. 4.7141817933203126e-10, 4.7581331823437496e-10, 4.8029840394531247e-10, 4.8487973809375004e-10,
  136. 4.8956424139453126e-10, 4.943595416328125e-10, 4.9927407779687501e-10, 5.0431722412109373e-10,
  137. 5.0949943883203125e-10, 5.1483244374218751e-10, 5.2032944281249999e-10, 5.2600539028906247e-10,
  138. 5.3187732267968745e-10, 5.3796477383984377e-10, 5.4429029952734371e-10, 5.5088014832421874e-10,
  139. 5.5776513099609373e-10, 5.6498176366796878e-10, 5.725737958203125e-10, 5.8059429076562498e-10,
  140. 5.8910851843359379e-10, 5.9819807578906255e-10, 6.0796692205859379e-10, 6.185505133828125e-10,
  141. 6.3013017932812498e-10, 6.4295684709374998e-10, 6.5739255938671875e-10, 6.7398878396093752e-10,
  142. 6.9364952928125e-10, 7.1802168155078126e-10, 7.5064859720703123e-10, 8.0193543731249999e-10,
  143. };
  144. /*************************************************************************
  145. rng_gauss:
  146. In: struct rng_state *rng - uniform RNG state
  147. Out: Returns a Gaussian variate (mean 0, variance 1)
  148. *************************************************************************/
  149. double rng_gauss(struct rng_state *rng)
  150. {
  151. double x, y;
  152. double sign = 1.0;
  153. int npasses = 0;
  154. do {
  155. unsigned long bits = rng_uint(rng);
  156. unsigned long region, pos_within_region;
  157. ++ npasses;
  158. /* Partition bits:
  159. * - Bits 0...7: select a region under the curve
  160. * - Bit 8: sign bit
  161. * - Bits 9...31 pick a point within the region
  162. * */
  163. sign = (bits & 0x80) ? -1.0 : 1.0;
  164. region = bits & 0x0000007f;
  165. pos_within_region = bits & 0xffffff00;
  166. /* Compute our X, and check if the X value lies entirely under the
  167. * curve for the chosen region */
  168. x = pos_within_region*WTAB[region];
  169. if (pos_within_region < KTAB[region]) break;
  170. /* If we're in one of the 127 cheap regions */
  171. if (region != 0)
  172. {
  173. double yR, yB;
  174. yB = YTAB[region];
  175. yR = YTAB[region-1] - yB;
  176. y = yB+yR*rng_dbl(rng);
  177. }
  178. /* If we're in the expensive region */
  179. else
  180. {
  181. x = SCALE_FACTOR - log1p(-rng_dbl(rng)) * RECIP_SCALE_FACTOR;
  182. y = exp(-SCALE_FACTOR*(x-0.5*SCALE_FACTOR))*rng_dbl(rng);
  183. }
  184. } while (y >= exp(-0.5*x*x));
  185. return sign * x;
  186. }