1 module rmathd.exponential; 2 3 public import rmathd.common; 4 5 /* 6 ** dmd exponential.d common.d && ./exponential 7 */ 8 9 T dexp(T: double)(T x, T scale, int give_log) 10 { 11 /* NaNs propagated correctly */ 12 if (isNaN(x) || isNaN(scale)) 13 return x + scale; 14 if (scale <= 0.0) 15 return T.nan; 16 17 mixin R_D__0!(give_log); 18 if (x < 0.) 19 return R_D__0; 20 return (give_log ? (-x / scale) - log(scale) : exp(-x / scale) / scale); 21 } 22 23 24 T pexp(T: double)(T x, T scale, int lower_tail, int log_p) 25 { 26 if (isNaN(x) || isNaN(scale)) 27 return x + scale; 28 if (scale < 0) 29 return T.nan; 30 31 if (x <= 0.) 32 return R_DT_0!T(lower_tail, log_p); 33 /* same as weibull( shape = 1): */ 34 x = -(x / scale); 35 return lower_tail ? (log_p ? R_Log1_Exp!T(x) : -expm1(x)) : R_D_exp!T(x, log_p); 36 } 37 38 39 T qexp(T: double)(T p, T scale, int lower_tail, int log_p) 40 { 41 if (isNaN(p) || isNaN(scale)) 42 return p + scale; 43 44 if (scale < 0) 45 return T.nan; 46 47 mixin (R_Q_P01_check!p()); 48 if (p == R_DT_0!T(lower_tail, log_p)) 49 return 0; 50 51 return - scale * R_DT_Clog!T(p, lower_tail, log_p); 52 } 53 54 55 T rexp(T: double)(T scale) 56 { 57 if (!isFinite(scale) || scale <= 0.0) { 58 if(scale == 0.) 59 return 0.; 60 /* else */ 61 return T.nan; 62 } 63 return scale * exp_rand!T(); // --> in ./sexp.c 64 } 65 66 67 68 void test_exp() 69 { 70 import std.stdio: write, writeln; 71 writeln("dexp: ", dexp(2., 1., 0)); 72 writeln("pexp: ", pexp(2., 1., 1, 0)); 73 writeln("qexp: ", qexp(.8, 1., 1, 0)); 74 writeln("rexp: ", rexp(1.), ", rexp: ", rexp(1.), 75 ", rexp: ", rexp(1.), ", rexp: ", rexp(1.)); 76 }