Skip to content

Commit

Permalink
And a little bit more
Browse files Browse the repository at this point in the history
Converting Statistical functions to be array-enabled (phase #2)
  • Loading branch information
MarkBaker committed Feb 15, 2022
1 parent f1cb75e commit 6843dcd
Show file tree
Hide file tree
Showing 10 changed files with 230 additions and 21 deletions.
12 changes: 6 additions & 6 deletions src/PhpSpreadsheet/Calculation/Statistical.php
Original file line number Diff line number Diff line change
Expand Up @@ -1155,7 +1155,7 @@ public static function NEGBINOMDIST($failures, $successes, $probability)
* @param mixed $stdDev Standard Deviation
* @param mixed $cumulative
*
* @return float|string The result, or a string containing an error
* @return array|float|string The result, or a string containing an error
*/
public static function NORMDIST($value, $mean, $stdDev, $cumulative)
{
Expand All @@ -1176,7 +1176,7 @@ public static function NORMDIST($value, $mean, $stdDev, $cumulative)
* @param mixed $mean Mean Value
* @param mixed $stdDev Standard Deviation
*
* @return float|string The result, or a string containing an error
* @return array|float|string The result, or a string containing an error
*/
public static function NORMINV($probability, $mean, $stdDev)
{
Expand All @@ -1197,7 +1197,7 @@ public static function NORMINV($probability, $mean, $stdDev)
*
* @param mixed $value
*
* @return float|string The result, or a string containing an error
* @return array|float|string The result, or a string containing an error
*/
public static function NORMSDIST($value)
{
Expand All @@ -1219,7 +1219,7 @@ public static function NORMSDIST($value)
* @param mixed $value
* @param mixed $cumulative
*
* @return float|string The result, or a string containing an error
* @return array|float|string The result, or a string containing an error
*/
public static function NORMSDIST2($value, $cumulative)
{
Expand All @@ -1238,7 +1238,7 @@ public static function NORMSDIST2($value, $cumulative)
*
* @param mixed $value
*
* @return float|string The result, or a string containing an error
* @return array|float|string The result, or a string containing an error
*/
public static function NORMSINV($value)
{
Expand Down Expand Up @@ -1331,7 +1331,7 @@ public static function PERMUT($numObjs, $numInSet)
* @param mixed $mean Mean Value
* @param mixed $cumulative
*
* @return float|string The result, or a string containing an error
* @return array|float|string The result, or a string containing an error
*/
public static function POISSON($value, $mean, $cumulative)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions;

use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
use PhpOffice\PhpSpreadsheet\Calculation\Engineering;
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;

class Normal
{
use ArrayEnabled;

public const SQRT2PI = 2.5066282746310005024157652848110452530069867406099;

/**
Expand All @@ -18,17 +21,23 @@ class Normal
* testing.
*
* @param mixed $value Float value for which we want the probability
* Or can be an array of values
* @param mixed $mean Mean value as a float
* Or can be an array of values
* @param mixed $stdDev Standard Deviation as a float
* Or can be an array of values
* @param mixed $cumulative Boolean value indicating if we want the cdf (true) or the pdf (false)
* Or can be an array of values
*
* @return float|string The result, or a string containing an error
* @return array|float|string The result, or a string containing an error
* If an array of numbers is passed as an argument, then the returned result will also be an array
* with the same dimensions
*/
public static function distribution($value, $mean, $stdDev, $cumulative)
{
$value = Functions::flattenSingleValue($value);
$mean = Functions::flattenSingleValue($mean);
$stdDev = Functions::flattenSingleValue($stdDev);
if (is_array($value) || is_array($mean) || is_array($stdDev) || is_array($cumulative)) {
return self::evaluateArrayArguments([self::class, __FUNCTION__], $value, $mean, $stdDev, $cumulative);
}

try {
$value = DistributionValidations::validateFloat($value);
Expand Down Expand Up @@ -56,16 +65,21 @@ public static function distribution($value, $mean, $stdDev, $cumulative)
* Returns the inverse of the normal cumulative distribution for the specified mean and standard deviation.
*
* @param mixed $probability Float probability for which we want the value
* Or can be an array of values
* @param mixed $mean Mean Value as a float
* Or can be an array of values
* @param mixed $stdDev Standard Deviation as a float
* Or can be an array of values
*
* @return float|string The result, or a string containing an error
* @return array|float|string The result, or a string containing an error
* If an array of numbers is passed as an argument, then the returned result will also be an array
* with the same dimensions
*/
public static function inverse($probability, $mean, $stdDev)
{
$probability = Functions::flattenSingleValue($probability);
$mean = Functions::flattenSingleValue($mean);
$stdDev = Functions::flattenSingleValue($stdDev);
if (is_array($probability) || is_array($mean) || is_array($stdDev)) {
return self::evaluateArrayArguments([self::class, __FUNCTION__], $probability, $mean, $stdDev);
}

try {
$probability = DistributionValidations::validateProbability($probability);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions;

use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;

class Poisson
{
use ArrayEnabled;

/**
* POISSON.
*
Expand All @@ -16,15 +19,21 @@ class Poisson
* cars arriving at a toll plaza in 1 minute.
*
* @param mixed $value Float value for which we want the probability
* Or can be an array of values
* @param mixed $mean Mean value as a float
* Or can be an array of values
* @param mixed $cumulative Boolean value indicating if we want the cdf (true) or the pdf (false)
* Or can be an array of values
*
* @return float|string The result, or a string containing an error
* @return array|float|string The result, or a string containing an error
* If an array of numbers is passed as an argument, then the returned result will also be an array
* with the same dimensions
*/
public static function distribution($value, $mean, $cumulative)
{
$value = Functions::flattenSingleValue($value);
$mean = Functions::flattenSingleValue($mean);
if (is_array($value) || is_array($mean) || is_array($cumulative)) {
return self::evaluateArrayArguments([self::class, __FUNCTION__], $value, $mean, $cumulative);
}

try {
$value = DistributionValidations::validateFloat($value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,16 @@ class StandardNormal
* a mean of 0 (zero) and a standard deviation of one. Use this function in place of a
* table of standard normal curve areas.
*
* NOTE: We don't need to check for arrays to array-enable this function, because that is already
* handled by the logic in Normal::distribution()
* All we need to do is pass the value through as scalar or as array.
*
* @param mixed $value Float value for which we want the probability
* Or can be an array of values
*
* @return float|string The result, or a string containing an error
* @return array|float|string The result, or a string containing an error
* If an array of numbers is passed as an argument, then the returned result will also be an array
* with the same dimensions
*/
public static function cumulative($value)
{
Expand All @@ -34,10 +41,18 @@ public static function cumulative($value)
* a mean of 0 (zero) and a standard deviation of one. Use this function in place of a
* table of standard normal curve areas.
*
* NOTE: We don't need to check for arrays to array-enable this function, because that is already
* handled by the logic in Normal::distribution()
* All we need to do is pass the value and cumulative through as scalar or as array.
*
* @param mixed $value Float value for which we want the probability
* Or can be an array of values
* @param mixed $cumulative Boolean value indicating if we want the cdf (true) or the pdf (false)
* Or can be an array of values
*
* @return float|string The result, or a string containing an error
* @return array|float|string The result, or a string containing an error
* If an array of numbers is passed as an argument, then the returned result will also be an array
* with the same dimensions
*/
public static function distribution($value, $cumulative)
{
Expand All @@ -49,9 +64,16 @@ public static function distribution($value, $cumulative)
*
* Returns the inverse of the standard normal cumulative distribution
*
* @param mixed $value Float probability for which we want the value
* @param mixed $value float probability for which we want the value
* Or can be an array of values
*
* NOTE: We don't need to check for arrays to array-enable this function, because that is already
* handled by the logic in Normal::inverse()
* All we need to do is pass the value through as scalar or as array
*
* @return float|string The result, or a string containing an error
* @return array|float|string The result, or a string containing an error
* If an array of numbers is passed as an argument, then the returned result will also be an array
* with the same dimensions
*/
public static function inverse($value)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;

use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
use PHPUnit\Framework\TestCase;

Expand All @@ -22,4 +23,32 @@ public function providerNORMDIST(): array
{
return require 'tests/data/Calculation/Statistical/NORMDIST.php';
}

/**
* @dataProvider providerNormDistArray
*/
public function testNormDistArray(array $expectedResult, string $values, string $mean, string $stdDev): void
{
$calculation = Calculation::getInstance();

$formula = "=NORMDIST({$values}, {$mean}, {$stdDev}, false)";
$result = $calculation->_calculateFormulaValue($formula);
self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14);
}

public function providerNormDistArray(): array
{
return [
'row/column vectors' => [
[
[0.04324582990797181, 0.03549422283581691, 0.026885636057682592],
[0.07365402806066465, 0.038837210996642585, 0.015790031660178828],
[0.12098536225957167, 0.0022159242059690033, 7.991870553452737E-6],
],
'12',
'{10, 6, 3}',
'{9; 5; 2}',
],
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;

use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
use PHPUnit\Framework\TestCase;

Expand All @@ -22,4 +23,32 @@ public function providerNORMINV(): array
{
return require 'tests/data/Calculation/Statistical/NORMINV.php';
}

/**
* @dataProvider providerNormInvArray
*/
public function testNormInvArray(array $expectedResult, string $probabilities, string $mean, string $stdDev): void
{
$calculation = Calculation::getInstance();

$formula = "=NORMINV({$probabilities}, {$mean}, {$stdDev})";
$result = $calculation->_calculateFormulaValue($formula);
self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14);
}

public function providerNormInvArray(): array
{
return [
'row/column vectors' => [
[
[2.651020499553155, 4.651020499553155],
[1.9765307493297324, 3.9765307493297324],
[-0.7214282515639576, 1.2785717484360424],
],
'0.25',
'{4, 6}',
'{2; 3; 7}',
],
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;

use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
use PHPUnit\Framework\TestCase;

Expand All @@ -22,4 +23,29 @@ public function providerNORMSDIST2(): array
{
return require 'tests/data/Calculation/Statistical/NORMSDIST2.php';
}

/**
* @dataProvider providerNormSDist2Array
*/
public function testNormSDist2Array(array $expectedResult, string $values): void
{
$calculation = Calculation::getInstance();

$formula = "=NORM.S.DIST({$values}, true)";
$result = $calculation->_calculateFormulaValue($formula);
self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14);
}

public function providerNormSDist2Array(): array
{
return [
'row/column vectors' => [
[
[0.3085375387259869, 0.7733726476231317],
[0.99865010196837, 1.0],
],
'{-0.5, 0.75; 3, 12.5}',
],
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;

use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
use PHPUnit\Framework\TestCase;

Expand All @@ -23,4 +24,29 @@ public function providerNORMSDIST(): array
{
return require 'tests/data/Calculation/Statistical/NORMSDIST.php';
}

/**
* @dataProvider providerNormSDistArray
*/
public function testNormSDistArray(array $expectedResult, string $values): void
{
$calculation = Calculation::getInstance();

$formula = "=NORMSDIST({$values})";
$result = $calculation->_calculateFormulaValue($formula);
self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14);
}

public function providerNormSDistArray(): array
{
return [
'row/column vectors' => [
[
[0.3085375387259869, 0.7733726476231317],
[0.99865010196837, 1.0],
],
'{-0.5, 0.75; 3, 12.5}',
],
];
}
}
Loading

0 comments on commit 6843dcd

Please sign in to comment.