Skip to content

Commit

Permalink
More unit tests for statistical functions, including a bugfix to LARG…
Browse files Browse the repository at this point in the history
…E() (PHPOffice#1601)

* More unit tests for statistical functions, including a bugfix to LARGE() that was identified in testing
  • Loading branch information
Mark Baker authored Jul 29, 2020
1 parent a203c3a commit 9683e5b
Show file tree
Hide file tree
Showing 23 changed files with 478 additions and 28 deletions.
4 changes: 2 additions & 2 deletions src/PhpSpreadsheet/Calculation/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ public static function DSUM($database, $field, $criteria)
* the column label in which you specify a condition for the
* column.
*
* @return float
* @return float|string (string if result is an error)
*/
public static function DVAR($database, $field, $criteria)
{
Expand Down Expand Up @@ -591,7 +591,7 @@ public static function DVAR($database, $field, $criteria)
* the column label in which you specify a condition for the
* column.
*
* @return float
* @return float|string (string if result is an error)
*/
public static function DVARP($database, $field, $criteria)
{
Expand Down
6 changes: 3 additions & 3 deletions src/PhpSpreadsheet/Calculation/LookupRef.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public static function COLUMN($cellAddress = null)
*
* @param null|array|string $cellAddress An array or array formula, or a reference to a range of cells for which you want the number of columns
*
* @return int The number of columns in cellAddress
* @return int|string The number of columns in cellAddress, or a string if arguments are invalid
*/
public static function COLUMNS($cellAddress = null)
{
Expand Down Expand Up @@ -160,7 +160,7 @@ public static function COLUMNS($cellAddress = null)
*
* @param null|array|string $cellAddress A reference to a range of cells for which you want the row numbers
*
* @return int or array of integer
* @return int|mixed[]|string
*/
public static function ROW($cellAddress = null)
{
Expand Down Expand Up @@ -203,7 +203,7 @@ public static function ROW($cellAddress = null)
*
* @param null|array|string $cellAddress An array or array formula, or a reference to a range of cells for which you want the number of rows
*
* @return int The number of rows in cellAddress
* @return int|string The number of rows in cellAddress, or a string if arguments are invalid
*/
public static function ROWS($cellAddress = null)
{
Expand Down
13 changes: 7 additions & 6 deletions src/PhpSpreadsheet/Calculation/MathTrig.php
Original file line number Diff line number Diff line change
Expand Up @@ -871,7 +871,7 @@ public static function MROUND($number, $multiple)
*
* Returns the ratio of the factorial of a sum of values to the product of factorials.
*
* @param array of mixed Data Series
* @param mixed[] $args An array of mixed values for the Data Series
*
* @return float|string The result, or a string containing an error
*/
Expand Down Expand Up @@ -1149,7 +1149,7 @@ public static function ROUNDDOWN($number, $digits)
*
* Returns the sum of a power series
*
* @param array of mixed Data Series
* @param mixed[] $args An array of mixed values for the Data Series
*
* @return float|string The result, or a string containing an error
*/
Expand Down Expand Up @@ -1273,21 +1273,22 @@ function ($index) use ($cellReference) {
*
* Returns a subtotal in a list or database.
*
* @param int the number 1 to 11 that specifies which function to
* @param int $functionType
* A number 1 to 11 that specifies which function to
* use in calculating subtotals within a range
* list
* Numbers 101 to 111 shadow the functions of 1 to 11
* but ignore any values in the range that are
* in hidden rows or columns
* @param array of mixed Data Series
* @param mixed[] $args A mixed data series of values
*
* @return float|string
*/
public static function SUBTOTAL(...$args)
public static function SUBTOTAL($functionType, ...$args)
{
$cellReference = array_pop($args);
$aArgs = Functions::flattenArrayIndexed($args);
$subtotal = array_shift($aArgs);
$subtotal = Functions::flattenSingleValue($functionType);

// Calculate
if ((is_numeric($subtotal)) && (!is_string($subtotal))) {
Expand Down
31 changes: 16 additions & 15 deletions src/PhpSpreadsheet/Calculation/Statistical.php
Original file line number Diff line number Diff line change
Expand Up @@ -1445,7 +1445,7 @@ public static function DEVSQ(...$args)
return $returnValue;
}

return self::NA();
return Functions::NA();
}

/**
Expand Down Expand Up @@ -1701,7 +1701,6 @@ public static function GAMMAINV($probability, $alpha, $beta)
$xHi = $alpha * $beta * 5;

$x = $xNew = 1;
$error = $pdf = 0;
$dx = 1024;
$i = 0;

Expand Down Expand Up @@ -2019,11 +2018,12 @@ public static function KURT(...$args)
public static function LARGE(...$args)
{
$aArgs = Functions::flattenArray($args);

// Calculate
$entry = floor(array_pop($aArgs));
$entry = array_pop($aArgs);

if ((is_numeric($entry)) && (!is_string($entry))) {
$entry = (int) floor($entry);

// Calculate
$mArgs = [];
foreach ($aArgs as $arg) {
// Is it a numeric value?
Expand All @@ -2032,7 +2032,7 @@ public static function LARGE(...$args)
}
}
$count = self::COUNT($mArgs);
$entry = floor(--$entry);
--$entry;
if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
return Functions::NAN();
}
Expand Down Expand Up @@ -2873,7 +2873,7 @@ public static function PERCENTILE(...$args)
* @param int $value the number whose rank you want to find
* @param int $significance the number of significant digits for the returned percentage value
*
* @return float
* @return float|string (string if result is an error)
*/
public static function PERCENTRANK($valueSet, $value, $significance = 3)
{
Expand Down Expand Up @@ -3169,6 +3169,8 @@ public static function SMALL(...$args)
$entry = array_pop($aArgs);

if ((is_numeric($entry)) && (!is_string($entry))) {
$entry = (int) floor($entry);

$mArgs = [];
foreach ($aArgs as $arg) {
// Is it a numeric value?
Expand All @@ -3177,7 +3179,7 @@ public static function SMALL(...$args)
}
}
$count = self::COUNT($mArgs);
$entry = floor(--$entry);
--$entry;
if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
return Functions::NAN();
}
Expand Down Expand Up @@ -3481,7 +3483,6 @@ public static function TDIST($value, $degrees, $tails)
$ttheta = atan2($value, sqrt($tterm));
$tc = cos($ttheta);
$ts = sin($ttheta);
$tsum = 0;

if (($degrees % 2) == 1) {
$ti = 3;
Expand Down Expand Up @@ -3657,7 +3658,7 @@ public static function TRIMMEAN(...$args)
*
* @param mixed ...$args Data values
*
* @return float
* @return float|string (string if result is an error)
*/
public static function VARFunc(...$args)
{
Expand Down Expand Up @@ -3699,7 +3700,7 @@ public static function VARFunc(...$args)
*
* @param mixed ...$args Data values
*
* @return float
* @return float|string (string if result is an error)
*/
public static function VARA(...$args)
{
Expand Down Expand Up @@ -3754,7 +3755,7 @@ public static function VARA(...$args)
*
* @param mixed ...$args Data values
*
* @return float
* @return float|string (string if result is an error)
*/
public static function VARP(...$args)
{
Expand Down Expand Up @@ -3797,7 +3798,7 @@ public static function VARP(...$args)
*
* @param mixed ...$args Data values
*
* @return float
* @return float|string (string if result is an error)
*/
public static function VARPA(...$args)
{
Expand Down Expand Up @@ -3853,7 +3854,7 @@ public static function VARPA(...$args)
* @param float $beta Beta Parameter
* @param bool $cumulative
*
* @return float
* @return float|string (string if result is an error)
*/
public static function WEIBULL($value, $alpha, $beta, $cumulative)
{
Expand Down Expand Up @@ -3887,7 +3888,7 @@ public static function WEIBULL($value, $alpha, $beta, $cumulative)
* @param float $m0 Alpha Parameter
* @param float $sigma Beta Parameter
*
* @return float|string
* @return float|string (string if result is an error)
*/
public static function ZTEST($dataSet, $m0, $sigma = null)
{
Expand Down
5 changes: 3 additions & 2 deletions src/PhpSpreadsheet/Calculation/TextData.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PhpOffice\PhpSpreadsheet\Calculation;

use DateTimeInterface;
use PhpOffice\PhpSpreadsheet\Shared\Date;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
Expand Down Expand Up @@ -98,7 +99,7 @@ private static function convertBooleanValue($value)
*
* @param string $characters Value
*
* @return int
* @return int|string A string if arguments are invalid
*/
public static function ASCIICODE($characters)
{
Expand Down Expand Up @@ -543,7 +544,7 @@ public static function TEXTFORMAT($value, $format)
*
* @param mixed $value Value to check
*
* @return bool
* @return DateTimeInterface|float|int|string A string if arguments are invalid
*/
public static function VALUE($value = '')
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;

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

class LargeTest extends TestCase
{
/**
* @dataProvider providerLARGE
*
* @param mixed $expectedResult
* @param mixed $values
* @param mixed $position
*/
public function testLARGE($expectedResult, $values, $position): void
{
$result = Statistical::LARGE($values, $position);
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
}

public function providerLARGE()
{
return require 'tests/data/Calculation/Statistical/LARGE.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;

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

class LinEstTest extends TestCase
{
/**
* @dataProvider providerLINEST
*
* @param mixed $expectedResult
* @param mixed $xValues
* @param mixed $yValues
* @param mixed $const
* @param mixed $stats
*/
public function testLINEST($expectedResult, $yValues, $xValues, $const, $stats): void
{
$result = Statistical::LINEST($yValues, $xValues, $const, $stats);

$elements = count($expectedResult);
for ($element = 0; $element < $elements; ++$element) {
self::assertEqualsWithDelta($expectedResult[$element], $result[$element], 1E-12);
}
}

public function providerLINEST()
{
return require 'tests/data/Calculation/Statistical/LINEST.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;

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

class LogEstTest extends TestCase
{
/**
* @dataProvider providerLOGEST
*
* @param mixed $expectedResult
* @param mixed $xValues
* @param mixed $yValues
* @param mixed $const
* @param mixed $stats
*/
public function testLOGEST($expectedResult, $yValues, $xValues, $const, $stats): void
{
$result = Statistical::LOGEST($yValues, $xValues, $const, $stats);

$elements = count($expectedResult);
for ($element = 0; $element < $elements; ++$element) {
self::assertEqualsWithDelta($expectedResult[$element], $result[$element], 1E-12);
}
}

public function providerLOGEST()
{
return require 'tests/data/Calculation/Statistical/LOGEST.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;

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

class LogInvTest extends TestCase
{
/**
* @dataProvider providerLOGINV
*
* @param mixed $expectedResult
*/
public function testLOGINV($expectedResult, ...$args): void
{
$result = Statistical::LOGINV(...$args);
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
}

public function providerLOGINV(): array
{
return require 'tests/data/Calculation/Statistical/LOGINV.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;

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

class MaxATest extends TestCase
{
/**
* @dataProvider providerMAXA
*
* @param mixed $expectedResult
*/
public function testMAXA($expectedResult, ...$args): void
{
$result = Statistical::MAXA(...$args);
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
}

public function providerMAXA(): array
{
return require 'tests/data/Calculation/Statistical/MAXA.php';
}
}
Loading

0 comments on commit 9683e5b

Please sign in to comment.