float8 studentT_cdf(int64 nu, float8 t) { float8 z, t_by_sqrt_nu; float8 A, /* contains A(t|nu) */ prod = 1., sum = 1.; /* Handle extreme cases. See above. */ if (nu <= 0) return NAN; else if (nu >= 1000000) return normal_cdf(t); else if (nu >= 200) return studentT_cdf_approx(nu, t); /* Handle main case (nu < 200) in the rest of the function. */ z = 1. + t * t / nu; t_by_sqrt_nu = fabs(t) / sqrt(nu); if (nu == 1) { A = 2. / M_PI * atan(t_by_sqrt_nu); } else if (nu & 1) /* odd nu > 1 */ { for (int j = 2; j <= nu - 3; j += 2) { prod = prod * j / ((j + 1) * z); sum = sum + prod; } A = 2 / M_PI * ( atan(t_by_sqrt_nu) + t_by_sqrt_nu / z * sum ); } else /* even nu */ { for (int j = 2; j <= nu - 2; j += 2) { prod = prod * (j - 1) / (j * z); sum = sum + prod; } A = t_by_sqrt_nu / sqrt(z) * sum; } /* A should obviously lie withing the interval [0,1] plus minus (hopefully * small) rounding errors. */ if (A > 1.) A = 1.; else if (A < 0.) A = 0.; /* The Student-T distribution is obviously symmetric around t=0... */ if (t < 0) return .5 * (1. - A); else return 1. - .5 * (1. - A); }
double studentT_CDF(int64_t nu, double t) { double z, t_by_sqrt_nu; double A, /* contains A(t|nu) */ prod = 1., sum = 1.; /* Handle extreme cases. See above. */ if (nu <= 0) return std::numeric_limits<double>::quiet_NaN(); else if (t == std::numeric_limits<double>::infinity()) return 1; else if (t == -std::numeric_limits<double>::infinity()) return 0; else if (nu >= 1000000) return normal_cdf(t); else if (nu >= 200) return studentT_cdf_approx(nu, t); /* Handle main case (nu < 200) in the rest of the function. */ z = 1. + t * t / nu; t_by_sqrt_nu = std::fabs(t) / std::sqrt(static_cast<double>(nu)); if (nu == 1) { A = 2. / M_PI * std::atan(t_by_sqrt_nu); } else if (nu & 1) /* odd nu > 1 */ { for (int j = 2; j <= nu - 3; j += 2) { prod = prod * j / ((j + 1) * z); sum = sum + prod; } A = 2 / M_PI * ( std::atan(t_by_sqrt_nu) + t_by_sqrt_nu / z * sum ); } else /* even nu */ { for (int j = 2; j <= nu - 2; j += 2) { prod = prod * (j - 1) / (j * z); sum = sum + prod; } A = t_by_sqrt_nu / std::sqrt(z) * sum; } /* A should obviously be within the interval [0,1] plus minus (hopefully * small) rounding errors. */ if (A > 1.) A = 1.; else if (A < 0.) A = 0.; /* The Student-T distribution is obviously symmetric around t=0... */ if (t < 0) return .5 * (1. - A); else return 1. - .5 * (1. - A); }