Continue MathTrig Breakup - Penultimate? (#1973)
* Continue MathTrig Breakup - Penultimate? Continuing the process of breaking MathTrip.php up into smaller classes. This round takes care of about half of what is left, so perhaps one round after this one will finish the job: - ARABIC - COMBIN; also implemented COMBINA - FACTDOUBLE - GCD (which accepts and ignores empty cells as arguments, but returns VALUE if all the arguments are that way; LCM does the same) - LOG_BASE, LOG10, LN - implemented MUNIT - MOD - POWER - RAND, RANDBETWEEN (RANDARRAY is too complicated to implement with this ticket) As you can see from the description, there are some functions which were combined in a single class. When not combined, I adopted PowerKiki's suggestion of using "execute" as the function name. Co-authored-by: Mark Baker <mark@lange.demon.co.uk>
This commit is contained in:
parent
0c403efe60
commit
a4982fd9fe
|
|
@ -288,7 +288,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'ARABIC' => [
|
'ARABIC' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'ARABIC'],
|
'functionCall' => [MathTrig\Arabic::class, 'evaluate'],
|
||||||
'argumentCount' => '1',
|
'argumentCount' => '1',
|
||||||
],
|
],
|
||||||
'AREAS' => [
|
'AREAS' => [
|
||||||
|
|
@ -555,12 +555,12 @@ class Calculation
|
||||||
],
|
],
|
||||||
'COMBIN' => [
|
'COMBIN' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'COMBIN'],
|
'functionCall' => [MathTrig\Combinations::class, 'withoutRepetition'],
|
||||||
'argumentCount' => '2',
|
'argumentCount' => '2',
|
||||||
],
|
],
|
||||||
'COMBINA' => [
|
'COMBINA' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [Functions::class, 'DUMMY'],
|
'functionCall' => [MathTrig\Combinations::class, 'withRepetition'],
|
||||||
'argumentCount' => '2',
|
'argumentCount' => '2',
|
||||||
],
|
],
|
||||||
'COMPLEX' => [
|
'COMPLEX' => [
|
||||||
|
|
@ -995,7 +995,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'FACTDOUBLE' => [
|
'FACTDOUBLE' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'FACTDOUBLE'],
|
'functionCall' => [MathTrig\FactDouble::class, 'evaluate'],
|
||||||
'argumentCount' => '1',
|
'argumentCount' => '1',
|
||||||
],
|
],
|
||||||
'FALSE' => [
|
'FALSE' => [
|
||||||
|
|
@ -1187,7 +1187,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'GCD' => [
|
'GCD' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'GCD'],
|
'functionCall' => [MathTrig\Gcd::class, 'evaluate'],
|
||||||
'argumentCount' => '1+',
|
'argumentCount' => '1+',
|
||||||
],
|
],
|
||||||
'GEOMEAN' => [
|
'GEOMEAN' => [
|
||||||
|
|
@ -1566,17 +1566,17 @@ class Calculation
|
||||||
],
|
],
|
||||||
'LN' => [
|
'LN' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'builtinLN'],
|
'functionCall' => [MathTrig\Logarithms::class, 'natural'],
|
||||||
'argumentCount' => '1',
|
'argumentCount' => '1',
|
||||||
],
|
],
|
||||||
'LOG' => [
|
'LOG' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'logBase'],
|
'functionCall' => [MathTrig\Logarithms::class, 'withBase'],
|
||||||
'argumentCount' => '1,2',
|
'argumentCount' => '1,2',
|
||||||
],
|
],
|
||||||
'LOG10' => [
|
'LOG10' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'builtinLOG10'],
|
'functionCall' => [MathTrig\Logarithms::class, 'base10'],
|
||||||
'argumentCount' => '1',
|
'argumentCount' => '1',
|
||||||
],
|
],
|
||||||
'LOGEST' => [
|
'LOGEST' => [
|
||||||
|
|
@ -1701,7 +1701,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'MOD' => [
|
'MOD' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'MOD'],
|
'functionCall' => [MathTrig\Mod::class, 'evaluate'],
|
||||||
'argumentCount' => '2',
|
'argumentCount' => '2',
|
||||||
],
|
],
|
||||||
'MODE' => [
|
'MODE' => [
|
||||||
|
|
@ -1736,7 +1736,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'MUNIT' => [
|
'MUNIT' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [Functions::class, 'DUMMY'],
|
'functionCall' => [MathTrig\MatrixFunctions::class, 'funcMUnit'],
|
||||||
'argumentCount' => '1',
|
'argumentCount' => '1',
|
||||||
],
|
],
|
||||||
'N' => [
|
'N' => [
|
||||||
|
|
@ -1973,7 +1973,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'POWER' => [
|
'POWER' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'POWER'],
|
'functionCall' => [MathTrig\Power::class, 'evaluate'],
|
||||||
'argumentCount' => '2',
|
'argumentCount' => '2',
|
||||||
],
|
],
|
||||||
'PPMT' => [
|
'PPMT' => [
|
||||||
|
|
@ -2043,7 +2043,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'RAND' => [
|
'RAND' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'RAND'],
|
'functionCall' => [MathTrig\Random::class, 'randNoArgs'],
|
||||||
'argumentCount' => '0',
|
'argumentCount' => '0',
|
||||||
],
|
],
|
||||||
'RANDARRAY' => [
|
'RANDARRAY' => [
|
||||||
|
|
@ -2053,7 +2053,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'RANDBETWEEN' => [
|
'RANDBETWEEN' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'RAND'],
|
'functionCall' => [MathTrig\Random::class, 'randBetween'],
|
||||||
'argumentCount' => '2',
|
'argumentCount' => '2',
|
||||||
],
|
],
|
||||||
'RANK' => [
|
'RANK' => [
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,15 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheet\Calculation;
|
namespace PhpOffice\PhpSpreadsheet\Calculation;
|
||||||
|
|
||||||
use Exception;
|
|
||||||
|
|
||||||
class MathTrig
|
class MathTrig
|
||||||
{
|
{
|
||||||
private static function strSplit(string $roman): array
|
|
||||||
{
|
|
||||||
$rslt = str_split($roman);
|
|
||||||
|
|
||||||
return is_array($rslt) ? $rslt : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ARABIC.
|
* ARABIC.
|
||||||
*
|
*
|
||||||
* Converts a Roman numeral to an Arabic numeral.
|
* Converts a Roman numeral to an Arabic numeral.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the evaluate method in the MathTrig\Arabic class instead
|
||||||
|
*
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* ARABIC(text)
|
* ARABIC(text)
|
||||||
*
|
*
|
||||||
|
|
@ -27,69 +20,7 @@ class MathTrig
|
||||||
*/
|
*/
|
||||||
public static function ARABIC($roman)
|
public static function ARABIC($roman)
|
||||||
{
|
{
|
||||||
// An empty string should return 0
|
return MathTrig\Arabic::evaluate($roman);
|
||||||
$roman = substr(trim(strtoupper((string) Functions::flattenSingleValue($roman))), 0, 255);
|
|
||||||
if ($roman === '') {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the roman numeral to an arabic number
|
|
||||||
$negativeNumber = $roman[0] === '-';
|
|
||||||
if ($negativeNumber) {
|
|
||||||
$roman = substr($roman, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$arabic = self::calculateArabic(self::strSplit($roman));
|
|
||||||
} catch (Exception $e) {
|
|
||||||
return Functions::VALUE(); // Invalid character detected
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($negativeNumber) {
|
|
||||||
$arabic *= -1; // The number should be negative
|
|
||||||
}
|
|
||||||
|
|
||||||
return $arabic;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursively calculate the arabic value of a roman numeral.
|
|
||||||
*
|
|
||||||
* @param int $sum
|
|
||||||
* @param int $subtract
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
protected static function calculateArabic(array $roman, &$sum = 0, $subtract = 0)
|
|
||||||
{
|
|
||||||
$lookup = [
|
|
||||||
'M' => 1000,
|
|
||||||
'D' => 500,
|
|
||||||
'C' => 100,
|
|
||||||
'L' => 50,
|
|
||||||
'X' => 10,
|
|
||||||
'V' => 5,
|
|
||||||
'I' => 1,
|
|
||||||
];
|
|
||||||
|
|
||||||
$numeral = array_shift($roman);
|
|
||||||
if (!isset($lookup[$numeral])) {
|
|
||||||
throw new Exception('Invalid character detected');
|
|
||||||
}
|
|
||||||
|
|
||||||
$arabic = $lookup[$numeral];
|
|
||||||
if (count($roman) > 0 && isset($lookup[$roman[0]]) && $arabic < $lookup[$roman[0]]) {
|
|
||||||
$subtract += $arabic;
|
|
||||||
} else {
|
|
||||||
$sum += ($arabic - $subtract);
|
|
||||||
$subtract = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($roman) > 0) {
|
|
||||||
self::calculateArabic($roman, $sum, $subtract);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $sum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -172,6 +103,8 @@ class MathTrig
|
||||||
* Returns the number of combinations for a given number of items. Use COMBIN to
|
* Returns the number of combinations for a given number of items. Use COMBIN to
|
||||||
* determine the total possible number of groups for a given number of items.
|
* determine the total possible number of groups for a given number of items.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the without method in the MathTrig\Combinations class instead
|
||||||
|
*
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* COMBIN(numObjs,numInSet)
|
* COMBIN(numObjs,numInSet)
|
||||||
*
|
*
|
||||||
|
|
@ -182,20 +115,7 @@ class MathTrig
|
||||||
*/
|
*/
|
||||||
public static function COMBIN($numObjs, $numInSet)
|
public static function COMBIN($numObjs, $numInSet)
|
||||||
{
|
{
|
||||||
$numObjs = Functions::flattenSingleValue($numObjs);
|
return MathTrig\Combinations::withoutRepetition($numObjs, $numInSet);
|
||||||
$numInSet = Functions::flattenSingleValue($numInSet);
|
|
||||||
|
|
||||||
if ((is_numeric($numObjs)) && (is_numeric($numInSet))) {
|
|
||||||
if ($numObjs < $numInSet) {
|
|
||||||
return Functions::NAN();
|
|
||||||
} elseif ($numInSet < 0) {
|
|
||||||
return Functions::NAN();
|
|
||||||
}
|
|
||||||
|
|
||||||
return round(MathTrig\Fact::funcFact($numObjs) / MathTrig\Fact::funcFact($numObjs - $numInSet)) / MathTrig\Fact::funcFact($numInSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -256,6 +176,8 @@ class MathTrig
|
||||||
*
|
*
|
||||||
* Returns the double factorial of a number.
|
* Returns the double factorial of a number.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the evaluate method in the MathTrig\FactDouble class instead
|
||||||
|
*
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* FACTDOUBLE(factVal)
|
* FACTDOUBLE(factVal)
|
||||||
*
|
*
|
||||||
|
|
@ -265,23 +187,7 @@ class MathTrig
|
||||||
*/
|
*/
|
||||||
public static function FACTDOUBLE($factVal)
|
public static function FACTDOUBLE($factVal)
|
||||||
{
|
{
|
||||||
$factLoop = Functions::flattenSingleValue($factVal);
|
return MathTrig\FactDouble::evaluate($factVal);
|
||||||
|
|
||||||
if (is_numeric($factLoop)) {
|
|
||||||
$factLoop = floor($factLoop);
|
|
||||||
if ($factVal < 0) {
|
|
||||||
return Functions::NAN();
|
|
||||||
}
|
|
||||||
$factorial = 1;
|
|
||||||
while ($factLoop > 1) {
|
|
||||||
$factorial *= $factLoop--;
|
|
||||||
--$factLoop;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $factorial;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -351,11 +257,6 @@ class MathTrig
|
||||||
return MathTrig\FloorPrecise::funcFloorPrecise($number, $significance);
|
return MathTrig\FloorPrecise::funcFloorPrecise($number, $significance);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function evaluateGCD($a, $b)
|
|
||||||
{
|
|
||||||
return $b ? self::evaluateGCD($b, $a % $b) : $a;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* INT.
|
* INT.
|
||||||
*
|
*
|
||||||
|
|
@ -384,6 +285,8 @@ class MathTrig
|
||||||
* The greatest common divisor is the largest integer that divides both
|
* The greatest common divisor is the largest integer that divides both
|
||||||
* number1 and number2 without a remainder.
|
* number1 and number2 without a remainder.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the evaluate method in the MathTrig\Gcd class instead
|
||||||
|
*
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* GCD(number1[,number2[, ...]])
|
* GCD(number1[,number2[, ...]])
|
||||||
*
|
*
|
||||||
|
|
@ -393,22 +296,7 @@ class MathTrig
|
||||||
*/
|
*/
|
||||||
public static function GCD(...$args)
|
public static function GCD(...$args)
|
||||||
{
|
{
|
||||||
$args = Functions::flattenArray($args);
|
return MathTrig\Gcd::evaluate(...$args);
|
||||||
// Loop through arguments
|
|
||||||
foreach (Functions::flattenArray($args) as $value) {
|
|
||||||
if (!is_numeric($value)) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
} elseif ($value < 0) {
|
|
||||||
return Functions::NAN();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$gcd = (int) array_pop($args);
|
|
||||||
do {
|
|
||||||
$gcd = self::evaluateGCD($gcd, (int) array_pop($args));
|
|
||||||
} while (!empty($args));
|
|
||||||
|
|
||||||
return $gcd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -438,6 +326,8 @@ class MathTrig
|
||||||
*
|
*
|
||||||
* Returns the logarithm of a number to a specified base. The default base is 10.
|
* Returns the logarithm of a number to a specified base. The default base is 10.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the withBase method in the MathTrig\Logarithms class instead
|
||||||
|
*
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* LOG(number[,base])
|
* LOG(number[,base])
|
||||||
*
|
*
|
||||||
|
|
@ -446,19 +336,9 @@ class MathTrig
|
||||||
*
|
*
|
||||||
* @return float|string The result, or a string containing an error
|
* @return float|string The result, or a string containing an error
|
||||||
*/
|
*/
|
||||||
public static function logBase($number = null, $base = 10)
|
public static function logBase($number, $base = 10)
|
||||||
{
|
{
|
||||||
$number = Functions::flattenSingleValue($number);
|
return MathTrig\Logarithms::withBase($number, $base);
|
||||||
$base = ($base === null) ? 10 : (float) Functions::flattenSingleValue($base);
|
|
||||||
|
|
||||||
if ((!is_numeric($base)) || (!is_numeric($number))) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
if (($base <= 0) || ($number <= 0)) {
|
|
||||||
return Functions::NAN();
|
|
||||||
}
|
|
||||||
|
|
||||||
return log($number, $base);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -517,6 +397,8 @@ class MathTrig
|
||||||
/**
|
/**
|
||||||
* MOD.
|
* MOD.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the evaluate method in the MathTrig\Mod class instead
|
||||||
|
*
|
||||||
* @param int $a Dividend
|
* @param int $a Dividend
|
||||||
* @param int $b Divisor
|
* @param int $b Divisor
|
||||||
*
|
*
|
||||||
|
|
@ -524,18 +406,7 @@ class MathTrig
|
||||||
*/
|
*/
|
||||||
public static function MOD($a = 1, $b = 1)
|
public static function MOD($a = 1, $b = 1)
|
||||||
{
|
{
|
||||||
$a = (float) Functions::flattenSingleValue($a);
|
return MathTrig\Mod::evaluate($a, $b);
|
||||||
$b = (float) Functions::flattenSingleValue($b);
|
|
||||||
|
|
||||||
if ($b == 0.0) {
|
|
||||||
return Functions::DIV0();
|
|
||||||
} elseif (($a < 0.0) && ($b > 0.0)) {
|
|
||||||
return $b - fmod(abs($a), $b);
|
|
||||||
} elseif (($a > 0.0) && ($b < 0.0)) {
|
|
||||||
return $b + fmod($a, abs($b));
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmod($a, $b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -562,6 +433,8 @@ class MathTrig
|
||||||
*
|
*
|
||||||
* Returns the ratio of the factorial of a sum of values to the product of factorials.
|
* Returns the ratio of the factorial of a sum of values to the product of factorials.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the funcMultinomial method in the MathTrig\Multinomial class instead
|
||||||
|
*
|
||||||
* @param mixed[] $args An array of mixed values for the 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
|
* @return float|string The result, or a string containing an error
|
||||||
|
|
@ -592,27 +465,16 @@ class MathTrig
|
||||||
*
|
*
|
||||||
* Computes x raised to the power y.
|
* Computes x raised to the power y.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the evaluate method in the MathTrig\Power class instead
|
||||||
|
*
|
||||||
* @param float $x
|
* @param float $x
|
||||||
* @param float $y
|
* @param float $y
|
||||||
*
|
*
|
||||||
* @return float|string The result, or a string containing an error
|
* @return float|int|string The result, or a string containing an error
|
||||||
*/
|
*/
|
||||||
public static function POWER($x = 0, $y = 2)
|
public static function POWER($x = 0, $y = 2)
|
||||||
{
|
{
|
||||||
$x = Functions::flattenSingleValue($x);
|
return MathTrig\Power::evaluate($x, $y);
|
||||||
$y = Functions::flattenSingleValue($y);
|
|
||||||
|
|
||||||
// Validate parameters
|
|
||||||
if ($x == 0.0 && $y == 0.0) {
|
|
||||||
return Functions::NAN();
|
|
||||||
} elseif ($x == 0.0 && $y < 0.0) {
|
|
||||||
return Functions::DIV0();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return
|
|
||||||
$result = $x ** $y;
|
|
||||||
|
|
||||||
return (!is_nan($result) && !is_infinite($result)) ? $result : Functions::NAN();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -656,23 +518,18 @@ class MathTrig
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RAND.
|
* RAND/RANDBETWEEN.
|
||||||
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the randNoArg or randBetween method in the MathTrig\Random class instead
|
||||||
*
|
*
|
||||||
* @param int $min Minimal value
|
* @param int $min Minimal value
|
||||||
* @param int $max Maximal value
|
* @param int $max Maximal value
|
||||||
*
|
*
|
||||||
* @return int Random number
|
* @return float|int|string Random number
|
||||||
*/
|
*/
|
||||||
public static function RAND($min = 0, $max = 0)
|
public static function RAND($min = 0, $max = 0)
|
||||||
{
|
{
|
||||||
$min = Functions::flattenSingleValue($min);
|
return MathTrig\Random::randBetween($min, $max);
|
||||||
$max = Functions::flattenSingleValue($max);
|
|
||||||
|
|
||||||
if ($min == 0 && $max == 0) {
|
|
||||||
return (mt_rand(0, 10000000)) / 10000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mt_rand($min, $max);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1388,19 +1245,15 @@ class MathTrig
|
||||||
*
|
*
|
||||||
* Returns the result of builtin function log after validating args.
|
* Returns the result of builtin function log after validating args.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the natural method in the MathTrig\Logarithms class instead
|
||||||
|
*
|
||||||
* @param mixed $number Should be numeric
|
* @param mixed $number Should be numeric
|
||||||
*
|
*
|
||||||
* @return float|string Rounded number
|
* @return float|string Rounded number
|
||||||
*/
|
*/
|
||||||
public static function builtinLN($number)
|
public static function builtinLN($number)
|
||||||
{
|
{
|
||||||
$number = Functions::flattenSingleValue($number);
|
return MathTrig\Logarithms::natural($number);
|
||||||
|
|
||||||
if (!is_numeric($number)) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
|
|
||||||
return log($number);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1408,19 +1261,15 @@ class MathTrig
|
||||||
*
|
*
|
||||||
* Returns the result of builtin function log after validating args.
|
* Returns the result of builtin function log after validating args.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the base10 method in the MathTrig\Logarithms class instead
|
||||||
|
*
|
||||||
* @param mixed $number Should be numeric
|
* @param mixed $number Should be numeric
|
||||||
*
|
*
|
||||||
* @return float|string Rounded number
|
* @return float|string Rounded number
|
||||||
*/
|
*/
|
||||||
public static function builtinLOG10($number)
|
public static function builtinLOG10($number)
|
||||||
{
|
{
|
||||||
$number = Functions::flattenSingleValue($number);
|
return MathTrig\Logarithms::base10($number);
|
||||||
|
|
||||||
if (!is_numeric($number)) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
|
|
||||||
return log10($number);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
|
||||||
|
class Arabic
|
||||||
|
{
|
||||||
|
private const ROMAN_LOOKUP = [
|
||||||
|
'M' => 1000,
|
||||||
|
'D' => 500,
|
||||||
|
'C' => 100,
|
||||||
|
'L' => 50,
|
||||||
|
'X' => 10,
|
||||||
|
'V' => 5,
|
||||||
|
'I' => 1,
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively calculate the arabic value of a roman numeral.
|
||||||
|
*
|
||||||
|
* @param int $sum
|
||||||
|
* @param int $subtract
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private static function calculateArabic(array $roman, &$sum = 0, $subtract = 0)
|
||||||
|
{
|
||||||
|
$numeral = array_shift($roman);
|
||||||
|
if (!isset(self::ROMAN_LOOKUP[$numeral])) {
|
||||||
|
throw new Exception('Invalid character detected');
|
||||||
|
}
|
||||||
|
|
||||||
|
$arabic = self::ROMAN_LOOKUP[$numeral];
|
||||||
|
if (count($roman) > 0 && isset(self::ROMAN_LOOKUP[$roman[0]]) && $arabic < self::ROMAN_LOOKUP[$roman[0]]) {
|
||||||
|
$subtract += $arabic;
|
||||||
|
} else {
|
||||||
|
$sum += ($arabic - $subtract);
|
||||||
|
$subtract = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($roman) > 0) {
|
||||||
|
self::calculateArabic($roman, $sum, $subtract);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function strSplit(string $roman): array
|
||||||
|
{
|
||||||
|
$rslt = str_split($roman);
|
||||||
|
|
||||||
|
return is_array($rslt) ? $rslt : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ARABIC.
|
||||||
|
*
|
||||||
|
* Converts a Roman numeral to an Arabic numeral.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* ARABIC(text)
|
||||||
|
*
|
||||||
|
* @param string $roman
|
||||||
|
*
|
||||||
|
* @return int|string the arabic numberal contrived from the roman numeral
|
||||||
|
*/
|
||||||
|
public static function evaluate($roman)
|
||||||
|
{
|
||||||
|
// An empty string should return 0
|
||||||
|
$roman = substr(trim(strtoupper((string) Functions::flattenSingleValue($roman))), 0, 255);
|
||||||
|
if ($roman === '') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the roman numeral to an arabic number
|
||||||
|
$negativeNumber = $roman[0] === '-';
|
||||||
|
if ($negativeNumber) {
|
||||||
|
$roman = substr($roman, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$arabic = self::calculateArabic(self::strSplit($roman));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return Functions::VALUE(); // Invalid character detected
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($negativeNumber) {
|
||||||
|
$arabic *= -1; // The number should be negative
|
||||||
|
}
|
||||||
|
|
||||||
|
return $arabic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class Combinations
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* COMBIN.
|
||||||
|
*
|
||||||
|
* Returns the number of combinations for a given number of items. Use COMBIN to
|
||||||
|
* determine the total possible number of groups for a given number of items.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* COMBIN(numObjs,numInSet)
|
||||||
|
*
|
||||||
|
* @param mixed $numObjs Number of different objects
|
||||||
|
* @param mixed $numInSet Number of objects in each combination
|
||||||
|
*
|
||||||
|
* @return float|int|string Number of combinations, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function withoutRepetition($numObjs, $numInSet)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$numObjs = Helpers::validateNumericNullSubstitution($numObjs, null);
|
||||||
|
$numInSet = Helpers::validateNumericNullSubstitution($numInSet, null);
|
||||||
|
Helpers::validateNotNegative($numInSet);
|
||||||
|
Helpers::validateNotNegative($numObjs - $numInSet);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
return round(Fact::funcFact($numObjs) / Fact::funcFact($numObjs - $numInSet)) / Fact::funcFact($numInSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* COMBIN.
|
||||||
|
*
|
||||||
|
* Returns the number of combinations for a given number of items. Use COMBIN to
|
||||||
|
* determine the total possible number of groups for a given number of items.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* COMBIN(numObjs,numInSet)
|
||||||
|
*
|
||||||
|
* @param mixed $numObjs Number of different objects
|
||||||
|
* @param mixed $numInSet Number of objects in each combination
|
||||||
|
*
|
||||||
|
* @return float|int|string Number of combinations, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function withRepetition($numObjs, $numInSet)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$numObjs = Helpers::validateNumericNullSubstitution($numObjs, null);
|
||||||
|
$numInSet = Helpers::validateNumericNullSubstitution($numInSet, null);
|
||||||
|
Helpers::validateNotNegative($numInSet);
|
||||||
|
Helpers::validateNotNegative($numObjs);
|
||||||
|
$numObjs = (int) $numObjs;
|
||||||
|
$numInSet = (int) $numInSet;
|
||||||
|
// Microsoft documentation says following is true, but Excel
|
||||||
|
// does not enforce this restriction.
|
||||||
|
//Helpers::validateNotNegative($numObjs - $numInSet);
|
||||||
|
if ($numObjs === 0) {
|
||||||
|
Helpers::validateNotNegative(-$numInSet);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
return round(Fact::funcFact($numObjs + $numInSet - 1) / Fact::funcFact($numObjs - 1)) / Fact::funcFact($numInSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
|
||||||
|
class Gcd
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Recursively determine GCD.
|
||||||
|
*
|
||||||
|
* Returns the greatest common divisor of a series of numbers.
|
||||||
|
* The greatest common divisor is the largest integer that divides both
|
||||||
|
* number1 and number2 without a remainder.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* GCD(number1[,number2[, ...]])
|
||||||
|
*
|
||||||
|
* @param float|int $a
|
||||||
|
* @param float|int $b
|
||||||
|
*
|
||||||
|
* @return float|int
|
||||||
|
*/
|
||||||
|
private static function evaluateGCD($a, $b)
|
||||||
|
{
|
||||||
|
return $b ? self::evaluateGCD($b, $a % $b) : $a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GCD.
|
||||||
|
*
|
||||||
|
* Returns the greatest common divisor of a series of numbers.
|
||||||
|
* The greatest common divisor is the largest integer that divides both
|
||||||
|
* number1 and number2 without a remainder.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* GCD(number1[,number2[, ...]])
|
||||||
|
*
|
||||||
|
* @param mixed ...$args Data values
|
||||||
|
*
|
||||||
|
* @return float|int|string Greatest Common Divisor, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function evaluate(...$args)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$arrayArgs = [];
|
||||||
|
foreach (Functions::flattenArray($args) as $value1) {
|
||||||
|
if ($value1 !== null) {
|
||||||
|
$value = Helpers::validateNumericNullSubstitution($value1, 1);
|
||||||
|
Helpers::validateNotNegative($value);
|
||||||
|
$arrayArgs[] = (int) $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($arrayArgs) <= 0) {
|
||||||
|
return Functions::VALUE();
|
||||||
|
}
|
||||||
|
$gcd = (int) array_pop($arrayArgs);
|
||||||
|
do {
|
||||||
|
$gcd = self::evaluateGCD($gcd, (int) array_pop($arrayArgs));
|
||||||
|
} while (!empty($arrayArgs));
|
||||||
|
|
||||||
|
return $gcd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -66,13 +66,27 @@ class Helpers
|
||||||
*
|
*
|
||||||
* @param float|int $number
|
* @param float|int $number
|
||||||
*/
|
*/
|
||||||
public static function validateNotNegative($number): void
|
public static function validateNotNegative($number, ?string $except = null): void
|
||||||
{
|
{
|
||||||
if ($number >= 0) {
|
if ($number >= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception(Functions::NAN());
|
throw new Exception($except ?? Functions::NAN());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirm number > 0.
|
||||||
|
*
|
||||||
|
* @param float|int $number
|
||||||
|
*/
|
||||||
|
public static function validatePositive($number, ?string $except = null): void
|
||||||
|
{
|
||||||
|
if ($number > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception($except ?? Functions::NAN());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -53,12 +53,15 @@ class Lcm
|
||||||
try {
|
try {
|
||||||
$arrayArgs = [];
|
$arrayArgs = [];
|
||||||
$anyZeros = 0;
|
$anyZeros = 0;
|
||||||
|
$anyNonNulls = 0;
|
||||||
foreach (Functions::flattenArray($args) as $value1) {
|
foreach (Functions::flattenArray($args) as $value1) {
|
||||||
|
$anyNonNulls += (int) ($value1 !== null);
|
||||||
$value = Helpers::validateNumericNullSubstitution($value1, 1);
|
$value = Helpers::validateNumericNullSubstitution($value1, 1);
|
||||||
Helpers::validateNotNegative($value);
|
Helpers::validateNotNegative($value);
|
||||||
$arrayArgs[] = (int) $value;
|
$arrayArgs[] = (int) $value;
|
||||||
$anyZeros += (int) !((bool) $value);
|
$anyZeros += (int) !((bool) $value);
|
||||||
}
|
}
|
||||||
|
self::testNonNulls($anyNonNulls);
|
||||||
if ($anyZeros) {
|
if ($anyZeros) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -76,15 +79,7 @@ class Lcm
|
||||||
foreach ($myCountedFactors as $myCountedFactor => $myCountedPower) {
|
foreach ($myCountedFactors as $myCountedFactor => $myCountedPower) {
|
||||||
$myPoweredFactors[$myCountedFactor] = $myCountedFactor ** $myCountedPower;
|
$myPoweredFactors[$myCountedFactor] = $myCountedFactor ** $myCountedPower;
|
||||||
}
|
}
|
||||||
foreach ($myPoweredFactors as $myPoweredValue => $myPoweredFactor) {
|
self::processPoweredFactors($allPoweredFactors, $myPoweredFactors);
|
||||||
if (isset($allPoweredFactors[$myPoweredValue])) {
|
|
||||||
if ($allPoweredFactors[$myPoweredValue] < $myPoweredFactor) {
|
|
||||||
$allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
foreach ($allPoweredFactors as $allPoweredFactor) {
|
foreach ($allPoweredFactors as $allPoweredFactor) {
|
||||||
$returnValue *= (int) $allPoweredFactor;
|
$returnValue *= (int) $allPoweredFactor;
|
||||||
|
|
@ -92,4 +87,24 @@ class Lcm
|
||||||
|
|
||||||
return $returnValue;
|
return $returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function processPoweredFactors(array &$allPoweredFactors, array &$myPoweredFactors): void
|
||||||
|
{
|
||||||
|
foreach ($myPoweredFactors as $myPoweredValue => $myPoweredFactor) {
|
||||||
|
if (isset($allPoweredFactors[$myPoweredValue])) {
|
||||||
|
if ($allPoweredFactors[$myPoweredValue] < $myPoweredFactor) {
|
||||||
|
$allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function testNonNulls(int $anyNonNulls): void
|
||||||
|
{
|
||||||
|
if (!$anyNonNulls) {
|
||||||
|
throw new Exception(Functions::VALUE());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class Logarithms
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* LOG_BASE.
|
||||||
|
*
|
||||||
|
* Returns the logarithm of a number to a specified base. The default base is 10.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* LOG(number[,base])
|
||||||
|
*
|
||||||
|
* @param mixed $number The positive real number for which you want the logarithm
|
||||||
|
* @param mixed $base The base of the logarithm. If base is omitted, it is assumed to be 10.
|
||||||
|
*
|
||||||
|
* @return float|string The result, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function withBase($number, $base = 10)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$number = Helpers::validateNumericNullBool($number);
|
||||||
|
Helpers::validatePositive($number);
|
||||||
|
$base = Helpers::validateNumericNullBool($base);
|
||||||
|
Helpers::validatePositive($base);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
return log($number, $base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LOG10.
|
||||||
|
*
|
||||||
|
* Returns the result of builtin function log after validating args.
|
||||||
|
*
|
||||||
|
* @param mixed $number Should be numeric
|
||||||
|
*
|
||||||
|
* @return float|string Rounded number
|
||||||
|
*/
|
||||||
|
public static function base10($number)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$number = Helpers::validateNumericNullBool($number);
|
||||||
|
Helpers::validatePositive($number);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
return log10($number);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LN.
|
||||||
|
*
|
||||||
|
* Returns the result of builtin function log after validating args.
|
||||||
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the natural method in the MathTrig\Logarithms class instead
|
||||||
|
*
|
||||||
|
* @param mixed $number Should be numeric
|
||||||
|
*
|
||||||
|
* @return float|string Rounded number
|
||||||
|
*/
|
||||||
|
public static function natural($number)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$number = Helpers::validateNumericNullBool($number);
|
||||||
|
Helpers::validatePositive($number);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
return log($number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Matrix\Builder;
|
||||||
use Matrix\Exception as MatrixException;
|
use Matrix\Exception as MatrixException;
|
||||||
use Matrix\Matrix;
|
use Matrix\Matrix;
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
|
@ -111,4 +112,27 @@ class MatrixFunctions
|
||||||
return $e->getMessage();
|
return $e->getMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MUnit.
|
||||||
|
*
|
||||||
|
* @param mixed $dimension Number of rows and columns
|
||||||
|
*
|
||||||
|
* @return array|string The result, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function funcMUnit($dimension)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$dimension = (int) Helpers::validateNumericNullBool($dimension);
|
||||||
|
Helpers::validatePositive($dimension, Functions::VALUE());
|
||||||
|
$matrix = Builder::createFilledMatrix(0, $dimension)->toArray();
|
||||||
|
for ($x = 0; $x < $dimension; ++$x) {
|
||||||
|
$matrix[$x][$x] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $matrix;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class Mod
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* MOD.
|
||||||
|
*
|
||||||
|
* @param mixed $a Dividend
|
||||||
|
* @param mixed $b Divisor
|
||||||
|
*
|
||||||
|
* @return float|int|string Remainder, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function evaluate($a, $b)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$a = Helpers::validateNumericNullBool($a);
|
||||||
|
$b = Helpers::validateNumericNullBool($b);
|
||||||
|
Helpers::validateNotZero($b);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($a < 0.0) && ($b > 0.0)) {
|
||||||
|
return $b - fmod(abs($a), $b);
|
||||||
|
}
|
||||||
|
if (($a > 0.0) && ($b < 0.0)) {
|
||||||
|
return $b + fmod($a, abs($b));
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmod($a, $b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
|
||||||
|
class Power
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* POWER.
|
||||||
|
*
|
||||||
|
* Computes x raised to the power y.
|
||||||
|
*
|
||||||
|
* @param float|int $x
|
||||||
|
* @param float|int $y
|
||||||
|
*
|
||||||
|
* @return float|int|string The result, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function evaluate($x, $y)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$x = Helpers::validateNumericNullBool($x);
|
||||||
|
$y = Helpers::validateNumericNullBool($y);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate parameters
|
||||||
|
if (!$x && !$y) {
|
||||||
|
return Functions::NAN();
|
||||||
|
}
|
||||||
|
if (!$x && $y < 0.0) {
|
||||||
|
return Functions::DIV0();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
$result = $x ** $y;
|
||||||
|
|
||||||
|
return Helpers::numberOrNan($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class Random
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* RAND.
|
||||||
|
*
|
||||||
|
* @return float Random number
|
||||||
|
*/
|
||||||
|
public static function randNoArgs()
|
||||||
|
{
|
||||||
|
return (mt_rand(0, 10000000)) / 10000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RANDBETWEEN.
|
||||||
|
*
|
||||||
|
* @param mixed $min Minimal value
|
||||||
|
* @param mixed $max Maximal value
|
||||||
|
*
|
||||||
|
* @return float|int|string Random number
|
||||||
|
*/
|
||||||
|
public static function randBetween($min, $max)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$min = (int) Helpers::validateNumericNullBool($min);
|
||||||
|
$max = (int) Helpers::validateNumericNullBool($max);
|
||||||
|
Helpers::validateNotNegative($max - $min);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mt_rand($min, $max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -53,6 +53,7 @@ CODE
|
||||||
COLUMN
|
COLUMN
|
||||||
COLUMNS
|
COLUMNS
|
||||||
COMBIN
|
COMBIN
|
||||||
|
COMBINA
|
||||||
COMPLEX
|
COMPLEX
|
||||||
CONCAT
|
CONCAT
|
||||||
CONCATENATE
|
CONCATENATE
|
||||||
|
|
@ -249,6 +250,7 @@ MODE
|
||||||
MONTH
|
MONTH
|
||||||
MROUND
|
MROUND
|
||||||
MULTINOMIAL
|
MULTINOMIAL
|
||||||
|
MUNIT
|
||||||
N
|
N
|
||||||
NA
|
NA
|
||||||
NEGBINOMDIST
|
NEGBINOMDIST
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,8 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
class ArabicTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class ArabicTest extends TestCase
|
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerARABIC
|
* @dataProvider providerARABIC
|
||||||
*
|
*
|
||||||
|
|
@ -21,8 +12,12 @@ class ArabicTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testARABIC($expectedResult, $romanNumeral): void
|
public function testARABIC($expectedResult, $romanNumeral): void
|
||||||
{
|
{
|
||||||
$result = MathTrig::ARABIC($romanNumeral);
|
$this->mightHaveException($expectedResult);
|
||||||
self::assertEquals($expectedResult, $result);
|
$sheet = $this->sheet;
|
||||||
|
$sheet->getCell('A1')->setValue($romanNumeral);
|
||||||
|
$sheet->getCell('B1')->setValue('=ARABIC(A1)');
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
|
self::assertSame($expectedResult, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function providerARABIC()
|
public function providerARABIC()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
|
class CombinATest extends AllSetupTeardown
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @dataProvider providerCOMBINA
|
||||||
|
*
|
||||||
|
* @param mixed $expectedResult
|
||||||
|
* @param mixed $numObjs
|
||||||
|
* @param mixed $numInSet
|
||||||
|
*/
|
||||||
|
public function testCOMBINA($expectedResult, $numObjs, $numInSet): void
|
||||||
|
{
|
||||||
|
$this->mightHaveException($expectedResult);
|
||||||
|
$sheet = $this->sheet;
|
||||||
|
if ($numObjs !== null) {
|
||||||
|
$sheet->getCell('A1')->setValue($numObjs);
|
||||||
|
}
|
||||||
|
if ($numInSet !== null) {
|
||||||
|
$sheet->getCell('A2')->setValue($numInSet);
|
||||||
|
}
|
||||||
|
$sheet->getCell('B1')->setValue('=COMBINA(A1,A2)');
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
|
self::assertEquals($expectedResult, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providerCOMBINA()
|
||||||
|
{
|
||||||
|
return require 'tests/data/Calculation/MathTrig/COMBINA.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,26 +2,28 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
class CombinTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class CombinTest extends TestCase
|
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerCOMBIN
|
* @dataProvider providerCOMBIN
|
||||||
*
|
*
|
||||||
* @param mixed $expectedResult
|
* @param mixed $expectedResult
|
||||||
|
* @param mixed $numObjs
|
||||||
|
* @param mixed $numInSet
|
||||||
*/
|
*/
|
||||||
public function testCOMBIN($expectedResult, ...$args): void
|
public function testCOMBIN($expectedResult, $numObjs, $numInSet): void
|
||||||
{
|
{
|
||||||
$result = MathTrig::COMBIN(...$args);
|
$this->mightHaveException($expectedResult);
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
$sheet = $this->sheet;
|
||||||
|
if ($numObjs !== null) {
|
||||||
|
$sheet->getCell('A1')->setValue($numObjs);
|
||||||
|
}
|
||||||
|
if ($numInSet !== null) {
|
||||||
|
$sheet->getCell('A2')->setValue($numInSet);
|
||||||
|
}
|
||||||
|
$sheet->getCell('B1')->setValue('=COMBIN(A1,A2)');
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
|
self::assertEquals($expectedResult, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function providerCOMBIN()
|
public function providerCOMBIN()
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,8 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
class FactDoubleTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class FactDoubleTest extends TestCase
|
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerFACTDOUBLE
|
* @dataProvider providerFACTDOUBLE
|
||||||
*
|
*
|
||||||
|
|
@ -21,8 +12,12 @@ class FactDoubleTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testFACTDOUBLE($expectedResult, $value): void
|
public function testFACTDOUBLE($expectedResult, $value): void
|
||||||
{
|
{
|
||||||
$result = MathTrig::FACTDOUBLE($value);
|
$this->mightHaveException($expectedResult);
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
$sheet = $this->sheet;
|
||||||
|
$sheet->getCell('A1')->setValue($value);
|
||||||
|
$sheet->getCell('B1')->setValue('=FACTDOUBLE(A1)');
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
|
self::assertEquals($expectedResult, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function providerFACTDOUBLE()
|
public function providerFACTDOUBLE()
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,8 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
class GcdTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class GcdTest extends TestCase
|
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerGCD
|
* @dataProvider providerGCD
|
||||||
*
|
*
|
||||||
|
|
@ -20,7 +11,21 @@ class GcdTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testGCD($expectedResult, ...$args): void
|
public function testGCD($expectedResult, ...$args): void
|
||||||
{
|
{
|
||||||
$result = MathTrig::GCD(...$args);
|
$this->mightHaveException($expectedResult);
|
||||||
|
$sheet = $this->sheet;
|
||||||
|
$row = 0;
|
||||||
|
foreach ($args as $arg) {
|
||||||
|
++$row;
|
||||||
|
if ($arg !== null) {
|
||||||
|
$sheet->getCell("A$row")->setValue($arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($row < 1) {
|
||||||
|
$sheet->getCell('B1')->setValue('=GCD()');
|
||||||
|
} else {
|
||||||
|
$sheet->getCell('B1')->setValue("=GCD(A1:A$row)");
|
||||||
|
}
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,30 +2,27 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class LnTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class LnTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerLN
|
* @dataProvider providerLN
|
||||||
*
|
*
|
||||||
* @param mixed $expectedResult
|
* @param mixed $expectedResult
|
||||||
* @param mixed $val
|
* @param mixed $number
|
||||||
*/
|
*/
|
||||||
public function testLN($expectedResult, $val = null): void
|
public function testLN($expectedResult, $number = 'omitted'): void
|
||||||
{
|
{
|
||||||
if ($val === null) {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
$formula = '=LN()';
|
if ($number !== null) {
|
||||||
} else {
|
$sheet->getCell('A1')->setValue($number);
|
||||||
$formula = "=LN($val)";
|
|
||||||
}
|
}
|
||||||
$spreadsheet = new Spreadsheet();
|
if ($number === 'omitted') {
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
$sheet->getCell('B1')->setValue('=LN()');
|
||||||
$sheet->getCell('A1')->setValue($formula);
|
} else {
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$sheet->getCell('B1')->setValue('=LN(A1)');
|
||||||
|
}
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-6);
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,30 +2,27 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class Log10Test extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class Log10Test extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerLN
|
* @dataProvider providerLN
|
||||||
*
|
*
|
||||||
* @param mixed $expectedResult
|
* @param mixed $expectedResult
|
||||||
* @param mixed $val
|
* @param mixed $number
|
||||||
*/
|
*/
|
||||||
public function testLN($expectedResult, $val = null): void
|
public function testLN($expectedResult, $number = 'omitted'): void
|
||||||
{
|
{
|
||||||
if ($val === null) {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
$formula = '=LOG10()';
|
if ($number !== null) {
|
||||||
} else {
|
$sheet->getCell('A1')->setValue($number);
|
||||||
$formula = "=LOG10($val)";
|
|
||||||
}
|
}
|
||||||
$spreadsheet = new Spreadsheet();
|
if ($number === 'omitted') {
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
$sheet->getCell('B1')->setValue('=LOG10()');
|
||||||
$sheet->getCell('A1')->setValue($formula);
|
} else {
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$sheet->getCell('B1')->setValue('=LOG10(A1)');
|
||||||
|
}
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-6);
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,25 +2,33 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
class LogTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class LogTest extends TestCase
|
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerLOG
|
* @dataProvider providerLOG
|
||||||
*
|
*
|
||||||
* @param mixed $expectedResult
|
* @param mixed $expectedResult
|
||||||
|
* @param mixed $number
|
||||||
|
* @param mixed $base
|
||||||
*/
|
*/
|
||||||
public function testLOG($expectedResult, ...$args): void
|
public function testLOG($expectedResult, $number = 'omitted', $base = 'omitted'): void
|
||||||
{
|
{
|
||||||
$result = MathTrig::logBase(...$args);
|
$this->mightHaveException($expectedResult);
|
||||||
|
$sheet = $this->sheet;
|
||||||
|
if ($number !== null) {
|
||||||
|
$sheet->getCell('A1')->setValue($number);
|
||||||
|
}
|
||||||
|
if ($base !== null) {
|
||||||
|
$sheet->getCell('A2')->setValue($base);
|
||||||
|
}
|
||||||
|
if ($number === 'omitted') {
|
||||||
|
$sheet->getCell('B1')->setValue('=LOG()');
|
||||||
|
} elseif ($base === 'omitted') {
|
||||||
|
$sheet->getCell('B1')->setValue('=LOG(A1)');
|
||||||
|
} else {
|
||||||
|
$sheet->getCell('B1')->setValue('=LOG(A1,A2)');
|
||||||
|
}
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,5 +28,16 @@ class MMultTest extends AllSetupTeardown
|
||||||
$sheet = $this->sheet;
|
$sheet = $this->sheet;
|
||||||
$sheet->getCell('A1')->setValue('=MMULT({1,2,3}, {1,2,3})'); // incompatible dimensions
|
$sheet->getCell('A1')->setValue('=MMULT({1,2,3}, {1,2,3})'); // incompatible dimensions
|
||||||
self::assertSame('#VALUE!', $sheet->getCell('A1')->getCalculatedValue());
|
self::assertSame('#VALUE!', $sheet->getCell('A1')->getCalculatedValue());
|
||||||
|
|
||||||
|
$sheet->getCell('A11')->setValue('=MMULT({1, 2, 3, 4}, {5; 6; 7; 8})');
|
||||||
|
self::assertEquals(70, $sheet->getCell('A11')->getCalculatedValue());
|
||||||
|
$sheet->getCell('A2')->setValue(1);
|
||||||
|
$sheet->getCell('B2')->setValue(2);
|
||||||
|
$sheet->getCell('C2')->setValue(3);
|
||||||
|
$sheet->getCell('D2')->setValue(4);
|
||||||
|
$sheet->getCell('D3')->setValue(5);
|
||||||
|
$sheet->getCell('D4')->setValue(6);
|
||||||
|
$sheet->getCell('A12')->setValue('=MMULT(A2:C2,D2:D4)');
|
||||||
|
self::assertEquals(32, $sheet->getCell('A12')->getCalculatedValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig\MatrixFunctions;
|
||||||
|
|
||||||
|
class MUnitTest extends AllSetupTeardown
|
||||||
|
{
|
||||||
|
public function testMUNIT(): void
|
||||||
|
{
|
||||||
|
$identity = MatrixFunctions::funcMUnit(3);
|
||||||
|
self::assertEquals([[1, 0, 0], [0, 1, 0], [0, 0, 1]], $identity);
|
||||||
|
$startArray = [[1, 2, 2], [4, 5, 6], [7, 8, 9]];
|
||||||
|
$resultArray = MatrixFunctions::funcMMult($startArray, $identity);
|
||||||
|
self::assertEquals($startArray, $resultArray);
|
||||||
|
$inverseArray = MatrixFunctions::funcMInverse($startArray);
|
||||||
|
$resultArray = MatrixFunctions::funcMMult($startArray, $inverseArray);
|
||||||
|
self::assertEquals($identity, $resultArray);
|
||||||
|
self::assertEquals('#VALUE!', MatrixFunctions::funcMUnit(0));
|
||||||
|
self::assertEquals('#VALUE!', MatrixFunctions::funcMUnit(-1));
|
||||||
|
self::assertEquals('#VALUE!', MatrixFunctions::funcMUnit('X'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,25 +2,33 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
class ModTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class ModTest extends TestCase
|
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerMOD
|
* @dataProvider providerMOD
|
||||||
*
|
*
|
||||||
* @param mixed $expectedResult
|
* @param mixed $expectedResult
|
||||||
|
* @param mixed $dividend
|
||||||
|
* @param mixed $divisor
|
||||||
*/
|
*/
|
||||||
public function testMOD($expectedResult, ...$args): void
|
public function testMOD($expectedResult, $dividend = 'omitted', $divisor = 'omitted'): void
|
||||||
{
|
{
|
||||||
$result = MathTrig::MOD(...$args);
|
$this->mightHaveException($expectedResult);
|
||||||
|
$sheet = $this->sheet;
|
||||||
|
if ($dividend !== null) {
|
||||||
|
$sheet->getCell('A1')->setValue($dividend);
|
||||||
|
}
|
||||||
|
if ($divisor !== null) {
|
||||||
|
$sheet->getCell('A2')->setValue($divisor);
|
||||||
|
}
|
||||||
|
if ($dividend === 'omitted') {
|
||||||
|
$sheet->getCell('B1')->setValue('=MOD()');
|
||||||
|
} elseif ($divisor === 'omitted') {
|
||||||
|
$sheet->getCell('B1')->setValue('=MOD(A1)');
|
||||||
|
} else {
|
||||||
|
$sheet->getCell('B1')->setValue('=MOD(A1,A2)');
|
||||||
|
}
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ class MovedFunctionsTest extends TestCase
|
||||||
self::assertEqualsWithDelta(0, MathTrig::builtinACOSH(1), 1E-9);
|
self::assertEqualsWithDelta(0, MathTrig::builtinACOSH(1), 1E-9);
|
||||||
self::assertEqualsWithDelta(3.04192400109863, MathTrig::ACOT(-10), 1E-9);
|
self::assertEqualsWithDelta(3.04192400109863, MathTrig::ACOT(-10), 1E-9);
|
||||||
self::assertEqualsWithDelta(-0.20273255405408, MathTrig::ACOTH(-5), 1E-9);
|
self::assertEqualsWithDelta(-0.20273255405408, MathTrig::ACOTH(-5), 1E-9);
|
||||||
|
self::assertSame(49, MathTrig::ARABIC('XLIX'));
|
||||||
self::assertEqualsWithDelta(0, MathTrig::builtinASIN(0), 1E-9);
|
self::assertEqualsWithDelta(0, MathTrig::builtinASIN(0), 1E-9);
|
||||||
self::assertEqualsWithDelta(0, MathTrig::builtinASINH(0), 1E-9);
|
self::assertEqualsWithDelta(0, MathTrig::builtinASINH(0), 1E-9);
|
||||||
self::assertEqualsWithDelta(0, MathTrig::builtinATAN(0), 1E-9);
|
self::assertEqualsWithDelta(0, MathTrig::builtinATAN(0), 1E-9);
|
||||||
|
|
@ -27,6 +28,7 @@ class MovedFunctionsTest extends TestCase
|
||||||
self::assertEqualsWithDelta('#DIV/0!', MathTrig::ATAN2(0, 0), 1E-9);
|
self::assertEqualsWithDelta('#DIV/0!', MathTrig::ATAN2(0, 0), 1E-9);
|
||||||
self::assertEquals('12', MathTrig::BASE(10, 8));
|
self::assertEquals('12', MathTrig::BASE(10, 8));
|
||||||
self::assertEquals(-6, MathTrig::CEILING(-4.5, -2));
|
self::assertEquals(-6, MathTrig::CEILING(-4.5, -2));
|
||||||
|
self::assertEquals(15, MathTrig::COMBIN(6, 2));
|
||||||
self::assertEquals(1, MathTrig::builtinCOS(0));
|
self::assertEquals(1, MathTrig::builtinCOS(0));
|
||||||
self::assertEquals(1, MathTrig::builtinCOSH(0));
|
self::assertEquals(1, MathTrig::builtinCOSH(0));
|
||||||
self::assertEquals('#DIV/0!', MathTrig::COT(0));
|
self::assertEquals('#DIV/0!', MathTrig::COT(0));
|
||||||
|
|
@ -35,25 +37,32 @@ class MovedFunctionsTest extends TestCase
|
||||||
self::assertEquals('#DIV/0!', MathTrig::CSCH(0));
|
self::assertEquals('#DIV/0!', MathTrig::CSCH(0));
|
||||||
self::assertEquals(6, MathTrig::EVEN(4.5));
|
self::assertEquals(6, MathTrig::EVEN(4.5));
|
||||||
self::assertEquals(6, MathTrig::FACT(3));
|
self::assertEquals(6, MathTrig::FACT(3));
|
||||||
|
self::assertEquals(105, MathTrig::FACTDOUBLE(7));
|
||||||
self::assertEquals(-6, MathTrig::FLOOR(-4.5, 2));
|
self::assertEquals(-6, MathTrig::FLOOR(-4.5, 2));
|
||||||
self::assertEquals(0.23, MathTrig::FLOORMATH(0.234, 0.01));
|
self::assertEquals(0.23, MathTrig::FLOORMATH(0.234, 0.01));
|
||||||
self::assertEquals(-4, MathTrig::FLOORPRECISE(-2.5, 2));
|
self::assertEquals(-4, MathTrig::FLOORPRECISE(-2.5, 2));
|
||||||
self::assertEquals(-9, MathTrig::INT(-8.3));
|
self::assertEquals(-9, MathTrig::INT(-8.3));
|
||||||
self::assertEquals(12, MathTrig::LCM(4, 6));
|
self::assertEquals(12, MathTrig::LCM(4, 6));
|
||||||
|
self::assertEqualswithDelta(2.302585, MathTrig::builtinLN(10), 1E-6);
|
||||||
|
self::assertEqualswithDelta(0.306762486567556, MathTrig::logBase(1.5, 3.75), 1E-6);
|
||||||
|
self::assertEqualswithDelta(0.301030, MathTrig::builtinLOG10(2), 1E-6);
|
||||||
self::assertEquals(1, MathTrig::MDETERM([1]));
|
self::assertEquals(1, MathTrig::MDETERM([1]));
|
||||||
self::assertEquals(
|
self::assertEquals(
|
||||||
[[2, 2], [2, 1]],
|
[[2, 2], [2, 1]],
|
||||||
MathTrig::MINVERSE([[-0.5, 1.0], [1.0, -1.0]])
|
MathTrig::MINVERSE([[-0.5, 1.0], [1.0, -1.0]])
|
||||||
);
|
);
|
||||||
self::assertEquals(
|
self::assertEquals(
|
||||||
[[23], [53]],
|
[[23], [53]],
|
||||||
MathTrig::MMULT([[1, 2], [3, 4]], [[7], [8]])
|
MathTrig::MMULT([[1, 2], [3, 4]], [[7], [8]])
|
||||||
);
|
);
|
||||||
|
self::assertEquals(1, MathTrig::MOD(5, 2));
|
||||||
self::assertEquals(6, MathTrig::MROUND(7.3, 3));
|
self::assertEquals(6, MathTrig::MROUND(7.3, 3));
|
||||||
self::assertEquals(1, MathTrig::MULTINOMIAL(1));
|
self::assertEquals(1, MathTrig::MULTINOMIAL(1));
|
||||||
self::assertEquals(5, MathTrig::ODD(4.5));
|
self::assertEquals(5, MathTrig::ODD(4.5));
|
||||||
|
self::assertEquals(8, MathTrig::POWER(2, 3));
|
||||||
self::assertEquals(8, MathTrig::PRODUCT(1, 2, 4));
|
self::assertEquals(8, MathTrig::PRODUCT(1, 2, 4));
|
||||||
self::assertEquals(8, MathTrig::QUOTIENT(17, 2));
|
self::assertEquals(8, MathTrig::QUOTIENT(17, 2));
|
||||||
|
self::assertGreaterThanOrEqual(0, MATHTRIG::RAND());
|
||||||
self::assertEquals('I', MathTrig::ROMAN(1));
|
self::assertEquals('I', MathTrig::ROMAN(1));
|
||||||
self::assertEquals(3.3, MathTrig::builtinROUND(3.27, 1));
|
self::assertEquals(3.3, MathTrig::builtinROUND(3.27, 1));
|
||||||
self::assertEquals(662, MathTrig::ROUNDDOWN(662.79, 0));
|
self::assertEquals(662, MathTrig::ROUNDDOWN(662.79, 0));
|
||||||
|
|
|
||||||
|
|
@ -2,25 +2,33 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
class PowerTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class PowerTest extends TestCase
|
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerPOWER
|
* @dataProvider providerPOWER
|
||||||
*
|
*
|
||||||
* @param mixed $expectedResult
|
* @param mixed $expectedResult
|
||||||
|
* @param mixed $base
|
||||||
|
* @param mixed $exponent
|
||||||
*/
|
*/
|
||||||
public function testPOWER($expectedResult, ...$args): void
|
public function testPOWER($expectedResult, $base = 'omitted', $exponent = 'omitted'): void
|
||||||
{
|
{
|
||||||
$result = MathTrig::POWER(...$args);
|
$this->mightHaveException($expectedResult);
|
||||||
|
$sheet = $this->sheet;
|
||||||
|
if ($base !== null) {
|
||||||
|
$sheet->getCell('A1')->setValue($base);
|
||||||
|
}
|
||||||
|
if ($exponent !== null) {
|
||||||
|
$sheet->getCell('A2')->setValue($exponent);
|
||||||
|
}
|
||||||
|
if ($base === 'omitted') {
|
||||||
|
$sheet->getCell('B1')->setValue('=POWER()');
|
||||||
|
} elseif ($exponent === 'omitted') {
|
||||||
|
$sheet->getCell('B1')->setValue('=POWER(A1)');
|
||||||
|
} else {
|
||||||
|
$sheet->getCell('B1')->setValue('=POWER(A1,A2)');
|
||||||
|
}
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
|
class RandBetweenTest extends AllSetupTeardown
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @dataProvider providerRANDBETWEEN
|
||||||
|
*
|
||||||
|
* @param mixed $expectedResult
|
||||||
|
* @param mixed $min
|
||||||
|
* @param mixed $max
|
||||||
|
*/
|
||||||
|
public function testRANDBETWEEN($expectedResult, $min = 'omitted', $max = 'omitted'): void
|
||||||
|
{
|
||||||
|
$this->mightHaveException($expectedResult);
|
||||||
|
$sheet = $this->sheet;
|
||||||
|
$lower = (int) $min;
|
||||||
|
$upper = (int) $max;
|
||||||
|
if ($min !== null) {
|
||||||
|
$sheet->getCell('A1')->setValue($min);
|
||||||
|
}
|
||||||
|
if ($max !== null) {
|
||||||
|
$sheet->getCell('A2')->setValue($max);
|
||||||
|
}
|
||||||
|
if ($min === 'omitted') {
|
||||||
|
$sheet->getCell('B1')->setValue('=RANDBETWEEN()');
|
||||||
|
} elseif ($max === 'omitted') {
|
||||||
|
$sheet->getCell('B1')->setValue('=RANDBETWEEN(A1)');
|
||||||
|
} else {
|
||||||
|
$sheet->getCell('B1')->setValue('=RANDBETWEEN(A1,A2)');
|
||||||
|
}
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
|
if (is_numeric($expectedResult)) {
|
||||||
|
self::assertGreaterThanOrEqual($lower, $result);
|
||||||
|
self::assertLessThanOrEqual($upper, $result);
|
||||||
|
} else {
|
||||||
|
self::assertSame($expectedResult, $result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providerRANDBETWEEN()
|
||||||
|
{
|
||||||
|
return require 'tests/data/Calculation/MathTrig/RANDBETWEEN.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
|
class RandTest extends AllSetupTeardown
|
||||||
|
{
|
||||||
|
public function testRand(): void
|
||||||
|
{
|
||||||
|
$sheet = $this->sheet;
|
||||||
|
$sheet->getCell('B1')->setValue('=RAND()');
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
|
self::assertGreaterThanOrEqual(0, $result);
|
||||||
|
self::assertLessThanOrEqual(1, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRandException(): void
|
||||||
|
{
|
||||||
|
$this->mightHaveException('exception');
|
||||||
|
$sheet = $this->sheet;
|
||||||
|
$sheet->getCell('B1')->setValue('=RAND(A1)');
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
|
self::assertEquals(0, $result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -71,6 +71,11 @@ return [
|
||||||
[
|
[
|
||||||
'#VALUE!',
|
'#VALUE!',
|
||||||
'ABCD',
|
'ABCD',
|
||||||
|
2,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#VALUE!',
|
||||||
|
3,
|
||||||
'EFGH',
|
'EFGH',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -123,4 +128,8 @@ return [
|
||||||
6,
|
6,
|
||||||
7,
|
7,
|
||||||
],
|
],
|
||||||
|
[1, 0, 0],
|
||||||
|
['#NUM!', 0, 1],
|
||||||
|
['#VALUE!', 1, true],
|
||||||
|
['#VALUE!', 1, null],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// NumObjs, NumInSet, Result
|
||||||
|
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
84,
|
||||||
|
7,
|
||||||
|
3,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
36,
|
||||||
|
8,
|
||||||
|
2,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
120,
|
||||||
|
8,
|
||||||
|
3,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
330,
|
||||||
|
8,
|
||||||
|
4,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
171700,
|
||||||
|
100,
|
||||||
|
3,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#NUM!',
|
||||||
|
-7,
|
||||||
|
-10,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#NUM!',
|
||||||
|
-7,
|
||||||
|
10,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#NUM!',
|
||||||
|
7,
|
||||||
|
-10,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
4,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
3,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
3,
|
||||||
|
2.5,
|
||||||
|
2,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#VALUE!',
|
||||||
|
'ABCD',
|
||||||
|
2,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#VALUE!',
|
||||||
|
3,
|
||||||
|
'EFGH',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
2002,
|
||||||
|
10,
|
||||||
|
5,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
220,
|
||||||
|
10,
|
||||||
|
3,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
53130,
|
||||||
|
21,
|
||||||
|
5,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
6,
|
||||||
|
6,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
21,
|
||||||
|
6,
|
||||||
|
2,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
56,
|
||||||
|
6,
|
||||||
|
3,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
126,
|
||||||
|
6,
|
||||||
|
4,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
252,
|
||||||
|
6,
|
||||||
|
5,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
462,
|
||||||
|
6,
|
||||||
|
6,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
792,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
],
|
||||||
|
[1, 0, 0],
|
||||||
|
['#NUM!', 0, 1],
|
||||||
|
['#VALUE!', 1, true],
|
||||||
|
['#VALUE!', 1, null],
|
||||||
|
];
|
||||||
|
|
@ -129,4 +129,8 @@ return [
|
||||||
481,
|
481,
|
||||||
143,
|
143,
|
||||||
],
|
],
|
||||||
|
[13, 182, 481, null, 143],
|
||||||
|
['#VALUE!', null, null, null, null],
|
||||||
|
['#VALUE!', null],
|
||||||
|
['exception'],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -69,5 +69,7 @@ return [
|
||||||
['#VALUE!', 7, 0, 'X'],
|
['#VALUE!', 7, 0, 'X'],
|
||||||
[18, 9.1, 6.7],
|
[18, 9.1, 6.7],
|
||||||
[12, 6, null, 4],
|
[12, 6, null, 4],
|
||||||
|
['#VALUE!', null, null, null],
|
||||||
|
['#VALUE!', null],
|
||||||
['#VALUE!', 6, false, 4],
|
['#VALUE!', 6, false, 4],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
['#VALUE!'], // exception not enough args
|
['exception'], // exception not enough args
|
||||||
['#VALUE!', '"ABC"'],
|
['#VALUE!', 'ABC'],
|
||||||
['#NUM!', 0],
|
['#NUM!', 0],
|
||||||
['#NUM!', -1],
|
['#NUM!', -1],
|
||||||
[-2.302585, 0.1],
|
[-2.302585, 0.1],
|
||||||
|
|
|
||||||
|
|
@ -341,4 +341,5 @@ return [
|
||||||
200,
|
200,
|
||||||
3,
|
3,
|
||||||
],
|
],
|
||||||
|
['exception'],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
['#VALUE!'], // exception not enough args
|
['exception'], // exception not enough args
|
||||||
['#VALUE!', '"ABC"'],
|
['#VALUE!', 'ABC'],
|
||||||
['#NUM!', 0],
|
['#NUM!', 0],
|
||||||
['#NUM!', -1],
|
['#NUM!', -1],
|
||||||
[-1, 0.1],
|
[-1, 0.1],
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ return [
|
||||||
[
|
[
|
||||||
1.81,
|
1.81,
|
||||||
[
|
[
|
||||||
[0.20, 1.0],
|
[0.20, 1.0],
|
||||||
[0.35, 10.8],
|
[0.35, 10.8],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
@ -73,17 +73,17 @@ return [
|
||||||
[
|
[
|
||||||
88,
|
88,
|
||||||
[
|
[
|
||||||
[1, 3, 8, 5],
|
[1, 3, 8, 5],
|
||||||
[1, 3, 6, 1],
|
[1, 3, 6, 1],
|
||||||
[1, 1, 1, 0],
|
[1, 1, 1, 0],
|
||||||
[7, 3, 10, 2],
|
[7, 3, 10, 2],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
1,
|
1,
|
||||||
[
|
[
|
||||||
[3, 6, 1],
|
[3, 6, 1],
|
||||||
[1, 1, 0],
|
[1, 1, 0],
|
||||||
[3, 10, 2],
|
[3, 10, 2],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
@ -104,25 +104,25 @@ return [
|
||||||
[
|
[
|
||||||
'#VALUE!', // null in array
|
'#VALUE!', // null in array
|
||||||
[
|
[
|
||||||
[0.20, 1.00, -0.90],
|
[0.20, 1.00, -0.90],
|
||||||
[0.35, 10.80, 4.00],
|
[0.35, 10.80, 4.00],
|
||||||
[-3.15, 5.00, null],
|
[-3.15, 5.00, null],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'#VALUE!', // string in array
|
'#VALUE!', // string in array
|
||||||
[
|
[
|
||||||
[0.20, 1.00, -0.90],
|
[0.20, 1.00, -0.90],
|
||||||
[0.35, 10.80, '="4.00"'],
|
[0.35, 10.80, '="4.00"'],
|
||||||
[-3.15, 5.00, 6.00],
|
[-3.15, 5.00, 6.00],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'#VALUE!', // string in array
|
'#VALUE!', // string in array
|
||||||
[
|
[
|
||||||
[0.20, 1.00, -0.90],
|
[0.20, 1.00, -0.90],
|
||||||
[0.35, 10.80, 'Y'],
|
[0.35, 10.80, 'Y'],
|
||||||
[-3.15, 5.00, 6.00],
|
[-3.15, 5.00, 6.00],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
return [
|
return [
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
[0.147222222222222, -0.14444444444444399, 0.063888888888888898],
|
[0.147222222222222, -0.14444444444444399, 0.063888888888888898],
|
||||||
[-0.061111111111111102, 0.022222222222222199, 0.105555555555556],
|
[-0.061111111111111102, 0.022222222222222199, 0.105555555555556],
|
||||||
[-0.0194444444444444, 0.18888888888888899, -0.102777777777778],
|
[-0.0194444444444444, 0.18888888888888899, -0.102777777777778],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[8, 1, 6],
|
[8, 1, 6],
|
||||||
|
|
@ -16,7 +16,7 @@ return [
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
[4, -1],
|
[4, -1],
|
||||||
[2, 0],
|
[2, 0],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[0.0, 0.5],
|
[0.0, 0.5],
|
||||||
|
|
@ -25,28 +25,28 @@ return [
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
[1, 2, 1],
|
[1, 2, 1],
|
||||||
[3, 4, -1],
|
[3, 4, -1],
|
||||||
[0, 2, 0],
|
[0, 2, 0],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[0.25, 0.25, -0.75],
|
[0.25, 0.25, -0.75],
|
||||||
[0.00, 0.00, 0.50],
|
[0.00, 0.00, 0.50],
|
||||||
[0.75, -0.25, -0.25],
|
[0.75, -0.25, -0.25],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
[-0.4545454545455, 1.8181818181818, 0.2727272727273, -0.4545454545455],
|
[-0.4545454545455, 1.8181818181818, 0.2727272727273, -0.4545454545455],
|
||||||
[-0.4545454545455, 1.8181818181818, -0.7272727272727, -0.4545454545455],
|
[-0.4545454545455, 1.8181818181818, -0.7272727272727, -0.4545454545455],
|
||||||
[0.9090909090909, 1.3636363636364, 0.4545454545455, 0.9090909090909],
|
[0.9090909090909, 1.3636363636364, 0.4545454545455, 0.9090909090909],
|
||||||
[2.2727272727273, 0.9090909090909, 5.6363636363636, 3.2727272727273],
|
[2.2727272727273, 0.9090909090909, 5.6363636363636, 3.2727272727273],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[3.2, -4.8, 2.8, -1.0],
|
[3.2, -4.8, 2.8, -1.0],
|
||||||
[0.2, 0.2, 0.2, 0.0],
|
[0.2, 0.2, 0.2, 0.0],
|
||||||
[1.0, -1.0, 0.0, 0.0],
|
[1.0, -1.0, 0.0, 0.0],
|
||||||
[-4.0, 5.0, -2.0, 1.0],
|
[-4.0, 5.0, -2.0, 1.0],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -55,7 +55,7 @@ return [
|
||||||
[3, 4],
|
[3, 4],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[-2.0, 1.0],
|
[-2.0, 1.0],
|
||||||
[1.5, -0.5],
|
[1.5, -0.5],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
@ -67,8 +67,8 @@ return [
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[-2, 1, 0],
|
[-2, 1, 0],
|
||||||
[1.3333333333333299, -0.33333333333332998, -0.33333333333332998],
|
[1.3333333333333299, -0.33333333333332998, -0.33333333333332998],
|
||||||
[0.33333333333332998, -0.33333333333332998, 0.66666666666666996],
|
[0.33333333333332998, -0.33333333333332998, 0.66666666666666996],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -77,7 +77,7 @@ return [
|
||||||
[4, 5],
|
[4, 5],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[-2.5, 1.5],
|
[-2.5, 1.5],
|
||||||
[2.0, -1.0],
|
[2.0, -1.0],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
@ -87,7 +87,7 @@ return [
|
||||||
[7, 9],
|
[7, 9],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[-0.81818181818181801, 0.72727272727272696],
|
[-0.81818181818181801, 0.72727272727272696],
|
||||||
[0.63636363636363602, -0.45454545454545497],
|
[0.63636363636363602, -0.45454545454545497],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
@ -98,7 +98,7 @@ return [
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[0.054112554112554001, -0.084415584415584],
|
[0.054112554112554001, -0.084415584415584],
|
||||||
[-0.018398268398268001, 0.048701298701299002],
|
[-0.018398268398268001, 0.048701298701299002],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -107,14 +107,14 @@ return [
|
||||||
[2, 1],
|
[2, 1],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[-0.5, 1.0],
|
[-0.5, 1.0],
|
||||||
[1.0, -1.0],
|
[1.0, -1.0],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'#VALUE!', // Not Square
|
'#VALUE!', // Not Square
|
||||||
[
|
[
|
||||||
[-0.5, 1.0, 1.5],
|
[-0.5, 1.0, 1.5],
|
||||||
[1.0, -1.0, 2.0],
|
[1.0, -1.0, 2.0],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,15 @@ return [
|
||||||
1.3,
|
1.3,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
0,
|
'#VALUE!', // had been 0, which was wrong
|
||||||
'',
|
'',
|
||||||
1,
|
1,
|
||||||
],
|
],
|
||||||
|
[0, null, 5],
|
||||||
|
[0, false, 5],
|
||||||
|
[1, true, 5],
|
||||||
|
['#VALUE!', 'XYZ', 2],
|
||||||
|
['#VALUE!', 2, 'XYZ'],
|
||||||
|
['exception', 2],
|
||||||
|
['exception'],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -406,4 +406,6 @@ return [
|
||||||
4.5,
|
4.5,
|
||||||
4.5,
|
4.5,
|
||||||
],
|
],
|
||||||
|
['#VALUE!', 'x', 2],
|
||||||
|
['#VALUE!', 2, 'x'],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
['#VALUE!', 'y', 3],
|
||||||
|
['#VALUE!', 3, 'y'],
|
||||||
|
['#NUM!', 3, -3],
|
||||||
|
['#NUM!', 30, 10],
|
||||||
|
[0, '20', 30],
|
||||||
|
[0, 20, '30'],
|
||||||
|
[0, 20, 30],
|
||||||
|
[0, null, 30],
|
||||||
|
[0, false, 30],
|
||||||
|
[0, true, 30],
|
||||||
|
[0, -30, true],
|
||||||
|
[0, -30, false],
|
||||||
|
[0, -30, null],
|
||||||
|
['exception', -30],
|
||||||
|
['exception'],
|
||||||
|
];
|
||||||
Loading…
Reference in New Issue