Skip to content

Commit 6843dcd

Browse files
author
MarkBaker
committed
And a little bit more
Converting Statistical functions to be array-enabled (phase #2)
1 parent f1cb75e commit 6843dcd

File tree

10 files changed

+230
-21
lines changed

10 files changed

+230
-21
lines changed

src/PhpSpreadsheet/Calculation/Statistical.php

+6-6
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
{

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

+22-8
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

+12-3
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

+26-4
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
{

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

+29
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
}

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

+29
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 providerNORMINV(): array
2223
{
2324
return require 'tests/data/Calculation/Statistical/NORMINV.php';
2425
}
26+
27+
/**
28+
* @dataProvider providerNormInvArray
29+
*/
30+
public function testNormInvArray(array $expectedResult, string $probabilities, string $mean, string $stdDev): void
31+
{
32+
$calculation = Calculation::getInstance();
33+
34+
$formula = "=NORMINV({$probabilities}, {$mean}, {$stdDev})";
35+
$result = $calculation->_calculateFormulaValue($formula);
36+
self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14);
37+
}
38+
39+
public function providerNormInvArray(): array
40+
{
41+
return [
42+
'row/column vectors' => [
43+
[
44+
[2.651020499553155, 4.651020499553155],
45+
[1.9765307493297324, 3.9765307493297324],
46+
[-0.7214282515639576, 1.2785717484360424],
47+
],
48+
'0.25',
49+
'{4, 6}',
50+
'{2; 3; 7}',
51+
],
52+
];
53+
}
2554
}

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

+26
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,29 @@ public function providerNORMSDIST2(): array
2223
{
2324
return require 'tests/data/Calculation/Statistical/NORMSDIST2.php';
2425
}
26+
27+
/**
28+
* @dataProvider providerNormSDist2Array
29+
*/
30+
public function testNormSDist2Array(array $expectedResult, string $values): void
31+
{
32+
$calculation = Calculation::getInstance();
33+
34+
$formula = "=NORM.S.DIST({$values}, true)";
35+
$result = $calculation->_calculateFormulaValue($formula);
36+
self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14);
37+
}
38+
39+
public function providerNormSDist2Array(): array
40+
{
41+
return [
42+
'row/column vectors' => [
43+
[
44+
[0.3085375387259869, 0.7733726476231317],
45+
[0.99865010196837, 1.0],
46+
],
47+
'{-0.5, 0.75; 3, 12.5}',
48+
],
49+
];
50+
}
2551
}

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

+26
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

@@ -23,4 +24,29 @@ public function providerNORMSDIST(): array
2324
{
2425
return require 'tests/data/Calculation/Statistical/NORMSDIST.php';
2526
}
27+
28+
/**
29+
* @dataProvider providerNormSDistArray
30+
*/
31+
public function testNormSDistArray(array $expectedResult, string $values): void
32+
{
33+
$calculation = Calculation::getInstance();
34+
35+
$formula = "=NORMSDIST({$values})";
36+
$result = $calculation->_calculateFormulaValue($formula);
37+
self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14);
38+
}
39+
40+
public function providerNormSDistArray(): array
41+
{
42+
return [
43+
'row/column vectors' => [
44+
[
45+
[0.3085375387259869, 0.7733726476231317],
46+
[0.99865010196837, 1.0],
47+
],
48+
'{-0.5, 0.75; 3, 12.5}',
49+
],
50+
];
51+
}
2652
}

0 commit comments

Comments
 (0)