commitall
This commit is contained in:
388
vendor/markbaker/complex/classes/src/Complex.php
vendored
Normal file
388
vendor/markbaker/complex/classes/src/Complex.php
vendored
Normal file
@ -0,0 +1,388 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
*
|
||||
* Class for the management of Complex numbers
|
||||
*
|
||||
* @copyright Copyright (c) 2013-2018 Mark Baker (https://github.com/MarkBaker/PHPComplex)
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
namespace Complex;
|
||||
|
||||
/**
|
||||
* Complex Number object.
|
||||
*
|
||||
* @package Complex
|
||||
*
|
||||
* @method float abs()
|
||||
* @method Complex acos()
|
||||
* @method Complex acosh()
|
||||
* @method Complex acot()
|
||||
* @method Complex acoth()
|
||||
* @method Complex acsc()
|
||||
* @method Complex acsch()
|
||||
* @method float argument()
|
||||
* @method Complex asec()
|
||||
* @method Complex asech()
|
||||
* @method Complex asin()
|
||||
* @method Complex asinh()
|
||||
* @method Complex atan()
|
||||
* @method Complex atanh()
|
||||
* @method Complex conjugate()
|
||||
* @method Complex cos()
|
||||
* @method Complex cosh()
|
||||
* @method Complex cot()
|
||||
* @method Complex coth()
|
||||
* @method Complex csc()
|
||||
* @method Complex csch()
|
||||
* @method Complex exp()
|
||||
* @method Complex inverse()
|
||||
* @method Complex ln()
|
||||
* @method Complex log2()
|
||||
* @method Complex log10()
|
||||
* @method Complex negative()
|
||||
* @method Complex pow(int|float $power)
|
||||
* @method float rho()
|
||||
* @method Complex sec()
|
||||
* @method Complex sech()
|
||||
* @method Complex sin()
|
||||
* @method Complex sinh()
|
||||
* @method Complex sqrt()
|
||||
* @method Complex tan()
|
||||
* @method Complex tanh()
|
||||
* @method float theta()
|
||||
* @method Complex add(...$complexValues)
|
||||
* @method Complex subtract(...$complexValues)
|
||||
* @method Complex multiply(...$complexValues)
|
||||
* @method Complex divideby(...$complexValues)
|
||||
* @method Complex divideinto(...$complexValues)
|
||||
*/
|
||||
class Complex
|
||||
{
|
||||
/**
|
||||
* @constant Euler's Number.
|
||||
*/
|
||||
const EULER = 2.7182818284590452353602874713526624977572;
|
||||
|
||||
/**
|
||||
* @constant Regexp to split an input string into real and imaginary components and suffix
|
||||
*/
|
||||
const NUMBER_SPLIT_REGEXP =
|
||||
'` ^
|
||||
( # Real part
|
||||
[-+]?(\d+\.?\d*|\d*\.?\d+) # Real value (integer or float)
|
||||
([Ee][-+]?[0-2]?\d{1,3})? # Optional real exponent for scientific format
|
||||
)
|
||||
( # Imaginary part
|
||||
[-+]?(\d+\.?\d*|\d*\.?\d+) # Imaginary value (integer or float)
|
||||
([Ee][-+]?[0-2]?\d{1,3})? # Optional imaginary exponent for scientific format
|
||||
)?
|
||||
( # Imaginary part is optional
|
||||
([-+]?) # Imaginary (implicit 1 or -1) only
|
||||
([ij]?) # Imaginary i or j - depending on whether mathematical or engineering
|
||||
)
|
||||
$`uix';
|
||||
|
||||
/**
|
||||
* @var float $realPart The value of of this complex number on the real plane.
|
||||
*/
|
||||
protected $realPart = 0.0;
|
||||
|
||||
/**
|
||||
* @var float $imaginaryPart The value of of this complex number on the imaginary plane.
|
||||
*/
|
||||
protected $imaginaryPart = 0.0;
|
||||
|
||||
/**
|
||||
* @var string $suffix The suffix for this complex number (i or j).
|
||||
*/
|
||||
protected $suffix;
|
||||
|
||||
|
||||
/**
|
||||
* Validates whether the argument is a valid complex number, converting scalar or array values if possible
|
||||
*
|
||||
* @param mixed $complexNumber The value to parse
|
||||
* @return array
|
||||
* @throws Exception If the argument isn't a Complex number or cannot be converted to one
|
||||
*/
|
||||
private static function parseComplex($complexNumber)
|
||||
{
|
||||
// Test for real number, with no imaginary part
|
||||
if (is_numeric($complexNumber)) {
|
||||
return [$complexNumber, 0, null];
|
||||
}
|
||||
|
||||
// Fix silly human errors
|
||||
$complexNumber = str_replace(
|
||||
['+-', '-+', '++', '--'],
|
||||
['-', '-', '+', '+'],
|
||||
$complexNumber
|
||||
);
|
||||
|
||||
// Basic validation of string, to parse out real and imaginary parts, and any suffix
|
||||
$validComplex = preg_match(
|
||||
self::NUMBER_SPLIT_REGEXP,
|
||||
$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('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;
|
||||
}
|
||||
} else {
|
||||
// ... or if we have only the real and no imaginary part
|
||||
// (in which case our real should be the imaginary)
|
||||
$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'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function __construct($realPart = 0.0, $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);
|
||||
}
|
||||
}
|
||||
|
||||
if ($imaginaryPart != 0.0 && empty($suffix)) {
|
||||
$suffix = 'i';
|
||||
} elseif ($imaginaryPart == 0.0 && !empty($suffix)) {
|
||||
$suffix = '';
|
||||
}
|
||||
|
||||
// Set parsed values in our properties
|
||||
$this->realPart = (float) $realPart;
|
||||
$this->imaginaryPart = (float) $imaginaryPart;
|
||||
$this->suffix = strtolower($suffix ?? '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the real part of this complex number
|
||||
*
|
||||
* @return Float
|
||||
*/
|
||||
public function getReal(): float
|
||||
{
|
||||
return $this->realPart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the imaginary part of this complex number
|
||||
*
|
||||
* @return Float
|
||||
*/
|
||||
public function getImaginary(): float
|
||||
{
|
||||
return $this->imaginaryPart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the suffix of this complex number
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public function getSuffix(): string
|
||||
{
|
||||
return $this->suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is a real value, false if a complex value
|
||||
*
|
||||
* @return Bool
|
||||
*/
|
||||
public function isReal(): bool
|
||||
{
|
||||
return $this->imaginaryPart == 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is a complex value, false if a real value
|
||||
*
|
||||
* @return Bool
|
||||
*/
|
||||
public function isComplex(): bool
|
||||
{
|
||||
return !$this->isReal();
|
||||
}
|
||||
|
||||
public function format(): string
|
||||
{
|
||||
$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;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->format();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates whether the argument is a valid complex number, converting scalar or array values if possible
|
||||
*
|
||||
* @param mixed $complex The value to validate
|
||||
* @return Complex
|
||||
* @throws Exception If the argument isn't a Complex number or cannot be converted to one
|
||||
*/
|
||||
public static function validateComplexArgument($complex): Complex
|
||||
{
|
||||
if (is_scalar($complex) || is_array($complex)) {
|
||||
$complex = new Complex($complex);
|
||||
} elseif (!is_object($complex) || !($complex instanceof Complex)) {
|
||||
throw new Exception('Value is not a valid complex number');
|
||||
}
|
||||
|
||||
return $complex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reverse of this complex number
|
||||
*
|
||||
* @return Complex
|
||||
*/
|
||||
public function reverse(): Complex
|
||||
{
|
||||
return new Complex(
|
||||
$this->imaginaryPart,
|
||||
$this->realPart,
|
||||
($this->realPart == 0.0) ? null : $this->suffix
|
||||
);
|
||||
}
|
||||
|
||||
public function invertImaginary(): Complex
|
||||
{
|
||||
return new Complex(
|
||||
$this->realPart,
|
||||
$this->imaginaryPart * -1,
|
||||
($this->imaginaryPart == 0.0) ? null : $this->suffix
|
||||
);
|
||||
}
|
||||
|
||||
public function invertReal(): Complex
|
||||
{
|
||||
return new Complex(
|
||||
$this->realPart * -1,
|
||||
$this->imaginaryPart,
|
||||
($this->imaginaryPart == 0.0) ? null : $this->suffix
|
||||
);
|
||||
}
|
||||
|
||||
protected static $functions = [
|
||||
'abs',
|
||||
'acos',
|
||||
'acosh',
|
||||
'acot',
|
||||
'acoth',
|
||||
'acsc',
|
||||
'acsch',
|
||||
'argument',
|
||||
'asec',
|
||||
'asech',
|
||||
'asin',
|
||||
'asinh',
|
||||
'atan',
|
||||
'atanh',
|
||||
'conjugate',
|
||||
'cos',
|
||||
'cosh',
|
||||
'cot',
|
||||
'coth',
|
||||
'csc',
|
||||
'csch',
|
||||
'exp',
|
||||
'inverse',
|
||||
'ln',
|
||||
'log2',
|
||||
'log10',
|
||||
'negative',
|
||||
'pow',
|
||||
'rho',
|
||||
'sec',
|
||||
'sech',
|
||||
'sin',
|
||||
'sinh',
|
||||
'sqrt',
|
||||
'tan',
|
||||
'tanh',
|
||||
'theta',
|
||||
];
|
||||
|
||||
protected static $operations = [
|
||||
'add',
|
||||
'subtract',
|
||||
'multiply',
|
||||
'divideby',
|
||||
'divideinto',
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns the result of the function call or operation
|
||||
*
|
||||
* @return Complex|float
|
||||
* @throws Exception|\InvalidArgumentException
|
||||
*/
|
||||
public function __call($functionName, $arguments)
|
||||
{
|
||||
$functionName = strtolower(str_replace('_', '', $functionName));
|
||||
|
||||
// Test for function calls
|
||||
if (in_array($functionName, self::$functions, true)) {
|
||||
return Functions::$functionName($this, ...$arguments);
|
||||
}
|
||||
// Test for operation calls
|
||||
if (in_array($functionName, self::$operations, true)) {
|
||||
return Operations::$functionName($this, ...$arguments);
|
||||
}
|
||||
throw new Exception('Complex Function or Operation does not exist');
|
||||
}
|
||||
}
|
13
vendor/markbaker/complex/classes/src/Exception.php
vendored
Normal file
13
vendor/markbaker/complex/classes/src/Exception.php
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Exception.
|
||||
*
|
||||
* @copyright Copyright (c) 2013-2018 Mark Baker (https://github.com/MarkBaker/PHPComplex)
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
namespace Complex;
|
||||
|
||||
class Exception extends \Exception
|
||||
{
|
||||
}
|
823
vendor/markbaker/complex/classes/src/Functions.php
vendored
Normal file
823
vendor/markbaker/complex/classes/src/Functions.php
vendored
Normal file
@ -0,0 +1,823 @@
|
||||
<?php
|
||||
|
||||
namespace Complex;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Functions
|
||||
{
|
||||
/**
|
||||
* Returns the absolute value (modulus) of a complex number.
|
||||
* Also known as the rho of the complex number, i.e. the distance/radius
|
||||
* from the centrepoint to the representation of the number in polar coordinates.
|
||||
*
|
||||
* This function is a synonym for rho()
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return float The absolute (or rho) value of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*
|
||||
* @see rho
|
||||
*
|
||||
*/
|
||||
public static function abs($complex): float
|
||||
{
|
||||
return self::rho($complex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse cosine of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse cosine of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function acos($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
$invsqrt = self::sqrt(Operations::subtract(1, Operations::multiply($complex, $complex)));
|
||||
$adjust = new Complex(
|
||||
$complex->getReal() - $invsqrt->getImaginary(),
|
||||
$complex->getImaginary() + $invsqrt->getReal()
|
||||
);
|
||||
$log = self::ln($adjust);
|
||||
|
||||
return new Complex(
|
||||
$log->getImaginary(),
|
||||
-1 * $log->getReal()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic cosine of a complex number.
|
||||
*
|
||||
* Formula from Wolfram Alpha:
|
||||
* cosh^(-1)z = ln(z + sqrt(z + 1) sqrt(z - 1)).
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse hyperbolic cosine of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function acosh($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal() && ($complex->getReal() > 1)) {
|
||||
return new Complex(\acosh($complex->getReal()));
|
||||
}
|
||||
|
||||
$acosh = self::ln(
|
||||
Operations::add(
|
||||
$complex,
|
||||
Operations::multiply(
|
||||
self::sqrt(Operations::add($complex, 1)),
|
||||
self::sqrt(Operations::subtract($complex, 1))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
return $acosh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse cotangent of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse cotangent of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function acot($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
return self::atan(self::inverse($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic cotangent of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse hyperbolic cotangent of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function acoth($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
return self::atanh(self::inverse($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse cosecant of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse cosecant of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function acsc($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return self::asin(self::inverse($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic cosecant of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse hyperbolic cosecant of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function acsch($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return self::asinh(self::inverse($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the argument of a complex number.
|
||||
* Also known as the theta of the complex number, i.e. the angle in radians
|
||||
* from the real axis to the representation of the number in polar coordinates.
|
||||
*
|
||||
* This function is a synonym for theta()
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return float The argument (or theta) value of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*
|
||||
* @see theta
|
||||
*/
|
||||
public static function argument($complex): float
|
||||
{
|
||||
return self::theta($complex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse secant of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse secant of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function asec($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return self::acos(self::inverse($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic secant of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse hyperbolic secant of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function asech($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return self::acosh(self::inverse($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse sine of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse sine of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function asin($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
$invsqrt = self::sqrt(Operations::subtract(1, Operations::multiply($complex, $complex)));
|
||||
$adjust = new Complex(
|
||||
$invsqrt->getReal() - $complex->getImaginary(),
|
||||
$invsqrt->getImaginary() + $complex->getReal()
|
||||
);
|
||||
$log = self::ln($adjust);
|
||||
|
||||
return new Complex(
|
||||
$log->getImaginary(),
|
||||
-1 * $log->getReal()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic sine of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse hyperbolic sine of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function asinh($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal() && ($complex->getReal() > 1)) {
|
||||
return new Complex(\asinh($complex->getReal()));
|
||||
}
|
||||
|
||||
$asinh = clone $complex;
|
||||
$asinh = $asinh->reverse()
|
||||
->invertReal();
|
||||
$asinh = self::asin($asinh);
|
||||
|
||||
return $asinh->reverse()
|
||||
->invertImaginary();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse tangent of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse tangent of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function atan($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal()) {
|
||||
return new Complex(\atan($complex->getReal()));
|
||||
}
|
||||
|
||||
$t1Value = new Complex(-1 * $complex->getImaginary(), $complex->getReal());
|
||||
$uValue = new Complex(1, 0);
|
||||
|
||||
$d1Value = clone $uValue;
|
||||
$d1Value = Operations::subtract($d1Value, $t1Value);
|
||||
$d2Value = Operations::add($t1Value, $uValue);
|
||||
$uResult = $d1Value->divideBy($d2Value);
|
||||
$uResult = self::ln($uResult);
|
||||
|
||||
$realMultiplier = -0.5;
|
||||
$imaginaryMultiplier = 0.5;
|
||||
|
||||
if (abs($uResult->getImaginary()) === M_PI) {
|
||||
// If we have an imaginary value at the max or min (PI or -PI), then we need to ensure
|
||||
// that the primary is assigned for the correct quadrant.
|
||||
$realMultiplier = (
|
||||
($uResult->getImaginary() === M_PI && $uResult->getReal() > 0.0) ||
|
||||
($uResult->getImaginary() === -M_PI && $uResult->getReal() < 0.0)
|
||||
) ? 0.5 : -0.5;
|
||||
}
|
||||
|
||||
return new Complex(
|
||||
$uResult->getImaginary() * $realMultiplier,
|
||||
$uResult->getReal() * $imaginaryMultiplier,
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic tangent of a complex number.
|
||||
*
|
||||
* Formula from Wolfram Alpha:
|
||||
* tanh^(-1)z = 1/2 [ln(1 + z) - ln(1 - z)].
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse hyperbolic tangent of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function atanh($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal()) {
|
||||
$real = $complex->getReal();
|
||||
if ($real >= -1.0 && $real <= 1.0) {
|
||||
return new Complex(\atanh($real));
|
||||
} else {
|
||||
return new Complex(\atanh(1 / $real), (($real < 0.0) ? M_PI_2 : -1 * M_PI_2));
|
||||
}
|
||||
}
|
||||
|
||||
$atanh = Operations::multiply(
|
||||
Operations::subtract(
|
||||
self::ln(Operations::add(1.0, $complex)),
|
||||
self::ln(Operations::subtract(1.0, $complex))
|
||||
),
|
||||
0.5
|
||||
);
|
||||
|
||||
return $atanh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the complex conjugate of a complex number
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The conjugate of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function conjugate($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
return new Complex(
|
||||
$complex->getReal(),
|
||||
-1 * $complex->getImaginary(),
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cosine of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The cosine of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function cos($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal()) {
|
||||
return new Complex(\cos($complex->getReal()));
|
||||
}
|
||||
|
||||
return self::conjugate(
|
||||
new Complex(
|
||||
\cos($complex->getReal()) * \cosh($complex->getImaginary()),
|
||||
\sin($complex->getReal()) * \sinh($complex->getImaginary()),
|
||||
$complex->getSuffix()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic cosine of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The hyperbolic cosine of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function cosh($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal()) {
|
||||
return new Complex(\cosh($complex->getReal()));
|
||||
}
|
||||
|
||||
return new Complex(
|
||||
\cosh($complex->getReal()) * \cos($complex->getImaginary()),
|
||||
\sinh($complex->getReal()) * \sin($complex->getImaginary()),
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cotangent of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The cotangent of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function cot($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return self::inverse(self::tan($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic cotangent of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The hyperbolic cotangent of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function coth($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
return self::inverse(self::tanh($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cosecant of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The cosecant of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function csc($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return self::inverse(self::sin($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic cosecant of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The hyperbolic cosecant of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function csch($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return self::inverse(self::sinh($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exponential of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The exponential of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function exp($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if (($complex->getReal() == 0.0) && (\abs($complex->getImaginary()) == M_PI)) {
|
||||
return new Complex(-1.0, 0.0);
|
||||
}
|
||||
|
||||
$rho = \exp($complex->getReal());
|
||||
|
||||
return new Complex(
|
||||
$rho * \cos($complex->getImaginary()),
|
||||
$rho * \sin($complex->getImaginary()),
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function inverse($complex): Complex
|
||||
{
|
||||
$complex = clone Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
throw new InvalidArgumentException('Division by zero');
|
||||
}
|
||||
|
||||
return $complex->divideInto(1.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the natural logarithm of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The natural logarithm of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws InvalidArgumentException If the real and the imaginary parts are both zero
|
||||
*/
|
||||
public static function ln($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if (($complex->getReal() == 0.0) && ($complex->getImaginary() == 0.0)) {
|
||||
throw new InvalidArgumentException();
|
||||
}
|
||||
|
||||
return new Complex(
|
||||
\log(self::rho($complex)),
|
||||
self::theta($complex),
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base-2 logarithm of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The base-2 logarithm of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws InvalidArgumentException If the real and the imaginary parts are both zero
|
||||
*/
|
||||
public static function log2($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if (($complex->getReal() == 0.0) && ($complex->getImaginary() == 0.0)) {
|
||||
throw new InvalidArgumentException();
|
||||
} elseif (($complex->getReal() > 0.0) && ($complex->getImaginary() == 0.0)) {
|
||||
return new Complex(\log($complex->getReal(), 2), 0.0, $complex->getSuffix());
|
||||
}
|
||||
|
||||
return self::ln($complex)
|
||||
->multiply(\log(Complex::EULER, 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the common logarithm (base 10) of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The common logarithm (base 10) of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws InvalidArgumentException If the real and the imaginary parts are both zero
|
||||
*/
|
||||
public static function log10($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if (($complex->getReal() == 0.0) && ($complex->getImaginary() == 0.0)) {
|
||||
throw new InvalidArgumentException();
|
||||
} elseif (($complex->getReal() > 0.0) && ($complex->getImaginary() == 0.0)) {
|
||||
return new Complex(\log10($complex->getReal()), 0.0, $complex->getSuffix());
|
||||
}
|
||||
|
||||
return self::ln($complex)
|
||||
->multiply(\log10(Complex::EULER));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negative of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The negative value of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*
|
||||
* @see rho
|
||||
*
|
||||
*/
|
||||
public static function negative($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
return new Complex(
|
||||
-1 * $complex->getReal(),
|
||||
-1 * $complex->getImaginary(),
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a complex number raised to a power.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @param float|integer $power The power to raise this value to
|
||||
* @return Complex The complex argument raised to the real power.
|
||||
* @throws Exception If the power argument isn't a valid real
|
||||
*/
|
||||
public static function pow($complex, $power): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if (!is_numeric($power)) {
|
||||
throw new Exception('Power argument must be a real number');
|
||||
}
|
||||
|
||||
if ($complex->getImaginary() == 0.0 && $complex->getReal() >= 0.0) {
|
||||
return new Complex(\pow($complex->getReal(), $power));
|
||||
}
|
||||
|
||||
$rValue = \sqrt(($complex->getReal() * $complex->getReal()) + ($complex->getImaginary() * $complex->getImaginary()));
|
||||
$rPower = \pow($rValue, $power);
|
||||
$theta = $complex->argument() * $power;
|
||||
if ($theta == 0) {
|
||||
return new Complex(1);
|
||||
}
|
||||
|
||||
return new Complex($rPower * \cos($theta), $rPower * \sin($theta), $complex->getSuffix());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the rho of a complex number.
|
||||
* This is the distance/radius from the centrepoint to the representation of the number in polar coordinates.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return float The rho value of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function rho($complex): float
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
return \sqrt(
|
||||
($complex->getReal() * $complex->getReal()) +
|
||||
($complex->getImaginary() * $complex->getImaginary())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the secant of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The secant of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function sec($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
return self::inverse(self::cos($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic secant of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The hyperbolic secant of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function sech($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
return self::inverse(self::cosh($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sine of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The sine of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function sin($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal()) {
|
||||
return new Complex(\sin($complex->getReal()));
|
||||
}
|
||||
|
||||
return new Complex(
|
||||
\sin($complex->getReal()) * \cosh($complex->getImaginary()),
|
||||
\cos($complex->getReal()) * \sinh($complex->getImaginary()),
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic sine of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The hyperbolic sine of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function sinh($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal()) {
|
||||
return new Complex(\sinh($complex->getReal()));
|
||||
}
|
||||
|
||||
return new Complex(
|
||||
\sinh($complex->getReal()) * \cos($complex->getImaginary()),
|
||||
\cosh($complex->getReal()) * \sin($complex->getImaginary()),
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square root of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The Square root of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function sqrt($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
$theta = self::theta($complex);
|
||||
$delta1 = \cos($theta / 2);
|
||||
$delta2 = \sin($theta / 2);
|
||||
$rho = \sqrt(self::rho($complex));
|
||||
|
||||
return new Complex($delta1 * $rho, $delta2 * $rho, $complex->getSuffix());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tangent of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The tangent of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function tan($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal()) {
|
||||
return new Complex(\tan($complex->getReal()));
|
||||
}
|
||||
|
||||
$real = $complex->getReal();
|
||||
$imaginary = $complex->getImaginary();
|
||||
$divisor = 1 + \pow(\tan($real), 2) * \pow(\tanh($imaginary), 2);
|
||||
if ($divisor == 0.0) {
|
||||
throw new InvalidArgumentException('Division by zero');
|
||||
}
|
||||
|
||||
return new Complex(
|
||||
\pow(self::sech($imaginary)->getReal(), 2) * \tan($real) / $divisor,
|
||||
\pow(self::sec($real)->getReal(), 2) * \tanh($imaginary) / $divisor,
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic tangent of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The hyperbolic tangent of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function tanh($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
$real = $complex->getReal();
|
||||
$imaginary = $complex->getImaginary();
|
||||
$divisor = \cos($imaginary) * \cos($imaginary) + \sinh($real) * \sinh($real);
|
||||
if ($divisor == 0.0) {
|
||||
throw new InvalidArgumentException('Division by zero');
|
||||
}
|
||||
|
||||
return new Complex(
|
||||
\sinh($real) * \cosh($real) / $divisor,
|
||||
0.5 * \sin(2 * $imaginary) / $divisor,
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the theta of a complex number.
|
||||
* This is the angle in radians from the real axis to the representation of the number in polar coordinates.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return float The theta value of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function theta($complex): float
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0) {
|
||||
if ($complex->isReal()) {
|
||||
return 0.0;
|
||||
} elseif ($complex->getImaginary() < 0.0) {
|
||||
return M_PI / -2;
|
||||
}
|
||||
return M_PI / 2;
|
||||
} elseif ($complex->getReal() > 0.0) {
|
||||
return \atan($complex->getImaginary() / $complex->getReal());
|
||||
} elseif ($complex->getImaginary() < 0.0) {
|
||||
return -(M_PI - \atan(\abs($complex->getImaginary()) / \abs($complex->getReal())));
|
||||
}
|
||||
|
||||
return M_PI - \atan($complex->getImaginary() / \abs($complex->getReal()));
|
||||
}
|
||||
}
|
210
vendor/markbaker/complex/classes/src/Operations.php
vendored
Normal file
210
vendor/markbaker/complex/classes/src/Operations.php
vendored
Normal file
@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
namespace Complex;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Operations
|
||||
{
|
||||
/**
|
||||
* Adds two or more complex numbers
|
||||
*
|
||||
* @param array of string|integer|float|Complex $complexValues The numbers to add
|
||||
* @return Complex
|
||||
*/
|
||||
public static function add(...$complexValues): Complex
|
||||
{
|
||||
if (count($complexValues) < 2) {
|
||||
throw new \Exception('This function requires at least 2 arguments');
|
||||
}
|
||||
|
||||
$base = array_shift($complexValues);
|
||||
$result = clone Complex::validateComplexArgument($base);
|
||||
|
||||
foreach ($complexValues as $complex) {
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($result->isComplex() && $complex->isComplex() &&
|
||||
$result->getSuffix() !== $complex->getSuffix()) {
|
||||
throw new Exception('Suffix Mismatch');
|
||||
}
|
||||
|
||||
$real = $result->getReal() + $complex->getReal();
|
||||
$imaginary = $result->getImaginary() + $complex->getImaginary();
|
||||
|
||||
$result = new Complex(
|
||||
$real,
|
||||
$imaginary,
|
||||
($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides two or more complex numbers
|
||||
*
|
||||
* @param array of string|integer|float|Complex $complexValues The numbers to divide
|
||||
* @return Complex
|
||||
*/
|
||||
public static function divideby(...$complexValues): Complex
|
||||
{
|
||||
if (count($complexValues) < 2) {
|
||||
throw new \Exception('This function requires at least 2 arguments');
|
||||
}
|
||||
|
||||
$base = array_shift($complexValues);
|
||||
$result = clone Complex::validateComplexArgument($base);
|
||||
|
||||
foreach ($complexValues as $complex) {
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($result->isComplex() && $complex->isComplex() &&
|
||||
$result->getSuffix() !== $complex->getSuffix()) {
|
||||
throw new Exception('Suffix Mismatch');
|
||||
}
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
throw new InvalidArgumentException('Division by zero');
|
||||
}
|
||||
|
||||
$delta1 = ($result->getReal() * $complex->getReal()) +
|
||||
($result->getImaginary() * $complex->getImaginary());
|
||||
$delta2 = ($result->getImaginary() * $complex->getReal()) -
|
||||
($result->getReal() * $complex->getImaginary());
|
||||
$delta3 = ($complex->getReal() * $complex->getReal()) +
|
||||
($complex->getImaginary() * $complex->getImaginary());
|
||||
|
||||
$real = $delta1 / $delta3;
|
||||
$imaginary = $delta2 / $delta3;
|
||||
|
||||
$result = new Complex(
|
||||
$real,
|
||||
$imaginary,
|
||||
($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides two or more complex numbers
|
||||
*
|
||||
* @param array of string|integer|float|Complex $complexValues The numbers to divide
|
||||
* @return Complex
|
||||
*/
|
||||
public static function divideinto(...$complexValues): Complex
|
||||
{
|
||||
if (count($complexValues) < 2) {
|
||||
throw new \Exception('This function requires at least 2 arguments');
|
||||
}
|
||||
|
||||
$base = array_shift($complexValues);
|
||||
$result = clone Complex::validateComplexArgument($base);
|
||||
|
||||
foreach ($complexValues as $complex) {
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($result->isComplex() && $complex->isComplex() &&
|
||||
$result->getSuffix() !== $complex->getSuffix()) {
|
||||
throw new Exception('Suffix Mismatch');
|
||||
}
|
||||
if ($result->getReal() == 0.0 && $result->getImaginary() == 0.0) {
|
||||
throw new InvalidArgumentException('Division by zero');
|
||||
}
|
||||
|
||||
$delta1 = ($complex->getReal() * $result->getReal()) +
|
||||
($complex->getImaginary() * $result->getImaginary());
|
||||
$delta2 = ($complex->getImaginary() * $result->getReal()) -
|
||||
($complex->getReal() * $result->getImaginary());
|
||||
$delta3 = ($result->getReal() * $result->getReal()) +
|
||||
($result->getImaginary() * $result->getImaginary());
|
||||
|
||||
$real = $delta1 / $delta3;
|
||||
$imaginary = $delta2 / $delta3;
|
||||
|
||||
$result = new Complex(
|
||||
$real,
|
||||
$imaginary,
|
||||
($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies two or more complex numbers
|
||||
*
|
||||
* @param array of string|integer|float|Complex $complexValues The numbers to multiply
|
||||
* @return Complex
|
||||
*/
|
||||
public static function multiply(...$complexValues): Complex
|
||||
{
|
||||
if (count($complexValues) < 2) {
|
||||
throw new \Exception('This function requires at least 2 arguments');
|
||||
}
|
||||
|
||||
$base = array_shift($complexValues);
|
||||
$result = clone Complex::validateComplexArgument($base);
|
||||
|
||||
foreach ($complexValues as $complex) {
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($result->isComplex() && $complex->isComplex() &&
|
||||
$result->getSuffix() !== $complex->getSuffix()) {
|
||||
throw new Exception('Suffix Mismatch');
|
||||
}
|
||||
|
||||
$real = ($result->getReal() * $complex->getReal()) -
|
||||
($result->getImaginary() * $complex->getImaginary());
|
||||
$imaginary = ($result->getReal() * $complex->getImaginary()) +
|
||||
($result->getImaginary() * $complex->getReal());
|
||||
|
||||
$result = new Complex(
|
||||
$real,
|
||||
$imaginary,
|
||||
($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts two or more complex numbers
|
||||
*
|
||||
* @param array of string|integer|float|Complex $complexValues The numbers to subtract
|
||||
* @return Complex
|
||||
*/
|
||||
public static function subtract(...$complexValues): Complex
|
||||
{
|
||||
if (count($complexValues) < 2) {
|
||||
throw new \Exception('This function requires at least 2 arguments');
|
||||
}
|
||||
|
||||
$base = array_shift($complexValues);
|
||||
$result = clone Complex::validateComplexArgument($base);
|
||||
|
||||
foreach ($complexValues as $complex) {
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($result->isComplex() && $complex->isComplex() &&
|
||||
$result->getSuffix() !== $complex->getSuffix()) {
|
||||
throw new Exception('Suffix Mismatch');
|
||||
}
|
||||
|
||||
$real = $result->getReal() - $complex->getReal();
|
||||
$imaginary = $result->getImaginary() - $complex->getImaginary();
|
||||
|
||||
$result = new Complex(
|
||||
$real,
|
||||
$imaginary,
|
||||
($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user