Next wave of grouping for the refactored MathTrig functions into small group classes, and renaming of methods

This commit is contained in:
MarkBaker 2021-05-12 21:56:20 +02:00 committed by Mark Baker
parent 22468a7965
commit 5715bf4644
16 changed files with 281 additions and 284 deletions

38
samples/bulkReadTest.php Normal file
View File

@ -0,0 +1,38 @@
<?php
// The following code can be used to submit an issue with the PHPSpreadsheet calculation engine
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\IOFactory;
error_reporting(E_ALL);
set_time_limit(0);
date_default_timezone_set('UTC');
// Adjust the path as required to reference the PHPSpreadsheet Bootstrap file
require_once __DIR__ . '/../vendor/autoload.php';
foreach (glob(__DIR__ . '/*') as $fileName) {
if (!in_array(pathinfo($fileName, PATHINFO_EXTENSION), ['xls', 'xlsx', 'gnumeric', 'ods'])) {
continue;
}
$callStartTime = microtime(true);
echo 'Current memory usage: ' , (memory_get_usage(true) / 1024) , ' KB' , PHP_EOL;
$spreadsheet = IOFactory::load($fileName);
echo 'Loaded spreadsheet file ', pathinfo($fileName, PATHINFO_FILENAME), PHP_EOL;
$callEndTime = microtime(true);
$loadCallTime = $callEndTime - $callStartTime;
echo 'Call time to load spreadsheet file was ' , sprintf('%.4f', $loadCallTime) , ' seconds' , PHP_EOL;
echo 'Current memory usage: ' , (memory_get_usage(true) / 1024) , ' KB' , PHP_EOL;
$spreadsheet->disconnectWorksheets();
$spreadsheet->garbageCollect();
unset($spreadsheet);
echo 'Unset Spreadsheet', PHP_EOL;
gc_collect_cycles();
echo 'Memory usage after unset: ' , (memory_get_usage(true) / 1024) , ' KB' , PHP_EOL;
}
// Echo memory usage
echo ' Current memory usage: ' , (memory_get_usage(true) / 1024) , ' KB' , PHP_EOL;
echo ' Peak memory usage: ' , (memory_get_peak_usage(true) / 1024) , ' KB' , PHP_EOL;

View File

