2
0

Stage.RandomLib.pas 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630
  1. //
  2. // The graphics engine GLScene
  3. //
  4. unit Stage.RandomLib;
  5. (*
  6. Some of the code is translated from:
  7. RANLIB - Library of Fortran Routines for Random Number Generation
  8. OR
  9. Adapted from Fortran 77 code from the book:
  10. Dagpunar, J. 'Principles of random variate generation' Clarendon Press,
  11. Oxford, 1988. ISBN 0-19-852202-9.
  12. First Delphi Version prepared by Glenn Crouch of ESB Consultancy
  13. In most of Dagpunar's routines, there is a test to see
  14. whether the value of one or two floating-point parameters
  15. has changed since the last call. These tests have been
  16. replaced by using a logical variable FIRST. This should be
  17. set to .TRUE. on the first call using new values of the
  18. parameters, and .FALSE. if the parameter values are the same
  19. as for the previous call.
  20. Generate a random ordering of the integers 1 .. N
  21. Random_Order Initialize (seed) the uniform random number
  22. generator for ANY compiler Seed_Rrandom_Number
  23. * Two functions are provided for the binomial distribution.
  24. If the parameter values remain constant, it is recommended
  25. that the first function is used (random_binomial1). If one or
  26. both of the parameters change, use the second function
  27. (random_binomial2).
  28. Delphi's own random number generator, Random, is used to
  29. provide a source of uniformly distributed random numbers.
  30. At this stage, only one random number is generated at
  31. each call to one of the functions above.
  32. The unit uses the following functions which are included
  33. here: bin_prob to calculate a single binomial probability
  34. lngamma to calculate the logarithm to base e of the gamma
  35. function
  36. *)
  37. interface
  38. uses
  39. System.Math,
  40. System.SysUtils;
  41. type
  42. // Used as a Dynamic Vector
  43. TAMFloatVector = array of Extended;
  44. type
  45. // Used for passing Random Number Generators
  46. TRandomGenFunction = function: Extended;
  47. (*
  48. Used to call Random Number Generator.
  49. Remember to use Randomize if you don't want repeatable sequences.
  50. *)
  51. function GenRandom: Extended;
  52. (*
  53. Common random distributions TEST :
  54. Unif. Expo. Norm.
  55. Total Numbers 100000 100000 100000
  56. Given Mean 50 25 25
  57. Computed Mean 49.9 24.9 24.9
  58. Expect.Strd_Dev 29 25 1
  59. *)
  60. // Uniform Random single numbers in RLow..RHigh range
  61. function RandUniform(RLow, RHigh: Single): Single; overload;
  62. function RandUniform(RLow, RHigh: Integer): Integer; overload;
  63. function RandExponent(Mean: Single): single;
  64. function RandNorm(Mean, StDev: single): single;
  65. function RandLogNorm(Mean, StDev: single): single;
  66. // Marsaglia-Bray algorithm
  67. function RandGauss(Mean, StdDev: single): single;
  68. (*
  69. Random Number for Empiricle Distribution
  70. X[I] - middle of I-interval
  71. Fx[I] - cummulative empiricle distribution with values in [0..1]
  72. *)
  73. function RandEmpiric(X: array of single; Fx: array of single; NClass: integer): single;
  74. (*
  75. Adapted from the following Fortran 77 code
  76. ALGORITHM 712, COLLECTED ALGORITHMS FROM ACM.
  77. THIS WORK PUBLISHED IN TRANSACTIONS ON MATHEMATICAL SOFTWARE,
  78. VOL. 18, NO. 4, DECEMBER, 1992, PP. 434-435.
  79. The algorithm uses the ratio of uniforms method of A.J. Kinderman
  80. and J.F. Monahan augmented with quadratic bounding curves
  81. Returns a normally distributed pseudo-random number with zero mean and unit variance
  82. *)
  83. function Random_Normal: Extended; overload;
  84. (*
  85. Adapted from COLLECTED ALGORITHMS FROM ACM.
  86. THIS WORK PUBLISHED IN TRANSACTIONS ON MATHEMATICAL SOFTWARE,
  87. VOL. 18, NO. 4, DECEMBER, 1992, PP. 434-435.
  88. Returns a normally distributed pseudo-random number with zero mean and unit variance.
  89. The algorithm uses the ratio of uniforms method of A.J. Kinderman
  90. and J.F. Monahan augmented with quadratic bounding curves
  91. *)
  92. function Random_Normal(RandomGenerator: TRandomGenFunction): Extended; overload;
  93. function Random_Normal(const Mean, StdDev: Extended): Extended; overload;
  94. function Random_Normal(const Mean, StdDev: Extended;
  95. RandomGenerator: TRandomGenFunction): Extended; overload;
  96. // Adapted from approach suggested by Greg Hood, used with Permission.
  97. function Random_LogNormal(const Mean, StdDev: Extended): Extended; overload;
  98. // Adapted from approach suggested by Greg Hood, used with Permission.
  99. function Random_LogNormal(const Mean, StdDev: Extended;
  100. RandomGenerator: TRandomGenFunction): Extended; overload;
  101. (*
  102. GENERATES A RANDOM GAMMA VARIATE.
  103. CALLS EITHER random_gamma1 (Shape > 1.0) OR random_exponential (Shape = 1.0)
  104. OR random_gamma2 (Shape < 1.0).
  105. Shape = Shape PARAMETER OF DISTRIBUTION (0 < REAL).
  106. *)
  107. function Random_Gamma(const Shape: Extended): Extended; overload;
  108. (*
  109. GENERATES A RANDOM GAMMA VARIATE.
  110. CALLS EITHER random_gamma1 (Shape > 1.0)
  111. OR random_exponential (Shape = 1.0)
  112. OR random_gamma2 (Shape < 1.0).
  113. Shape = Shape PARAMETER OF DISTRIBUTION (0 < REAL)
  114. *)
  115. function Random_Gamma(const Shape: Extended;
  116. RandomGenerator: TRandomGenFunction): Extended; overload;
  117. (*
  118. Uses the algorithm in Marsaglia, G. and Tsang, W.W. (2000)
  119. 'A simple method for generating gamma variables', Trans. om Math.
  120. Software (TOMS), vol.26(3), pp.363-372.
  121. Generates a random gamma deviate for shape parameter Shape >= 1.
  122. *)
  123. function Random_Gamma1(const Shape: Extended;
  124. RandomGenerator: TRandomGenFunction): Extended;
  125. (*
  126. Generates a random variate from the chi-squared distribution
  127. with dff degrees of freedom.
  128. *)
  129. function Random_ChiSq(const DF: Integer): Extended; overload;
  130. function Random_ChiSq(const DF: Integer; RandomGenerator: TRandomGenFunction)
  131. : Extended; overload;
  132. (*
  133. Generates a random variate in [0,INFINITY) FROM
  134. A NEGATIVE EXPONENTIAL DlSTRIBUTION WlTH DENSITY PROPORTIONAL
  135. TO EXP(-random_exponential), USING INVERSION.
  136. *)
  137. function Random_Exponential: Extended; overload;
  138. function Random_Exponential(RandomGenerator: TRandomGenFunction)
  139. : Extended; overload;
  140. (*
  141. Generates a random variate from the Weibull distribution with
  142. probability density:
  143. a
  144. a-1 -x
  145. f(x) = a.x e
  146. *)
  147. function Random_Weibull(const a: Extended): Extended; overload;
  148. function Random_Weibull(const a: Extended; RandomGenerator: TRandomGenFunction)
  149. : Extended; overload;
  150. (*
  151. Generates a random variate in [0,1]
  152. FROM A BETA DISTRIBUTION WITH DENSITY
  153. PROPORTIONAL TO BETA**(AA-1) * (1-BETA)**(BB-1).
  154. USING CHENG'S LOG LOGISTIC METHOD.
  155. AA = Shape PARAMETER FROM DISTRIBUTION (0 < REAL)
  156. BB = Shape PARAMETER FROM DISTRIBUTION (0 < REAL)
  157. *)
  158. function Random_Beta(const aa, bb: Extended): Extended; overload;
  159. function Random_Beta(const aa, bb: Extended;
  160. RandomGenerator: TRandomGenFunction): Extended; overload;
  161. (*
  162. Generates a random variate FROM A
  163. T DISTRIBUTION USING KINDERMAN AND MONAHAN'S RATIO METHOD.
  164. DF = DEGREES OF FREEDOM OF DISTRIBUTION (DF >= 1)
  165. *)
  166. function Random_T(const DF: Integer): Extended; overload;
  167. function Random_T(const DF: Integer; RandomGenerator: TRandomGenFunction)
  168. : Extended; overload;
  169. (*
  170. GENERATES AN N VARIATE RANDOM NORMAL
  171. Vector USING A CHOLESKY DECOMPOSITION.
  172. ARGUMENTS:
  173. N = NUMBER OF VARIATES IN Vector (INPUT,INTEGER >= 1)
  174. H(J) = J'TH ELEMENT OF Vector OF MEANS (INPUT,REAL)
  175. X(J) = J'TH ELEMENT OF DELIVERED Vector (OUTPUT,REAL)
  176. D(J*(J-1)/2+I) = (I,J)'TH ELEMENT OF VARIANCE MATRIX (J> = I) (INPUT,REAL)
  177. F((J-1)*(2*N-J)/2+I) = (I,J)'TH ELEMENT OF LOWER TRIANGULAR
  178. DECOMPOSITION OF VARIANCE MATRIX (J <= I) (OUTPUT,REAL)
  179. ier = 1 if the input covariance matrix is not +ve definite = 0 otherwise
  180. *)
  181. procedure Random_MVNorm(const h, d: TAMFloatVector; var f, x: TAMFloatVector;
  182. var ier: Integer); overload;
  183. procedure Random_MVNorm(const h, d: TAMFloatVector; var f, x: TAMFloatVector;
  184. var ier: Integer; RandomGenerator: TRandomGenFunction); overload;
  185. (*
  186. Generates a random variate in [0,INFINITY] FROM
  187. A REPARAMETERISED GENERALISED INVERSE GAUSSIAN (GIG) DISTRIBUTION
  188. WITH DENSITY PROPORTIONAL TO GIG**(H-1) * EXP(-0.5*B*(GIG+1/GIG))
  189. USING A RATIO METHOD.
  190. h = PARAMETER OF DISTRIBUTION (0 <= REAL)
  191. b = PARAMETER OF DISTRIBUTION (0 < REAL)
  192. *)
  193. function Random_Inv_Gauss(const h, b: Extended): Extended; overload;
  194. function Random_Inv_Gauss(const h, b: Extended;
  195. RandomGenerator: TRandomGenFunction): Extended; overload;
  196. (*
  197. GENERATES A RANDOM BINOMIAL VARIATE USING C.D.Kemp's method.
  198. This algorithm is suitable when many random variates are required
  199. with the SAME parameter values for n & p.
  200. P = Bernoulli SUCCESS PROBABILITY
  201. (0 <= REAL <= 1)
  202. N = Number of Bernoulli trials
  203. (1 <= INTEGER)
  204. Reference: Kemp, C.D. (1986). `A modal method for generating binomial
  205. variables', Commun. Statist. - Theor. Meth. 15(3), 805-813.
  206. *)
  207. function Random_Binomial1(const n: Integer; const p: Extended): Int64; overload;
  208. function Random_Binomial1(const n: Integer; const p: Extended;
  209. RandomGenerator: TRandomGenFunction): Int64; overload;
  210. (*
  211. Generates a single random deviate from a binomial
  212. distribution whose number of trials is N and whose
  213. probability of an event in each trial is P.
  214. Arguments
  215. N --> The number of trials in the binomial distribution
  216. from which a random deviate is to be generated.
  217. INTEGER N
  218. P --> The probability of an event in each trial of the
  219. binomial distribution from which a random deviate
  220. is to be generated.
  221. REAL P
  222. *)
  223. function Random_Binomial2(const n: Int64; const pp: Extended): Int64; overload;
  224. (*
  225. FIRST --> Set FIRST = .TRUE. for the first call to perform initialization
  226. the set FIRST = .FALSE. for further calls using the same pair
  227. of parameter values (N, P).
  228. LOGICAL FIRST
  229. random_binomial2 <-- A random deviate yielding the number of events
  230. from N independent trials, each of which has a probability of event P.
  231. INTEGER --> random_binomial
  232. Method:
  233. This is algorithm BTPE from:
  234. Kachitvichyanukul, V. and Schmeiser, B. W.
  235. Binomial Random Variate Generation.
  236. Communications of the ACM, 31, 2 (February, 1988) 216.
  237. *)
  238. function Random_Binomial2(const n: Int64; const pp: Extended;
  239. RandomGenerator: TRandomGenFunction): Int64; overload;
  240. (*
  241. GENERATES A RANDOM NEGATIVE BINOMIAL VARIATE USING UNSTORED
  242. INVERSION AND/OR THE REPRODUCTIVE PROPERTY.
  243. SK = NUMBER OF FAILURES REQUIRED (Dagpunar's words!)
  244. = the `power' parameter of the negative binomial
  245. (0 < REAL)
  246. P = BERNOULLI SUCCESS PROBABILITY
  247. (0 < REAL < 1)
  248. THE PARAMETER H IS SET SO THAT UNSTORED INVERSION ONLY IS USED WHEN P <= H,
  249. OTHERWISE A COMBINATION OF UNSTORED INVERSION AND
  250. THE REPRODUCTIVE PROPERTY IS USED.
  251. *)
  252. function Random_Neg_Binomial(const sk, p: Extended): Int64; overload;
  253. function Random_Neg_Binomial(const sk, p: Extended;
  254. RandomGenerator: TRandomGenFunction): Int64; overload;
  255. (*
  256. Algorithm VMD
  257. Arguments: k (real) - parameter of the von Mises distribution.
  258. *)
  259. function Random_von_Mises(const k: Extended): Extended; overload;
  260. function Random_von_Mises(const k: Extended;
  261. RandomGenerator: TRandomGenFunction): Extended; overload;
  262. // Generate a random deviate from the standard Cauchy distribution
  263. function Random_Cauchy: Extended; overload;
  264. function Random_Cauchy(RandomGenerator: TRandomGenFunction): Extended; overload;
  265. (*
  266. Generates a single random deviate from a Poisson distribution with mean mu.
  267. Arguments:
  268. mu --> The mean of the Poisson distribution from which
  269. a random deviate is to be generated.
  270. REAL mu
  271. Method: For details see Ahrens, J.H. and Dieter, U.
  272. Computer Generation of Poisson Deviates
  273. From Modified Normal Distributions. ACM Trans. Math. Software, 8, 2
  274. (June 1982),163-179
  275. TABLES: COEFFICIENTS A0-A7 FOR STEP F. FACTORIALS FACT
  276. COEFFICIENTS A(K) - FOR PX = FK*V*V*SUM(A(K)*V**K)-DEL
  277. *)
  278. function Random_Poisson(var mu: Extended): Int64; overload;
  279. function Random_Poisson(var mu: Extended; RandomGenerator: TRandomGenFunction)
  280. : Int64; overload;
  281. (*
  282. Logarithm to base e of the gamma function.
  283. Accurate to about 1.e-14.
  284. Programmer: Alan Miller
  285. Latest revision of Fortran 77 version - 28 February 1988
  286. *)
  287. function LnGamma(const x: Extended): Extended;
  288. // =====================================================================
  289. implementation
  290. // =====================================================================
  291. const
  292. VSmall = MinDouble;
  293. VLarge = MaxDouble;
  294. function GenRandom: Extended;
  295. begin
  296. Result := Random;
  297. end;
  298. //---------------------------------------------------------------
  299. function RandUniform(RLow, RHigh: Single): Single; overload;
  300. begin
  301. Result := RLow + (RHigh - RLow) * Random();
  302. end;
  303. function RandUniform(RLow, RHigh: Integer): Integer; overload;
  304. begin
  305. Result := RLow + Round((RHigh - RLow) * Random());
  306. end;
  307. //------------------------------------------------------
  308. // RANDOM EXPONENTIAL
  309. //------------------------------------------------------
  310. function RandExponent(Mean: single): single;
  311. begin
  312. RandExponent := -Mean * Ln(Random());
  313. end;
  314. //------------------------------------------------------
  315. // RANDOM NORMAL
  316. //------------------------------------------------------
  317. function RandNorm(Mean, StDev: single): single;
  318. var
  319. S, Y, U1, U2: single;
  320. begin
  321. repeat
  322. U1 := 2 * Random() - 1;
  323. U2 := 2 * Random() - 1;
  324. S := U1 * U1 + U2 * U2;
  325. until (S < 1);
  326. Y := U2 * Sqrt(-2 * Ln(S) / S);
  327. RandNorm := Mean + StDev * Y;
  328. end; // of Normal
  329. //-------------------------------------------------------
  330. // RANDOM GAUSSIAN
  331. //-------------------------------------------------------
  332. function RandGauss(Mean, StdDev: single): single;
  333. var
  334. U1, S2: single;
  335. begin
  336. repeat
  337. U1 := 2 * Random - 1;
  338. S2 := Sqr(U1) + Sqr(2 * Random - 1);
  339. until S2 < 1;
  340. RandGauss := Sqrt(-2 * Ln(S2) / S2) * U1 * StdDev + Mean;
  341. end;
  342. //------------------------------------------------------
  343. // RANDOM LOGNORMAL
  344. //------------------------------------------------------
  345. function RandLogNorm(Mean, StDev: single): single;
  346. var
  347. S, Y, U1, U2: single;
  348. begin
  349. S := 0.0;
  350. repeat
  351. U1 := 2 * Random - 1;
  352. U2 := 2 * Random - 1;
  353. S := U1 * U1 + U2 * U2;
  354. until (S < 1);
  355. Y := Sqrt(-2 * Ln(S) / S) * U2;
  356. RandLogNorm := Exp(Y) + Mean;
  357. end; // of LogNorm
  358. function RandEmpiric(X: array of single; Fx: array of single; NClass: integer): single;
  359. var
  360. I: integer;
  361. R: single;
  362. begin
  363. RandEmpiric := 0;
  364. R := Random;
  365. for I := 1 to NClass do
  366. begin
  367. if (R <= Fx[I]) then
  368. RandEmpiric := X[I];
  369. end;
  370. end;
  371. //---------------------------------------------------------------
  372. function Random_Normal(RandomGenerator: TRandomGenFunction): Extended;
  373. const
  374. s = 0.449871;
  375. t = -0.386595;
  376. a = 0.19600;
  377. b = 0.25472;
  378. r1 = 0.27597;
  379. r2 = 0.27846;
  380. var
  381. u, v, x, y, q: Extended;
  382. Done: Boolean;
  383. begin
  384. // Generate P = (u,v) uniform in rectangle enclosing acceptance region
  385. Done := False;
  386. repeat
  387. u := RandomGenerator;
  388. v := RandomGenerator;
  389. v := 1.7156 * (v - 0.5);
  390. // Evaluate the quadratic form
  391. x := u - s;
  392. y := abs(v) - t;
  393. q := Sqr(x) + y * (a * y - b * x);
  394. // Accept P if inside inner ellipse
  395. if (q < r1) then
  396. Done := True
  397. else if (q <= r2) and (Sqr(v) < -4.0 * Ln(u) * Sqr(u)) then
  398. Done := True;
  399. until Done;
  400. // Return ratio of P's coordinates as the normal deviate
  401. if u < VSmall then
  402. raise EMathError.Create('Divided By Zero');
  403. Result := v / u;
  404. end;
  405. //---------------------------------------------------------------
  406. function Random_Normal: Extended;
  407. begin
  408. Result := Random_Normal(GenRandom);
  409. end;
  410. function Random_Normal(const Mean, StdDev: Extended;
  411. RandomGenerator: TRandomGenFunction): Extended;
  412. begin
  413. Result := Random_Normal(RandomGenerator) * StdDev + Mean;
  414. end;
  415. function Random_Normal(const Mean, StdDev: Extended): Extended;
  416. begin
  417. Result := Random_Normal(Mean, StdDev, GenRandom);
  418. end;
  419. //---------------------------------------------------------------
  420. function Random_LogNormal(const Mean, StdDev: Extended;
  421. RandomGenerator: TRandomGenFunction): Extended;
  422. var
  423. C, M, s: Extended;
  424. begin
  425. if Mean <= 0 then
  426. raise EMathError.Create('Invalid Mean');
  427. if StdDev <= 0 then
  428. raise EMathError.Create('Invalid StdDev');
  429. C := StdDev / Mean;
  430. M := Ln(Mean) - 0.5 * Ln(Sqr(C) + 1);
  431. s := Sqrt(Ln(Sqr(C) + 1));
  432. Result := Exp(Random_Normal(M, s, RandomGenerator));
  433. end;
  434. function Random_LogNormal(const Mean, StdDev: Extended): Extended;
  435. begin
  436. Result := Random_LogNormal(Mean, StdDev, GenRandom);
  437. end;
  438. //---------------------------------------------------------------
  439. function Random_Gamma1(const Shape: Extended;
  440. RandomGenerator: TRandomGenFunction): Extended;
  441. var
  442. C, d: Extended;
  443. u, v, x: Extended;
  444. Done: Boolean;
  445. begin
  446. if (Shape <= 1.0) then
  447. raise EMathError.Create('Invalid Shape');
  448. d := Shape - 1 / 3;
  449. C := 1 / Sqrt(9.0 * d);
  450. Result := 0.0;
  451. Done := False;
  452. repeat
  453. // Generate v = (1+cx)^3 where x is random normal; repeat if v <= 0.
  454. repeat
  455. x := Random_Normal(RandomGenerator);
  456. v := Power(1 + C * x, 3);
  457. until v > 0;
  458. // Generate uniform variable U
  459. u := RandomGenerator;
  460. if (u < 1.0 - 0.0331 * Sqr(Sqr(x))) then
  461. begin
  462. Result := d * v;
  463. Done := True;
  464. end
  465. else if Ln(u) < 0.5 * Sqr(x) + d * (1.0 - v + Ln(v)) then
  466. begin
  467. Result := d * v;
  468. Done := True;
  469. end
  470. until Done;
  471. end;
  472. (*
  473. Generates a RANDOM VARIATE in [0,INFINITY) from
  474. A GAMMA DISTRIBUTION with DENSITY proportional to
  475. GAMMA2**(S-1) * EXP(-GAMMA2),
  476. using a switching method.
  477. S = Shape PARAMETER of distribution
  478. (real < 1.0)
  479. *)
  480. function Random_Gamma2(const Shape: Extended;
  481. RandomGenerator: TRandomGenFunction): Extended;
  482. var
  483. r, x, w: Extended;
  484. a, p, C, uf, vr, d: Extended;
  485. Done: Boolean;
  486. begin
  487. if (Shape <= 0.0) and (Shape >= 1.0) then
  488. raise EMathError.Create('Invalid Shape');
  489. if (Shape < VSmall) then
  490. raise EMathError.Create('Shape Too Small');
  491. a := 1.0 - Shape;
  492. p := a / (a + Shape * Exp(-a));
  493. C := 1.0 / Shape;
  494. uf := p * Power(VSmall / a, Shape);
  495. vr := 1.0 - VSmall;
  496. d := a * Ln(a);
  497. w := 0;
  498. x := 0;
  499. Done := False;
  500. repeat
  501. r := RandomGenerator;
  502. if (r >= vr) then
  503. Continue;
  504. if (r > p) then
  505. begin
  506. x := a - Ln((1.0 - r) / (1.0 - p));
  507. w := a * Ln(x) - d;
  508. end
  509. else if (r > uf) then
  510. begin
  511. x := a * Power(r / p, C);
  512. w := x;
  513. end
  514. else
  515. begin
  516. Result := 0.0;
  517. Exit;
  518. end;
  519. r := RandomGenerator;
  520. if (1.0 - r <= w) and (r > 0.0) then
  521. begin
  522. if (r * (w + 1.0) >= 1.0) then
  523. Continue;
  524. if (-Ln(r) <= w) then
  525. Continue;
  526. end;
  527. Done := True;
  528. until Done;
  529. Result := x;
  530. end;
  531. //---------------------------------------------------------------
  532. function Random_Gamma(const Shape: Extended;
  533. RandomGenerator: TRandomGenFunction): Extended;
  534. begin
  535. if (Shape <= 0.0) then
  536. raise EMathError.Create('Invalid Shape');
  537. if (Shape > 1.0) then
  538. Result := Random_Gamma1(Shape, RandomGenerator)
  539. else if (Shape < 1.0) then
  540. Result := Random_Gamma2(Shape, RandomGenerator)
  541. else
  542. Result := Random_Exponential(RandomGenerator);
  543. end;
  544. function Random_Gamma(const Shape: Extended): Extended;
  545. begin
  546. Result := Random_Gamma(Shape, GenRandom);
  547. end;
  548. function Random_ChiSq(const DF: Integer; RandomGenerator: TRandomGenFunction)
  549. : Extended;
  550. begin
  551. Result := 2.0 * Random_Gamma(0.5 * DF, RandomGenerator)
  552. end;
  553. function Random_ChiSq(const DF: Integer): Extended;
  554. begin
  555. Result := Random_ChiSq(DF, GenRandom);
  556. end;
  557. //---------------------------------------------------------------
  558. function Random_Exponential(RandomGenerator: TRandomGenFunction): Extended;
  559. var
  560. r: Extended;
  561. Done: Boolean;
  562. begin
  563. Done := False;
  564. repeat
  565. r := RandomGenerator;
  566. if (r > VSmall) then
  567. Done := True;
  568. until Done;
  569. Result := -Ln(r)
  570. end;
  571. function Random_Exponential: Extended;
  572. begin
  573. Result := Random_Exponential(GenRandom);
  574. end;
  575. function Random_Weibull(const a: Extended;
  576. RandomGenerator: TRandomGenFunction): Extended;
  577. begin
  578. if abs(a) <= VSmall then
  579. raise EMathError.Create('Invalid Value');
  580. Result := Power(Random_Exponential(RandomGenerator), 1.0 / a);
  581. end;
  582. //---------------------------------------------------------------
  583. function Random_Weibull(const a: Extended): Extended;
  584. begin
  585. Result := Random_Weibull(a, GenRandom);
  586. end;
  587. function Random_Beta(const aa, bb: Extended;
  588. RandomGenerator: TRandomGenFunction): Extended;
  589. const
  590. aln4 = 1.3862943611198906;
  591. var
  592. a, b, g, r, s, x, y, z: Extended;
  593. d, f, h, t, C: Extended;
  594. Swap: Boolean;
  595. Done: Boolean;
  596. begin
  597. if (aa <= 0.0) or (bb <= 0.0) then
  598. raise EMathError.Create('Invalid Value');
  599. a := aa;
  600. b := bb;
  601. Swap := b > a;
  602. if Swap then
  603. begin
  604. g := b;
  605. b := a;
  606. a := g;
  607. end;
  608. d := a / b;
  609. f := a + b;
  610. if (b > 1.0) then
  611. begin
  612. h := Sqrt((2.0 * a * b - f) / (f - 2.0));
  613. t := 1.0;
  614. end
  615. else
  616. begin
  617. h := b;
  618. t := 1.0 / (1.0 + Power(a / (VLarge * b), b));
  619. end;
  620. C := a + h;
  621. Done := False;
  622. Result := 0.0;
  623. repeat
  624. r := RandomGenerator;
  625. x := RandomGenerator;
  626. s := Sqr(r) * x;
  627. if (r < VSmall) or (s <= 0.0) then
  628. Continue;
  629. if (r < t) then
  630. begin
  631. x := Ln(r / (1.0 - r)) / h;
  632. y := d * Exp(x);
  633. z := C * x + f * Ln((1.0 + d) / (1.0 + y)) - aln4;
  634. if (s - 1.0 > z) then
  635. begin
  636. if (s - s * z > 1.0) then
  637. Continue;
  638. if (Ln(s) > z) then
  639. Continue;
  640. end;
  641. Result := y / (1.0 + y);
  642. end
  643. else
  644. begin
  645. if 4.0 * s > Power(1.0 + 1.0 / d, f) then
  646. Continue;
  647. Result := 1.0
  648. end;
  649. Done := True
  650. until Done;
  651. if Swap then
  652. Result := 1 - Result;
  653. end;
  654. //---------------------------------------------------------------
  655. function Random_Beta(const aa, bb: Extended): Extended;
  656. begin
  657. Result := Random_Beta(aa, bb, GenRandom);
  658. end;
  659. function Random_T(const DF: Integer; RandomGenerator: TRandomGenFunction)
  660. : Extended;
  661. var
  662. s, C, a, f, g: Extended;
  663. r, x, v: Extended;
  664. Done: Boolean;
  665. begin
  666. if (DF < 1) then
  667. raise EMathError.Create('Invalid Value');
  668. s := DF;
  669. C := -0.25 * (s + 1.0);
  670. a := 4.0 / Power(1.0 + 1.0 / s, C);
  671. f := 16.0 / a;
  672. if (DF > 1) then
  673. begin
  674. g := s - 1.0;
  675. g := Power((s + 1.0) / g, C) * Sqrt((s + s) / g);
  676. end
  677. else
  678. g := 1.0;
  679. Done := False;
  680. x := 0;
  681. repeat
  682. r := RandomGenerator;
  683. if (r <= 0.0) then
  684. Continue;
  685. v := RandomGenerator;
  686. x := (2.0 * v - 1.0) * g / r;
  687. v := Sqr(x);
  688. if (v > 5.0 - a * r) then
  689. begin
  690. if (DF >= 1) and (r * (v + 3.0) > f) then
  691. Continue;
  692. if r > Power(1.0 + v / s, C) then
  693. Continue;
  694. end;
  695. Done := True;
  696. until Done;
  697. Result := x;
  698. end;
  699. //---------------------------------------------------------------
  700. function Random_T(const DF: Integer): Extended;
  701. begin
  702. Result := Random_T(DF, GenRandom);
  703. end;
  704. procedure Random_MVNorm(const h, d: TAMFloatVector; var f, x: TAMFloatVector;
  705. var ier: Integer; RandomGenerator: TRandomGenFunction);
  706. var
  707. i, j, M, n, n2, fn: Integer;
  708. y, v: Extended;
  709. begin
  710. n := Length(h);
  711. if (n = 0) then
  712. raise EMathError.Create('Vector Empty');
  713. fn := n * (n + 1) div 2;
  714. if (Length(d) < fn) then
  715. raise EMathError.Create('Vector Too Small');
  716. SetLength(f, fn);
  717. ier := 0;
  718. n2 := 2 * n;
  719. if (d[0] <= 0.0) then
  720. begin
  721. ier := 1;
  722. Exit;
  723. end;
  724. f[0] := Sqrt(d[0]);
  725. y := 1.0 / f[0];
  726. for j := 2 to n do
  727. f[j - 1] := d[j * (j - 1) div 2] * y;
  728. for i := 2 to n do
  729. begin
  730. v := d[i * (i - 1) div 2 + i - 1];
  731. for M := 1 to i - 1 do
  732. v := v - Sqr(f[(M - 1) * (n2 - M) div 2 + i - 1]);
  733. if (v <= 0.0) then
  734. begin
  735. ier := 1;
  736. Exit;
  737. end;
  738. v := Sqrt(v);
  739. y := 1.0 / v;
  740. f[(i - 1) * (n2 - i) div 2 + i - 1] := v;
  741. for j := i + 1 to n do
  742. begin
  743. v := d[j * (j - 1) div 2 + i - 1];
  744. for M := 1 to i - 1 do
  745. begin
  746. v := v - f[(M - 1) * (n2 - M) div 2 + i - 1] *
  747. f[(M - 1) * (n2 - M) div 2 + j - 1]
  748. end;
  749. f[(i - 1) * (n2 - i) div 2 + j - 1] := v * y;
  750. end;
  751. end;
  752. x := Copy(h, 0, n);
  753. for j := 1 to n do
  754. begin
  755. y := Random_Normal(RandomGenerator);
  756. for i := j to n do
  757. x[i - 1] := x[i - 1] + f[(j - 1) * (n2 - j) div 2 + i - 1] * y;
  758. end;
  759. end;
  760. procedure Random_MVNorm(const h, d: TAMFloatVector; var f, x: TAMFloatVector;
  761. var ier: Integer);
  762. begin
  763. Random_MVNorm(h, d, f, x, ier, GenRandom);
  764. end;
  765. //---------------------------------------------------------------
  766. function Random_Inv_Gauss(const h, b: Extended;
  767. RandomGenerator: TRandomGenFunction): Extended;
  768. var
  769. ym, xm, r, w, r1, r2, x: Extended;
  770. a, C, d, e: Extended;
  771. Done: Boolean;
  772. begin
  773. if (h < 0.0) or (b <= 0.0) then
  774. raise EMathError.Create('Invalid Value');
  775. if (h > 0.25 * b * Sqrt(VLarge)) then
  776. raise EMathError.Create('Invalid Value');
  777. e := Sqr(b);
  778. d := h + 1.0;
  779. ym := (-d + Sqrt(Sqr(d) + e)) / b;
  780. if (ym < VSmall) then
  781. raise EMathError.Create('Invalid Value');
  782. d := h - 1.0;
  783. xm := (d + Sqrt(Sqr(d) + e)) / b;
  784. if (xm < VSmall) then
  785. raise EMathError.Create('Invalid Value');
  786. d := 0.5 * d;
  787. e := -0.25 * b;
  788. r := xm + 1.0 / xm;
  789. w := xm * ym;
  790. a := Power(w, -0.5 * h) * Sqrt(xm / ym) * Exp(-e * (r - ym - 1.0 / ym));
  791. if (a < VSmall) then
  792. raise EMathError.Create('Invalid Value');
  793. C := -d * Ln(xm) - e * r;
  794. Done := False;
  795. x := 0.0;
  796. repeat
  797. r1 := RandomGenerator;
  798. if (r1 > 0.0) then
  799. begin
  800. r2 := RandomGenerator;
  801. x := a * r2 / r1;
  802. if (x > 0.0) then
  803. begin
  804. if (Ln(r1) < d * Ln(x) + e * (x + 1.0 / x) + C) then
  805. Done := True
  806. end;
  807. end
  808. until Done;
  809. Result := x;
  810. end;
  811. function Random_Inv_Gauss(const h, b: Extended): Extended;
  812. begin
  813. Result := Random_Inv_Gauss(h, b, GenRandom);
  814. end;
  815. //---------------------------------------------------------------
  816. function LnGamma(const x: Extended): Extended;
  817. const
  818. a1 = -4.166666666554424E-02;
  819. a2 = 2.430554511376954E-03;
  820. a3 = -7.685928044064347E-04;
  821. a4 = 5.660478426014386E-04;
  822. lnrt2pi = 9.189385332046727E-1;
  823. pi = 3.141592653589793E0;
  824. var
  825. temp, arg, product: Extended;
  826. reflect: Boolean;
  827. begin
  828. // lngamma is not defined if x = 0 or a negative integer.
  829. if (x = 0.0) or ((x < 0.0) and (abs(x - Int(x)) < VSmall)) then
  830. raise EMathError.Create('Invalid Value');
  831. // If x < 0, use the reflection formula:
  832. // gamma(x) * gamma(1-x) = pi * cosec(pi.x)
  833. reflect := x < 0.0;
  834. if reflect then
  835. arg := 1.0 - x
  836. else
  837. arg := x;
  838. // Increase the argument, if necessary, to make it > 10.
  839. product := 1.0;
  840. while (arg <= 10.0) do
  841. begin
  842. product := product * arg;
  843. arg := arg + 1.0;
  844. end;
  845. // Use a polynomial approximation to Stirling's formula.
  846. // N.B. The real Stirling's formula is used here, not the simpler, but less
  847. // accurate formula given by De Moivre in a letter to Stirling, which
  848. // is the one usually quoted.
  849. arg := arg - 0.5;
  850. temp := 1.0 / Sqr(arg);
  851. Result := lnrt2pi + arg *
  852. (Ln(arg) - 1.0 + (((a4 * temp + a3) * temp + a2) * temp + a1) * temp) -
  853. Ln(product);
  854. if reflect then
  855. begin
  856. temp := Sin(pi * x);
  857. Result := Ln(pi / temp) - Result;
  858. end;
  859. end;
  860. // Calculate a binomial probability
  861. function Bin_Prob(const n: Int64; const p: Extended; const r: Int64)
  862. : Extended;
  863. begin
  864. Result := Exp(LnGamma(n + 1.0) - LnGamma(r + 1.0) - LnGamma(n - r + 1.0) +
  865. r * Ln(p) + (n - r) * Ln(1.0 - p));
  866. end;
  867. //---------------------------------------------------------------
  868. function Random_Binomial1(const n: Integer; const p: Extended;
  869. RandomGenerator: TRandomGenFunction): Int64;
  870. var
  871. ru, rd: Int64;
  872. r0: Int64;
  873. u, pd, pu: Real;
  874. odds_ratio, p_r: Real;
  875. begin
  876. r0 := Trunc((n + 1) * p);
  877. p_r := Bin_Prob(n, p, r0);
  878. if p < 1 then
  879. odds_ratio := p / (1.0 - p)
  880. else
  881. odds_ratio := VLarge;
  882. u := RandomGenerator;
  883. u := u - p_r;
  884. if (u < 0.0) then
  885. begin
  886. Result := r0;
  887. Exit;
  888. end;
  889. pu := p_r;
  890. ru := r0;
  891. pd := p_r;
  892. rd := r0;
  893. repeat
  894. Dec(rd);
  895. if (rd >= 0) then
  896. begin
  897. pd := pd * (rd + 1.0) / (odds_ratio * (n - rd));
  898. u := u - pd;
  899. if (u < 0.0) then
  900. begin
  901. Result := rd;
  902. Exit;
  903. end;
  904. end;
  905. Inc(ru);
  906. if (ru <= n) then
  907. begin
  908. pu := pu * (n - ru + 1.0) * odds_ratio / ru;
  909. u := u - pu;
  910. if (u < 0.0) then
  911. begin
  912. Result := ru;
  913. Exit;
  914. end;
  915. end;
  916. until False;
  917. end;
  918. //---------------------------------------------------------------
  919. function Random_Binomial1(const n: Integer; const p: Extended): Int64;
  920. begin
  921. Result := Random_Binomial1(n, p, GenRandom);
  922. end;
  923. function Random_Binomial2(const n: Int64; const pp: Extended;
  924. RandomGenerator: TRandomGenFunction): Int64;
  925. var
  926. alv, amaxp, f, f1, f2, u, v, w, w2, x, x1, x2, ynorm, z, z2: Extended;
  927. i: Integer;
  928. ix, ix1, k, mp: Int64;
  929. M: Int64;
  930. p, q, xnp, ffm, fm, xnpq, p1, xm, xl, xr, C, al, xll, xlr, p2, p3, p4, qn,
  931. r, g: Extended;
  932. Done: Boolean;
  933. begin
  934. // SETUP
  935. p := Min(pp, 1.0 - pp);
  936. q := 1.0 - p;
  937. xnp := n * p;
  938. if (xnp > 30.0) then
  939. begin
  940. ffm := xnp + p;
  941. M := Trunc(ffm);
  942. fm := M;
  943. xnpq := xnp * q;
  944. p1 := Int(2.195 * Sqrt(xnpq) - 4.6 * q) + 0.5;
  945. xm := fm + 0.5;
  946. xl := xm - p1;
  947. xr := xm + p1;
  948. C := 0.134 + 20.5 / (15.3 + fm);
  949. al := (ffm - xl) / (ffm - xl * p);
  950. xll := al * (1.0 + 0.5 * al);
  951. al := (xr - ffm) / (xr * q);
  952. xlr := al * (1.0 + 0.5 * al);
  953. p2 := p1 * (1.0 + C + C);
  954. p3 := p2 + C / xll;
  955. p4 := p3 + C / xlr;
  956. // GENERATE VARIATE, Binomial mean at least 30.
  957. ix := 0;
  958. repeat
  959. ;
  960. u := RandomGenerator; // 20
  961. u := u * p4;
  962. v := RandomGenerator;
  963. // TRIANGULAR REGION
  964. if (u <= p1) then
  965. begin
  966. ix := Trunc(xm - p1 * v + u);
  967. Break;
  968. end;
  969. // PARALLELOGRAM REGION
  970. if (u <= p2) then
  971. begin
  972. x := xl + (u - p1) / C;
  973. v := v * C + 1.0 - abs(xm - x) / p1;
  974. if (v > 1.0) or (v <= 0) then
  975. Continue;
  976. ix := Trunc(x);
  977. end
  978. else
  979. begin
  980. // LEFT TAIL
  981. if (u <= p3) then
  982. begin
  983. ix := Trunc(xl + Ln(v) / xll);
  984. if (ix < 0) then
  985. Continue;
  986. v := v * (u - p2) * xll
  987. end
  988. // RIGHT TAIL
  989. else
  990. begin
  991. ix := Trunc(xr - Ln(v) / xlr);
  992. if (ix > n) then
  993. Continue;
  994. v := v * (u - p3) * xlr;
  995. end;
  996. end;
  997. // DETERMINE APPROPRIATE WAY TO PERFORM ACCEPT/REJECT TEST
  998. k := abs(ix - M);
  999. if (k <= 20) or (k >= xnpq / 2 - 1) then
  1000. begin
  1001. // EXPLICIT EVALUATION
  1002. f := 1.0;
  1003. r := p / q;
  1004. g := (n + 1) * r;
  1005. if (M < ix) then
  1006. begin
  1007. mp := M + 1;
  1008. for i := mp to ix do
  1009. f := f * (g / i - r);
  1010. end
  1011. else if (M > ix) then
  1012. begin
  1013. ix1 := ix + 1;
  1014. for i := ix1 to M do
  1015. f := f / (g / i - r);
  1016. end;
  1017. if (v > f) then
  1018. Continue
  1019. else
  1020. Break
  1021. end;
  1022. // SQUEEZING USING UPPER AND LOWER BOUNDS ON LOG(F(X))
  1023. amaxp := (k / xnpq) * ((k * (k / 3.0 + 0.625) + 0.1666666666666) /
  1024. xnpq + 0.5);
  1025. ynorm := -Sqr(k) / (2.0 * xnpq);
  1026. alv := Ln(v);
  1027. if (alv < ynorm - amaxp) then
  1028. Break;
  1029. if (alv > ynorm + amaxp) then
  1030. Continue;
  1031. // STIRLING'S (actually de Moivre's) FORMULA TO MACHINE ACCURACY FOR
  1032. // THE FINAL ACCEPTANCE/REJECTION TEST
  1033. x1 := ix + 1;
  1034. f1 := fm + 1.0;
  1035. z := n + 1 - fm;
  1036. w := n - ix + 1.0;
  1037. z2 := Sqr(z);
  1038. x2 := Sqr(x1);
  1039. f2 := Sqr(f1);
  1040. w2 := Sqr(w);
  1041. if (alv - (xm * Ln(f1 / x1) + (n - M + 0.5) * Ln(z / w) + (ix - M) *
  1042. Ln(w * p / (x1 * q)) + (13860.0 -
  1043. (462.0 - (132.0 - (99.0 - 140.0 / f2) / f2) / f2) / f2) / f1 /
  1044. 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / z2) / z2) /
  1045. z2) / z2) / z / 166320.0 +
  1046. (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / x2) / x2) / x2) / x2) /
  1047. x1 / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / w2) /
  1048. w2) / w2) / w2) / w / 166320.0) > 0.0) then
  1049. begin
  1050. Continue;
  1051. end
  1052. else
  1053. Break;
  1054. until False;
  1055. end
  1056. else
  1057. begin
  1058. // INVERSE CDF LOGIC FOR MEAN LESS THAN 30
  1059. qn := Power(q, n);
  1060. r := p / q;
  1061. g := r * (n + 1);
  1062. Done := False;
  1063. repeat
  1064. ix := 0;
  1065. f := qn;
  1066. u := RandomGenerator;
  1067. while (u >= f) do
  1068. begin
  1069. if (ix > 110) then
  1070. Done := False
  1071. else
  1072. begin
  1073. Done := True;
  1074. u := u - f;
  1075. ix := ix + 1;
  1076. f := f * (g / ix - r);
  1077. end;
  1078. end;
  1079. until Done;
  1080. end;
  1081. if (pp > 0.5) then
  1082. ix := n - ix;
  1083. Result := ix;
  1084. end;
  1085. //---------------------------------------------------------------
  1086. function Random_Binomial2(const n: Int64; const pp: Extended): Int64;
  1087. begin
  1088. Result := Random_Binomial2(n, pp, GenRandom);
  1089. end;
  1090. function Random_Neg_Binomial(const sk, p: Extended;
  1091. RandomGenerator: TRandomGenFunction): Int64;
  1092. const
  1093. h = 0.7;
  1094. var
  1095. q, x, st, uln, v, r, s, y, g: Extended;
  1096. k, n: Int64;
  1097. i: Integer;
  1098. begin
  1099. if (sk <= 0.0) or (p <= 0.0) or (p >= 1.0) then
  1100. raise EMathError.Create('Invalid Value');
  1101. q := 1.0 - p;
  1102. x := 0.0;
  1103. st := sk;
  1104. if (p > h) then
  1105. begin
  1106. v := 1.0 / Ln(p);
  1107. k := Trunc(st);
  1108. for i := 1 to k do
  1109. begin
  1110. repeat
  1111. r := RandomGenerator;
  1112. until r > 0.0;
  1113. n := Trunc(v * Ln(r));
  1114. x := x + n;
  1115. end;
  1116. st := st - k;
  1117. end;
  1118. s := 0.0;
  1119. uln := -Ln(VSmall);
  1120. if (st > -uln / Ln(q)) then
  1121. raise EMathError.Create('Invalid Value');
  1122. y := Power(q, st);
  1123. g := st;
  1124. r := RandomGenerator;
  1125. while (y <= r) do
  1126. begin
  1127. r := r - y;
  1128. s := s + 1.0;
  1129. y := y * p * g / s;
  1130. g := g + 1.0;
  1131. end;
  1132. Result := Trunc(x + s + 0.5)
  1133. end;
  1134. //---------------------------------------------------------------
  1135. function Random_Neg_Binomial(const sk, p: Extended): Int64;
  1136. begin
  1137. Result := Random_Neg_Binomial(sk, p, GenRandom);
  1138. end;
  1139. // Gaussian integration of exp(k.cosx) from a to b.
  1140. procedure Integral(const a, b: Extended; var res: Extended;
  1141. const dk: Extended);
  1142. var
  1143. xmid, range, x1, x2: Extended;
  1144. x, w: array [1 .. 3] of Extended;
  1145. i: Integer;
  1146. begin
  1147. x[1] := 0.238619186083197;
  1148. x[2] := 0.661209386466265;
  1149. x[3] := 0.932469514203152;
  1150. w[1] := 0.467913934572691;
  1151. w[2] := 0.360761573048139;
  1152. w[3] := 0.171324492379170;
  1153. xmid := (a + b) / 2.0;
  1154. range := (b - a) / 2.0;
  1155. res := 0.0;
  1156. for i := 1 to 3 do
  1157. begin
  1158. x1 := xmid + x[i] * range;
  1159. x2 := xmid - x[i] * range;
  1160. res := res + w[i] * (Exp(dk * Cos(x1)) + Exp(dk * Cos(x2)))
  1161. end;
  1162. res := res * range;
  1163. end;
  1164. function Random_von_Mises(const k: Extended;
  1165. RandomGenerator: TRandomGenFunction): Extended;
  1166. var
  1167. j, n, jj: Integer;
  1168. nk: Integer;
  1169. p: array [1 .. 20] of Extended;
  1170. theta: array [0 .. 20] of Extended;
  1171. xx, sump, r, th, lambda, rlast: Extended;
  1172. dk: Extended;
  1173. begin
  1174. if (k < 0.0) then
  1175. raise EMathError.Create('Invalid Value');
  1176. nk := Trunc(k + k + 1.0);
  1177. if (nk > 20) then
  1178. raise EMathError.Create('Invalid Value');
  1179. dk := k;
  1180. theta[0] := 0.0;
  1181. if (k > 0.5) then
  1182. begin
  1183. // Set up array p of probabilities.
  1184. sump := 0.0;
  1185. for j := 1 to nk do
  1186. begin
  1187. if (j < nk) then
  1188. theta[j] := ArcCos(1.0 - j / k)
  1189. else
  1190. theta[nk] := pi;
  1191. // Numerical integration of e^[k.cos(x)] from theta(j-1) to theta(j)
  1192. Integral(theta[j - 1], theta[j], p[j], dk);
  1193. sump := sump + p[j];
  1194. end;
  1195. for j := 1 to nk do
  1196. p[j] := p[j] / sump;
  1197. end
  1198. else
  1199. begin
  1200. p[1] := 1.0;
  1201. theta[1] := pi;
  1202. end;
  1203. r := RandomGenerator;
  1204. jj := nk;
  1205. for j := 1 to nk do
  1206. begin
  1207. r := r - p[j];
  1208. if (r < 0.0) then
  1209. begin
  1210. jj := j;
  1211. Break;
  1212. end;
  1213. end;
  1214. r := -r / p[jj];
  1215. repeat
  1216. th := theta[jj - 1] + r * (theta[jj] - theta[j - 1]);
  1217. lambda := k - jj + 1.0 - k * Cos(th);
  1218. n := 1;
  1219. rlast := lambda;
  1220. repeat
  1221. r := RandomGenerator;
  1222. if r <= rlast then
  1223. begin
  1224. Inc(n);
  1225. rlast := r;
  1226. end;
  1227. until (r > rlast);
  1228. if not Odd(n) then
  1229. r := RandomGenerator until Odd(n);
  1230. th := abs(th);
  1231. xx := (r - rlast) / (1.0 - rlast) - 0.5;
  1232. if xx < 0 then
  1233. Result := -1 * th
  1234. else
  1235. Result := th;
  1236. end;
  1237. //---------------------------------------------------------------
  1238. function Random_von_Mises(const k: Extended): Extended;
  1239. begin
  1240. Result := Random_von_Mises(k, GenRandom);
  1241. end;
  1242. function Random_Cauchy(RandomGenerator: TRandomGenFunction): Extended;
  1243. var
  1244. V1, V2: Extended;
  1245. begin
  1246. repeat
  1247. V1 := 2.0 * (RandomGenerator - 0.5);
  1248. V2 := 2.0 * (RandomGenerator - 0.5);
  1249. until (abs(V2) > VSmall) and (Sqr(V1) + Sqr(V2) < 1.0);
  1250. Result := V1 / V2;
  1251. end;
  1252. function Random_Cauchy: Extended;
  1253. begin
  1254. Result := Random_Cauchy(GenRandom);
  1255. end;
  1256. //---------------------------------------------------------------
  1257. function Random_Poisson(var mu: Extended;
  1258. RandomGenerator: TRandomGenFunction): Int64;
  1259. const
  1260. a0 = -0.5;
  1261. a1 = 0.3333333;
  1262. a2 = -0.2500068;
  1263. a3 = 0.2000118;
  1264. a4 = -0.1661269;
  1265. a5 = 0.1421878;
  1266. a6 = -0.1384794;
  1267. a7 = 0.1250060;
  1268. var
  1269. b1, b2, C, c0, c1, c2, c3, del, difmuk, e, fk, fx, fy, g, omega, px, py,
  1270. t, u, v, x, xx: Extended;
  1271. s, d, p, q, p0: Extended;
  1272. j, k, kflag: Integer;
  1273. l, M: Integer;
  1274. pp: array [1 .. 35] of Extended;
  1275. fact: array [1 .. 10] of Extended;
  1276. FirstK0: Boolean;
  1277. begin
  1278. u := 0;
  1279. e := 0;
  1280. fk := 0;
  1281. difmuk := 0;
  1282. fact[1] := 1; // Factorial 0
  1283. fact[2] := 1;
  1284. fact[3] := 2;
  1285. fact[4] := 6;
  1286. fact[5] := 24;
  1287. fact[6] := 120;
  1288. fact[7] := 720;
  1289. fact[8] := 5040;
  1290. fact[9] := 40320;
  1291. fact[10] := 362880; // Factorial 9
  1292. Result := 0;
  1293. if (mu > 10.0) then
  1294. begin
  1295. // C A S E A. (RECALCULATION OF S, D, L IF MU HAS CHANGED)
  1296. FirstK0 := False;
  1297. s := Sqrt(mu);
  1298. d := 6.0 * Sqr(mu);
  1299. // THE POISSON PROBABILITIES PK EXCEED THE DISCRETE NORMAL
  1300. // PROBABILITIES FK WHENEVER K >= M(MU). L=IFIX(MU-1.1484)
  1301. // IS AN UPPER BOUND TO M(MU) FOR ALL MU >= 10 .
  1302. l := Trunc(mu - 1.1484);
  1303. // STEP N. NORMAL SAMPLE - random_normal() FOR STANDARD NORMAL DEVIATE
  1304. g := mu + s * Random_Normal(RandomGenerator);
  1305. if (g > 0.0) then
  1306. begin
  1307. Result := Trunc(g);
  1308. // STEP I. IMMEDIATE ACCEPTANCE IF ival IS LARGE ENOUGH
  1309. if (Result >= l) then
  1310. Exit;
  1311. // STEP S. SQUEEZE ACCEPTANCE - SAMPLE U
  1312. fk := Result;
  1313. difmuk := mu - fk;
  1314. u := RandomGenerator;
  1315. if (d * u >= Sqr(difmuk) * difmuk) then
  1316. Exit;
  1317. end;
  1318. // STEP P. PREPARATIONS FOR STEPS Q AND H.
  1319. // (RECALCULATIONS OF PARAMETERS IF NECESSARY)
  1320. // .3989423=(2*Pi)**(-.5) .416667E-1=1./24. .1428571=1./7.
  1321. // THE QUANTITIES B1, B2, C3, C2, C1, C0 ARE FOR THE HERMITE
  1322. // APPROXIMATIONS TO THE DISCRETE NORMAL PROBABILITIES FK.
  1323. // C=.1069/MU GUARANTEES MAJORIZATION BY THE 'HAT'-FUNCTION.
  1324. omega := 0.3989423 / s;
  1325. b1 := 0.4166667E-1 / mu;
  1326. b2 := 0.3 * Sqr(b1);
  1327. c3 := 0.1428571 * b1 * b2;
  1328. c2 := b2 - 15.0 * c3;
  1329. c1 := b1 - 6.0 * b2 + 45.0 * c3;
  1330. c0 := 1.0 - b1 + 3.0 * b2 - 15.0 * c3;
  1331. C := 0.1069 / mu;
  1332. kflag := -1;
  1333. if (g >= 0.0) then
  1334. begin
  1335. // 'SUBROUTINE' F IS CALLED (KFLAG=0 FOR CORRECT RETURN)
  1336. kflag := 0;
  1337. FirstK0 := True;
  1338. end;
  1339. // STEP E. EXPONENTIAL SAMPLE - random_exponential() FOR STANDARD EXPONENTIAL
  1340. // DEVIATE E AND SAMPLE T FROM THE LAPLACE 'HAT'
  1341. // (IF T <= -.6744 THEN PK < FK FOR ALL MU >= 10.)
  1342. repeat // 50
  1343. if not FirstK0 then
  1344. begin
  1345. repeat // 50
  1346. e := Random_Exponential(RandomGenerator);
  1347. u := RandomGenerator;
  1348. u := u + u - 1.0;
  1349. if u < 0 then
  1350. t := 1.8 - abs(e)
  1351. else
  1352. t := 1.8 + abs(e);
  1353. until t > -0.6744;
  1354. Result := Trunc(mu + s * t);
  1355. fk := Result;
  1356. difmuk := mu - fk;
  1357. // 'SUBROUTINE' F IS CALLED (KFLAG=1 FOR CORRECT RETURN)
  1358. kflag := 1
  1359. end
  1360. else
  1361. FirstK0 := False;
  1362. // STEP F. 'SUBROUTINE' F. CALCULATION OF PX, PY, FX, FY.
  1363. // CASE ival < 10 USES FACTORIALS FROM TABLE FACT
  1364. if (Result < 10) then // 70
  1365. begin
  1366. px := -mu;
  1367. py := Power(mu, Result) / fact[Result + 1];
  1368. end
  1369. else
  1370. begin
  1371. // CASE ival >= 10 USES POLYNOMIAL APPROXIMATION
  1372. // A0-A7 FOR ACCURACY WHEN ADVISABLE
  1373. // .8333333E-1=1./12. .3989423=(2*Pi)**(-.5)
  1374. del := 0.8333333E-1 / fk; // 80
  1375. del := del - 4.8 * Sqr(del) * del;
  1376. v := difmuk / fk;
  1377. if abs(v) > 0.25 then
  1378. px := fk * Ln(1.0 + v) - difmuk - del
  1379. else
  1380. px := fk * Sqr(v) *
  1381. (((((((a7 * v + a6) * v + a5) * v + a4) * v + a3) * v + a2) *
  1382. v + a1) * v + a0) - del;
  1383. py := 0.3989423 / Sqrt(fk);
  1384. end;
  1385. x := (0.5 - difmuk) / s; // 110
  1386. xx := Sqr(x);
  1387. fx := -0.5 * xx;
  1388. fy := omega * (((c3 * xx + c2) * xx + c1) * xx + c0);
  1389. if (kflag <= 0) then
  1390. begin
  1391. // STEP Q. QUOTIENT ACCEPTANCE (RARE CASE)
  1392. if (fy - u * fy <= py * Exp(px - fx)) then // 40
  1393. Exit;
  1394. end
  1395. else
  1396. begin
  1397. // STEP H. HAT ACCEPTANCE (E IS REPEATED ON REJECTION)
  1398. if (C * abs(u) <= py * Exp(px + e) - fy * Exp(fx + e)) then // 60
  1399. Exit;
  1400. end;
  1401. until False;
  1402. end
  1403. else
  1404. begin
  1405. // C A S E B. mu < 10
  1406. // START NEW TABLE AND CALCULATE P0 IF NECESSARY
  1407. M := MAX(1, Trunc(mu));
  1408. l := 0;
  1409. p := Exp(-mu);
  1410. q := p;
  1411. p0 := p;
  1412. // STEP U. UNIFORM SAMPLE FOR INVERSION METHOD
  1413. repeat
  1414. u := RandomGenerator;
  1415. Result := 0;
  1416. if (u <= p0) then
  1417. Exit;
  1418. // STEP T. TABLE COMPARISON UNTIL THE END PP(L) OF THE
  1419. // PP-TABLE OF CUMULATIVE POISSON PROBABILITIES
  1420. // (0.458=PP(9) FOR MU=10)
  1421. if l <> 0 then
  1422. begin
  1423. j := 1;
  1424. if (u > 0.458) then
  1425. j := Min(l, M);
  1426. for k := j to l do
  1427. if (u <= pp[k]) then
  1428. begin
  1429. Result := k;
  1430. Exit;
  1431. end;
  1432. if l = 35 then
  1433. Continue;
  1434. end;
  1435. // STEP C. CREATION OF NEW POISSON PROBABILITIES P
  1436. // AND THEIR CUMULATIVES Q = PP(K)
  1437. l := l + 1; // 150
  1438. for k := l to 35 do
  1439. begin
  1440. p := p * mu / k;
  1441. q := q + p;
  1442. pp[k] := q;
  1443. if (u <= q) then
  1444. begin
  1445. Result := k;
  1446. Exit;
  1447. end;
  1448. end;
  1449. l := 35;
  1450. until False end;
  1451. end;
  1452. //---------------------------------------------------------------
  1453. function Random_Poisson(var mu: Extended): Int64;
  1454. begin
  1455. Result := Random_Poisson(mu, GenRandom);
  1456. end;
  1457. end.