Skip to content

Commit a5647a2

Browse files
author
MarkBaker
committed
Converting Statistical functions to be array-enabled (phase #2)
1 parent f1cb75e commit a5647a2

File tree

15 files changed

+349
-36
lines changed

15 files changed

+349
-36
lines changed

src/PhpSpreadsheet/Calculation/Statistical.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,7 +1155,7 @@ public static function NEGBINOMDIST($failures, $successes, $probability)
11551155
* @param mixed $stdDev Standard Deviation
11561156
* @param mixed $cumulative
11571157
*
1158-
* @return float|string The result, or a string containing an error
1158+
* @return array|float|string The result, or a string containing an error
11591159
*/
11601160
public static function NORMDIST($value, $mean, $stdDev, $cumulative)
11611161
{
@@ -1176,7 +1176,7 @@ public static function NORMDIST($value, $mean, $stdDev, $cumulative)
11761176
* @param mixed $mean Mean Value
11771177
* @param mixed $stdDev Standard Deviation
11781178
*
1179-
* @return float|string The result, or a string containing an error
1179+
* @return array|float|string The result, or a string containing an error
11801180
*/
11811181
public static function NORMINV($probability, $mean, $stdDev)
11821182
{
@@ -1197,7 +1197,7 @@ public static function NORMINV($probability, $mean, $stdDev)
11971197
*
11981198
* @param mixed $value
11991199
*
1200-
* @return float|string The result, or a string containing an error
1200+
* @return array|float|string The result, or a string containing an error
12011201
*/
12021202
public static function NORMSDIST($value)
12031203
{
@@ -1219,7 +1219,7 @@ public static function NORMSDIST($value)
12191219
* @param mixed $value
12201220
* @param mixed $cumulative
12211221
*
1222-
* @return float|string The result, or a string containing an error
1222+
* @return array|float|string The result, or a string containing an error
12231223
*/
12241224
public static function NORMSDIST2($value, $cumulative)
12251225
{
@@ -1238,7 +1238,7 @@ public static function NORMSDIST2($value, $cumulative)
12381238
*
12391239
* @param mixed $value
12401240
*
1241-
* @return float|string The result, or a string containing an error
1241+
* @return array|float|string The result, or a string containing an error
12421242
*/
12431243
public static function NORMSINV($value)
12441244
{
@@ -1331,7 +1331,7 @@ public static function PERMUT($numObjs, $numInSet)
13311331
* @param mixed $mean Mean Value
13321332
* @param mixed $cumulative
13331333
*
1334-
* @return float|string The result, or a string containing an error
1334+
* @return array|float|string The result, or a string containing an error
13351335
*/
13361336
public static function POISSON($value, $mean, $cumulative)
13371337
{
@@ -1610,7 +1610,7 @@ public static function STEYX($yValues, $xValues)
16101610
* @param float $degrees degrees of freedom
16111611
* @param float $tails number of tails (1 or 2)
16121612
*
1613-
* @return float|string The result, or a string containing an error
1613+
* @return array|float|string The result, or a string containing an error
16141614
*/
16151615
public static function TDIST($value, $degrees, $tails)
16161616
{
@@ -1630,7 +1630,7 @@ public static function TDIST($value, $degrees, $tails)
16301630
* @param float $probability Probability for the function
16311631
* @param float $degrees degrees of freedom
16321632
*
1633-
* @return float|string The result, or a string containing an error
1633+
* @return array|float|string The result, or a string containing an error
16341634
*/
16351635
public static function TINV($probability, $degrees)
16361636
{
@@ -1787,7 +1787,7 @@ public static function VARPA(...$args)
17871787
* @param float $beta Beta Parameter
17881788
* @param bool $cumulative
17891789
*
1790-
* @return float|string (string if result is an error)
1790+
* @return array|float|string (string if result is an error)
17911791
*/
17921792
public static function WEIBULL($value, $alpha, $beta, $cumulative)
17931793
{

src/PhpSpreadsheet/Calculation/Statistical/Distributions/Normal.php

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22

33
namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions;
44

5+
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
56
use PhpOffice\PhpSpreadsheet\Calculation\Engineering;
67
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
78
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
89

910
class Normal
1011
{
12+
use ArrayEnabled;
13+
1114
public const SQRT2PI = 2.5066282746310005024157652848110452530069867406099;
1215

1316
/**
@@ -18,17 +21,23 @@ class Normal
1821
* testing.
1922
*
2023
* @param mixed $value Float value for which we want the probability
24+
* Or can be an array of values
2125
* @param mixed $mean Mean value as a float
26+
* Or can be an array of values
2227
* @param mixed $stdDev Standard Deviation as a float
28+
* Or can be an array of values
2329
* @param mixed $cumulative Boolean value indicating if we want the cdf (true) or the pdf (false)
30+
* Or can be an array of values
2431
*
25-
* @return float|string The result, or a string containing an error
32+
* @return array|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
2635
*/
2736
public static function distribution($value, $mean, $stdDev, $cumulative)
2837
{
29-
$value = Functions::flattenSingleValue($value);
30-
$mean = Functions::flattenSingleValue($mean);
31-
$stdDev = Functions::flattenSingleValue($stdDev);
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+
}
3241

3342
try {
3443
$value = DistributionValidations::validateFloat($value);
@@ -56,16 +65,21 @@ public static function distribution($value, $mean, $stdDev, $cumulative)
5665
* Returns the inverse of the normal cumulative distribution for the specified mean and standard deviation.
5766
*
5867
* @param mixed $probability Float probability for which we want the value
68+
* Or can be an array of values
5969
* @param mixed $mean Mean Value as a float
70+
* Or can be an array of values
6071
* @param mixed $stdDev Standard Deviation as a float
72+
* Or can be an array of values
6173
*
62-
* @return float|string The result, or a string containing an error
74+
* @return array|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
6377
*/
6478
public static function inverse($probability, $mean, $stdDev)
6579
{
66-
$probability = Functions::flattenSingleValue($probability);
67-
$mean = Functions::flattenSingleValue($mean);
68-
$stdDev = Functions::flattenSingleValue($stdDev);
80+
if (is_array($probability) || is_array($mean) || is_array($stdDev)) {
81+
return self::evaluateArrayArguments([self::class, __FUNCTION__], $probability, $mean, $stdDev);
82+
}
6983

7084
try {
7185
$probability = DistributionValidations::validateProbability($probability);

src/PhpSpreadsheet/Calculation/Statistical/Distributions/Poisson.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22

33
namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions;
44

5+
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
56
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
67
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
78
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
89

910
class Poisson
1011
{
12+
use ArrayEnabled;
13+
1114
/**
1215
* POISSON.
1316
*
@@ -16,15 +19,21 @@ class Poisson
1619
* cars arriving at a toll plaza in 1 minute.
1720
*
1821
* @param mixed $value Float value for which we want the probability
22+
* Or can be an array of values
1923
* @param mixed $mean Mean value as a float
24+
* Or can be an array of values
2025
* @param mixed $cumulative Boolean value indicating if we want the cdf (true) or the pdf (false)
26+
* Or can be an array of values
2127
*
22-
* @return float|string The result, or a string containing an error
28+
* @return array|float|string The result, or a string containing an error
29+
* If an array of numbers is passed as an argument, then the returned result will also be an array
30+
* with the same dimensions
2331
*/
2432
public static function distribution($value, $mean, $cumulative)
2533
{
26-
$value = Functions::flattenSingleValue($value);
27-
$mean = Functions::flattenSingleValue($mean);
34+
if (is_array($value) || is_array($mean) || is_array($cumulative)) {
35+
return self::evaluateArrayArguments([self::class, __FUNCTION__], $value, $mean, $cumulative);
36+
}
2837

2938
try {
3039
$value = DistributionValidations::validateFloat($value);

src/PhpSpreadsheet/Calculation/Statistical/Distributions/StandardNormal.php

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,16 @@ class StandardNormal
1818
* a mean of 0 (zero) and a standard deviation of one. Use this function in place of a
1919
* table of standard normal curve areas.
2020
*
21+
* NOTE: We don't need to check for arrays to array-enable this function, because that is already
22+
* handled by the logic in Normal::distribution()
23+
* All we need to do is pass the value through as scalar or as array.
24+
*
2125
* @param mixed $value Float value for which we want the probability
26+
* Or can be an array of values
2227
*
23-
* @return float|string The result, or a string containing an error
28+
* @return array|float|string The result, or a string containing an error
29+
* If an array of numbers is passed as an argument, then the returned result will also be an array
30+
* with the same dimensions
2431
*/
2532
public static function cumulative($value)
2633
{
@@ -34,10 +41,18 @@ public static function cumulative($value)
3441
* a mean of 0 (zero) and a standard deviation of one. Use this function in place of a
3542
* table of standard normal curve areas.
3643
*
44+
* NOTE: We don't need to check for arrays to array-enable this function, because that is already
45+
* handled by the logic in Normal::distribution()
46+
* All we need to do is pass the value and cumulative through as scalar or as array.
47+
*
3748
* @param mixed $value Float value for which we want the probability
49+
* Or can be an array of values
3850
* @param mixed $cumulative Boolean value indicating if we want the cdf (true) or the pdf (false)
51+
* Or can be an array of values
3952
*
40-
* @return float|string The result, or a string containing an error
53+
* @return array|float|string The result, or a string containing an error
54+
* If an array of numbers is passed as an argument, then the returned result will also be an array
55+
* with the same dimensions
4156
*/
4257
public static function distribution($value, $cumulative)
4358
{
@@ -49,9 +64,16 @@ public static function distribution($value, $cumulative)
4964
*
5065
* Returns the inverse of the standard normal cumulative distribution
5166
*
52-
* @param mixed $value Float probability for which we want the value
67+
* @param mixed $value float probability for which we want the value
68+
* Or can be an array of values
69+
*
70+
* NOTE: We don't need to check for arrays to array-enable this function, because that is already
71+
* handled by the logic in Normal::inverse()
72+
* All we need to do is pass the value through as scalar or as array
5373
*
54-
* @return float|string The result, or a string containing an error
74+
* @return array|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
5577
*/
5678
public static function inverse($value)
5779
{

src/PhpSpreadsheet/Calculation/Statistical/Distributions/StudentT.php

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions;
44

5+
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
56
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
67
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
78

89
class StudentT
910
{
11+
use ArrayEnabled;
12+
1013
private const MAX_ITERATIONS = 256;
1114

1215
/**
@@ -15,16 +18,21 @@ class StudentT
1518
* Returns the probability of Student's T distribution.
1619
*
1720
* @param mixed $value Float value for the distribution
21+
* Or can be an array of values
1822
* @param mixed $degrees Integer value for degrees of freedom
23+
* Or can be an array of values
1924
* @param mixed $tails Integer value for the number of tails (1 or 2)
25+
* Or can be an array of values
2026
*
21-
* @return float|string The result, or a string containing an error
27+
* @return array|float|string The result, or a string containing an error
28+
* If an array of numbers is passed as an argument, then the returned result will also be an array
29+
* with the same dimensions
2230
*/
2331
public static function distribution($value, $degrees, $tails)
2432
{
25-
$value = Functions::flattenSingleValue($value);
26-
$degrees = Functions::flattenSingleValue($degrees);
27-
$tails = Functions::flattenSingleValue($tails);
33+
if (is_array($value) || is_array($degrees) || is_array($tails)) {
34+
return self::evaluateArrayArguments([self::class, __FUNCTION__], $value, $degrees, $tails);
35+
}
2836

2937
try {
3038
$value = DistributionValidations::validateFloat($value);
@@ -47,14 +55,19 @@ public static function distribution($value, $degrees, $tails)
4755
* Returns the one-tailed probability of the chi-squared distribution.
4856
*
4957
* @param mixed $probability Float probability for the function
58+
* Or can be an array of values
5059
* @param mixed $degrees Integer value for degrees of freedom
60+
* Or can be an array of values
5161
*
52-
* @return float|string The result, or a string containing an error
62+
* @return array|float|string The result, or a string containing an error
63+
* If an array of numbers is passed as an argument, then the returned result will also be an array
64+
* with the same dimensions
5365
*/
5466
public static function inverse($probability, $degrees)
5567
{
56-
$probability = Functions::flattenSingleValue($probability);
57-
$degrees = Functions::flattenSingleValue($degrees);
68+
if (is_array($probability) || is_array($degrees)) {
69+
return self::evaluateArrayArguments([self::class, __FUNCTION__], $probability, $degrees);
70+
}
5871

5972
try {
6073
$probability = DistributionValidations::validateProbability($probability);

src/PhpSpreadsheet/Calculation/Statistical/Distributions/Weibull.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,38 @@
22

33
namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions;
44

5+
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
56
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
67
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
78

89
class Weibull
910
{
11+
use ArrayEnabled;
12+
1013
/**
1114
* WEIBULL.
1215
*
1316
* Returns the Weibull distribution. Use this distribution in reliability
1417
* analysis, such as calculating a device's mean time to failure.
1518
*
1619
* @param mixed $value Float value for the distribution
20+
* Or can be an array of values
1721
* @param mixed $alpha Float alpha Parameter
22+
* Or can be an array of values
1823
* @param mixed $beta Float beta Parameter
24+
* Or can be an array of values
1925
* @param mixed $cumulative Boolean value indicating if we want the cdf (true) or the pdf (false)
26+
* Or can be an array of values
2027
*
21-
* @return float|string (string if result is an error)
28+
* @return array|float|string (string if result is an error)
29+
* If an array of numbers is passed as an argument, then the returned result will also be an array
30+
* with the same dimensions
2231
*/
2332
public static function distribution($value, $alpha, $beta, $cumulative)
2433
{
25-
$value = Functions::flattenSingleValue($value);
26-
$alpha = Functions::flattenSingleValue($alpha);
27-
$beta = Functions::flattenSingleValue($beta);
28-
$cumulative = Functions::flattenSingleValue($cumulative);
34+
if (is_array($value) || is_array($alpha) || is_array($beta) || is_array($cumulative)) {
35+
return self::evaluateArrayArguments([self::class, __FUNCTION__], $value, $alpha, $beta, $cumulative);
36+
}
2937

3038
try {
3139
$value = DistributionValidations::validateFloat($value);

tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/NormDistTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;
44

5+
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
56
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
67
use PHPUnit\Framework\TestCase;
78

@@ -22,4 +23,32 @@ public function providerNORMDIST(): array
2223
{
2324
return require 'tests/data/Calculation/Statistical/NORMDIST.php';
2425
}
26+
27+
/**
28+
* @dataProvider providerNormDistArray
29+
*/
30+
public function testNormDistArray(array $expectedResult, string $values, string $mean, string $stdDev): void
31+
{
32+
$calculation = Calculation::getInstance();
33+
34+
$formula = "=NORMDIST({$values}, {$mean}, {$stdDev}, false)";
35+
$result = $calculation->_calculateFormulaValue($formula);
36+
self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14);
37+
}
38+
39+
public function providerNormDistArray(): array
40+
{
41+
return [
42+
'row/column vectors' => [
43+
[
44+
[0.04324582990797181, 0.03549422283581691, 0.026885636057682592],
45+
[0.07365402806066465, 0.038837210996642585, 0.015790031660178828],
46+
[0.12098536225957167, 0.0022159242059690033, 7.991870553452737E-6],
47+
],
48+
'12',
49+
'{10, 6, 3}',
50+
'{9; 5; 2}',
51+
],
52+
];
53+
}
2554
}

0 commit comments

Comments
 (0)