A game about forced loneliness, made by TACStudios
1using System;
2using static System.Math;
3
4namespace Unity.PerformanceTesting.Statistics
5{
6 static class StudentDistributionHelper
7 {
8 public static double InverseTwoTailedStudent(double p, double n)
9 {
10 var lower = 0.0;
11 var upper = 1000.0;
12 while (upper - lower > 1e-9)
13 {
14 var t = (lower + upper) / 2;
15 var p2 = TwoTailedStudent(t, n);
16 if (p2 < p)
17 upper = t;
18 else
19 lower = t;
20 }
21
22 return (lower + upper) / 2;
23 }
24
25 /// <summary>
26 /// ACM Algorithm 395: Student's t-distribution
27 ///
28 /// Evaluates the two-tail probability P(t|n) that t is exceeded
29 /// in magnitude for Student's t-distribution with n degrees of freedom.
30 ///
31 /// http://dl.acm.org/citation.cfm?id=355599
32 /// </summary>
33 /// <param name="t">t-value, t > 0</param>
34 /// <param name="n">Degree of freedom, n >= 1</param>
35 /// <returns>2-tail p-value</returns>
36 static double TwoTailedStudent(double t, double n)
37 {
38 if (t < 0)
39 throw new ArgumentOutOfRangeException(nameof(t), "t should be >= 0");
40 if (n < 1)
41 throw new ArgumentOutOfRangeException(nameof(n), "n should be >= 1");
42
43 t = t * t;
44 var y = t / n;
45 var b = y + 1.0;
46 var nn = (int)Round(n);
47 if (Abs(n - nn) > 1e-9 || n >= 20 || t < n && n > 200)
48 {
49 if (y > 1.0e-6)
50 y = Log(b);
51 var a = n - 0.5;
52 b = 48.0 * (a * a);
53 y = a * y;
54 y = (((((-0.4 * y - 3.3) * y - 24.0) * y - 85.5) / (0.8 * (y * y) + 100.0 + b) + y + 3.0) / b + 1.0) * Sqrt(y);
55 return 2 * NormalDistributionHelper.Gauss(-y);
56 }
57
58 {
59 double z = 1;
60
61 double a;
62 if (n < 20 && t < 4.0)
63 {
64 y = Sqrt(y);
65 a = y;
66 if (nn == 1)
67 a = 0;
68 }
69 else
70 {
71 a = Sqrt(b);
72 y = a * nn;
73 var j = 0;
74 while (Abs(a - z) > 0)
75 {
76 j += 2;
77 z = a;
78 y *= (j - 1) / (b * j);
79 a += y / (nn + j);
80 }
81
82 nn += 2;
83 z = 0;
84 y = 0;
85 a = -a;
86 }
87
88 while (true)
89 {
90 nn -= 2;
91 if (nn > 1)
92 a = (nn - 1) / (b * nn) * a + y;
93 else
94 break;
95 }
96
97 a = nn == 0 ? a / Sqrt(b) : (Atan(y) + a / b) * 2 / PI;
98 return z - a;
99 }
100 }
101 }
102}