1 module rmathd.common;
2 
3 public import std.math: sin, cos, tan, atan, sqrt, exp, expm1, log, isNaN, isFinite, ldexp, nearbyint, floor,
4                         round, abs, fabs, fmod, trunc, log1p, pow, ceil;
5 public import core.stdc.math: lgammaf, lgammal;
6 public import core.stdc.float_ : FLT_MIN_EXP, FLT_MANT_DIG, LDBL_MIN_EXP, DBL_MIN_EXP, DBL_MANT_DIG, LDBL_MANT_DIG,
7                           FLT_MIN, DBL_MIN, LDBL_MIN, FLT_MAX, DBL_MAX, LDBL_MAX, FLT_EPSILON, DBL_EPSILON,
8                           LDBL_EPSILON, FLT_MAX_EXP, DBL_MAX_EXP, LDBL_MAX_EXP, FLT_RADIX;
9 
10 enum M_PI = 3.141592653589793238462643383280;
11 enum M_LN2 = 0.693147180559945309417232121458;
12 enum M_2PI = 6.283185307179586476925286766559;
13 enum M_LN10 = 2.302585092994045684017991454684;
14 enum M_1_PI = 0.318309886183790671537767526745;
15 enum M_PI_2 = 1.570796326794896619231321691640;
16 enum M_SQRT2 = 1.414213562373095048801688724210;
17 enum M_LN_2PI = 1.837877066409345483560659472811;
18 enum M_LOG10_2 = 0.301029995663981195213738894724;
19 enum M_SQRT_32 = 5.656854249492380195206754896838;
20 enum M_SQRT_PI = 1.772453850905516027298167483341;
21 enum M_SQRT_2dPI = 0.797884560802865355879892119869;
22 enum M_1_SQRT_2PI = 0.398942280401432677939946059934;
23 enum M_LN_SQRT_PI = 0.572364942924700087071713675677;
24 enum M_LN_SQRT_2PI = 0.918938533204672741780329736406;
25 enum M_LN_SQRT_PId2	= 0.225791352644727432363097614947;
26 enum CHAR_BIT = 8;
27 enum INT_MAX = int.max;
28 
29 enum N01type {
30     BUGGY_KINDERMAN_RAMAGE,
31     AHRENS_DIETER,
32     BOX_MULLER,
33     USER_NORM,
34     INVERSION,
35     KINDERMAN_RAMAGE
36 }
37 
38 enum BUGGY_KINDERMAN_RAMAGE = N01type.BUGGY_KINDERMAN_RAMAGE;
39 enum AHRENS_DIETER = N01type.AHRENS_DIETER;
40 enum BOX_MULLER = N01type.BOX_MULLER;
41 enum USER_NORM = N01type.USER_NORM;
42 enum INVERSION = N01type.INVERSION;
43 enum KINDERMAN_RAMAGE = N01type.KINDERMAN_RAMAGE;
44 
45 void doNothing(){};
46 
47 T fmax2(T)(T x, T y)
48 {
49     if (isNaN(x) || isNaN(y))
50         return x + y;
51     return (x < y) ? y : x;
52 }
53 
54 T max(T)(T x, T y)
55 {
56     return (x < y) ? y : x;
57 }
58 
59 alias imax2 = max;
60 
61 T min(T)(T x, T y)
62 {
63     return (x < y) ? x : y;
64 }
65 alias imin2 = min;
66 
67 T fmin2(T)(T x, T y)
68 {
69     if (isNaN(x) || isNaN(y))
70         return x + y;
71     return (x < y) ? x : y;
72 }
73 
74 T fsign(T)(T x, T y)
75 {
76     if (isNaN(x) || isNaN(y))
77 	    return x + y;
78     return ((y >= 0) ? fabs(x) : -fabs(x));
79 }
80 
81 /* lgamma float, double, real */
82 T lgamma(T: float)(T x)
83 {
84     return lgammaf(x);
85 }
86 
87 T lgamma(T: double)(T x)
88 {
89     import core.stdc.math: lgamma;
90     return lgamma(x);
91 }
92 
93 T lgamma(T: real)(T x)
94 {
95     return lgammal(x);
96 }
97 
98 
99 template SQR(T)
100 {
101 	auto SQR(T x)
102 	{
103 		return x*x;
104 	}
105 }
106 
107 enum scalefactor = SQR(SQR(SQR(4294967296.0)));
108 
109 template R_Log1_Exp(T)
110 {
111     auto R_Log1_Exp(T x)
112     {
113     	return (x > -M_LN2 ? log(-expm1(x)) : log1p(-exp(x)));
114     }
115 }
116 
117 template R_DT_Log(T)
118 {
119     auto R_DT_Log(T p, int lower_tail)
120     {
121         return (lower_tail? p : R_Log1_Exp!T(p));
122     }
123 }
124 
125 template R_D_exp(T)
126 {
127 	auto R_D_exp(T x, int log_p)
128 	{
129 		return (log_p ? x : exp(x));
130 	}
131 }
132 
133 template R_D_log(T)
134 {
135 	auto R_D_log(T p, int log_p)
136 	{
137 		return (log_p ? p : log(p));
138 	}
139 }
140 
141 template R_D_fexp(T)
142 {
143 	auto R_D_fexp(T f, T x, int give_log)
144 	{
145 		return (give_log ? -0.5*log(f) + x : exp(x)/sqrt(f));
146 	}
147 }
148 
149 template MIN_EXP(T)
150 {
151     static if(is(T : double))
152         enum MIN_EXP = DBL_MIN_EXP;
153     else static if(is(T : real))
154         enum MIN_EXP = LDBL_MIN_EXP;
155     else
156         enum MIN_EXP = FLT_MIN_EXP;
157 }
158 
159 template MANT_DIG(T)
160 {
161     static if(is(T : double))
162         enum MANT_DIG = DBL_MANT_DIG;
163     else static if(is(T : real))
164         enum MANT_DIG = LDBL_MANT_DIG;
165     else
166         enum MANT_DIG = FLT_MANT_DIG;
167 }
168 
169 template MIN(T)
170 {
171     static if(is(T : double))
172         enum MIN = DBL_MIN;
173     else static if(is(T : real))
174         enum MIN = LDBL_MIN;
175     else
176         enum MIN = FLT_MIN;
177 }
178 
179 template MAX(T)
180 {
181     static if(is(T : double))
182         enum MAX = DBL_MAX;
183     else static if(is(T : real))
184         enum MAX = LDBL_MAX;
185     else
186         enum MAX = FLT_MAX;
187 }
188 
189 template EPSILON(T)
190 {
191     static if(is(T : double))
192         enum EPSILON = DBL_EPSILON;
193     else static if(is(T : real))
194         enum EPSILON = LDBL_EPSILON;
195     else
196         enum EPSILON = FLT_EPSILON;
197 }
198 
199 template MAX_EXP(T)
200 {
201     static if(is(T : double))
202         enum MAX_EXP = DBL_MAX_EXP;
203     else static if(is(T : real))
204         enum MAX_EXP = LDBL_MAX_EXP;
205     else
206         enum MAX_EXP = FLT_MAX_EXP;
207 }
208 
209 //static const double M_cutoff = M_LN2 * MAX_EXP!T/EPSILON!T;/*=3.196577e18*/
210 
211 mixin template M_cutoff(T)
212 {
213 	static const(T) M_cutoff = M_LN2 * MAX_EXP!T/EPSILON!T;
214 }
215 
216 
217 
218 mixin template R_D__0(alias log_p)
219 {
220     T R_D__0 = (log_p ? -T.infinity : 0.);
221 }
222 
223 
224 mixin template R_D__1(alias log_p)
225 {
226     T R_D__1 = (log_p ? 0. : 1.);
227 }
228 
229 template R_D_val(T)
230 {
231 	auto R_D_val (T x, int log_p)
232 	{
233 		return (log_p ? log(x) : x);
234 	}
235 }
236 
237 template R_D_Clog(T)
238 {
239     auto R_D_Clog(T p, int log_p)
240     {
241         return (log_p ? log1p(-p) : (0.5 - p + 0.5));
242     }
243 }
244 
245 template R_DT_val(T)
246 {
247     auto R_DT_val(T x, int lower_tail, int log_p)
248     {
249         return (lower_tail ? R_D_val!T(x, log_p) : R_D_Clog!T(x, log_p));
250     }
251 }
252 
253 template R_D_qIv(T)
254 {
255     auto R_D_qIv(T p, int log_p)
256     {
257         return (log_p ? exp(p) : p);
258     }
259 }
260 
261 template R_DT_0(T)
262 {
263     auto R_DT_0(int lower_tail, int log_p)
264     {
265         mixin R_D__0!log_p;
266         mixin R_D__1!log_p;
267         return (lower_tail ? R_D__0 : R_D__1);
268     }
269 }
270 
271 
272 /*
273 template R_DT_0(alias lower_tail, alias log_p)
274 {
275     mixin R_D__0!log_p;
276     mixin R_D__1!log_p;
277     T R_DT_0 = (lower_tail ? R_D__0 : R_D__1);
278 }
279 */
280 
281 
282 template R_DT_1(T)
283 {
284     auto R_DT_1(int lower_tail, int log_p)
285     {
286         mixin R_D__0!log_p;
287         mixin R_D__1!log_p;
288         return (lower_tail ? R_D__1 : R_D__0);
289     }
290 }
291 
292 
293 auto R_D_half(int log_p){
294     return (log_p ? -M_LN2 : 0.5);
295 }
296 
297 
298 /*
299 template R_DT_1(alias lower_tail, alias log_p)
300 {
301     mixin R_D__0!log_p;
302     mixin R_D__1!log_p;
303     T R_DT_1 = (lower_tail ? R_D__1 : R_D__0);
304 }
305 */
306 
307 /* Mixin technique! */
308 
309 /*
310 mixin template R_D_Lval(alias p)
311 {
312     T R_D_Lval = (lower_tail ? (p) : (0.5 - p + 0.5));
313 }
314 
315 mixin template R_DT_qIv(alias p)
316 {
317     mixin R_D_Lval!(p);
318     T R_DT_qIv = (log_p ? (lower_tail ? exp(p) : - expm1(p)) : R_D_Lval);
319 }
320 */
321 
322 template R_D_Lval(T)
323 {
324     auto R_D_Lval(T p, int lower_tail)
325     {
326         return (lower_tail ? p : (0.5 - p + 0.5));
327     }
328 }
329 
330 mixin template R_DT_qIv(alias p)
331 {
332     T R_DT_qIv = (log_p ? (lower_tail ? exp(p) : - expm1(p)) : R_D_Lval!T(p, lower_tail));
333 }
334 
335 
336 mixin template R_D_Cval(alias p)
337 {
338     T R_D_Cval = (lower_tail ? (0.5 - p + 0.5) : p);
339 }
340 
341 mixin template R_DT_CIv(alias p)
342 {
343     mixin R_D_Cval!(p);
344     T R_DT_CIv = (log_p ? (lower_tail ? -expm1(p) : exp(p)) : R_D_Cval);
345 }
346 
347 template R_Q_P01_boundaries(alias p, alias LEFT, alias RIGHT)
348 {
349     immutable(string) R_Q_P01_boundaries(){
350         return `if (log_p) {
351         if(p > 0)
352             return T.nan;
353         if(p == 0) /* upper bound*/
354             return lower_tail ? ` ~ RIGHT.stringof ~ ` : ` ~ LEFT.stringof ~ `;
355         if(p == -T.infinity)
356             return lower_tail ? `~ LEFT.stringof ~ ` : ` ~ RIGHT.stringof ~ `;
357         } else { /* !log_p */
358         if(p < 0 || p > 1)
359             return T.nan;
360         if(p == 0)
361             return lower_tail ? ` ~ LEFT.stringof ~ ` : ` ~ RIGHT.stringof ~ `;
362         if(p == 1)
363             return lower_tail ? ` ~ RIGHT.stringof ~ ` : ` ~ LEFT.stringof ~ `;
364         }`;
365     }
366 }
367 
368 template R_Q_P01_check(alias p)
369 {
370 	immutable(string) R_Q_P01_check(){
371 	    return `if ((log_p	&& ` ~ p.stringof ~ ` > 0) || (!log_p && (` ~ p.stringof ~ ` < 0 || ` ~ p.stringof ~ ` > 1)))
372 	            return T.nan;`;
373 	}
374 }
375 
376 template R_P_bounds_01(alias x, alias x_min, alias x_max)
377 {
378     immutable(string) R_P_bounds_01(){
379     	return `if(` ~ x.stringof ~ ` <= ` ~ x_min.stringof ~ `) return R_DT_0!T(lower_tail, log_p);
380                if(` ~ x.stringof ~ ` >= ` ~ x_max.stringof ~ `) return R_DT_1!T(lower_tail, log_p);`;
381     }
382 }
383 
384 /* is typically not quite optimal for (-Inf,Inf) where
385  * you'd rather have */
386 template R_P_bounds_Inf_01(alias x)
387 {
388     immutable(string) R_P_bounds_Inf_01(){
389         return `if(!isFinite(` ~ x.stringof ~ `)) {
390                     if (` ~ x.stringof ~ ` > 0) return R_DT_1!T(lower_tail, log_p);
391                     return R_DT_0!T(lower_tail, log_p);
392                 }`;
393     }
394 }
395 
396 
397 template R_D_LExp(T)
398 {
399     auto R_D_LExp(T x, int log_p)
400     {
401     	return (log_p ? R_Log1_Exp!T(x) : log1p(-x));
402     }
403 }
404 
405 template R_DT_Clog(T)
406 {
407     auto R_DT_Clog(T p, int lower_tail, int log_p)
408     {
409     	return (lower_tail? R_D_LExp!T(p, log_p): R_D_log!T(p, lower_tail)); /* log(1-p) in qF*/
410     }
411 }
412 
413 
414 template R_DT_log(T)
415 {
416     auto R_DT_log(T p, int lower_tail)
417     {
418     	return (lower_tail? R_D_log!T(p, lower_tail) : R_D_LExp!T(p, lower_tail));
419     }
420 }
421 
422 auto R_pow_di(T)(T x, int n)
423 {
424     T pow_ = 1.0;
425 
426     if (isNaN(x)) return x;
427     if (n != 0) {
428         if (!isFinite(x))
429             return pow(x, cast(T)n);
430         if (n < 0) {
431             n = -n; x = 1/x;
432         }
433         for(;;) {
434             if(n & 01)
435                 pow_ *= x;
436             if(n >>= 1)
437                 x *= x;
438             else
439                 break;
440         }
441     }
442     return pow_;
443 }
444 
445 
446 template R_nonint(T){
447 	auto R_nonint(T x){
448 		return (fabs(x - nearbyint(x)) > 1e-7*fmax2!T(1., fabs(x)));
449 	}
450 }
451 
452 
453 template R_D_negInonint(T)
454 {
455     auto R_D_negInonint(T x)
456     {
457     	return (x < 0. || R_nonint!T(x));
458     }
459 }
460 
461 /*
462 template R_D_Lval(T)
463 {
464 	auto R_D_Lval(T p, T lower_tail){
465 		return (lower_tail ? p : (0.5 - p + 0.5));
466 	}
467 }
468 */
469 
470 /*
471 template R_DT_qIv(T)
472 {
473 	auto R_DT_qIv(T p, T log_p, T lower_tail){
474 		return (log_p ? (lower_tail ? exp(p) : - expm1(p)) : R_D_Lval!T(p, lower_tail));
475 	}
476 }
477 */
478 
479 template R_D_nonint_check(alias x){
480     enum R_D_nonint_check = `if(R_nonint(` ~ x.stringof ~ `)) {
481 	                             return R_D__0;
482                              }`;
483 }
484 
485 int chebyshev_init(T)(T* dos, int nos, T eta)
486 {
487     int i, ii;
488     T err;
489 
490     if (nos < 1)
491 	return 0;
492 
493     err = 0.0;
494     i = 0;			/* just to avoid compiler warnings */
495     for (ii = 1; ii <= nos; ii++) {
496 	i = nos - ii;
497 	err += fabs(dos[i]);
498 	if (err > eta) {
499 	    return i;
500 	}
501     }
502     return i;
503 }
504 
505 T chebyshev_eval(T)(T x, const(T)* a, const(int) n)
506 {
507     T b0, b1, b2, twox;
508     int i;
509 
510     if (n < 1 || n > 1000)
511     	return T.nan;
512 
513     if (x < -1.1 || x > 1.1)
514     	return T.nan;
515 
516     twox = x * 2;
517     b2 = b1 = 0;
518     b0 = 0;
519     for (i = 1; i <= n; i++) {
520 	    b2 = b1;
521 	    b1 = b0;
522 	    b0 = twox * b1 - b2 + a[n - i];
523     }
524     return (b0 - b2) * 0.5;
525 }
526 
527 T d1mach(T)(int i)
528 {
529     switch(i) {
530     case 1: return MIN!T;
531     case 2: return MAX!T;
532 
533     case 3: /* = FLT_RADIX  ^ - DBL_MANT_DIG
534 	      for IEEE:  = 2^-53 = 1.110223e-16 = .5*DBL_EPSILON */
535 	return 0.5*EPSILON!T;
536 
537     case 4: /* = FLT_RADIX  ^ (1- DBL_MANT_DIG) =
538 	      for IEEE:  = 2^-52 = DBL_EPSILON */
539 	return EPSILON!T;
540 
541     case 5: return M_LOG10_2;
542 
543     default: return 0.0;
544     }
545 }
546 
547 int i1mach(int i)
548 {
549     switch(i) {
550 
551     case  1: return 5;
552     case  2: return 6;
553     case  3: return 0;
554     case  4: return 0;
555 
556     case  5: return CHAR_BIT*int.sizeof;
557     case  6: return int.sizeof/char.sizeof;
558 
559     case  7: return 2;
560     case  8: return CHAR_BIT*int.sizeof - 1;
561     case  9: return INT_MAX;
562 
563     case 10: return FLT_RADIX;
564 
565     case 11: return FLT_MANT_DIG;
566     case 12: return FLT_MIN_EXP;
567     case 13: return FLT_MAX_EXP;
568 
569     case 14: return DBL_MANT_DIG;
570     case 15: return DBL_MIN_EXP;
571     case 16: return DBL_MAX_EXP;
572 
573     default: return 0;
574     }
575 }
576 
577 
578 void gammalims(T)(T* xmin, T* xmax)
579 {
580 /* FIXME: Even better: If IEEE, #define these in nmath.h
581 	  and don't call gammalims() at all
582 */
583 
584     *xmin = -170.5674972726612;
585     *xmax =  171.61447887182298;/*(3 Intel/Sparc architectures)*/
586 
587     double alnbig, alnsml, xln, xold;
588     int i;
589 
590     alnsml = log(d1mach!T(1));
591     *xmin = -alnsml;
592     for (i = 1; i <= 10; ++i) {
593 	    xold = *xmin;
594 	    xln = log(*xmin);
595 	    *xmin -= *xmin * ((*xmin + .5) * xln - *xmin - .2258 + alnsml) /
596 	    	(*xmin * xln + .5);
597 	    if (fabs(*xmin - xold) < .005) {
598 	        *xmin = -(*xmin) + .01;
599 	        goto find_xmax;
600 	    }
601     }
602 
603     /* unable to find xmin */
604 
605     //ML_ERROR(ME_NOCONV, "gammalims");
606     *xmin = *xmax = T.nan;
607 
608 find_xmax:
609 
610     alnbig = log(d1mach!T(2));
611     *xmax = alnbig;
612     for (i = 1; i <= 10; ++i) {
613 	    xold = *xmax;
614 	    xln = log(*xmax);
615 	    *xmax -= *xmax * ((*xmax - .5) * xln - *xmax + .9189 - alnbig) /
616 	    	(*xmax * xln - .5);
617 	    if (fabs(*xmax - xold) < .005) {
618 	        *xmax += -.01;
619 	        goto done;
620 	    }
621     }
622 
623     /* unable to find xmax */
624 
625     //ML_ERROR(ME_NOCONV, "gammalims");
626     *xmin = *xmax = T.nan;
627 
628 done:
629     *xmin = fmax2(*xmin, -(*xmax) + 1);
630 }
631 
632 T lgammacor(T)(T x)
633 {
634     const static T[15] algmcs = [
635 	+.1666389480451863247205729650822e+0,
636 	-.1384948176067563840732986059135e-4,
637 	+.9810825646924729426157171547487e-8,
638 	-.1809129475572494194263306266719e-10,
639 	+.6221098041892605227126015543416e-13,
640 	-.3399615005417721944303330599666e-15,
641 	+.2683181998482698748957538846666e-17,
642 	-.2868042435334643284144622399999e-19,
643 	+.3962837061046434803679306666666e-21,
644 	-.6831888753985766870111999999999e-23,
645 	+.1429227355942498147573333333333e-24,
646 	-.3547598158101070547199999999999e-26,
647 	+.1025680058010470912000000000000e-27,
648 	-.3401102254316748799999999999999e-29,
649 	+.1276642195630062933333333333333e-30
650     ];
651 
652     T tmp;
653 
654 /* For IEEE double precision DBL_EPSILON = 2^-52 = 2.220446049250313e-16 :
655  *   xbig = 2 ^ 26.5
656  *   xmax = DBL_MAX / 48 =  2^1020 / 3 */
657     const(int) nalgm = 5;
658     const(T) xbig  = 94906265.62425156;
659     const(T) xmax  = 3.745194030963158e306;
660 
661     if (x < 10)
662 	    return T.nan;
663     else if (x >= xmax) {
664 	    //ML_ERROR(ME_UNDERFLOW, "lgammacor");
665 	    /* allow to underflow below */
666     }
667     else if (x < xbig) {
668 	tmp = 10 / x;
669 	return chebyshev_eval!T(tmp * tmp * 2 - 1, algmcs.ptr, nalgm) / x;
670     }
671     return 1 / (x * 12);
672 }
673 
674 /* Start of trig pi functions */
675 
676 // cos(pi * x)  -- exact when x = k/2  for all integer k
677 T cospi(T: double)(T x) {
678     if (isNaN(x))
679     	return x;
680     if(!isFinite(x))
681     	return T.nan;
682 
683     x = fmod(fabs(x), 2.);// cos() symmetric; cos(pi(x + 2k)) == cos(pi x) for all integer k
684     if(fmod(x, 1.) == 0.5)
685     	return 0.;
686     if(x == 1.)
687     	return -1.;
688     if(x == 0.)
689     	return  1.;
690     // otherwise
691     return cos(M_PI * x);
692 }
693 
694 // sin(pi * x)  -- exact when x = k/2  for all integer k
695 T sinpi(T: double)(T x) {
696     if (isNaN(x)) return x;
697     if(!isFinite(x))
698     	return T.nan;
699 
700     x = fmod(x, 2.); // sin(pi(x + 2k)) == sin(pi x)  for all integer k
701     // map (-2,2) --> (-1,1] :
702     if(x <= -1)
703     	x += 2.;
704     else if (x > 1.)
705     	x -= 2.;
706     if(x == 0. || x == 1.)
707     	return 0.;
708     if(x ==  0.5)
709     	return  1.;
710     if(x == -0.5)
711     	return -1.;
712     // otherwise
713     return sin(M_PI * x);
714 }
715 
716 
717 T tanpi(T: double)(T x)
718 {
719     if (isNaN(x))
720     	return x;
721     if(!isFinite(x))
722     	return T.nan;
723 
724     x = fmod(x, 1.); // tan(pi(x + k)) == tan(pi x)  for all integer k
725     // map (-1,1) --> (-1/2, 1/2] :
726     if(x <= -0.5)
727     	x++;
728     else if(x > 0.5)
729     	x--;
730     return (x == 0.) ? 0. : ((x == 0.5) ? T.nan : tan(M_PI * x));
731 }
732 /* End of trig pi functions */
733 
734 T lgammafn_sign(T: double)(T x, int* sgn)
735 {
736     T ans, y, sinpiy;
737 
738     //#ifdef NOMORE_FOR_THREADS
739     //    static double xmax = 0.;
740     //    static double dxrel = 0.;
741     //
742     //    if (xmax == 0) {/* initialize machine dependent constants _ONCE_ */
743     //	xmax = d1mach(2)/log(d1mach(2));/* = 2.533 e305	 for IEEE double */
744     //	dxrel = sqrt (d1mach(4));/* sqrt(Eps) ~ 1.49 e-8  for IEEE double */
745     //    }
746     //#else
747     /* For IEEE double precision DBL_EPSILON = 2^-52 = 2.220446049250313e-16 :
748        xmax  = DBL_MAX / log(DBL_MAX) = 2^1024 / (1024 * log(2)) = 2^1014 / log(2)
749        dxrel = sqrt(DBL_EPSILON) = 2^-26 = 5^26 * 1e-26 (is *exact* below !)
750      */
751     enum xmax  = 2.5327372760800758e+305;
752     enum dxrel = 1.490116119384765625e-8;
753 
754     if (sgn != null) *sgn = 1;
755 
756     if(isNaN(x))
757     	return x;
758 
759 
760     if (sgn != null && x < 0 && fmod(floor(-x), 2.) == 0)
761 	    *sgn = -1;
762 
763     if (x <= 0 && x == trunc(x)) { /* Negative integer argument */
764 	    //ML_ERROR(ME_RANGE, "lgamma");
765 	    return T.infinity;/* +Inf, since lgamma(x) = log|gamma(x)| */
766     }
767 
768     y = fabs(x);
769 
770     if (y < 1e-306)
771         return -log(y); // denormalized range, R change
772     if (y <= 10)
773     	return log(fabs(gammafn(x)));
774     /*
775       ELSE  y = |x| > 10 ---------------------- */
776 
777     if (y > xmax) {
778 	    //ML_ERROR(ME_RANGE, "lgamma");
779 	    return T.infinity;
780     }
781 
782     if (x > 0) { /* i.e. y = x > 10 */
783 	    if(x > 1e17)
784 	        return(x*(log(x) - 1.));
785 	    else if(x > 4934720.)
786 	        return(M_LN_SQRT_2PI + (x - 0.5) * log(x) - x);
787 	    else
788 	        return M_LN_SQRT_2PI + (x - 0.5) * log(x) - x + lgammacor!T(x);
789     }
790     /* else: x < -10; y = -x */
791     sinpiy = fabs(sinpi!T(y));
792 
793     if (sinpiy == 0) { /* Negative integer argument ===
794 			  Now UNNECESSARY: caught above */
795 	    //MATHLIB_WARNING(" ** should NEVER happen! *** [lgamma.c: Neg.int, y=%g]\n",y);
796 	    return T.nan;
797     }
798 
799     ans = M_LN_SQRT_PId2 + (x - 0.5) * log(y) - x - log(sinpiy) - lgammacor!T(y);
800 
801     if(fabs((x - trunc(x - 0.5)) * ans / x) < dxrel) {
802 
803 	    /* The answer is less than half precision because
804 	     * the argument is too near a negative integer. */
805 
806 	    //ML_ERROR(ME_PRECISION, "lgamma");
807     }
808 
809     return ans;
810 }
811 
812 T lgammafn(T: double)(T x)
813 {
814     return lgammafn_sign!T(x, null);
815 }
816 
817 
818 T stirlerr(T)(T n)
819 {
820 
821     enum S0 = 0.083333333333333333333;        /* 1/12 */
822     enum S1 = 0.00277777777777777777778;      /* 1/360 */
823     enum S2 = 0.00079365079365079365079365;   /* 1/1260 */
824     enum S3 = 0.000595238095238095238095238;  /* 1/1680 */
825     enum S4 = 0.0008417508417508417508417508; /* 1/1188 */
826 
827 /*
828   error for 0, 0.5, 1.0, 1.5, ..., 14.5, 15.0.
829 */
830     const static T[31] sferr_halves = [
831 	0.0, /* n=0 - wrong, place holder only */
832 	0.1534264097200273452913848,  /* 0.5 */
833 	0.0810614667953272582196702,  /* 1.0 */
834 	0.0548141210519176538961390,  /* 1.5 */
835 	0.0413406959554092940938221,  /* 2.0 */
836 	0.03316287351993628748511048, /* 2.5 */
837 	0.02767792568499833914878929, /* 3.0 */
838 	0.02374616365629749597132920, /* 3.5 */
839 	0.02079067210376509311152277, /* 4.0 */
840 	0.01848845053267318523077934, /* 4.5 */
841 	0.01664469118982119216319487, /* 5.0 */
842 	0.01513497322191737887351255, /* 5.5 */
843 	0.01387612882307074799874573, /* 6.0 */
844 	0.01281046524292022692424986, /* 6.5 */
845 	0.01189670994589177009505572, /* 7.0 */
846 	0.01110455975820691732662991, /* 7.5 */
847 	0.010411265261972096497478567, /* 8.0 */
848 	0.009799416126158803298389475, /* 8.5 */
849 	0.009255462182712732917728637, /* 9.0 */
850 	0.008768700134139385462952823, /* 9.5 */
851 	0.008330563433362871256469318, /* 10.0 */
852 	0.007934114564314020547248100, /* 10.5 */
853 	0.007573675487951840794972024, /* 11.0 */
854 	0.007244554301320383179543912, /* 11.5 */
855 	0.006942840107209529865664152, /* 12.0 */
856 	0.006665247032707682442354394, /* 12.5 */
857 	0.006408994188004207068439631, /* 13.0 */
858 	0.006171712263039457647532867, /* 13.5 */
859 	0.005951370112758847735624416, /* 14.0 */
860 	0.005746216513010115682023589, /* 14.5 */
861 	0.005554733551962801371038690  /* 15.0 */
862     ];
863     T nn;
864 
865     if (n <= 15.0) {
866 	    nn = n + n;
867 	    if (nn == cast(int)nn) return(sferr_halves[cast(int)nn]);
868 	        return(lgammafn!T(n + 1.) - (n + 0.5)*log(n) + n - M_LN_SQRT_2PI);
869     }
870 
871     nn = n*n;
872     if (n > 500)
873     	return((S0 - S1/nn)/n);
874     if (n >  80)
875     	return((S0 - (S1 - S2/nn)/nn)/n);
876     if (n >  35)
877     	return((S0 - (S1 - (S2 - S3/nn)/nn)/nn)/n);
878     /* 15 < n <= 35 : */
879     return ((S0 - (S1 - (S2 - (S3 - S4/nn)/nn)/nn)/nn)/n);
880 }
881 
882 
883 
884 T gammafn(T: double)(T x)
885 {
886     const static T[42] gamcs = [
887 	+.8571195590989331421920062399942e-2,
888 	+.4415381324841006757191315771652e-2,
889 	+.5685043681599363378632664588789e-1,
890 	-.4219835396418560501012500186624e-2,
891 	+.1326808181212460220584006796352e-2,
892 	-.1893024529798880432523947023886e-3,
893 	+.3606925327441245256578082217225e-4,
894 	-.6056761904460864218485548290365e-5,
895 	+.1055829546302283344731823509093e-5,
896 	-.1811967365542384048291855891166e-6,
897 	+.3117724964715322277790254593169e-7,
898 	-.5354219639019687140874081024347e-8,
899 	+.9193275519859588946887786825940e-9,
900 	-.1577941280288339761767423273953e-9,
901 	+.2707980622934954543266540433089e-10,
902 	-.4646818653825730144081661058933e-11,
903 	+.7973350192007419656460767175359e-12,
904 	-.1368078209830916025799499172309e-12,
905 	+.2347319486563800657233471771688e-13,
906 	-.4027432614949066932766570534699e-14,
907 	+.6910051747372100912138336975257e-15,
908 	-.1185584500221992907052387126192e-15,
909 	+.2034148542496373955201026051932e-16,
910 	-.3490054341717405849274012949108e-17,
911 	+.5987993856485305567135051066026e-18,
912 	-.1027378057872228074490069778431e-18,
913 	+.1762702816060529824942759660748e-19,
914 	-.3024320653735306260958772112042e-20,
915 	+.5188914660218397839717833550506e-21,
916 	-.8902770842456576692449251601066e-22,
917 	+.1527474068493342602274596891306e-22,
918 	-.2620731256187362900257328332799e-23,
919 	+.4496464047830538670331046570666e-24,
920 	-.7714712731336877911703901525333e-25,
921 	+.1323635453126044036486572714666e-25,
922 	-.2270999412942928816702313813333e-26,
923 	+.3896418998003991449320816639999e-27,
924 	-.6685198115125953327792127999999e-28,
925 	+.1146998663140024384347613866666e-28,
926 	-.1967938586345134677295103999999e-29,
927 	+.3376448816585338090334890666666e-30,
928 	-.5793070335782135784625493333333e-31
929     ];
930 
931     int i, n;
932     T y;
933     T sinpiy, value;
934 
935     //static int ngam = 0;
936     //static T xmin = 0, xmax = 0., xsml = 0., dxrel = 0.;
937 
938     /* Initialize machine dependent constants, the first time gamma() is called.
939 	FIXME for threads ! */
940     //if (ngam == 0) {
941 	//    ngam = chebyshev_init!T(gamcs, 42, EPSILON!T/20);/*was .1*d1mach(3)*/
942 	//    gammalims!T(&xmin, &xmax);/*-> ./gammalims.c */
943 	//    xsml = exp(fmax2(log(MIN!T), -log(MAX!T)) + 0.01);
944 	//    /*   = exp(.01)*DBL_MIN = 2.247e-308 for IEEE */
945 	//    dxrel = sqrt(EPSILON!T);/*was sqrt(d1mach(4)) */
946     //}
947 
948     /* For IEEE double precision DBL_EPSILON = 2^-52 = 2.220446049250313e-16 :
949      * (xmin, xmax) are non-trivial, see ./gammalims.c
950      * xsml = exp(.01)*DBL_MIN
951      * dxrel = sqrt(DBL_EPSILON) = 2 ^ -26
952     */
953     const(int) ngam = 22;
954     const(T) xmin = -170.5674972726612;
955     const(T) xmax = 171.61447887182298;
956     const(T) xsml = 2.2474362225598545e-308;
957     const(T) dxrel = 1.490116119384765696e-8;
958 
959     if(isNaN(x))
960     	return x;
961 
962     /* If the argument is exactly zero or a negative integer
963      * then return NaN. */
964     if (x == 0 || (x < 0 && x == round(x))) {
965     	//ML_ERROR(ME_DOMAIN, "gammafn");
966 	    return T.nan;
967     }
968 
969     y = fabs(x);
970 
971     if (y <= 10) {
972 
973 	/* Compute gamma(x) for -10 <= x <= 10
974 	 * Reduce the interval and find gamma(1 + y) for 0 <= y < 1
975 	 * first of all. */
976 
977 	n = cast(int) x;
978 	if(x < 0)
979 		--n;
980 	y = x - n;/* n = floor(x)  ==>	y in [ 0, 1 ) */
981 	--n;
982 	value = chebyshev_eval!T(y * 2 - 1, gamcs.ptr, ngam) + .9375;
983 	if (n == 0)
984 	    return value;/* x = 1.dddd = 1+y */
985 
986 	if (n < 0) {
987 	    /* compute gamma(x) for -10 <= x < 1 */
988 
989 	    /* exact 0 or "-n" checked already above */
990 
991 	    /* The answer is less than half precision */
992 	    /* because x too near a negative integer. */
993 	    if (x < -0.5 && fabs(x - cast(int)(x - 0.5) / x) < dxrel) {
994 		    //ML_ERROR(ME_PRECISION, "gammafn");
995 	    }
996 
997 	    /* The argument is so close to 0 that the result would overflow. */
998 	    if (y < xsml) {
999 		    //ML_ERROR(ME_RANGE, "gammafn");
1000 		    if(x > 0)
1001 		    	return T.infinity;
1002 		    else
1003 		    	return -T.infinity;
1004 	    }
1005 
1006 	    n = -n;
1007 
1008 	    for (i = 0; i < n; i++) {
1009 		    value /= (x + i);
1010 	    }
1011 	    return value;
1012 	} else {
1013 	    /* gamma(x) for 2 <= x <= 10 */
1014 
1015 	    for (i = 1; i <= n; i++) {
1016 		    value *= (y + i);
1017 	    }
1018 	    return value;
1019 	}
1020     }
1021     else {
1022 	/* gamma(x) for	 y = |x| > 10. */
1023 
1024 	if (x > xmax) {			/* Overflow */
1025 	    //ML_ERROR(ME_RANGE, "gammafn");
1026 	    return T.infinity;
1027 	}
1028 
1029 	if (x < xmin) {			/* Underflow */
1030 	    //ML_ERROR(ME_UNDERFLOW, "gammafn");
1031 	    return 0.;
1032 	}
1033 
1034 	if(y <= 50 && y == cast(int)y) { /* compute (n - 1)! */
1035 	    value = 1.;
1036 	    for (i = 2; i < y; i++)
1037 	    	value *= i;
1038 	}
1039 	else { /* normal case */
1040 	    value = exp((y - 0.5) * log(y) - y + M_LN_SQRT_2PI +
1041 			((2*y == cast(int)2*y)? stirlerr!T(y) : lgammacor!T(y)));
1042 	}
1043 	if (x > 0)
1044 	    return value;
1045 
1046 	if (fabs((x - cast(int)(x - 0.5))/x) < dxrel){
1047 
1048 	    /* The answer is less than half precision because */
1049 	    /* the argument is too near a negative integer. */
1050 
1051 	    //ML_ERROR(ME_PRECISION, "gammafn");
1052 	}
1053 
1054 	sinpiy = sinpi!T(y);
1055 	if (sinpiy == 0) {		/* Negative integer arg - overflow */
1056 	    //ML_ERROR(ME_RANGE, "gammafn");
1057 	    return T.infinity;
1058 	}
1059 
1060 	return -M_PI / (y * sinpiy * value);
1061     }
1062 }
1063 
1064 
1065 T bd0(T)(T x, T np)
1066 {
1067     T ej, s, s1, v;
1068     int j;
1069 
1070     if(!isFinite(x) || !isFinite(np) || np == 0.0)
1071     	return T.nan;
1072 
1073     if (fabs(x - np) < 0.1*(x + np)) {
1074 	    v = (x - np)/(x + np);  // might underflow to 0
1075 	    s = (x - np)*v;/* s using v -- change by MM */
1076 	    if(fabs(s) < MIN!T)
1077 	    	return s;
1078 	    ej = 2*x*v;
1079 	    v = v*v;
1080 	    for (j = 1; j < 1000; j++) { /* Taylor series; 1000: no infinite loop
1081 	    				as |v| < .1,  v^2000 is "zero" */
1082 	        ej *= v;// = v^(2j+1)
1083 	        s1 = s + ej/((j << 1) + 1);
1084 	        if (s1 == s) /* last term was effectively 0 */
1085 	    	    return s1 ;
1086 	        s = s1;
1087 	    }
1088     }
1089     /* else:  | x - np |  is not too small */
1090     return(x*log(x/np) + np - x);
1091 }
1092 
1093 
1094 // called from dpois, dgamma, pgamma, dnbeta, dnbinom, dnchisq :
1095 T dpois_raw(T)(T x, T lambda, int give_log)
1096 {
1097 	mixin R_D__1!give_log;
1098 	mixin R_D__0!give_log;
1099     if (lambda == 0)
1100     	return( (x == 0) ? R_D__1 : R_D__0 );
1101     if (!isFinite(lambda))
1102         return R_D__0; // including for the case where  x = lambda = +Inf
1103     if (x < 0)
1104     	return R_D__0;
1105     if (x <= lambda * MIN!T)
1106     	return R_D_exp!T(-lambda, give_log);
1107     if (lambda < x * MIN!T) {
1108 	    if (!isFinite(x)) // lambda < x = +Inf
1109 	        return R_D__0;
1110 	    return(R_D_exp!T(-lambda + x*log(lambda) - lgammafn!T(x + 1), give_log));
1111     }
1112     return(R_D_fexp!T( M_2PI*x, -stirlerr!T(x) - bd0(x, lambda), give_log));
1113 }
1114 
1115 
1116 /* unif_rand */
1117 /*
1118 static uint I1 = 1234, I2 = 5678;
1119 void set_seed(uint i1, uint i2)
1120 {
1121 	I1 = i1; I2 = i2;
1122 }
1123 void get_seed(uint* i1, uint* i2)
1124 {
1125 	*i1 = I1; *i2 = I2;
1126 }
1127 T unif_rand(T)()
1128 {
1129     import std.conv : octal;
1130 	I1 = 36969*(I1 & octal!177777) + (I1>>16);
1131     I2 = 18000*(I2 & octal!177777) + (I2>>16);
1132     return ((I1 << 16)^(I2 & octal!177777)) * 2.328306437080797e-10;
1133 }
1134 */
1135 
1136 public import rmathd.rng.rng;
1137 auto unif_rand(T)(double lower = 0, double upper = 1)
1138 {
1139     return rand!double(lower, upper);
1140 }
1141 
1142 void rng_demo()
1143 {
1144     import std.stdio: writeln;
1145     set_seed(789);
1146     foreach(i; 0..5)
1147         writeln(unif_rand!double());
1148 
1149     RandomNumberGenerator anotherRNG = new MINSTDRAND();
1150     setRNG(anotherRNG);
1151     
1152     writeln("Just after setRNG.");
1153     set_seed(101113);
1154     writeln("Next random numbers");
1155     foreach(i; 0..5)
1156         writeln(unif_rand!double());
1157 
1158     setRNG(cast(RandomNumberGenerator)(new MINSTDRAND0()));
1159 
1160     writeln("Next random numbers");
1161     set_seed(50);
1162     foreach(i; 0..5)
1163         writeln(unif_rand!double());
1164 }
1165 
1166 
1167 
1168 T exp_rand(T)()
1169 {
1170     /* q[k-1] = sum(log(2)^k / k!)  k=1,..,n, */
1171     /* The highest n (here 16) is determined by q[n-1] = 1.0 */
1172     /* within standard precision */
1173     const static T[] q =
1174     [
1175 	0.6931471805599453,
1176 	0.9333736875190459,
1177 	0.9888777961838675,
1178 	0.9984959252914960,
1179 	0.9998292811061389,
1180 	0.9999833164100727,
1181 	0.9999985691438767,
1182 	0.9999998906925558,
1183 	0.9999999924734159,
1184 	0.9999999995283275,
1185 	0.9999999999728814,
1186 	0.9999999999985598,
1187 	0.9999999999999289,
1188 	0.9999999999999968,
1189 	0.9999999999999999,
1190 	1.0000000000000000
1191     ];
1192 
1193     T a = 0.;
1194     T u = unif_rand!T();    /* precaution if u = 0 is ever returned */
1195     while(u <= 0. || u >= 1.)
1196     	u = unif_rand!T();
1197     for (;;) {
1198 	    u += u;
1199 	    if (u > 1.)
1200 	        break;
1201 	    a += q[0];
1202     }
1203     u -= 1.;
1204 
1205     if (u <= q[0])
1206 	    return a + u;
1207 
1208     int i = 0;
1209     T ustar = unif_rand!T(), umin = ustar;
1210     do {
1211 	    ustar = unif_rand!T();
1212 	    if (umin > ustar)
1213 	        umin = ustar;
1214 	    i++;
1215     } while (u > q[i]);
1216     return a + umin * q[0];
1217 }
1218 
1219 
1220 auto dbinom_raw(T)(T x, T n, T p, T q, int give_log)
1221 {
1222     T lf, lc;
1223 
1224     mixin R_D__0!give_log;
1225     mixin R_D__1!give_log;
1226 
1227     if (p == 0)
1228         return((x == 0) ? R_D__1 : R_D__0);
1229     if (q == 0)
1230         return((x == n) ? R_D__1 : R_D__0);
1231 
1232     if (x == 0) {
1233         if(n == 0)
1234             return R_D__1;
1235         lc = (p < 0.1) ? -bd0(n,n*q) - n*p : n*log(q);
1236         return( R_D_exp!T(lc, give_log) );
1237     }
1238     if (x == n) {
1239     lc = (q < 0.1) ? -bd0(n,n*p) - n*q : n*log(p);
1240     return( R_D_exp!T(lc, give_log) );
1241     }
1242     if (x < 0 || x > n) return( R_D__0 );
1243 
1244     /* n*p or n*q can underflow to zero if n and p or q are small.  This
1245        used to occur in dbeta, and gives NaN as from R 2.3.0.  */
1246     lc = stirlerr!T(n) - stirlerr!T(x) - stirlerr!T(n - x) - bd0!T(x,n*p) - bd0!T(n - x, n*q);
1247 
1248     /* f = (M_2PI*x*(n-x))/n; could overflow or underflow */
1249     /* Upto R 2.7.1:
1250      * lf = log(M_2PI) + log(x) + log(n-x) - log(n);
1251      * -- following is much better for  x << n : */
1252     lf = M_LN_2PI + log(x) + log1p(- x/n);
1253 
1254     return R_D_exp!T(lc - 0.5*lf, give_log);
1255 }
1256