@ -993,12 +993,12 @@ class Calculation
],
'FACT' => [
'category' => Category::CATEGORY_MATH_AND_TRIG,
'functionCall' => [MathTrig\Fact::class, 'evaluate'],
'functionCall' => [MathTrig\Factorial::class, 'fact'],
'argumentCount' => '1',
],
'FACTDOUBLE' => [
'category' => Category::CATEGORY_MATH_AND_TRIG,
'functionCall' => [MathTrig\FactDouble::class, 'evaluate'],
'functionCall' => [MathTrig\Factorial::class, 'factDouble'],
'argumentCount' => '1',
],
'FALSE' => [
@ -1729,12 +1729,12 @@ class Calculation
],
'MROUND' => [
'category' => Category::CATEGORY_MATH_AND_TRIG,
'functionCall' => [MathTrig\Mround::class, 'evaluate'],
'functionCall' => [MathTrig\Round::class, 'multiple'],
'argumentCount' => '2',
],
'MULTINOMIAL' => [
'category' => Category::CATEGORY_MATH_AND_TRIG,
'functionCall' => [MathTrig\Multinomial::class, 'evaluate'],
'functionCall' => [MathTrig\Factorial::class, 'multinomial'],
'argumentCount' => '1+',
],
'MUNIT' => [
@ -2046,7 +2046,7 @@ class Calculation
],
'RAND' => [
'category' => Category::CATEGORY_MATH_AND_TRIG,
'functionCall' => [MathTrig\Random::class, 'randNoArgs'],
'functionCall' => [MathTrig\Random::class, 'rand'],
'argumentCount' => '0',
],
'RANDARRAY' => [
@ -2116,17 +2116,17 @@ class Calculation
],
'ROUND' => [
'category' => Category::CATEGORY_MATH_AND_TRIG,
'functionCall' => [MathTrig\Round::class, 'evaluate'],
'functionCall' => [MathTrig\Round::class, 'round'],
'argumentCount' => '2',
],
'ROUNDDOWN' => [
'category' => Category::CATEGORY_MATH_AND_TRIG,
'functionCall' => [MathTrig\RoundDown::class, 'evaluate'],
'functionCall' => [MathTrig\Round::class, 'down'],
'argumentCount' => '2',
],
'ROUNDUP' => [
'category' => Category::CATEGORY_MATH_AND_TRIG,
'functionCall' => [MathTrig\RoundUp::class, 'evaluate'],
'functionCall' => [MathTrig\Round::class, 'up'],
'argumentCount' => '2',
],
'ROW' => [

View File

@ -184,16 +184,16 @@ class MathTrig
*
* @Deprecated 1.18.0
*
* @see MathTrig\Fact::evaluate()
* Use the evaluate() method in the MathTrig\Fact class instead
*
* @param float $factVal Factorial Value
*
* @return float|int|string Factorial, or a string containing an error
*
*@see MathTrig\Factorial::fact()
* Use the fact() method in the MathTrig\Factorial class instead
*/
public static function FACT($factVal)
{
return MathTrig\Fact::evaluate($factVal);
return MathTrig\Factorial::fact($factVal);
}
/**
@ -206,16 +206,16 @@ class MathTrig
*
* @Deprecated 1.18.0
*
* @see MathTrig\FactDouble::evaluate()
* Use the evaluate() method in the MathTrig\FactDouble class instead
*
* @param float $factVal Factorial Value
*
* @return float|int|string Double Factorial, or a string containing an error
*
*@see MathTrig\Factorial::factDouble()
* Use the factDouble() method in the MathTrig\Factorial class instead
*/
public static function FACTDOUBLE($factVal)
{
return MathTrig\FactDouble::evaluate($factVal);
return MathTrig\Factorial::factDouble($factVal);
}
/**
@ -469,17 +469,17 @@ class MathTrig
*
* @Deprecated 1.17.0
*
* @see MathTrig\Mround::evaluate()
* Use the evaluate() method in the MathTrig\Mround class instead
*
* @param float $number Number to round
* @param int $multiple Multiple to which you want to round $number
*
* @return float|string Rounded Number, or a string containing an error
*
*@see MathTrig\Round::multiple()
* Use the multiple() method in the MathTrig\Mround class instead
*/
public static function MROUND($number, $multiple)
{
return MathTrig\Mround::evaluate($number, $multiple);
return MathTrig\Round::multiple($number, $multiple);
}
/**
@ -489,8 +489,8 @@ class MathTrig
*
* @Deprecated 1.18.0
*
* @See MathTrig\Multinomial::evaluate()
* Use the evaluate method in the MathTrig\Multinomial class instead
* @See MathTrig\Factorial::multinomial()
* Use the multinomial method in the MathTrig\Factorial class instead
*
* @param mixed[] $args An array of mixed values for the Data Series
*
@ -498,7 +498,7 @@ class MathTrig
*/
public static function MULTINOMIAL(...$args)
{
return MathTrig\Multinomial::evaluate(...$args);
return MathTrig\Factorial::multinomial(...$args);
}
/**
@ -631,8 +631,8 @@ class MathTrig
*
* @Deprecated 1.17.0
*
* @See MathTrig\RoundUp::evaluate()
* Use the evaluate() method in the MathTrig\RoundUp class instead
* @See MathTrig\Round::up()
* Use the up() method in the MathTrig\Round class instead
*
* @param float $number Number to round
* @param int $digits Number of digits to which you want to round $number
@ -641,7 +641,7 @@ class MathTrig
*/
public static function ROUNDUP($number, $digits)
{
return MathTrig\RoundUp::evaluate($number, $digits);
return MathTrig\Round::up($number, $digits);
}
/**
@ -651,8 +651,8 @@ class MathTrig
*
* @Deprecated 1.17.0
*
* @See MathTrig\RoundDown::evaluate()
* Use the evaluate() method in the MathTrig\RoundDown class instead
* @See MathTrig\Round::down()
* Use the down() method in the MathTrig\Round class instead
*
* @param float $number Number to round
* @param int $digits Number of digits to which you want to round $number
@ -661,7 +661,7 @@ class MathTrig
*/
public static function ROUNDDOWN($number, $digits)
{
return MathTrig\RoundDown::evaluate($number, $digits);
return MathTrig\Round::down($number, $digits);
}
/**
@ -1124,8 +1124,8 @@ class MathTrig
*
* @Deprecated 1.17.0
*
* @See MathTrig\Round::evaluate()
* Use the evaluate() method in the MathTrig\Round class instead
* @See MathTrig\Round::round()
* Use the round() method in the MathTrig\Round class instead
*
* @param mixed $number Should be numeric
* @param mixed $precision Should be int
@ -1134,7 +1134,7 @@ class MathTrig
*/
public static function builtinROUND($number, $precision)
{
return MathTrig\Round::evaluate($number, $precision);
return MathTrig\Round::round($number, $precision);
}
/**

View File

@ -31,7 +31,7 @@ class Combinations
return $e->getMessage();
}
return round(Fact::evaluate($numObjs) / Fact::evaluate($numObjs - $numInSet)) / Fact::evaluate($numInSet);
return round(Factorial::fact($numObjs) / Factorial::fact($numObjs - $numInSet)) / Factorial::fact($numInSet);
}
/**
@ -69,6 +69,6 @@ class Combinations
return $e->getMessage();
}
return round(Fact::evaluate($numObjs + $numInSet - 1) / Fact::evaluate($numObjs - 1)) / Fact::evaluate($numInSet);
return round(Factorial::fact($numObjs + $numInSet - 1) / Factorial::fact($numObjs - 1)) / Factorial::fact($numInSet);
}
}

View File

@ -1,47 +0,0 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
use Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
class Fact
{
/**
* FACT.
*
* Returns the factorial of a number.
* The factorial of a number is equal to 1*2*3*...* number.
*
* Excel Function:
* FACT(factVal)
*
* @param float $factVal Factorial Value
*
* @return float|int|string Factorial, or a string containing an error
*/
public static function evaluate($factVal)
{
try {
$factVal = Helpers::validateNumericNullBool($factVal);
Helpers::validateNotNegative($factVal);
} catch (Exception $e) {
return $e->getMessage();
}
$factLoop = floor($factVal);
if ($factVal > $factLoop) {
if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
return Statistical\Distributions\Gamma::gammaValue($factVal + 1);
}
}
$factorial = 1;
while ($factLoop > 1) {
$factorial *= $factLoop--;
}
return $factorial;
}
}

