/// <summary> /// Computes Owen's T function for arbitrary H and A. /// </summary> /// /// <param name="h">Owen's T function argument H.</param> /// <param name="a">Owen's T function argument A.</param> /// /// <returns>The value of Owen's T function.</returns> /// public static double Function(double h, double a) { double absa; double absh; double ah; const double cut = 0.67; double normah; double normh; double value; absh = Math.Abs(h); absa = Math.Abs(a); ah = absa * absh; if (absa <= 1.0) { value = Function(absh, absa, ah); } else if (absh <= cut) { value = 0.25 - (-0.5 + Normal.Function(absh)) * (-0.5 + Normal.Function(ah)) - Function(ah, 1.0 / absa, absh); } else { normh = Normal.Complemented(absh); normah = Normal.Complemented(ah); value = 0.5 * (normh + normah) - normh * normah - Function(ah, 1.0 / absa, absh); } if (a < 0.0) { value = -value; } return(value); }
/// <summary> /// Owen's T function for a restricted range of parameters. /// </summary> /// /// <param name="h">Owen's T function argument H (where 0 <= H).</param> /// <param name="a">Owen's T function argument A (where 0 <= A <= 1).</param> /// <param name="ah">The value of A*H.</param> /// /// <returns>The value of Owen's T function.</returns> /// public static double Function(double h, double a, double ah) { double ai; double aj; double AS; double dhs; double dj; double gj; double hs; int i; int iaint; int icode; int ihint; int ii; int j; int jj; int m; int maxii; double normh; double r; const double rrtpi = 0.39894228040143267794; const double rtwopi = 0.15915494309189533577; double y; double yi; double z; double zi; double value = 0; double vi; /* * Determine appropriate method from t1...t6 */ ihint = 15; for (i = 1; i <= 14; i++) { if (h <= hrange[i - 1]) { ihint = i; break; } } iaint = 8; for (i = 1; i <= 7; i++) { if (a <= arange[i - 1]) { iaint = i; break; } } icode = select[ihint - 1 + (iaint - 1) * 15]; m = ord[icode - 1]; /* * t1(h, a, m) ; m = 2, 3, 4, 5, 7, 10, 12 or 18 * jj = 2j - 1 ; gj = exp(-h*h/2) * (-h*h/2)**j / j * aj = a**(2j-1) / (2*pi) */ if (meth[icode - 1] == 1) { hs = -0.5 * h * h; dhs = Math.Exp(hs); AS = a * a; j = 1; jj = 1; aj = rtwopi * a; value = rtwopi * Math.Atan(a); dj = dhs - 1.0; gj = hs * dhs; for (; ;) { value = value + dj * aj / jj; if (m <= j) { return(value); } j = j + 1; jj = jj + 2; aj = aj * AS; dj = gj - dj; gj = gj * hs / j; } } /* * t2(h, a, m) ; m = 10, 20 or 30 * z = (-1)^(i-1) * zi ; ii = 2i - 1 * vi = (-1)^(i-1) * a^(2i-1) * exp[-(a*h)^2/2] / sqrt(2*pi) */ else if (meth[icode - 1] == 2) { maxii = m + m + 1; ii = 1; value = 0.0; hs = h * h; AS = -a * a; vi = rrtpi * a * Math.Exp(-0.5 * ah * ah); z = 0.5 * (-0.5 + Normal.Function(ah)) / h; y = 1.0 / hs; for (; ;) { value = value + z; if (maxii <= ii) { value = value * rrtpi * Math.Exp(-0.5 * hs); return(value); } z = y * (vi - ii * z); vi = AS * vi; ii = ii + 2; } } /* * t3(h, a, m) ; m = 20 * ii = 2i - 1 * vi = a**(2i-1) * exp[-(a*h)**2/2] / sqrt(2*pi) */ else if (meth[icode - 1] == 3) { i = 1; ii = 1; value = 0.0; hs = h * h; AS = a * a; vi = rrtpi * a * Math.Exp(-0.5 * ah * ah); zi = 0.5 * (-0.5 + Normal.Function(ah)) / h; y = 1.0 / hs; for (; ;) { value = value + zi * c2[i - 1]; if (m < i) { value = value * rrtpi * Math.Exp(-0.5 * hs); return(value); } zi = y * (ii * zi - vi); vi = AS * vi; i = i + 1; ii = ii + 2; } } /* * t4(h, a, m) ; m = 4, 7, 8 or 20; ii = 2i + 1 * ai = a * exp[-h*h*(1+a*a)/2] * (-a*a)**i / (2*pi) */ else if (meth[icode - 1] == 4) { maxii = m + m + 1; ii = 1; hs = h * h; AS = -a * a; value = 0.0; ai = rtwopi * a * Math.Exp(-0.5 * hs * (1.0 - AS)); yi = 1.0; for (; ;) { value = value + ai * yi; if (maxii <= ii) { return(value); } ii = ii + 2; yi = (1.0 - hs * yi) / ii; ai = ai * AS; } } /* * t5(h, a, m) ; m = 13 * 2m - point gaussian quadrature */ else if (meth[icode - 1] == 5) { value = 0.0; AS = a * a; hs = -0.5 * h * h; for (i = 1; i <= m; i++) { r = 1.0 + AS * pts[i - 1]; value = value + wts[i - 1] * Math.Exp(hs * r) / r; } value = a * value; } /* * t6(h, a); approximation for a near 1, (a<=1) */ else if (meth[icode - 1] == 6) { normh = Normal.Complemented(h); value = 0.5 * normh * (1.0 - normh); y = 1.0 - a; r = Math.Atan(y / (1.0 + a)); if (r != 0.0) { value = value - rtwopi * r * Math.Exp(-0.5 * y * h * h / r); } } return(value); }