Add new Complex Number Functions introduced in MS Excel 2013 (#601)

* - Refactored Complex Engineering Functions to use external complex number library
- Added calculation engine support for the new complex number functions that were added in MS Excel 2013
    - IMCOSH()  Returns the hyperbolic cosine of a complex number
    - IMCOT()   Returns the cotangent of a complex number
    - IMCSC()   Returns the cosecant of a complex number
    - IMCSCH()  Returns the hyperbolic cosecant of a complex number
    - IMSEC()   Returns the secant of a complex number
    - IMSECH()  Returns the hyperbolic secant of a complex number
    - IMSINH()  Returns the hyperbolic sine of a complex number
    - IMTAN()   Returns the tangent of a complex number
* Simplified the parseComplex() method in the PhpOffice\PhpSpreadsheet\Calculation\Engineering class, using Complex\Complex; and docblock flagged as deprecated
This commit is contained in:
Mark Baker 2018-07-25 14:38:44 +01:00 committed by GitHub
parent 57a0297011
commit 1b96c95a44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 1598 additions and 522 deletions

View File

@ -13,11 +13,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Support workbook view attributes for Xlsx format - [#523](https://github.com/PHPOffice/PhpSpreadsheet/issues/523)
- Read and write hyperlink for drawing image - [#490](https://github.com/PHPOffice/PhpSpreadsheet/pull/490)
- Added calculation engine support for the new bitwise functions that were added in MS Excel 2013
- BITAND() Returns a Bitwise 'And' of two numbers
- BITOR() Returns a Bitwise 'Or' of two number
- BITXOR() Returns a Bitwise 'Exclusive Or' of two numbers
- BITLSHIFT() Returns a number shifted left by a specified number of bits
- BITRSHIFT() Returns a number shifted right by a specified number of bits
- BITAND() Returns a Bitwise 'And' of two numbers
- BITOR() Returns a Bitwise 'Or' of two number
- BITXOR() Returns a Bitwise 'Exclusive Or' of two numbers
- BITLSHIFT() Returns a number shifted left by a specified number of bits
- BITRSHIFT() Returns a number shifted right by a specified number of bits
- Added calculation engine support for other new functions that were added in MS Excel 2013 and MS Excel 2016
- Text Functions
- CONCAT() Synonym for CONCATENATE()
@ -46,6 +46,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- COTH() Returns the hyperbolic cotangent of an angle
- ACOT() Returns the cotangent of an angle
- ACOTH() Returns the hyperbolic cotangent of an angle
- Refactored Complex Engineering Functions to use external complex number library
- Added calculation engine support for the new complex number functions that were added in MS Excel 2013
- IMCOSH() Returns the hyperbolic cosine of a complex number
- IMCOT() Returns the cotangent of a complex number
- IMCSC() Returns the cosecant of a complex number
- IMCSCH() Returns the hyperbolic cosecant of a complex number
- IMSEC() Returns the secant of a complex number
- IMSECH() Returns the hyperbolic secant of a complex number
- IMSINH() Returns the hyperbolic sine of a complex number
- IMTAN() Returns the tangent of a complex number
### Fixed

View File

@ -46,7 +46,8 @@
"ext-xmlwriter": "*",
"ext-zip": "*",
"ext-zlib": "*",
"psr/simple-cache": "^1.0"
"psr/simple-cache": "^1.0",
"markbaker/complex": "^1.4.1"
},
"require-dev": {
"tecnickcom/tcpdf": "^6.2",

97
composer.lock generated
View File

@ -4,8 +4,103 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "e61a906bd83393400add286703f10557",
"content-hash": "1aba55e3ac36d8d5015f9b3193f93c23",
"packages": [
{
"name": "markbaker/complex",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/MarkBaker/PHPComplex.git",
"reference": "615f5443473cf37729666e2354fd8dfa2cb48e91"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/615f5443473cf37729666e2354fd8dfa2cb48e91",
"reference": "615f5443473cf37729666e2354fd8dfa2cb48e91",
"shasum": ""
},
"require": {
"php": "^5.6.0|^7.0.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.4.3",
"phpdocumentor/phpdocumentor": "2.*",
"phploc/phploc": "2.*",
"phpmd/phpmd": "2.*",
"phpunit/phpunit": "^4.8.35|^5.4.0",
"sebastian/phpcpd": "2.*",
"squizlabs/php_codesniffer": "^3.1.1",
"wimg/php-compatibility": "^8.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Complex\\": "classes/src/"
},
"files": [
"classes/src/functions/abs.php",
"classes/src/functions/acos.php",
"classes/src/functions/acosh.php",
"classes/src/functions/acot.php",
"classes/src/functions/acoth.php",
"classes/src/functions/acsc.php",
"classes/src/functions/acsch.php",
"classes/src/functions/argument.php",
"classes/src/functions/asec.php",
"classes/src/functions/asech.php",
"classes/src/functions/asin.php",
"classes/src/functions/asinh.php",
"classes/src/functions/atan.php",
"classes/src/functions/atanh.php",
"classes/src/functions/conjugate.php",
"classes/src/functions/cos.php",
"classes/src/functions/cosh.php",
"classes/src/functions/cot.php",
"classes/src/functions/coth.php",
"classes/src/functions/csc.php",
"classes/src/functions/csch.php",
"classes/src/functions/exp.php",
"classes/src/functions/inverse.php",
"classes/src/functions/ln.php",
"classes/src/functions/log2.php",
"classes/src/functions/log10.php",
"classes/src/functions/negative.php",
"classes/src/functions/pow.php",
"classes/src/functions/rho.php",
"classes/src/functions/sec.php",
"classes/src/functions/sech.php",
"classes/src/functions/sin.php",
"classes/src/functions/sinh.php",
"classes/src/functions/sqrt.php",
"classes/src/functions/tan.php",
"classes/src/functions/tanh.php",
"classes/src/functions/theta.php",
"classes/src/operations/add.php",
"classes/src/operations/subtract.php",
"classes/src/operations/multiply.php",
"classes/src/operations/divideby.php",
"classes/src/operations/divideinto.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Baker",
"email": "mark@lange.demon.co.uk"
}
],
"description": "PHP Class for working with complex numbers",
"homepage": "https://github.com/MarkBaker/PHPComplex",
"keywords": [
"complex",
"mathematics"
],
"time": "2018-07-24T19:47:28+00:00"
},
{
"name": "psr/simple-cache",
"version": "1.0.0",

View File

@ -86,6 +86,10 @@ IMAGINARY | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMAGINA
IMARGUMENT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMARGUMENT
IMCONJUGATE | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCONJUGATE
IMCOS | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCOS
IMCOSH | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCOSH
IMCOT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCOT
IMCSC | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCSC
IMCSCH | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCSCH
IMDIV | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMDIV
IMEXP | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMEXP
IMLN | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMLN
@ -94,10 +98,14 @@ IMLOG2 | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMLOG2
IMPOWER | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMPOWER
IMPRODUCT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMPRODUCT
IMREAL | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMREAL
IMSEC | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSEC
IMSECH | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSECH
IMSIN | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSIN
IMSINH | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSINH
IMSQRT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSQRT
IMSUB | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSUB
IMSUM | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSUM
IMTAN | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMTAN
OCT2BIN | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::OCTTOBIN
OCT2DEC | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::OCTTODEC
OCT2HEX | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::OCTTOHEX

View File

@ -206,6 +206,10 @@ IMAGINARY | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet
IMARGUMENT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMARGUMENT
IMCONJUGATE | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCONJUGATE
IMCOS | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCOS
IMCOSH | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCOSH
IMCOT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCOT
IMCSC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCSC
IMCSCH | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCSCH
IMDIV | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMDIV
IMEXP | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMEXP
IMLN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMLN
@ -214,10 +218,14 @@ IMLOG2 | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet
IMPOWER | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMPOWER
IMPRODUCT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMPRODUCT
IMREAL | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMREAL
IMSEC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSEC
IMSECH | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSECH
IMSIN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSIN
IMSINH | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSINH
IMSQRT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSQRT
IMSUB | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSUB
IMSUM | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSUM
IMTAN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMTAN
INDEX | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::INDEX
INDIRECT | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::INDIRECT
INFO | CATEGORY_INFORMATION | **Not yet Implemented**

View File

@ -1038,6 +1038,26 @@ class Calculation
'functionCall' => [Engineering::class, 'IMCOS'],
'argumentCount' => '1',
],
'IMCOSH' => [
'category' => Category::CATEGORY_ENGINEERING,
'functionCall' => [Engineering::class, 'IMCOSH'],
'argumentCount' => '1',
],
'IMCOT' => [
'category' => Category::CATEGORY_ENGINEERING,
'functionCall' => [Engineering::class, 'IMCOT'],
'argumentCount' => '1',
],
'IMCSC' => [
'category' => Category::CATEGORY_ENGINEERING,
'functionCall' => [Engineering::class, 'IMCSC'],
'argumentCount' => '1',
],
'IMCSCH' => [
'category' => Category::CATEGORY_ENGINEERING,
'functionCall' => [Engineering::class, 'IMCSCH'],
'argumentCount' => '1',
],
'IMDIV' => [
'category' => Category::CATEGORY_ENGINEERING,
'functionCall' => [Engineering::class, 'IMDIV'],
@ -1078,11 +1098,26 @@ class Calculation
'functionCall' => [Engineering::class, 'IMREAL'],
'argumentCount' => '1',
],
'IMSEC' => [
'category' => Category::CATEGORY_ENGINEERING,
'functionCall' => [Engineering::class, 'IMSEC'],
'argumentCount' => '1',
],
'IMSECH' => [
'category' => Category::CATEGORY_ENGINEERING,
'functionCall' => [Engineering::class, 'IMSECH'],
'argumentCount' => '1',
],
'IMSIN' => [
'category' => Category::CATEGORY_ENGINEERING,
'functionCall' => [Engineering::class, 'IMSIN'],
'argumentCount' => '1',
],
'IMSINH' => [
'category' => Category::CATEGORY_ENGINEERING,
'functionCall' => [Engineering::class, 'IMSINH'],
'argumentCount' => '1',
],
'IMSQRT' => [
'category' => Category::CATEGORY_ENGINEERING,
'functionCall' => [Engineering::class, 'IMSQRT'],
@ -1098,6 +1133,11 @@ class Calculation
'functionCall' => [Engineering::class, 'IMSUM'],
'argumentCount' => '1+',
],
'IMTAN' => [
'category' => Category::CATEGORY_ENGINEERING,
'functionCall' => [Engineering::class, 'IMTAN'],
'argumentCount' => '1',
],
'INDEX' => [
'category' => Category::CATEGORY_LOOKUP_AND_REFERENCE,
'functionCall' => [LookupRef::class, 'INDEX'],

View File

@ -2,6 +2,9 @@
namespace PhpOffice\PhpSpreadsheet\Calculation;
use Complex\Complex;
use Complex\Exception as ComplexException;
class Engineering
{
/**
@ -718,83 +721,23 @@ class Engineering
*
* Parses a complex number into its real and imaginary parts, and an I or J suffix
*
* @deprecated 2.0.0 No longer used by internal code. Please use the Complex\Complex class instead
*
* @param string $complexNumber The complex number
*
* @return string[] Indexed on "real", "imaginary" and "suffix"
* @return mixed[] Indexed on "real", "imaginary" and "suffix"
*/
public static function parseComplex($complexNumber)
{
$workString = (string) $complexNumber;
$realNumber = $imaginary = 0;
// Extract the suffix, if there is one
$suffix = substr($workString, -1);
if (!is_numeric($suffix)) {
$workString = substr($workString, 0, -1);
} else {
$suffix = '';
}
// Split the input into its Real and Imaginary components
$leadingSign = 0;
if (strlen($workString) > 0) {
$leadingSign = (($workString[0] == '+') || ($workString[0] == '-')) ? 1 : 0;
}
$power = '';
$realNumber = strtok($workString, '+-');
if (strtoupper(substr($realNumber, -1)) == 'E') {
$power = strtok('+-');
++$leadingSign;
}
$realNumber = substr($workString, 0, strlen($realNumber) + strlen($power) + $leadingSign);
if ($suffix != '') {
$imaginary = substr($workString, strlen($realNumber));
if (($imaginary == '') && (($realNumber == '') || ($realNumber == '+') || ($realNumber == '-'))) {
$imaginary = $realNumber . '1';
$realNumber = '0';
} elseif ($imaginary == '') {
$imaginary = $realNumber;
$realNumber = '0';
} elseif (($imaginary == '+') || ($imaginary == '-')) {
$imaginary .= '1';
}
}
$complex = new Complex($complexNumber);
return [
'real' => $realNumber,
'imaginary' => $imaginary,
'suffix' => $suffix,
'real' => $complex->getReal(),
'imaginary' => $complex->getImaginary(),
'suffix' => $complex->getSuffix(),
];
}
/**
* Cleans the leading characters in a complex number string.
*
* @param string $complexNumber The complex number to clean
*
* @return string The "cleaned" complex number
*/
private static function cleanComplex($complexNumber)
{
if ($complexNumber[0] == '+') {
$complexNumber = substr($complexNumber, 1);
}
if ($complexNumber[0] == '0') {
$complexNumber = substr($complexNumber, 1);
}
if ($complexNumber[0] == '.') {
$complexNumber = '0' . $complexNumber;
}
if ($complexNumber[0] == '+') {
$complexNumber = substr($complexNumber, 1);
}
return $complexNumber;
}
/**
* Formats a number base string value with leading zeroes.
*
@ -1745,10 +1688,10 @@ class Engineering
/**
* COMPLEX.
*
* Converts real and imaginary coefficients into a complex number of the form x + yi or x + yj.
* Converts real and imaginary coefficients into a complex number of the form x +/- yi or x +/- yj.
*
* Excel Function:
* COMPLEX(realNumber,imaginary[,places])
* COMPLEX(realNumber,imaginary[,suffix])
*
* @category Engineering Functions
*
@ -1768,34 +1711,9 @@ class Engineering
if (((is_numeric($realNumber)) && (is_numeric($imaginary))) &&
(($suffix == 'i') || ($suffix == 'j') || ($suffix == ''))
) {
$realNumber = (float) $realNumber;
$imaginary = (float) $imaginary;
$complex = new Complex($realNumber, $imaginary, $suffix);
if ($suffix == '') {
$suffix = 'i';
}
if ($realNumber == 0.0) {
if ($imaginary == 0.0) {
return (string) '0';
} elseif ($imaginary == 1.0) {
return (string) $suffix;
} elseif ($imaginary == -1.0) {
return (string) '-' . $suffix;
}
return (string) $imaginary . $suffix;
} elseif ($imaginary == 0.0) {
return (string) $realNumber;
} elseif ($imaginary == 1.0) {
return (string) $realNumber . '+' . $suffix;
} elseif ($imaginary == -1.0) {
return (string) $realNumber . '-' . $suffix;
}
if ($imaginary > 0) {
$imaginary = (string) '+' . $imaginary;
}
return (string) $realNumber . $imaginary . $suffix;
return (string) $complex;
}
return Functions::VALUE();
@ -1820,9 +1738,7 @@ class Engineering
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
$parsedComplex = self::parseComplex($complexNumber);
return $parsedComplex['imaginary'];
return (new Complex($complexNumber))->getImaginary();
}
/**
@ -1843,9 +1759,7 @@ class Engineering
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
$parsedComplex = self::parseComplex($complexNumber);
return $parsedComplex['real'];
return (new Complex($complexNumber))->getReal();
}
/**
@ -1864,12 +1778,7 @@ class Engineering
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
$parsedComplex = self::parseComplex($complexNumber);
return sqrt(
($parsedComplex['real'] * $parsedComplex['real']) +
($parsedComplex['imaginary'] * $parsedComplex['imaginary'])
);
return (new Complex($complexNumber))->abs();
}
/**
@ -1883,27 +1792,18 @@ class Engineering
*
* @param string $complexNumber the complex number for which you want the argument theta
*
* @return float
* @return float|string
*/
public static function IMARGUMENT($complexNumber)
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
$parsedComplex = self::parseComplex($complexNumber);
if ($parsedComplex['real'] == 0.0) {
if ($parsedComplex['imaginary'] == 0.0) {
return Functions::DIV0();
} elseif ($parsedComplex['imaginary'] < 0.0) {
return M_PI / -2;
}
return M_PI / 2;
} elseif ($parsedComplex['real'] > 0.0) {
return atan($parsedComplex['imaginary'] / $parsedComplex['real']);
} elseif ($parsedComplex['imaginary'] < 0.0) {
return 0 - (M_PI - atan(abs($parsedComplex['imaginary']) / abs($parsedComplex['real'])));
$complex = new Complex($complexNumber);
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
return Functions::DIV0();
}
return M_PI - atan($parsedComplex['imaginary'] / abs($parsedComplex['real']));
return $complex->argument();
}
/**
@ -1922,19 +1822,7 @@ class Engineering
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
$parsedComplex = self::parseComplex($complexNumber);
if ($parsedComplex['imaginary'] == 0.0) {
return $parsedComplex['real'];
}
return self::cleanComplex(
self::COMPLEX(
$parsedComplex['real'],
0 - $parsedComplex['imaginary'],
$parsedComplex['suffix']
)
);
return (string) (new Complex($complexNumber))->conjugate();
}
/**
@ -1953,19 +1841,83 @@ class Engineering
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
$parsedComplex = self::parseComplex($complexNumber);
return (string) (new Complex($complexNumber))->cos();
}
if ($parsedComplex['imaginary'] == 0.0) {
return cos($parsedComplex['real']);
}
/**
* IMCOSH.
*
* Returns the hyperbolic cosine of a complex number in x + yi or x + yj text format.
*
* Excel Function:
* IMCOSH(complexNumber)
*
* @param string $complexNumber the complex number for which you want the hyperbolic cosine
*
* @return float|string
*/
public static function IMCOSH($complexNumber)
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
return self::IMCONJUGATE(
self::COMPLEX(
cos($parsedComplex['real']) * cosh($parsedComplex['imaginary']),
sin($parsedComplex['real']) * sinh($parsedComplex['imaginary']),
$parsedComplex['suffix']
)
);
return (string) (new Complex($complexNumber))->cosh();
}
/**
* IMCOT.
*
* Returns the cotangent of a complex number in x + yi or x + yj text format.
*
* Excel Function:
* IMCOT(complexNumber)
*
* @param string $complexNumber the complex number for which you want the cotangent
*
* @return float|string
*/
public static function IMCOT($complexNumber)
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
return (string) (new Complex($complexNumber))->cot();
}
/**
* IMCSC.
*
* Returns the cosecant of a complex number in x + yi or x + yj text format.
*
* Excel Function:
* IMCSC(complexNumber)
*
* @param string $complexNumber the complex number for which you want the cosecant
*
* @return float|string
*/
public static function IMCSC($complexNumber)
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
return (string) (new Complex($complexNumber))->csc();
}
/**
* IMCSCH.
*
* Returns the hyperbolic cosecant of a complex number in x + yi or x + yj text format.
*
* Excel Function:
* IMCSCH(complexNumber)
*
* @param string $complexNumber the complex number for which you want the hyperbolic cosecant
*
* @return float|string
*/
public static function IMCSCH($complexNumber)
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
return (string) (new Complex($complexNumber))->csch();
}
/**
@ -1984,17 +1936,83 @@ class Engineering
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
$parsedComplex = self::parseComplex($complexNumber);
return (string) (new Complex($complexNumber))->sin();
}
if ($parsedComplex['imaginary'] == 0.0) {
return sin($parsedComplex['real']);
}
/**
* IMSINH.
*
* Returns the hyperbolic sine of a complex number in x + yi or x + yj text format.
*
* Excel Function:
* IMSINH(complexNumber)
*
* @param string $complexNumber the complex number for which you want the hyperbolic sine
*
* @return float|string
*/
public static function IMSINH($complexNumber)
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
return self::COMPLEX(
sin($parsedComplex['real']) * cosh($parsedComplex['imaginary']),
cos($parsedComplex['real']) * sinh($parsedComplex['imaginary']),
$parsedComplex['suffix']
);
return (string) (new Complex($complexNumber))->sinh();
}
/**
* IMSEC.
*
* Returns the secant of a complex number in x + yi or x + yj text format.
*
* Excel Function:
* IMSEC(complexNumber)
*
* @param string $complexNumber the complex number for which you want the secant
*
* @return float|string
*/
public static function IMSEC($complexNumber)
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
return (string) (new Complex($complexNumber))->sec();
}
/**
* IMSECH.
*
* Returns the hyperbolic secant of a complex number in x + yi or x + yj text format.
*
* Excel Function:
* IMSECH(complexNumber)
*
* @param string $complexNumber the complex number for which you want the hyperbolic secant
*
* @return float|string
*/
public static function IMSECH($complexNumber)
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
return (string) (new Complex($complexNumber))->sech();
}
/**
* IMTAN.
*
* Returns the tangent of a complex number in x + yi or x + yj text format.
*
* Excel Function:
* IMTAN(complexNumber)
*
* @param string $complexNumber the complex number for which you want the tangent
*
* @return float|string
*/
public static function IMTAN($complexNumber)
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
return (string) (new Complex($complexNumber))->tan();
}
/**
@ -2013,22 +2031,12 @@ class Engineering
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
$parsedComplex = self::parseComplex($complexNumber);
$theta = self::IMARGUMENT($complexNumber);
if ($theta === Functions::DIV0()) {
return '0';
}
$d1 = cos($theta / 2);
$d2 = sin($theta / 2);
$r = sqrt(sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])));
if ($parsedComplex['suffix'] == '') {
return self::COMPLEX($d1 * $r, $d2 * $r);
}
return self::COMPLEX($d1 * $r, $d2 * $r, $parsedComplex['suffix']);
return (string) (new Complex($complexNumber))->sqrt();
}
/**
@ -2047,20 +2055,12 @@ class Engineering
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
$parsedComplex = self::parseComplex($complexNumber);
if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
$complex = new Complex($complexNumber);
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
return Functions::NAN();
}
$logR = log(sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])));
$t = self::IMARGUMENT($complexNumber);
if ($parsedComplex['suffix'] == '') {
return self::COMPLEX($logR, $t);
}
return self::COMPLEX($logR, $t, $parsedComplex['suffix']);
return (string) (new Complex($complexNumber))->ln();
}
/**
@ -2079,15 +2079,12 @@ class Engineering
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
$parsedComplex = self::parseComplex($complexNumber);
if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
$complex = new Complex($complexNumber);
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
return Functions::NAN();
} elseif (($parsedComplex['real'] > 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
return log10($parsedComplex['real']);
}
return self::IMPRODUCT(log10(self::EULER), self::IMLN($complexNumber));
return (string) (new Complex($complexNumber))->log10();
}
/**
@ -2106,15 +2103,12 @@ class Engineering
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
$parsedComplex = self::parseComplex($complexNumber);
if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
$complex = new Complex($complexNumber);
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
return Functions::NAN();
} elseif (($parsedComplex['real'] > 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
return log($parsedComplex['real'], 2);
}
return self::IMPRODUCT(log(self::EULER, 2), self::IMLN($complexNumber));
return (string) (new Complex($complexNumber))->log2();
}
/**
@ -2133,21 +2127,7 @@ class Engineering
{
$complexNumber = Functions::flattenSingleValue($complexNumber);
$parsedComplex = self::parseComplex($complexNumber);
if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
return '1';
}
$e = exp($parsedComplex['real']);
$eX = $e * cos($parsedComplex['imaginary']);
$eY = $e * sin($parsedComplex['imaginary']);
if ($parsedComplex['suffix'] == '') {
return self::COMPLEX($eX, $eY);
}
return self::COMPLEX($eX, $eY, $parsedComplex['suffix']);
return (string) (new Complex($complexNumber))->exp();
}
/**
@ -2172,18 +2152,7 @@ class Engineering
return Functions::VALUE();
}
$parsedComplex = self::parseComplex($complexNumber);
$r = sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary']));
$rPower = pow($r, $realNumber);
$theta = self::IMARGUMENT($complexNumber) * $realNumber;
if ($theta == 0) {
return 1;
} elseif ($parsedComplex['imaginary'] == 0.0) {
return self::COMPLEX($rPower * cos($theta), $rPower * sin($theta), $parsedComplex['suffix']);
}
return self::COMPLEX($rPower * cos($theta), $rPower * sin($theta), $parsedComplex['suffix']);
return (string) (new Complex($complexNumber))->pow($realNumber);
}
/**
@ -2204,32 +2173,11 @@ class Engineering
$complexDividend = Functions::flattenSingleValue($complexDividend);
$complexDivisor = Functions::flattenSingleValue($complexDivisor);
$parsedComplexDividend = self::parseComplex($complexDividend);
$parsedComplexDivisor = self::parseComplex($complexDivisor);
if (($parsedComplexDividend['suffix'] != '') && ($parsedComplexDivisor['suffix'] != '') &&
($parsedComplexDividend['suffix'] != $parsedComplexDivisor['suffix'])
) {
try {
return (string) (new Complex($complexDividend))->divideby(new Complex($complexDivisor));
} catch (ComplexException $e) {
return Functions::NAN();
}
if (($parsedComplexDividend['suffix'] != '') && ($parsedComplexDivisor['suffix'] == '')) {
$parsedComplexDivisor['suffix'] = $parsedComplexDividend['suffix'];
}
$d1 = ($parsedComplexDividend['real'] * $parsedComplexDivisor['real']) + ($parsedComplexDividend['imaginary'] * $parsedComplexDivisor['imaginary']);
$d2 = ($parsedComplexDividend['imaginary'] * $parsedComplexDivisor['real']) - ($parsedComplexDividend['real'] * $parsedComplexDivisor['imaginary']);
$d3 = ($parsedComplexDivisor['real'] * $parsedComplexDivisor['real']) + ($parsedComplexDivisor['imaginary'] * $parsedComplexDivisor['imaginary']);
$r = $d1 / $d3;
$i = $d2 / $d3;
if ($i > 0.0) {
return self::cleanComplex($r . '+' . $i . $parsedComplexDivisor['suffix']);
} elseif ($i < 0.0) {
return self::cleanComplex($r . $i . $parsedComplexDivisor['suffix']);
}
return $r;
}
/**
@ -2250,21 +2198,11 @@ class Engineering
$complexNumber1 = Functions::flattenSingleValue($complexNumber1);
$complexNumber2 = Functions::flattenSingleValue($complexNumber2);
$parsedComplex1 = self::parseComplex($complexNumber1);
$parsedComplex2 = self::parseComplex($complexNumber2);
if ((($parsedComplex1['suffix'] != '') && ($parsedComplex2['suffix'] != '')) &&
($parsedComplex1['suffix'] != $parsedComplex2['suffix'])
) {
try {
return (string) (new Complex($complexNumber1))->subtract(new Complex($complexNumber2));
} catch (ComplexException $e) {
return Functions::NAN();
} elseif (($parsedComplex1['suffix'] == '') && ($parsedComplex2['suffix'] != '')) {
$parsedComplex1['suffix'] = $parsedComplex2['suffix'];
}
$d1 = $parsedComplex1['real'] - $parsedComplex2['real'];
$d2 = $parsedComplex1['imaginary'] - $parsedComplex2['imaginary'];
return self::COMPLEX($d1, $d2, $parsedComplex1['suffix']);
}
/**
@ -2282,29 +2220,19 @@ class Engineering
public static function IMSUM(...$complexNumbers)
{
// Return value
$returnValue = self::parseComplex('0');
$activeSuffix = '';
// Loop through the arguments
$returnValue = new Complex(0.0);
$aArgs = Functions::flattenArray($complexNumbers);
foreach ($aArgs as $arg) {
$parsedComplex = self::parseComplex($arg);
if ($activeSuffix == '') {
$activeSuffix = $parsedComplex['suffix'];
} elseif (($parsedComplex['suffix'] != '') && ($activeSuffix != $parsedComplex['suffix'])) {
return Functions::NAN();
try {
// Loop through the arguments
foreach ($aArgs as $complex) {
$returnValue = $returnValue->add(new Complex($complex));
}
$returnValue['real'] += $parsedComplex['real'];
$returnValue['imaginary'] += $parsedComplex['imaginary'];
} catch (ComplexException $e) {
return Functions::NAN();
}
if ($returnValue['imaginary'] == 0.0) {
$activeSuffix = '';
}
return self::COMPLEX($returnValue['real'], $returnValue['imaginary'], $activeSuffix);
return (string) $returnValue;
}
/**
@ -2322,29 +2250,19 @@ class Engineering
public static function IMPRODUCT(...$complexNumbers)
{
// Return value
$returnValue = self::parseComplex('1');
$activeSuffix = '';
// Loop through the arguments
$returnValue = new Complex(1.0);
$aArgs = Functions::flattenArray($complexNumbers);
foreach ($aArgs as $arg) {
$parsedComplex = self::parseComplex($arg);
$workValue = $returnValue;
if (($parsedComplex['suffix'] != '') && ($activeSuffix == '')) {
$activeSuffix = $parsedComplex['suffix'];
} elseif (($parsedComplex['suffix'] != '') && ($activeSuffix != $parsedComplex['suffix'])) {
return Functions::NAN();
try {
// Loop through the arguments
foreach ($aArgs as $complex) {
$returnValue = $returnValue->multiply(new Complex($complex));
}
$returnValue['real'] = ($workValue['real'] * $parsedComplex['real']) - ($workValue['imaginary'] * $parsedComplex['imaginary']);
$returnValue['imaginary'] = ($workValue['real'] * $parsedComplex['imaginary']) + ($workValue['imaginary'] * $parsedComplex['real']);
} catch (ComplexException $e) {
return Functions::NAN();
}
if ($returnValue['imaginary'] == 0.0) {
$activeSuffix = '';
}
return self::COMPLEX($returnValue['real'], $returnValue['imaginary'], $activeSuffix);
return (string) $returnValue;
}
/**

View File

@ -163,6 +163,10 @@ IMAGINARY
IMARGUMENT
IMCONJUGATE
IMCOS
IMCOSH
IMCOT
IMCSC
IMCSCH
IMEXP
IMLN
IMLOG10
@ -170,10 +174,14 @@ IMLOG2
IMPOWER
IMPRODUCT
IMREAL
IMSEC
IMSECH
IMSIN
IMSINH
IMSQRT
IMSUB
IMSUM
IMTAN
INDEX
INDIRECT
INFO

View File

@ -14,6 +14,10 @@ class EngineeringTest extends TestCase
*/
protected $complexAssert;
const BESSEL_PRECISION = 1E-8;
const COMPLEX_PRECISION = 1E-8;
const ERF_PRECISION = 1E-12;
public function setUp()
{
$this->complexAssert = new ComplexAssert();
@ -33,7 +37,7 @@ class EngineeringTest extends TestCase
public function testBESSELI($expectedResult, ...$args)
{
$result = Engineering::BESSELI(...$args);
self::assertEquals($expectedResult, $result, null, 1E-8);
self::assertEquals($expectedResult, $result, null, self::BESSEL_PRECISION);
}
public function providerBESSELI()
@ -49,7 +53,7 @@ class EngineeringTest extends TestCase
public function testBESSELJ($expectedResult, ...$args)
{
$result = Engineering::BESSELJ(...$args);
self::assertEquals($expectedResult, $result, null, 1E-8);
self::assertEquals($expectedResult, $result, null, self::BESSEL_PRECISION);
}
public function providerBESSELJ()
@ -65,7 +69,7 @@ class EngineeringTest extends TestCase
public function testBESSELK($expectedResult, ...$args)
{
$result = Engineering::BESSELK(...$args);
self::assertEquals($expectedResult, $result, null, 1E-8);
self::assertEquals($expectedResult, $result, null, self::BESSEL_PRECISION);
}
public function providerBESSELK()
@ -81,7 +85,7 @@ class EngineeringTest extends TestCase
public function testBESSELY($expectedResult, ...$args)
{
$result = Engineering::BESSELY(...$args);
self::assertEquals($expectedResult, $result, null, 1E-8);
self::assertEquals($expectedResult, $result, null, self::BESSEL_PRECISION);
}
public function providerBESSELY()
@ -89,6 +93,24 @@ class EngineeringTest extends TestCase
return require 'data/Calculation/Engineering/BESSELY.php';
}
/**
* @dataProvider providerCOMPLEX
*
* @param mixed $expectedResult
*/
public function testParseComplex()
{
list($real, $imaginary, $suffix) = [1.23e-4, 5.67e+8, 'j'];
$result = Engineering::parseComplex('1.23e-4+5.67e+8j');
$this->assertArrayHasKey('real', $result);
$this->assertEquals($real, $result['real']);
$this->assertArrayHasKey('imaginary', $result);
$this->assertEquals($imaginary, $result['imaginary']);
$this->assertArrayHasKey('suffix', $result);
$this->assertEquals($suffix, $result['suffix']);
}
/**
* @dataProvider providerCOMPLEX
*
@ -109,11 +131,12 @@ class EngineeringTest extends TestCase
* @dataProvider providerIMAGINARY
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMAGINARY($expectedResult, ...$args)
public function testIMAGINARY($expectedResult, $value)
{
$result = Engineering::IMAGINARY(...$args);
self::assertEquals($expectedResult, $result, null, 1E-8);
$result = Engineering::IMAGINARY($value);
self::assertEquals($expectedResult, $result, null, self::COMPLEX_PRECISION);
}
public function providerIMAGINARY()
@ -125,11 +148,12 @@ class EngineeringTest extends TestCase
* @dataProvider providerIMREAL
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMREAL($expectedResult, ...$args)
public function testIMREAL($expectedResult, $value)
{
$result = Engineering::IMREAL(...$args);
self::assertEquals($expectedResult, $result, null, 1E-8);
$result = Engineering::IMREAL($value);
self::assertEquals($expectedResult, $result, null, self::COMPLEX_PRECISION);
}
public function providerIMREAL()
@ -141,11 +165,12 @@ class EngineeringTest extends TestCase
* @dataProvider providerIMABS
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMABS($expectedResult, ...$args)
public function testIMABS($expectedResult, $value)
{
$result = Engineering::IMABS(...$args);
self::assertEquals($expectedResult, $result, null, 1E-8);
$result = Engineering::IMABS($value);
self::assertEquals($expectedResult, $result, null, self::COMPLEX_PRECISION);
}
public function providerIMABS()
@ -157,11 +182,12 @@ class EngineeringTest extends TestCase
* @dataProvider providerIMARGUMENT
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMARGUMENT($expectedResult, ...$args)
public function testIMARGUMENT($expectedResult, $value)
{
$result = Engineering::IMARGUMENT(...$args);
self::assertEquals($expectedResult, $result, null, 1E-8);
$result = Engineering::IMARGUMENT($value);
self::assertEquals($expectedResult, $result, null, self::COMPLEX_PRECISION);
}
public function providerIMARGUMENT()
@ -173,11 +199,15 @@ class EngineeringTest extends TestCase
* @dataProvider providerIMCONJUGATE
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMCONJUGATE($expectedResult, ...$args)
public function testIMCONJUGATE($expectedResult, $value)
{
$result = Engineering::IMCONJUGATE(...$args);
self::assertTrue($this->complexAssert->assertComplexEquals($expectedResult, $result, 1E-8), $this->complexAssert->getErrorMessage());
$result = Engineering::IMCONJUGATE($value);
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMCONJUGATE()
@ -189,11 +219,15 @@ class EngineeringTest extends TestCase
* @dataProvider providerIMCOS
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMCOS($expectedResult, ...$args)
public function testIMCOS($expectedResult, $value)
{
$result = Engineering::IMCOS(...$args);
self::assertTrue($this->complexAssert->assertComplexEquals($expectedResult, $result, 1E-8), $this->complexAssert->getErrorMessage());
$result = Engineering::IMCOS($value);
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMCOS()
@ -201,6 +235,126 @@ class EngineeringTest extends TestCase
return require 'data/Calculation/Engineering/IMCOS.php';
}
/**
* @dataProvider providerIMCOSH
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMCOSH($expectedResult, $value)
{
$result = Engineering::IMCOSH($value);
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMCOSH()
{
return require 'data/Calculation/Engineering/IMCOSH.php';
}
/**
* @dataProvider providerIMCOT
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMCOT($expectedResult, $value)
{
$result = Engineering::IMCOT($value);
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMCOT()
{
return require 'data/Calculation/Engineering/IMCOT.php';
}
/**
* @dataProvider providerIMCSC
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMCSC($expectedResult, $value)
{
$result = Engineering::IMCSC($value);
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMCSC()
{
return require 'data/Calculation/Engineering/IMCSC.php';
}
/**
* @dataProvider providerIMCSCH
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMCSCH($expectedResult, $value)
{
$result = Engineering::IMCSCH($value);
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMCSCH()
{
return require 'data/Calculation/Engineering/IMCSCH.php';
}
/**
* @dataProvider providerIMSEC
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMSEC($expectedResult, $value)
{
$result = Engineering::IMSEC($value);
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMSEC()
{
return require 'data/Calculation/Engineering/IMSEC.php';
}
/**
* @dataProvider providerIMSECH
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMSECH($expectedResult, $value)
{
$result = Engineering::IMSECH($value);
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMSECH()
{
return require 'data/Calculation/Engineering/IMSECH.php';
}
/**
* @dataProvider providerIMDIV
*
@ -208,10 +362,11 @@ class EngineeringTest extends TestCase
*/
public function testIMDIV($expectedResult, ...$args)
{
$this->markTestIncomplete('TODO: This test should be fixed');
$result = Engineering::IMDIV(...$args);
self::assertTrue($this->complexAssert->assertComplexEquals($expectedResult, $result, 1E-8), $this->complexAssert->getErrorMessage());
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMDIV()
@ -223,11 +378,15 @@ class EngineeringTest extends TestCase
* @dataProvider providerIMEXP
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMEXP($expectedResult, ...$args)
public function testIMEXP($expectedResult, $value)
{
$result = Engineering::IMEXP(...$args);
self::assertTrue($this->complexAssert->assertComplexEquals($expectedResult, $result, 1E-8), $this->complexAssert->getErrorMessage());
$result = Engineering::IMEXP($value);
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMEXP()
@ -239,11 +398,15 @@ class EngineeringTest extends TestCase
* @dataProvider providerIMLN
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMLN($expectedResult, ...$args)
public function testIMLN($expectedResult, $value)
{
$result = Engineering::IMLN(...$args);
self::assertTrue($this->complexAssert->assertComplexEquals($expectedResult, $result, 1E-8), $this->complexAssert->getErrorMessage());
$result = Engineering::IMLN($value);
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMLN()
@ -255,11 +418,15 @@ class EngineeringTest extends TestCase
* @dataProvider providerIMLOG2
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMLOG2($expectedResult, ...$args)
public function testIMLOG2($expectedResult, $value)
{
$result = Engineering::IMLOG2(...$args);
self::assertTrue($this->complexAssert->assertComplexEquals($expectedResult, $result, 1E-8), $this->complexAssert->getErrorMessage());
$result = Engineering::IMLOG2($value);
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMLOG2()
@ -271,11 +438,15 @@ class EngineeringTest extends TestCase
* @dataProvider providerIMLOG10
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMLOG10($expectedResult, ...$args)
public function testIMLOG10($expectedResult, $value)
{
$result = Engineering::IMLOG10(...$args);
self::assertTrue($this->complexAssert->assertComplexEquals($expectedResult, $result, 1E-8), $this->complexAssert->getErrorMessage());
$result = Engineering::IMLOG10($value);
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMLOG10()
@ -290,10 +461,11 @@ class EngineeringTest extends TestCase
*/
public function testIMPOWER($expectedResult, ...$args)
{
$this->markTestIncomplete('TODO: This test should be fixed');
$result = Engineering::IMPOWER(...$args);
self::assertTrue($this->complexAssert->assertComplexEquals($expectedResult, $result, 1E-8), $this->complexAssert->getErrorMessage());
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMPOWER()
@ -309,7 +481,10 @@ class EngineeringTest extends TestCase
public function testIMPRODUCT($expectedResult, ...$args)
{
$result = Engineering::IMPRODUCT(...$args);
self::assertTrue($this->complexAssert->assertComplexEquals($expectedResult, $result, 1E-8), $this->complexAssert->getErrorMessage());
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMPRODUCT()
@ -321,11 +496,15 @@ class EngineeringTest extends TestCase
* @dataProvider providerIMSIN
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMSIN($expectedResult, ...$args)
public function testIMSIN($expectedResult, $value)
{
$result = Engineering::IMSIN(...$args);
self::assertTrue($this->complexAssert->assertComplexEquals($expectedResult, $result, 1E-8), $this->complexAssert->getErrorMessage());
$result = Engineering::IMSIN($value);
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMSIN()
@ -333,15 +512,59 @@ class EngineeringTest extends TestCase
return require 'data/Calculation/Engineering/IMSIN.php';
}
/**
* @dataProvider providerIMSINH
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMSINH($expectedResult, $value)
{
$result = Engineering::IMSINH($value);
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMSINH()
{
return require 'data/Calculation/Engineering/IMSINH.php';
}
/**
* @dataProvider providerIMTAN
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMTAN($expectedResult, $value)
{
$result = Engineering::IMTAN($value);
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMTAN()
{
return require 'data/Calculation/Engineering/IMTAN.php';
}
/**
* @dataProvider providerIMSQRT
*
* @param mixed $expectedResult
* @param mixed $value
*/
public function testIMSQRT($expectedResult, ...$args)
public function testIMSQRT($expectedResult, $value)
{
$result = Engineering::IMSQRT(...$args);
self::assertTrue($this->complexAssert->assertComplexEquals($expectedResult, $result, 1E-8), $this->complexAssert->getErrorMessage());
$result = Engineering::IMSQRT($value);
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMSQRT()
@ -356,10 +579,11 @@ class EngineeringTest extends TestCase
*/
public function testIMSUB($expectedResult, ...$args)
{
$this->markTestIncomplete('TODO: This test should be fixed');
$result = Engineering::IMSUB(...$args);
self::assertTrue($this->complexAssert->assertComplexEquals($expectedResult, $result, 1E-8), $this->complexAssert->getErrorMessage());
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMSUB()
@ -375,7 +599,10 @@ class EngineeringTest extends TestCase
public function testIMSUM($expectedResult, ...$args)
{
$result = Engineering::IMSUM(...$args);
self::assertTrue($this->complexAssert->assertComplexEquals($expectedResult, $result, 1E-8), $this->complexAssert->getErrorMessage());
self::assertTrue(
$this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION),
$this->complexAssert->getErrorMessage()
);
}
public function providerIMSUM()
@ -391,7 +618,7 @@ class EngineeringTest extends TestCase
public function testERF($expectedResult, ...$args)
{
$result = Engineering::ERF(...$args);
self::assertEquals($expectedResult, $result, null, 1E-12);
self::assertEquals($expectedResult, $result, null, self::ERF_PRECISION);
}
public function providerERF()
@ -407,7 +634,7 @@ class EngineeringTest extends TestCase
public function testERFPRECISE($expectedResult, ...$args)
{
$result = Engineering::ERFPRECISE(...$args);
self::assertEquals($expectedResult, $result, null, 1E-12);
self::assertEquals($expectedResult, $result, null, self::ERF_PRECISION);
}
public function providerERFPRECISE()
@ -423,7 +650,7 @@ class EngineeringTest extends TestCase
public function testERFC($expectedResult, ...$args)
{
$result = Engineering::ERFC(...$args);
self::assertEquals($expectedResult, $result, null, 1E-12);
self::assertEquals($expectedResult, $result, null, self::ERF_PRECISION);
}
public function providerERFC()

View File

@ -1,126 +0,0 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Custom;
use PhpOffice\PhpSpreadsheet\Exception;
class Complex
{
private $realPart = 0;
private $imaginaryPart = 0;
private $suffix;
public static function _parseComplex($complexNumber)
{
// Test for real number, with no imaginary part
if (is_numeric($complexNumber)) {
return [$complexNumber, 0, null];
}
// Fix silly human errors
if (strpos($complexNumber, '+-') !== false) {
$complexNumber = str_replace('+-', '-', $complexNumber);
}
if (strpos($complexNumber, '++') !== false) {
$complexNumber = str_replace('++', '+', $complexNumber);
}
if (strpos($complexNumber, '--') !== false) {
$complexNumber = str_replace('--', '-', $complexNumber);
}
// Basic validation of string, to parse out real and imaginary parts, and any suffix
$validComplex = preg_match('/^([\-\+]?(\d+\.?\d*|\d*\.?\d+)([Ee][\-\+]?[0-2]?\d{1,3})?)([\-\+]?(\d+\.?\d*|\d*\.?\d+)([Ee][\-\+]?[0-2]?\d{1,3})?)?(([\-\+]?)([ij]?))$/ui', $complexNumber, $complexParts);
if (!$validComplex) {
// Neither real nor imaginary part, so test to see if we actually have a suffix
$validComplex = preg_match('/^([\-\+]?)([ij])$/ui', $complexNumber, $complexParts);
if (!$validComplex) {
throw new Exception('COMPLEX: Invalid complex number');
}
// We have a suffix, so set the real to 0, the imaginary to either 1 or -1 (as defined by the sign)
$imaginary = 1;
if ($complexParts[1] === '-') {
$imaginary = 0 - $imaginary;
}
return [0, $imaginary, $complexParts[2]];
}
// If we don't have an imaginary part, identify whether it should be +1 or -1...
if (($complexParts[4] === '') && ($complexParts[9] !== '')) {
if ($complexParts[7] !== $complexParts[9]) {
$complexParts[4] = 1;
if ($complexParts[8] === '-') {
$complexParts[4] = -1;
}
// ... or if we have only the real and no imaginary part (in which case our real should be the imaginary)
} else {
$complexParts[4] = $complexParts[1];
$complexParts[1] = 0;
}
}
// Return real and imaginary parts and suffix as an array, and set a default suffix if user input lazily
return [$complexParts[1], $complexParts[4], !empty($complexParts[9]) ? $complexParts[9] : 'i'];
}
// function _parseComplex()
public function __construct($realPart, $imaginaryPart = null, $suffix = 'i')
{
if ($imaginaryPart === null) {
if (is_array($realPart)) {
// We have an array of (potentially) real and imaginary parts, and any suffix
list($realPart, $imaginaryPart, $suffix) = array_values($realPart) + [0.0, 0.0, 'i'];
} elseif ((is_string($realPart)) || (is_numeric($realPart))) {
// We've been given a string to parse to extract the real and imaginary parts, and any suffix
list($realPart, $imaginaryPart, $suffix) = self::_parseComplex($realPart);
}
}
// Set parsed values in our properties
$this->realPart = (float) $realPart;
$this->imaginaryPart = (float) $imaginaryPart;
$this->suffix = strtolower($suffix);
}
public function getReal()
{
return $this->realPart;
}
public function getImaginary()
{
return $this->imaginaryPart;
}
public function getSuffix()
{
return $this->suffix;
}
public function __toString()
{
$str = '';
if ($this->imaginaryPart != 0.0) {
if (abs($this->imaginaryPart) != 1.0) {
$str .= $this->imaginaryPart . $this->suffix;
} else {
$str .= (($this->imaginaryPart < 0.0) ? '-' : '') . $this->suffix;
}
}
if ($this->realPart != 0.0) {
if (($str) && ($this->imaginaryPart > 0.0)) {
$str = '+' . $str;
}
$str = $this->realPart . $str;
}
if (!$str) {
$str = '0.0';
}
return $str;
}
}

View File

@ -2,20 +2,41 @@
namespace PhpOffice\PhpSpreadsheetTests\Custom;
use Complex\Complex;
class ComplexAssert
{
private $errorMessage = '';
private function testExpectedExceptions($expected, $actual)
{
// Expecting an error, so we do a straight string comparison
if ($expected === $actual) {
return true;
} elseif ($expected === INF && $actual === 'INF') {
return true;
}
$this->errorMessage = 'Expected Error: ' . $actual . ' !== ' . $expected;
return false;
}
private function adjustDelta($expected, $actual, $delta)
{
$adjustedDelta = $delta;
if (abs($actual) > 10 && abs($expected) > 10) {
$variance = floor(log10(abs($expected)));
$adjustedDelta *= pow(10, $variance);
}
return $adjustedDelta > 1.0 ? 1.0 : $adjustedDelta;
}
public function assertComplexEquals($expected, $actual, $delta = 0)
{
if ($expected[0] === '#') {
// Expecting an error, so we do a straight string comparison
if ($expected === $actual) {
return true;
}
$this->errorMessage = 'Expected Error: ' . $actual . ' !== ' . $expected;
return false;
if ($expected === INF || $expected[0] === '#') {
return $this->testExpectedExceptions($expected, $actual);
}
$expectedComplex = new Complex($expected);
@ -31,15 +52,15 @@ class ComplexAssert
return true;
}
if ($actualComplex->getReal() < ($expectedComplex->getReal() - $delta) ||
$actualComplex->getReal() > ($expectedComplex->getReal() + $delta)) {
$adjustedDelta = $this->adjustDelta($expectedComplex->getReal(), $actualComplex->getReal(), $delta);
if (abs($actualComplex->getReal() - $expectedComplex->getReal()) > $adjustedDelta) {
$this->errorMessage = 'Mismatched Real part: ' . $actualComplex->getReal() . ' != ' . $expectedComplex->getReal();
return false;
}
if ($actualComplex->getImaginary() < ($expectedComplex->getImaginary() - $delta) ||
$actualComplex->getImaginary() > ($expectedComplex->getImaginary() + $delta)) {
$adjustedDelta = $this->adjustDelta($expectedComplex->getImaginary(), $actualComplex->getImaginary(), $delta);
if (abs($actualComplex->getImaginary() - $expectedComplex->getImaginary()) > $adjustedDelta) {
$this->errorMessage = 'Mismatched Imaginary part: ' . $actualComplex->getImaginary() . ' != ' . $expectedComplex->getImaginary();
return false;

View File

@ -0,0 +1,112 @@
<?php
return [
[
'93502.0563713182121-65794.6618967782119j',
'12.34+5.67j',
],
[
'-13.2772126767962807+9.90030162194353525i',
'3.5+2.5i',
],
[
'8.95433538452066202+13.9201408750362033i',
'3.5+i',
],
[
'16.5728246710573161',
'3.5',
],
[
'8.95433538452066202-13.9201408750362033i',
'3.5-i',
],
[
'-13.2772126767962807-9.90030162194353525i',
'3.5-2.5i',
],
[
'-1.23622919885634208+0.703325178113534826i',
'1+2.5i',
],
[
'0.833730025131149049+0.988897705762865096i',
'1+i',
],
[
'1.54308063481524378',
'1',
],
[
'0.833730025131149049-0.988897705762865096i',
'1-i',
],
[
'-1.23622919885634208-0.703325178113534826i',
'1-2.5i',
],
[
'-0.801143615546933715',
'2.5i',
],
[
'0.540302305868139717',
'i',
],
[
'1',
'0',
],
[
'0.540302305868139717',
'-i',
],
[
'-0.801143615546933715',
'-2.5i',
],
[
'-1.23622919885634208-0.703325178113534826i',
'-1+2.5i',
],
[
'0.833730025131149049-0.988897705762865096i',
'-1+i',
],
[
'1.54308063481524378',
'-1',
],
[
'0.833730025131149049+0.988897705762865096i',
'-1-i',
],
[
'-1.23622919885634208+0.703325178113534826i',
'-1-2.5i',
],
[
'-13.2772126767962807-9.90030162194353525i',
'-3.5+2.5i',
],
[
'8.95433538452066202-13.9201408750362033i',
'-3.5+i',
],
[
'16.5728246710573161',
'-3.5',
],
[
'8.95433538452066202+13.9201408750362033i',
'-3.5-i',
],
[
'-13.2772126767962807+9.90030162194353525i',
'-3.5-2.5i',
],
[
'10.0676619957777658',
'3',
],
];

View File

@ -0,0 +1,112 @@
<?php
return [
[
'-0.0000104004141424230319-1.00002138037057154j',
'12.34+5.67j',
],
[
'0.00894394174578834370-1.01017158348808170i',
'3.5+2.5i',
],
[
'0.218391793398543914-1.20562055667579681i',
'3.5+i',
],
[
'2.66961648496886604',
'3.5',
],
[
'0.218391793398543914+1.20562055667579681i',
'3.5-i',
],
[
'0.00894394174578834370+1.01017158348808170i',
'3.5-2.5i',
],
[
'0.0121847112919806296-0.994333285407756555i',
'1+2.5i',
],
[
'0.217621561854402681-0.868014142895924949i',
'1+i',
],
[
'0.642092615934330703',
'1',
],
[
'0.217621561854402681+0.868014142895924949i',
'1-i',
],
[
'0.0121847112919806296+0.994333285407756555i',
'1-2.5i',
],
[
'-1.01356730981260846i',
'2.5i',
],
[
'-1.31303528549933130i',
'i',
],
[
INF,
'0',
],
[
'1.31303528549933130i',
'-i',
],
[
'1.013567309812609i',
'-2.5i',
],
[
'-0.01218471129198063-0.994333285407757i',
'-1+2.5i',
],
[
'-0.21762156185440268-0.8680141428959249i',
'-1+i',
],
[
'-0.642092615934330703',
'-1',
],
[
'-0.21762156185440268+0.8680141428959249i',
'-1-i',
],
[
'-0.01218471129198063+0.994333285407757i',
'-1-2.5i',
],
[
'-0.00894394174578834-1.010171583488082i',
'-3.5+2.5i',
],
[
'-0.2183917933985438-1.205620556675797i',
'-3.5+i',
],
[
'-2.66961648496886604',
'-3.5',
],
[
'-0.2183917933985438+1.205620556675797i',
'-3.5-i',
],
[
'-0.00894394174578834+1.010171583488082i',
'-3.5-2.5i',
],
[
'-7.01525255143453347',
'3',
],
];

View File

@ -0,0 +1,112 @@
<?php
return [
[
'-0.00154774455592154432-0.00671986631601416928j',
'12.34+5.67j',
],
[
'-0.0585684747824233590+0.154262439469903774i',
'3.5+2.5i',
],
[
'-0.359863036667298479+0.731660683934045561i',
'3.5+i',
],
[
'-2.85076343754046413',
'3.5',
],
[
'-0.359863036667298479-0.731660683934045561i',
'3.5-i',
],
[
'-0.0585684747824233590-0.154262439469903774i',
'3.5-2.5i',
],
[
'0.138293277776215018-0.0876084810883255787i',
'1+2.5i',
],
[
'0.621518017170428421-0.303931001628426450i',
'1+i',
],
[
'1.18839510577812122',
'1',
],
[
'0.621518017170428421+0.303931001628426450i',
'1-i',
],
[
'0.138293277776215018+0.0876084810883255787i',
'1-2.5i',
],
[
'-0.165283669855095565i',
'2.5i',
],
[
'-0.850918128239321545i',
'i',
],
[
INF,
'0',
],
[
'0.850918128239321545i',
'-i',
],
[
'0.1652836698550956i',
'-2.5i',
],
[
'-0.138293277776215-0.0876084810883256i',
'-1+2.5i',
],
[
'-0.62151801717042842-0.30393100162842645i',
'-1+i',
],
[
'-1.18839510577812122',
'-1',
],
[
'-0.62151801717042842+0.30393100162842645i',
'-1-i',
],
[
'-0.138293277776215+0.0876084810883256i',
'-1-2.5i',
],
[
'0.05856847478242335+0.1542624394699038i',
'-3.5+2.5i',
],
[
'0.3598630366672985+0.7316606839340456i',
'-3.5+i',
],
[
'2.85076343754046413',
'-3.5',
],
[
'0.3598630366672985-0.7316606839340456i',
'-3.5-i',
],
[
'0.05856847478242335-0.1542624394699038i',
'-3.5-2.5i',
],
[
'7.08616739573718592',
'3',
],
];

View File

@ -0,0 +1,112 @@
<?php
return [
[
'7.15308425027293823E-6+5.03341614148979354E-6j',
'12.34+5.67j',
],
[
'-0.0483657415388563464-0.0361962406084861128i',
'3.5+2.5i',
],
[
'0.0325769243120443503-0.0508281676948511387i',
'3.5+i',
],
[
'0.0604498900091561051',
'3.5',
],
[
'0.0325769243120443503+0.0508281676948511387i',
'3.5-i',
],
[
'-0.0483657415388563464+0.0361962406084861128i',
'3.5-2.5i',
],
[
'-0.541322906190002332-0.530965577621174208i',
'1+2.5i',
],
[
'0.303931001628426450-0.621518017170428421i',
'1+i',
],
[
'0.850918128239321545',
'1',
],
[
'0.303931001628426450+0.621518017170428421i',
'1-i',
],
[
'-0.541322906190002332+0.530965577621174208i',
'1-2.5i',
],
[
'-1.67092154555867993i',
'2.5i',
],
[
'-1.18839510577812122i',
'i',
],
[
INF,
'0',
],
[
'1.18839510577812122i',
'-i',
],
[
'1.67092154555868i',
'-2.5i',
],
[
'0.5413229061900022-0.5309655776211742i',
'-1+2.5i',
],
[
'-0.30393100162842645-0.62151801717042842i',
'-1+i',
],
[
'-0.850918128239321545',
'-1',
],
[
'-0.30393100162842645+0.62151801717042842i',
'-1-i',
],
[
'0.5413229061900022+0.5309655776211742i',
'-1-2.5i',
],
[
'0.04836574153885635-0.03619624060848612i',
'-3.5+2.5i',
],
[
'-0.03257692431204435-0.05082816769485113i',
'-3.5+i',
],
[
'-0.0604498900091561051',
'-3.5',
],
[
'-0.03257692431204435+0.05082816769485113i',
'-3.5-i',
],
[
'0.04836574153885635+0.03619624060848612i',
'-3.5-2.5i',
],
[
'0.0998215696688227329',
'3',
],
];

View File

@ -71,21 +71,6 @@ return [
'-12.34-5.67i',
'123.45-67.89i',
],
[
'#NUM!',
'-12.34-5.67i',
'123.45-67.89',
],
[
'#NUM!',
'-12.34-5.67j',
'123.45-67.89',
],
[
'#NUM!',
'-12.34-5.67',
'123.45-67.89j',
],
[
'1',
'-12.34-5.67i',

View File

@ -3,7 +3,7 @@
return [
[
12.34,
'12.34+5.67j"',
'12.34+5.67j',
],
[
-1.234E-5,

View File

@ -0,0 +1,112 @@
<?php
return [
[
'0.00671973874162309199-0.00154764157870523791j',
'12.34+5.67j',
],
[
'-0.153210472299609239-0.0566222314884645297i',
'3.5+2.5i',
],
[
'-0.639945455994778845-0.182565069612144926i',
'3.5+i',
],
[
'-1.06785504719181066',
'3.5',
],
[
'-0.639945455994778845+0.182565069612144926i',
'3.5-i',
],
[
'-0.153210472299609239+0.0566222314884645297i',
'3.5-2.5i',
],
[
'0.0897986028721219428+0.137981006709970822i',
'1+2.5i',
],
[
'0.498337030555186785+0.591083841721045048i',
'1+i',
],
[
'1.85081571768092562',
'1',
],
[
'0.498337030555186785-0.591083841721045048i',
'1-i',
],
[
'0.0897986028721219428-0.137981006709970822i',
'1-2.5i',
],
[
'0.163071231929977826',
'2.5i',
],
[
'0.648054273663885400',
'i',
],
[
'1.0',
'0',
],
[
'0.648054273663885400',
'-i',
],
[
'0.163071231929977826',
'-2.5i',
],
[
'0.0897986028721219428-0.137981006709970822i',
'-1+2.5i',
],
[
'0.498337030555186785-0.591083841721045048i',
'-1+i',
],
[
'1.85081571768092562',
'-1',
],
[
'0.498337030555186785+0.591083841721045048i',
'-1-i',
],
[
'0.0897986028721219428+0.137981006709970822i',
'-1-2.5i',
],
[
'-0.153210472299609239+0.0566222314884645297i',
'-3.5+2.5i',
],
[
'-0.639945455994778845+0.182565069612144926i',
'-3.5+i',
],
[
'-1.06785504719181066',
'-3.5',
],
[
'-0.639945455994778845-0.182565069612144926i',
'-3.5-i',
],
[
'-0.153210472299609239-0.0566222314884645297i',
'-3.5-2.5i',
],
[
'-1.01010866590799375',
'3',
],
];

View File

@ -0,0 +1,112 @@
<?php
return [
[
'7.15308425036177674E-6+5.03341614116724074E-6j',
'12.34+5.67j',
],
[
'-0.0484039219824442559-0.0360929239424409676i',
'3.5+2.5i',
],
[
'0.0326859677559519711-0.0508126238588615047i',
'3.5+i',
],
[
'0.0603397441201676464',
'3.5',
],
[
'0.0326859677559519711+0.0508126238588615047i',
'3.5-i',
],
[
'-0.0484039219824442559+0.0360929239424409676i',
'3.5-2.5i',
],
[
'-0.611108564155231518-0.347676660710495997i',
'1+2.5i',
],
[
'0.498337030555186785-0.591083841721045048i',
'1+i',
],
[
'0.648054273663885400',
'1',
],
[
'0.498337030555186785+0.591083841721045048i',
'1-i',
],
[
'-0.611108564155231518+0.347676660710495997i',
'1-2.5i',
],
[
'-1.24821565146881783',
'2.5i',
],
[
'1.85081571768092562',
'i',
],
[
'1.0',
'0',
],
[
'1.85081571768092562',
'-i',
],
[
'-1.24821565146881783',
'-2.5i',
],
[
'-0.611108564155231518+0.347676660710495997i',
'-1+2.5i',
],
[
'0.498337030555186785+0.591083841721045048i',
'-1+i',
],
[
'0.648054273663885400',
'-1',
],
[
'0.498337030555186785-0.591083841721045048i',
'-1-i',
],
[
'-0.611108564155231518-0.347676660710495997i',
'-1-2.5i',
],
[
'-0.0484039219824442559+0.0360929239424409676i',
'-3.5+2.5i',
],
[
'0.0326859677559519711+0.0508126238588615047i',
'-3.5+i',
],
[
'0.0603397441201676464',
'-3.5',
],
[
'0.0326859677559519711-0.0508126238588615047i',
'-3.5-i',
],
[
'-0.0484039219824442559-0.0360929239424409676i',
'-3.5-2.5i',
],
[
'0.0993279274194332078',
'3',
],
];

View File

@ -0,0 +1,112 @@
<?php
return [
[
'93502.0563677416700-65794.6618992949199j',
'12.34+5.67j',
],
[
'-13.2530202358612674+9.91837391474661948i',
'3.5+2.5i',
],
[
'8.93801966862639899+13.9455510970032033i',
'3.5+i',
],
[
'16.5426272876349976',
'3.5',
],
[
'8.93801966862639899-13.9455510970032033i',
'3.5-i',
],
[
'-13.2530202358612674-9.91837391474661948i',
'3.5-2.5i',
],
[
'-0.941504933270867276+0.923490776043173241i',
'1+2.5i',
],
[
'0.634963914784736108+1.29845758141597729i',
'1+i',
],
[
'1.17520119364380146',
'1',
],
[
'0.634963914784736108-1.29845758141597729i',
'1-i',
],
[
'-0.941504933270867276-0.923490776043173241i',
'1-2.5i',
],
[
'0.598472144103956494i',
'2.5i',
],
[
'0.841470984807896507i',
'i',
],
[
'0.0',
'0',
],
[
'-0.841470984807896507i',
'-i',
],
[
'-0.5984721441039565i',
'-2.5i',
],
[
'0.941504933270867+0.923490776043173i',
'-1+2.5i',
],
[
'-0.63496391478473611+1.29845758141597729i',
'-1+i',
],
[
'-1.17520119364380146',
'-1',
],
[
'-0.63496391478473611-1.29845758141597729i',
'-1-i',
],
[
'0.941504933270867-0.923490776043173i',
'-1-2.5i',
],
[
'13.25302023586127+9.91837391474662i',
'-3.5+2.5i',
],
[
'-8.9380196686264+13.9455510970032i',
'-3.5+i',
],
[
'-16.5426272876349976',
'-3.5',
],
[
'-8.9380196686264-13.9455510970032i',
'-3.5-i',
],
[
'13.25302023586127-9.91837391474662i',
'-3.5-2.5i',
],
[
'10.0178749274099019',
'3',
],
];

View File

@ -78,8 +78,8 @@ return [
'-1+i',
],
[
'6.12303176911189E-017+i',
'-1',
'0.923879532511287+0.382683432365089i',
'0.707106781186548+0.707106781186547i',
],
[
'0.455089860562227-1.09868411346781i',
@ -98,7 +98,7 @@ return [
'-3.5+i',
],
[
'1.14551435241745E-016+1.87082869338697i',
'1.14602144155088E-16+1.87082869338697i',
'-3.5',
],
[

View File

@ -37,19 +37,4 @@ return [
'-12.34-5.67i',
'-123.45-67.89i',
],
[
'#NUM!',
'-12.34-5.67i',
'-123.45-67.89',
],
[
'#NUM!',
'-12.34-5.67j',
'-123.45-67.89',
],
[
'#NUM!',
'-12.34-5.67',
'-123.45-67.89j',
],
];

View File

@ -0,0 +1,112 @@
<?php
return [
[
'-0.0000103999694261435177+0.999978619978377253j',
'12.34+5.67j',
],
[
'0.00876404549513463160+0.989853240015864536i',
'3.5+2.5i',
],
[
'0.145476605392064825+0.803096047002175475i',
'3.5+i',
],
[
'0.374585640158594666',
'3.5',
],
[
'0.145476605392064825-0.803096047002175475i',
'3.5-i',
],
[
'0.00876404549513463160-0.989853240015864536i',
'3.5-2.5i',
],
[
'0.0123221382558283535+1.00554801189505998i',
'1+2.5i',
],
[
'0.271752585319511717+1.08392332733869454i',
'1+i',
],
[
'1.55740772465490223',
'1',
],
[
'0.271752585319511717-1.08392332733869454i',
'1-i',
],
[
'0.0123221382558283535-1.00554801189505998i',
'1-2.5i',
],
[
'0.986614298151430289i',
'2.5i',
],
[
'0.761594155955764888i',
'i',
],
[
'0.0',
'0',
],
[
'-0.761594155955764888i',
'-i',
],
[
'-0.98661429815143i',
'-2.5i',
],
[
'-0.01232213825582835+1.00554801189506i',
'-1+2.5i',
],
[
'-0.27175258531951172+1.0839233273386945i',
'-1+i',
],
[
'-1.55740772465490223',
'-1',
],
[
'-0.27175258531951172-1.08392332733869454i',
'-1-i',
],
[
'-0.01232213825582835-1.00554801189506i',
'-1-2.5i',
],
[
'-0.00876404549513463+0.989853240015864i',
'-3.5+2.5i',
],
[
'-0.1454766053920648+0.803096047002176i',
'-3.5+i',
],
[
'-0.374585640158594666',
'-3.5',
],
[
'-0.1454766053920648-0.803096047002176i',
'-3.5-i',
],
[
'-0.00876404549513463-0.989853240015864i',
'-3.5-2.5i',
],
[
'-0.142546543074277805',
'3',
],
];