View File

@ -1,39 +0,0 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
use Exception;
class FactDouble
{
/**
* FACTDOUBLE.
*
* Returns the double factorial of a number.
*
* Excel Function:
* FACTDOUBLE(factVal)
*
* @param float $factVal Factorial Value
*
* @return float|int|string Double Factorial, or a string containing an error
*/
public static function evaluate($factVal)
{
try {
$factVal = Helpers::validateNumericNullSubstitution($factVal, 0);
Helpers::validateNotNegative($factVal);
} catch (Exception $e) {
return $e->getMessage();
}
$factLoop = floor($factVal);
$factorial = 1;
while ($factLoop > 1) {
$factorial *= $factLoop;
$factLoop -= 2;
}
return $factorial;
}
}

View File

@ -0,0 +1,110 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
class Factorial
{
/**
* FACT.
*
* Returns the factorial of a number.
* The factorial of a number is equal to 1*2*3*...* number.
*
* Excel Function:
* FACT(factVal)
*
* @param float $factVal Factorial Value
*
* @return float|int|string Factorial, or a string containing an error
*/
public static function fact($factVal)
{
try {
$factVal = Helpers::validateNumericNullBool($factVal);
Helpers::validateNotNegative($factVal);
} catch (Exception $e) {
return $e->getMessage();
}
$factLoop = floor($factVal);
if ($factVal > $factLoop) {
if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
return Statistical\Distributions\Gamma::gammaValue($factVal + 1);
}
}
$factorial = 1;
while ($factLoop > 1) {
$factorial *= $factLoop--;
}
return $factorial;
}
/**
* FACTDOUBLE.
*
* Returns the double factorial of a number.
*
* Excel Function:
* FACTDOUBLE(factVal)
*
* @param float $factVal Factorial Value
*
* @return float|int|string Double Factorial, or a string containing an error
*/
public static function factDouble($factVal)
{
try {
$factVal = Helpers::validateNumericNullSubstitution($factVal, 0);
Helpers::validateNotNegative($factVal);
} catch (Exception $e) {
return $e->getMessage();
}
$factLoop = floor($factVal);
$factorial = 1;
while ($factLoop > 1) {
$factorial *= $factLoop;
$factLoop -= 2;
}
return $factorial;
}
/**
* MULTINOMIAL.
*
* Returns the ratio of the factorial of a sum of values to the product of factorials.
*
* @param mixed[] $args An array of mixed values for the Data Series
*
* @return float|string The result, or a string containing an error
*/
public static function multinomial(...$args)
{
$summer = 0;
$divisor = 1;
try {
// Loop through arguments
foreach (Functions::flattenArray($args) as $argx) {
$arg = Helpers::validateNumericNullSubstitution($argx, null);
Helpers::validateNotNegative($arg);
$arg = (int) $arg;
$summer += $arg;
$divisor *= self::fact($arg);
}
} catch (Exception $e) {
return $e->getMessage();
}
$summer = self::fact($summer);
return $summer / $divisor;
}
}

