PluginProbe
TablePress – Tables in WordPress made easy / 3.4
TablePress – Tables in WordPress made easy v3.4
3.4 3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 All 45 releases
tablepress / libraries / vendor / PhpSpreadsheet / Calculation / Statistical / Distributions / Normal.php

Normal.php in TablePress – Tables in WordPress made easy 3.4, at libraries/vendor/PhpSpreadsheet/Calculation/Statistical/Distributions/Normal.php

185 lines 6.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace TablePress\PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions;
4
5 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
6 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\Engineering;
7 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\Exception;
8 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
9
10 class Normal
11 {
12 use ArrayEnabled;
13
14 public const SQRT2PI = 2.5066282746310005024157652848110452530069867406099;
15
16 /**
17 * NORMDIST.
18 *
19 * Returns the normal distribution for the specified mean and standard deviation. This
20 * function has a very wide range of applications in statistics, including hypothesis
21 * testing.
22 *
23 * @param mixed $value Float value for which we want the probability
24 * Or can be an array of values
25 * @param mixed $mean Mean value as a float
26 * Or can be an array of values
27 * @param mixed $stdDev Standard Deviation as a float
28 * Or can be an array of values
29 * @param mixed $cumulative Boolean value indicating if we want the cdf (true) or the pdf (false)
30 * Or can be an array of values
31 *
32 * @return array<mixed>|float|string The result, or a string containing an error
33 * If an array of numbers is passed as an argument, then the returned result will also be an array
34 * with the same dimensions
35 */
36 public static function distribution($value, $mean, $stdDev, $cumulative)
37 {
38 if (is_array($value) || is_array($mean) || is_array($stdDev) || is_array($cumulative)) {
39 return self::evaluateArrayArguments([self::class, __FUNCTION__], $value, $mean, $stdDev, $cumulative);
40 }
41
42 try {
43 $value = DistributionValidations::validateFloat($value);
44 $mean = DistributionValidations::validateFloat($mean);
45 $stdDev = DistributionValidations::validateFloat($stdDev);
46 $cumulative = DistributionValidations::validateBool($cumulative);
47 } catch (Exception $e) {
48 return $e->getMessage();
49 }
50
51 if ($stdDev < 0) {
52 return ExcelError::NAN();
53 }
54
55 if ($cumulative) {
56 return 0.5 * (1 + Engineering\Erf::erfValue(($value - $mean) / ($stdDev * sqrt(2))));
57 }
58
59 return (1 / (self::SQRT2PI * $stdDev)) * exp(0 - (($value - $mean) ** 2 / (2 * ($stdDev * $stdDev))));
60 }
61
62 /**
63 * NORMINV.
64 *
65 * Returns the inverse of the normal cumulative distribution for the specified mean and standard deviation.
66 *
67 * @param mixed $probability Float probability for which we want the value
68 * Or can be an array of values
69 * @param mixed $mean Mean Value as a float
70 * Or can be an array of values
71 * @param mixed $stdDev Standard Deviation as a float
72 * Or can be an array of values
73 *
74 * @return array<mixed>|float|string The result, or a string containing an error
75 * If an array of numbers is passed as an argument, then the returned result will also be an array
76 * with the same dimensions
77 */
78 public static function inverse($probability, $mean, $stdDev)
79 {
80 if (is_array($probability) || is_array($mean) || is_array($stdDev)) {
81 return self::evaluateArrayArguments([self::class, __FUNCTION__], $probability, $mean, $stdDev);
82 }
83
84 try {
85 $probability = DistributionValidations::validateProbability($probability);
86 $mean = DistributionValidations::validateFloat($mean);
87 $stdDev = DistributionValidations::validateFloat($stdDev);
88 } catch (Exception $e) {
89 return $e->getMessage();
90 }
91
92 if ($stdDev < 0) {
93 return ExcelError::NAN();
94 }
95
96 return (self::inverseNcdf($probability) * $stdDev) + $mean;
97 }
98
99 /*
100 * inverse_ncdf.php
101 * -------------------
102 * begin : Friday, January 16, 2004
103 * copyright : (C) 2004 Michael Nickerson
104 * email : [email protected]
105 *
106 */
107 private static function inverseNcdf(float $p): float
108 {
109 // Inverse ncdf approximation by Peter J. Acklam, implementation adapted to
110 // PHP by Michael Nickerson, using Dr. Thomas Ziegler's C implementation as
111 // a guide. http://home.online.no/~pjacklam/notes/invnorm/index.html
112 // I have not checked the accuracy of this implementation. Be aware that PHP
113 // will truncate the coeficcients to 14 digits.
114
115 // You have permission to use and distribute this function freely for
116 // whatever purpose you want, but please show common courtesy and give credit
117 // where credit is due.
118
119 // Input parameter is $p - probability - where 0 < p < 1.
120
121 // Coefficients in rational approximations
122 /** @var array<int, float> */
123 static $a = [
124 1 => -3.969683028665376e+01,
125 2 => 2.209460984245205e+02,
126 3 => -2.759285104469687e+02,
127 4 => 1.383577518672690e+02,
128 5 => -3.066479806614716e+01,
129 6 => 2.506628277459239e+00,
130 ];
131
132 /** @var array<int, float> */
133 static $b = [
134 1 => -5.447609879822406e+01,
135 2 => 1.615858368580409e+02,
136 3 => -1.556989798598866e+02,
137 4 => 6.680131188771972e+01,
138 5 => -1.328068155288572e+01,
139 ];
140
141 /** @var array<int, float> */
142 static $c = [
143 1 => -7.784894002430293e-03,
144 2 => -3.223964580411365e-01,
145 3 => -2.400758277161838e+00,
146 4 => -2.549732539343734e+00,
147 5 => 4.374664141464968e+00,
148 6 => 2.938163982698783e+00,
149 ];
150
151 /** @var array<int, float> */
152 static $d = [
153 1 => 7.784695709041462e-03,
154 2 => 3.224671290700398e-01,
155 3 => 2.445134137142996e+00,
156 4 => 3.754408661907416e+00,
157 ];
158
159 // Define lower and upper region break-points.
160 $p_low = 0.02425; //Use lower region approx. below this
161 $p_high = 1 - $p_low; //Use upper region approx. above this
162
163 if (0 < $p && $p < $p_low) {
164 // Rational approximation for lower region.
165 $q = sqrt(-2 * log($p));
166
167 return ((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6])
168 / (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1);
169 } elseif ($p_high < $p && $p < 1) {
170 // Rational approximation for upper region.
171 $q = sqrt(-2 * log(1 - $p));
172
173 return -((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6])
174 / (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1);
175 }
176
177 // Rational approximation for central region.
178 $q = $p - 0.5;
179 $r = $q * $q;
180
181 return ((((($a[1] * $r + $a[2]) * $r + $a[3]) * $r + $a[4]) * $r + $a[5]) * $r + $a[6]) * $q
182 / ((((($b[1] * $r + $b[2]) * $r + $b[3]) * $r + $b[4]) * $r + $b[5]) * $r + 1);
183 }
184 }
185