Merge pull request #2583 from PHPOffice/Issue-2551_Enable-Array-Readiness-for-Functions-Maths

Issue 2551 - Enable array-readiness for more Math/Trig functions
This commit is contained in:
Mark Baker 2022-02-12 17:21:57 +01:00 committed by GitHub
commit 866dd38611
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 135 additions and 11 deletions

View File

@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
### Added ### Added
- Improved support for passing of array arguments to Excel function implementations to return array results (where appropriate). [PR #2562](https://github.com/PHPOffice/PhpSpreadsheet/pull/2562) - Improved support for passing of array arguments to Excel function implementations to return array results (where appropriate). [Issue #2551](https://github.com/PHPOffice/PhpSpreadsheet/issues/2551)
This is the first stage in an ongoing process of adding array support to all appropriate function implementations, This is the first stage in an ongoing process of adding array support to all appropriate function implementations,
- Support for the Excel365 Math/Trig SEQUENCE() function [PR #2536](https://github.com/PHPOffice/PhpSpreadsheet/pull/2536) - Support for the Excel365 Math/Trig SEQUENCE() function [PR #2536](https://github.com/PHPOffice/PhpSpreadsheet/pull/2536)

View File

@ -455,7 +455,7 @@ class MathTrig
* @param int $a Dividend * @param int $a Dividend
* @param int $b Divisor * @param int $b Divisor
* *
* @return float|int|string Remainder, or a string containing an error * @return array|float|int|string Remainder, or a string containing an error
*/ */
public static function MOD($a = 1, $b = 1) public static function MOD($a = 1, $b = 1)
{ {
@ -533,7 +533,7 @@ class MathTrig
* @param float $x * @param float $x
* @param float $y * @param float $y
* *
* @return float|int|string The result, or a string containing an error * @return array|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)
{ {
@ -579,7 +579,7 @@ class MathTrig
* @param mixed $numerator * @param mixed $numerator
* @param mixed $denominator * @param mixed $denominator
* *
* @return int|string * @return array|int|string
*/ */
public static function QUOTIENT($numerator, $denominator) public static function QUOTIENT($numerator, $denominator)
{ {
@ -617,7 +617,7 @@ class MathTrig
* @param mixed $aValue Number to convert * @param mixed $aValue Number to convert
* @param mixed $style Number indicating one of five possible forms * @param mixed $style Number indicating one of five possible forms
* *
* @return string Roman numeral, or a string containing an error * @return array|string Roman numeral, or a string containing an error
*/ */
public static function ROMAN($aValue, $style = 0) public static function ROMAN($aValue, $style = 0)
{ {

View File

@ -2,21 +2,32 @@
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig; namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
use PhpOffice\PhpSpreadsheet\Calculation\Exception; use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Calculation\Functions;
class Operations class Operations
{ {
use ArrayEnabled;
/** /**
* MOD. * MOD.
* *
* @param mixed $dividend Dividend * @param mixed $dividend Dividend
* Or can be an array of values
* @param mixed $divisor Divisor * @param mixed $divisor Divisor
* Or can be an array of values
* *
* @return float|int|string Remainder, or a string containing an error * @return array|float|int|string Remainder, or a string containing an error
* If an array of numbers is passed as an argument, then the returned result will also be an array
* with the same dimensions
*/ */
public static function mod($dividend, $divisor) public static function mod($dividend, $divisor)
{ {
if (is_array($dividend) || is_array($divisor)) {
return self::evaluateArrayArguments([self::class, __FUNCTION__], $dividend, $divisor);
}
try { try {
$dividend = Helpers::validateNumericNullBool($dividend); $dividend = Helpers::validateNumericNullBool($dividend);
$divisor = Helpers::validateNumericNullBool($divisor); $divisor = Helpers::validateNumericNullBool($divisor);
@ -40,13 +51,21 @@ class Operations
* *
* Computes x raised to the power y. * Computes x raised to the power y.
* *
* @param float|int $x * @param array|float|int $x
* @param float|int $y * Or can be an array of values
* @param array|float|int $y
* Or can be an array of values
* *
* @return float|int|string The result, or a string containing an error * @return array|float|int|string The result, or a string containing an error
* If an array of numbers is passed as an argument, then the returned result will also be an array
* with the same dimensions
*/ */
public static function power($x, $y) public static function power($x, $y)
{ {
if (is_array($x) || is_array($y)) {
return self::evaluateArrayArguments([self::class, __FUNCTION__], $x, $y);
}
try { try {
$x = Helpers::validateNumericNullBool($x); $x = Helpers::validateNumericNullBool($x);
$y = Helpers::validateNumericNullBool($y); $y = Helpers::validateNumericNullBool($y);
@ -117,12 +136,20 @@ class Operations
* QUOTIENT(value1,value2) * QUOTIENT(value1,value2)
* *
* @param mixed $numerator Expect float|int * @param mixed $numerator Expect float|int
* Or can be an array of values
* @param mixed $denominator Expect float|int * @param mixed $denominator Expect float|int
* Or can be an array of values
* *
* @return int|string * @return array|int|string
* If an array of numbers is passed as an argument, then the returned result will also be an array
* with the same dimensions
*/ */
public static function quotient($numerator, $denominator) public static function quotient($numerator, $denominator)
{ {
if (is_array($numerator) || is_array($denominator)) {
return self::evaluateArrayArguments([self::class, __FUNCTION__], $numerator, $denominator);
}
try { try {
$numerator = Helpers::validateNumericNullSubstitution($numerator, 0); $numerator = Helpers::validateNumericNullSubstitution($numerator, 0);
$denominator = Helpers::validateNumericNullSubstitution($denominator, 0); $denominator = Helpers::validateNumericNullSubstitution($denominator, 0);

View File

@ -2,11 +2,14 @@
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig; namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
use PhpOffice\PhpSpreadsheet\Calculation\Exception; use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Calculation\Functions;
class Roman class Roman
{ {
use ArrayEnabled;
private const VALUES = [ private const VALUES = [
45 => ['VL'], 45 => ['VL'],
46 => ['VLI'], 46 => ['VLI'],
@ -814,12 +817,20 @@ class Roman
* Converts a number to Roman numeral * Converts a number to Roman numeral
* *
* @param mixed $aValue Number to convert * @param mixed $aValue Number to convert
* Or can be an array of numbers
* @param mixed $style Number indicating one of five possible forms * @param mixed $style Number indicating one of five possible forms
* Or can be an array of styles
* *
* @return string Roman numeral, or a string containing an error * @return array|string Roman numeral, or a string containing an error
* If an array of numbers is passed as an argument, then the returned result will also be an array
* with the same dimensions
*/ */
public static function evaluate($aValue, $style = 0) public static function evaluate($aValue, $style = 0)
{ {
if (is_array($aValue) || is_array($style)) {
return self::evaluateArrayArguments([self::class, __FUNCTION__], $aValue, $style);
}
try { try {
$aValue = Helpers::validateNumericNullBool($aValue); $aValue = Helpers::validateNumericNullBool($aValue);
if (is_bool($style)) { if (is_bool($style)) {

View File

@ -2,6 +2,8 @@
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig; namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
class ModTest extends AllSetupTeardown class ModTest extends AllSetupTeardown
{ {
/** /**
@ -36,4 +38,23 @@ class ModTest extends AllSetupTeardown
{ {
return require 'tests/data/Calculation/MathTrig/MOD.php'; return require 'tests/data/Calculation/MathTrig/MOD.php';
} }
/**
* @dataProvider providerModArray
*/
public function testModArray(array $expectedResult, string $argument1, string $argument2): void
{
$calculation = Calculation::getInstance();
$formula = "=MOD({$argument1}, {$argument2})";
$result = $calculation->_calculateFormulaValue($formula);
self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14);
}
public function providerModArray(): array
{
return [
'matrix' => [[[4, 3, 2], [1, 0, 4], [3, 2, 1]], '{9, 8, 7; 6, 5, 4; 3, 2, 1}', '5'],
];
}
} }

View File

@ -2,6 +2,8 @@
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig; namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
class PowerTest extends AllSetupTeardown class PowerTest extends AllSetupTeardown
{ {
/** /**
@ -36,4 +38,23 @@ class PowerTest extends AllSetupTeardown
{ {
return require 'tests/data/Calculation/MathTrig/POWER.php'; return require 'tests/data/Calculation/MathTrig/POWER.php';
} }
/**
* @dataProvider providerPowerArray
*/
public function testPowerArray(array $expectedResult, string $argument1, string $argument2): void
{
$calculation = Calculation::getInstance();
$formula = "=POWER({$argument1}, {$argument2})";
$result = $calculation->_calculateFormulaValue($formula);
self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14);
}
public function providerPowerArray(): array
{
return [
'matrix' => [[[729, 512, 343], [216, 125, 64], [27, 8, 1]], '{9, 8, 7; 6, 5, 4; 3, 2, 1}', '3'],
];
}
} }

View File

@ -2,6 +2,8 @@
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig; namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
class QuotientTest extends AllSetupTeardown class QuotientTest extends AllSetupTeardown
{ {
/** /**
@ -36,4 +38,23 @@ class QuotientTest extends AllSetupTeardown
{ {
return require 'tests/data/Calculation/MathTrig/QUOTIENT.php'; return require 'tests/data/Calculation/MathTrig/QUOTIENT.php';
} }
/**
* @dataProvider providerQuotientArray
*/
public function testQuotientArray(array $expectedResult, string $argument1, string $argument2): void
{
$calculation = Calculation::getInstance();
$formula = "=QUOTIENT({$argument1}, {$argument2})";
$result = $calculation->_calculateFormulaValue($formula);
self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14);
}
public function providerQuotientArray(): array
{
return [
'matrix' => [[[3, 3, 2], [2, 2, 1], [1, 0, 0]], '{9, 8, 7; 6, 5, 4; 3, 2, 1}', '2.5'],
];
}
} }

View File

@ -2,6 +2,8 @@
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig; namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
class RomanTest extends AllSetupTeardown class RomanTest extends AllSetupTeardown
{ {
/** /**
@ -24,4 +26,25 @@ class RomanTest extends AllSetupTeardown
{ {
return require 'tests/data/Calculation/MathTrig/ROMAN.php'; return require 'tests/data/Calculation/MathTrig/ROMAN.php';
} }
/**
* @dataProvider providerRomanArray
*/
public function testRomanArray(array $expectedResult, string $values, string $styles): void
{
$calculation = Calculation::getInstance();
$formula = "=ROMAN({$values}, {$styles})";
$result = $calculation->_calculateFormulaValue($formula);
self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14);
}
public function providerRomanArray(): array
{
return [
'row vector' => [[['XLIX', 'MMXXII', 'CDXCIX']], '{49, 2022, 499}', '0'],
'column vector' => [[['XLIX'], ['MMXXII'], ['CDXCIX']], '{49; 2022; 499}', '0'],
'matrix' => [[['XLIX', 'MMXXII'], ['LXIV', 'CDXCIX']], '{49, 2022; 64, 499}', '0'],
];
}
} }