View File

@ -1,40 +0,0 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
use Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
class Mround
{
/**
* MROUND.
*
* Rounds a number to the nearest multiple of a specified value
*
* @param mixed $number Expect float. Number to round.
* @param mixed $multiple Expect int. Multiple to which you want to round.
*
* @return float|string Rounded Number, or a string containing an error
*/
public static function evaluate($number, $multiple)
{
try {
$number = Helpers::validateNumericNullSubstitution($number, 0);
$multiple = Helpers::validateNumericNullSubstitution($multiple, null);
} catch (Exception $e) {
return $e->getMessage();
}
if ($number == 0 || $multiple == 0) {
return 0;
}
if ((Helpers::returnSign($number)) == (Helpers::returnSign($multiple))) {
$multiplier = 1 / $multiple;
return round($number * $multiplier) / $multiplier;
}
return Functions::NAN();
}
}

View File

@ -1,41 +0,0 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
use Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
class Multinomial
{
/**
* MULTINOMIAL.
*
* Returns the ratio of the factorial of a sum of values to the product of factorials.
*
* @param mixed[] $args An array of mixed values for the Data Series
*
* @return float|string The result, or a string containing an error
*/
public static function evaluate(...$args)
{
$summer = 0;
$divisor = 1;
try {
// Loop through arguments
foreach (Functions::flattenArray($args) as $argx) {
$arg = Helpers::validateNumericNullSubstitution($argx, null);
Helpers::validateNotNegative($arg);
$arg = (int) $arg;
$summer += $arg;
$divisor *= Fact::evaluate($arg);
}
} catch (Exception $e) {
return $e->getMessage();
}
$summer = Fact::evaluate($summer);
return $summer / $divisor;
}
}

View File

@ -11,7 +11,7 @@ class Random
*
* @return float Random number
*/
public static function randNoArgs()
public static function rand()
{
return (mt_rand(0, 10000000)) / 10000000;
}

View File

@ -2,7 +2,8 @@
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
use Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
class Round
{
@ -16,7 +17,7 @@ class Round
*
* @return float|string Rounded number
*/
public static function evaluate($number, $precision)
public static function round($number, $precision)
{
try {
$number = Helpers::validateNumericNullBool($number);
@ -27,4 +28,95 @@ class Round
return round($number, (int) $precision);
}
/**
* ROUNDUP.
*
* Rounds a number up to a specified number of decimal places
*
* @param float $number Number to round
* @param int $digits Number of digits to which you want to round $number
*
* @return float|string Rounded Number, or a string containing an error
*/
public static function up($number, $digits)
{
try {
$number = Helpers::validateNumericNullBool($number);
$digits = (int) Helpers::validateNumericNullSubstitution($digits, null);
} catch (Exception $e) {
return $e->getMessage();
}
if ($number == 0.0) {
return 0.0;
}
if ($number < 0.0) {
return round($number - 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_DOWN);
}
return round($number + 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_DOWN);
}
/**
* ROUNDDOWN.
*
* Rounds a number down to a specified number of decimal places
*
* @param float $number Number to round
* @param int $digits Number of digits to which you want to round $number
*
* @return float|string Rounded Number, or a string containing an error
*/
public static function down($number, $digits)
{
try {
$number = Helpers::validateNumericNullBool($number);
$digits = (int) Helpers::validateNumericNullSubstitution($digits, null);
} catch (Exception $e) {
return $e->getMessage();
}
if ($number == 0.0) {
return 0.0;
}
if ($number < 0.0) {
return round($number + 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_UP);
}
return round($number - 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_UP);
}
/**
* MROUND.
*
* Rounds a number to the nearest multiple of a specified value
*
* @param mixed $number Expect float. Number to round.
* @param mixed $multiple Expect int. Multiple to which you want to round.
*
* @return float|string Rounded Number, or a string containing an error
*/
public static function multiple($number, $multiple)
{
try {
$number = Helpers::validateNumericNullSubstitution($number, 0);
$multiple = Helpers::validateNumericNullSubstitution($multiple, null);
} catch (Exception $e) {
return $e->getMessage();
}
if ($number == 0 || $multiple == 0) {
return 0;
}
if ((Helpers::returnSign($number)) == (Helpers::returnSign($multiple))) {
$multiplier = 1 / $multiple;
return round($number * $multiplier) / $multiplier;
}
return Functions::NAN();
}
}

View File

@ -1,38 +0,0 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
use Exception;
class RoundDown
{
/**
* ROUNDDOWN.
*
* Rounds a number down to a specified number of decimal places
*
* @param float $number Number to round
* @param int $digits Number of digits to which you want to round $number
*
* @return float|string Rounded Number, or a string containing an error
*/
public static function evaluate($number, $digits)
{
try {
$number = Helpers::validateNumericNullBool($number);
$digits = (int) Helpers::validateNumericNullSubstitution($digits, null);
} catch (Exception $e) {
return $e->getMessage();
}
if ($number == 0.0) {
return 0.0;
}
if ($number < 0.0) {
return round($number + 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_UP);
}
return round($number - 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_UP);
}
}

View File

@ -1,38 +0,0 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
use Exception;
class RoundUp
{
/**
* ROUNDUP.
*
* Rounds a number up to a specified number of decimal places
*
* @param float $number Number to round
* @param int $digits Number of digits to which you want to round $number
*
* @return float|string Rounded Number, or a string containing an error
*/
public static function evaluate($number, $digits)
{
try {
$number = Helpers::validateNumericNullBool($number);
$digits = (int) Helpers::validateNumericNullSubstitution($digits, null);
} catch (Exception $e) {
return $e->getMessage();
}
if ($number == 0.0) {
return 0.0;
}
if ($number < 0.0) {
return round($number - 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_DOWN);
}
return round($number + 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_DOWN);
}
}

View File

@ -42,12 +42,12 @@ class Poisson
$summer = 0;
$floor = floor($value);
for ($i = 0; $i <= $floor; ++$i) {
$summer += $mean ** $i / MathTrig\Fact::evaluate($i);
$summer += $mean ** $i / MathTrig\Factorial::fact($i);
}
return exp(0 - $mean) * $summer;
}
return (exp(0 - $mean) * $mean ** $value) / MathTrig\Fact::evaluate($value);
return (exp(0 - $mean) * $mean ** $value) / MathTrig\Factorial::fact($value);
}
}

View File

@ -38,7 +38,7 @@ class Permutations
return Functions::NAN();
}
return (int) round(MathTrig\Fact::evaluate($numObjs) / MathTrig\Fact::evaluate($numObjs - $numInSet));
return (int) round(MathTrig\Factorial::fact($numObjs) / MathTrig\Factorial::fact($numObjs - $numInSet));
}
/**

View File

@ -42,7 +42,7 @@ class Format
if ($value < 0) {
$round = 0 - $round;
}
$value = MathTrig\Mround::evaluate($value, $round);
$value = MathTrig\Round::multiple($value, $round);
}
$mask = "$mask;($mask)";