Spade

Mini Shell

Directory:~$ /home/lmsyaran/public_html/joomla4/
Upload File

[Home] [System Details] [Kill Me]
Current File:~$ /home/lmsyaran/public_html/joomla4/markbaker.tar

complex/classes/src/functions/abs.php000064400000001474151162047100013730
0ustar00<?php

/**
 *
 * Function code for the complex abs() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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
 *
 */
function abs($complex)
{
    return rho($complex);
}
complex/classes/src/functions/acos.php000064400000002051151162047100014100
0ustar00<?php

/**
 *
 * Function code for the complex acos() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace 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.
 */
function acos($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    $square = clone $complex;
    $square = multiply($square, $complex);
    $invsqrt = new Complex(1.0);
    $invsqrt = subtract($invsqrt, $square);
    $invsqrt = sqrt($invsqrt);
    $adjust = new Complex(
        $complex->getReal() - $invsqrt->getImaginary(),
        $complex->getImaginary() + $invsqrt->getReal()
    );
    $log = ln($adjust);

    return new Complex(
        $log->getImaginary(),
        -1 * $log->getReal()
    );
}
complex/classes/src/functions/acosh.php000064400000001630151162047100014252
0ustar00<?php

/**
 *
 * Function code for the complex acosh() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * Returns the inverse hyperbolic cosine of a complex number.
 *
 * @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.
 */
function acosh($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    if ($complex->isReal() && ($complex->getReal() > 1)) {
        return new Complex(\acosh($complex->getReal()));
    }

    $acosh = acos($complex)
        ->reverse();
    if ($acosh->getReal() < 0.0) {
        $acosh = $acosh->invertReal();
    }

    return $acosh;
}
complex/classes/src/functions/acot.php000064400000001364151162047100014107
0ustar00<?php

/**
 *
 * Function code for the complex acot() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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
 */
function acot($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    return atan(inverse($complex));
}
complex/classes/src/functions/acoth.php000064400000001415151162047100014254
0ustar00<?php

/**
 *
 * Function code for the complex acoth() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace 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
 */
function acoth($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    return atanh(inverse($complex));
}
complex/classes/src/functions/acsc.php000064400000001526151162047100014072
0ustar00<?php

/**
 *
 * Function code for the complex acsc() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace 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
 */
function acsc($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    if ($complex->getReal() == 0.0 &&
$complex->getImaginary() == 0.0) {
        return INF;
    }

    return asin(inverse($complex));
}
complex/classes/src/functions/acsch.php000064400000001557151162047100014246
0ustar00<?php

/**
 *
 * Function code for the complex acsch() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace 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
 */
function acsch($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    if ($complex->getReal() == 0.0 &&
$complex->getImaginary() == 0.0) {
        return INF;
    }

    return asinh(inverse($complex));
}
complex/classes/src/functions/argument.php000064400000001474151162047100015005
0ustar00<?php

/**
 *
 * Function code for the complex argument() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace 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
 */
function argument($complex)
{
    return theta($complex);
}
complex/classes/src/functions/asec.php000064400000001522151162047100014070
0ustar00<?php

/**
 *
 * Function code for the complex asec() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace 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
 */
function asec($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    if ($complex->getReal() == 0.0 &&
$complex->getImaginary() == 0.0) {
        return INF;
    }

    return acos(inverse($complex));
}
complex/classes/src/functions/asech.php000064400000001553151162047100014244
0ustar00<?php

/**
 *
 * Function code for the complex asech() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace 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
 */
function asech($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    if ($complex->getReal() == 0.0 &&
$complex->getImaginary() == 0.0) {
        return INF;
    }

    return acosh(inverse($complex));
}
complex/classes/src/functions/asin.php000064400000002010151162047100014100
0ustar00<?php

/**
 *
 * Function code for the complex asin() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace 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.
 */
function asin($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    $square = multiply($complex, $complex);
    $invsqrt = new Complex(1.0);
    $invsqrt = subtract($invsqrt, $square);
    $invsqrt = sqrt($invsqrt);
    $adjust = new Complex(
        $invsqrt->getReal() - $complex->getImaginary(),
        $invsqrt->getImaginary() + $complex->getReal()
    );
    $log = ln($adjust);

    return new Complex(
        $log->getImaginary(),
        -1 * $log->getReal()
    );
}
complex/classes/src/functions/asinh.php000064400000001650151162047100014261
0ustar00<?php

/**
 *
 * Function code for the complex asinh() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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.
 */
function asinh($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 = asin($asinh);
    return $asinh->reverse()
        ->invertImaginary();
}
complex/classes/src/functions/atan.php000064400000002531151162047100014101
0ustar00<?php

/**
 *
 * Function code for the complex atan() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

//include_once 'Math/Complex.php';
//include_once 'Math/ComplexOp.php';

/**
 * 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
 */
function atan($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 = subtract($d1Value, $t1Value);
    $d2Value = add($t1Value, $uValue);
    $uResult = $d1Value->divideBy($d2Value);
    $uResult = ln($uResult);

    return new Complex(
        (($uResult->getImaginary() == M_PI) ? -M_PI :
$uResult->getImaginary()) * -0.5,
        $uResult->getReal() * 0.5,
        $complex->getSuffix()
    );
}
complex/classes/src/functions/atanh.php000064400000002117151162047100014251
0ustar00<?php

/**
 *
 * Function code for the complex atanh() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * Returns the inverse hyperbolic tangent of a complex number.
 *
 * @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.
 */
function atanh($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));
        }
    }

    $iComplex = clone $complex;
    $iComplex = $iComplex->invertImaginary()
        ->reverse();
    return atan($iComplex)
        ->invertReal()
        ->reverse();
}
complex/classes/src/functions/conjugate.php000064400000001370151162047100015135
0ustar00<?php

/**
 *
 * Function code for the complex conjugate() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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.
 */
function conjugate($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    return new Complex(
        $complex->getReal(),
        -1 * $complex->getImaginary(),
        $complex->getSuffix()
    );
}
complex/classes/src/functions/cos.php000064400000001652151162047100013745
0ustar00<?php

/**
 *
 * Function code for the complex cos() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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.
 */
function cos($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    if ($complex->isReal()) {
        return new Complex(\cos($complex->getReal()));
    }

    return conjugate(
        new Complex(
            \cos($complex->getReal()) *
\cosh($complex->getImaginary()),
            \sin($complex->getReal()) *
\sinh($complex->getImaginary()),
            $complex->getSuffix()
        )
    );
}
complex/classes/src/functions/cosh.php000064400000001632151162047100014113
0ustar00<?php

/**
 *
 * Function code for the complex cosh() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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.
 */
function cosh($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()
    );
}
complex/classes/src/functions/cot.php000064400000001522151162047100013742
0ustar00<?php

/**
 *
 * Function code for the complex cot() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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
 */
function cot($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    if ($complex->getReal() == 0.0 &&
$complex->getImaginary() == 0.0) {
        return new Complex(INF);
    }

    return inverse(tan($complex));
}
complex/classes/src/functions/coth.php000064400000001371151162047100014114
0ustar00<?php

/**
 *
 * Function code for the complex coth() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace 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
 */
function coth($complex)
{
    $complex = Complex::validateComplexArgument($complex);
    return inverse(tanh($complex));
}
complex/classes/src/functions/csc.php000064400000001503151162047100013724
0ustar00<?php

/**
 *
 * Function code for the complex csc() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace 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
 */
function csc($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    if ($complex->getReal() == 0.0 &&
$complex->getImaginary() == 0.0) {
        return INF;
    }

    return inverse(sin($complex));
}
complex/classes/src/functions/csch.php000064400000001534151162047100014100
0ustar00<?php

/**
 *
 * Function code for the complex csch() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace 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
 */
function csch($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    if ($complex->getReal() == 0.0 &&
$complex->getImaginary() == 0.0) {
        return INF;
    }

    return inverse(sinh($complex));
}
complex/classes/src/functions/exp.php000064400000001655151162047100013760
0ustar00<?php

/**
 *
 * Function code for the complex exp() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace 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.
 */
function exp($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()
    );
}
complex/classes/src/functions/inverse.php000064400000001577151162047100014642
0ustar00<?php

/**
 *
 * Function code for the complex inverse() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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
 */
function inverse($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);
}
complex/classes/src/functions/ln.php000064400000001703151162047100013567
0ustar00<?php

/**
 *
 * Function code for the complex ln() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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
 */
function ln($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    if (($complex->getReal() == 0.0) &&
($complex->getImaginary() == 0.0)) {
        throw new \InvalidArgumentException();
    }

    return new Complex(
        \log(rho($complex)),
        theta($complex),
        $complex->getSuffix()
    );
}
complex/classes/src/functions/log10.php000064400000002123151162047100014075
0ustar00<?php

/**
 *
 * Function code for the complex log10() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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
 */
function log10($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 ln($complex)
        ->multiply(\log10(Complex::EULER));
}
complex/classes/src/functions/log2.php000064400000002077151162047100014026
0ustar00<?php

/**
 *
 * Function code for the complex log2() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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
 */
function log2($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 ln($complex)
        ->multiply(\log(Complex::EULER, 2));
}
complex/classes/src/functions/negative.php000064400000001415151162047100014760
0ustar00<?php

/**
 *
 * Function code for the complex negative() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * Returns the negative of a complex number.
 *
 * @param     Complex|mixed    $complex    Complex number or a numeric
value.
 * @return    float            The negative value of the complex argument.
 * @throws    Exception        If argument isn't a valid real or
complex number.
 *
 * @see    rho
 *
 */
function negative($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    return new Complex(
        -1 * $complex->getReal(),
        -1 * $complex->getImaginary(),
        $complex->getSuffix()
    );
}
complex/classes/src/functions/pow.php000064400000002431151162047100013762
0ustar00<?php

/**
 *
 * Function code for the complex pow() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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
 */
function pow($complex, $power)
{
    $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());
}
complex/classes/src/functions/rho.php000064400000001531151162047100013745
0ustar00<?php

/**
 *
 * Function code for the complex rho() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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.
 */
function rho($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    return \sqrt(
        ($complex->getReal() * $complex->getReal()) +
        ($complex->getImaginary() * $complex->getImaginary())
    );
}
complex/classes/src/functions/sec.php000064400000001333151162047100013727
0ustar00<?php

/**
 *
 * Function code for the complex sec() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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
 */
function sec($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    return inverse(cos($complex));
}
complex/classes/src/functions/sech.php000064400000001364151162047100014103
0ustar00<?php

/**
 *
 * Function code for the complex sech() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace 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
 */
function sech($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    return inverse(cosh($complex));
}
complex/classes/src/functions/sin.php000064400000001575151162047100013756
0ustar00<?php

/**
 *
 * Function code for the complex sin() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace 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.
 */
function sin($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()
    );
}
complex/classes/src/functions/sinh.php000064400000001626151162047100014123
0ustar00<?php

/**
 *
 * Function code for the complex sinh() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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.
 */
function sinh($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()
    );
}
complex/classes/src/functions/sqrt.php000064400000001471151162047100014151
0ustar00<?php

/**
 *
 * Function code for the complex sqrt() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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.
 */
function sqrt($complex)
{
    $complex = Complex::validateComplexArgument($complex);

    $theta = theta($complex);
    $delta1 = \cos($theta / 2);
    $delta2 = \sin($theta / 2);
    $rho = \sqrt(rho($complex));

    return new Complex($delta1 * $rho, $delta2 * $rho,
$complex->getSuffix());
}
complex/classes/src/functions/tan.php000064400000002326151162047100013742
0ustar00<?php

/**
 *
 * Function code for the complex tan() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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
 */
function tan($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(sech($imaginary)->getReal(), 2) * \tan($real) / $divisor,
        \pow(sec($real)->getReal(), 2) * \tanh($imaginary) / $divisor,
        $complex->getSuffix()
    );
}
complex/classes/src/functions/tanh.php000064400000002156151162047100014113
0ustar00<?php

/**
 *
 * Function code for the complex tanh() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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
 */
function tanh($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()
    );
}
complex/classes/src/functions/theta.php000064400000002375151162047100014271
0ustar00<?php

/**
 *
 * Function code for the complex theta() function
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * 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.
 */
function theta($complex)
{
    $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()));
}
complex/classes/src/operations/add.php000064400000002412151162047100014057
0ustar00<?php

/**
 *
 * Function code for the complex addition operation
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * Adds two or more complex numbers
 *
 * @param     array of string|integer|float|Complex    $complexValues   The
numbers to add
 * @return    Complex
 */
function add(...$complexValues)
{
    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;
}
complex/classes/src/operations/divideby.php000064400000003377151162047100015141
0ustar00<?php

/**
 *
 * Function code for the complex division operation
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * Divides two or more complex numbers
 *
 * @param     array of string|integer|float|Complex    $complexValues   The
numbers to divide
 * @return    Complex
 */
function divideby(...$complexValues)
{
    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;
}
complex/classes/src/operations/divideinto.php000064400000003373151162047100015474
0ustar00<?php

/**
 *
 * Function code for the complex division operation
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * Divides two or more complex numbers
 *
 * @param     array of string|integer|float|Complex    $complexValues   The
numbers to divide
 * @return    Complex
 */
function divideinto(...$complexValues)
{
    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;
}
complex/classes/src/operations/multiply.php000064400000002640151162047100015211
0ustar00<?php

/**
 *
 * Function code for the complex multiplication operation
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * Multiplies two or more complex numbers
 *
 * @param     array of string|integer|float|Complex    $complexValues   The
numbers to multiply
 * @return    Complex
 */
function multiply(...$complexValues)
{
    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;
}
complex/classes/src/operations/subtract.php000064400000002434151162047100015162
0ustar00<?php

/**
 *
 * Function code for the complex subtraction operation
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Complex;

/**
 * Subtracts two or more complex numbers
 *
 * @param     array of string|integer|float|Complex    $complexValues   The
numbers to subtract
 * @return    Complex
 */
function subtract(...$complexValues)
{
    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;
}
complex/classes/src/Complex.php000064400000026030151162047100012555
0ustar00<?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()
    {
        return $this->realPart;
    }

    /**
     * Gets the imaginary part of this complex number
     *
     * @return Float
     */
    public function getImaginary()
    {
        return $this->imaginaryPart;
    }

    /**
     * Gets the suffix of this complex number
     *
     * @return String
     */
    public function getSuffix()
    {
        return $this->suffix;
    }

    /**
     * Returns true if this is a real value, false if a complex value
     *
     * @return Bool
     */
    public function isReal()
    {
        return $this->imaginaryPart == 0.0;
    }

    /**
     * Returns true if this is a complex value, false if a real value
     *
     * @return Bool
     */
    public function isComplex()
    {
        return !$this->isReal();
    }

    public function format()
    {
        $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()
    {
        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)
    {
        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()
    {
        return new Complex(
            $this->imaginaryPart,
            $this->realPart,
            ($this->realPart == 0.0) ? null : $this->suffix
        );
    }

    public function invertImaginary()
    {
        return new Complex(
            $this->realPart,
            $this->imaginaryPart * -1,
            ($this->imaginaryPart == 0.0) ? null : $this->suffix
        );
    }

    public function invertReal()
    {
        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)) {
            $functionName = "\\" . __NAMESPACE__ .
"\\{$functionName}";
            return $functionName($this, ...$arguments);
        }
        // Test for operation calls
        if (in_array($functionName, self::$operations)) {
            $functionName = "\\" . __NAMESPACE__ .
"\\{$functionName}";
            return $functionName($this, ...$arguments);
        }
        throw new Exception('Function or Operation does not
exist');
    }
}
complex/classes/src/Exception.php000064400000000361151162047100013103
0ustar00<?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
{
}
complex/classes/Autoloader.php000064400000002757151162047100012470
0ustar00<?php

namespace Complex;

/**
 *
 * Autoloader for Complex classes
 *
 * @package Complex
 * @copyright  Copyright (c) 2014 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT          MIT
 */
class Autoloader
{
    /**
     * Register the Autoloader with SPL
     *
     */
    public static function Register()
    {
        if (function_exists('__autoload')) {
            //    Register any existing autoloader function with SPL, so we
don't get any clashes
            spl_autoload_register('__autoload');
        }
        //    Register ourselves with SPL
        return spl_autoload_register(['Complex\\Autoloader',
'Load']);
    }


    /**
     * Autoload a class identified by name
     *
     * @param    string    $pClassName    Name of the object to load
     */
    public static function Load($pClassName)
    {
        if ((class_exists($pClassName, false)) || (strpos($pClassName,
'Complex\\') !== 0)) {
            // Either already loaded, or not a Complex class request
            return false;
        }

        $pClassFilePath = __DIR__ . DIRECTORY_SEPARATOR .
                          'src' . DIRECTORY_SEPARATOR .
                          str_replace(['Complex\\',
'\\'], ['', '/'], $pClassName) .
                          '.php';

        if ((file_exists($pClassFilePath) === false) ||
(is_readable($pClassFilePath) === false)) {
            // Can't load
            return false;
        }
        require($pClassFilePath);
    }
}
complex/classes/Bootstrap.php000064400000001706151162047100012337
0ustar00<?php

include_once __DIR__ . '/Autoloader.php';

\Complex\Autoloader::Register();


abstract class FilesystemRegexFilter extends RecursiveRegexIterator
{
    protected $regex;
    public function __construct(RecursiveIterator $it, $regex)
    {
        $this->regex = $regex;
        parent::__construct($it, $regex);
    }
}

class FilenameFilter extends FilesystemRegexFilter
{
    // Filter files against the regex
    public function accept()
    {
        return (!$this->isFile() || preg_match($this->regex,
$this->getFilename()));
    }
}


$srcFolder = __DIR__ . DIRECTORY_SEPARATOR . 'src';
$srcDirectory = new RecursiveDirectoryIterator($srcFolder);

$filteredFileList = new FilenameFilter($srcDirectory,
'/(?:php)$/i');
$filteredFileList = new FilenameFilter($filteredFileList,
'/^(?!.*(Complex|Exception)\.php).*$/i');

foreach (new RecursiveIteratorIterator($filteredFileList) as $file) {
    if ($file->isFile()) {
        include_once $file;
    }
}
matrix/classes/src/functions/adjoint.php000064400000001305151162047100014441
0ustar00<?php

/**
 *
 * Function code for the matrix adjoint() function
 *
 * @copyright  Copyright (c) 2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

/**
 * Returns the adjoint of a matrix or an array.
 *
 * @param Matrix|array $matrix Matrix or an array to treat as a matrix.
 * @return Matrix The new matrix
 * @throws Exception If argument isn't a valid matrix or array.
 */
function adjoint($matrix)
{
    if (is_array($matrix)) {
        $matrix = new Matrix($matrix);
    }
    if (!$matrix instanceof Matrix) {
        throw new Exception('Must be Matrix or array');
    }

    return Functions::adjoint($matrix);
}
matrix/classes/src/functions/antidiagonal.php000064400000001372151162047100015447
0ustar00<?php

/**
 *
 * Function code for the matrix antidiagonal() function
 *
 * @copyright  Copyright (c) 2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Matrix;

/**
 * Returns the antidiagonal of a matrix or an array.
 *
 * @param     Matrix|array     $matrix    Matrix or an array to treat as a
matrix.
 * @return    Matrix           The new matrix
 * @throws    Exception        If argument isn't a valid matrix or
array.
 */
function antidiagonal($matrix)
{
    if (is_array($matrix)) {
        $matrix = new Matrix($matrix);
    }
    if (!$matrix instanceof Matrix) {
        throw new Exception('Must be Matrix or array');
    }

    return Functions::antidiagonal($matrix);
}
matrix/classes/src/functions/cofactors.php000064400000001315151162047100014775
0ustar00<?php

/**
 *
 * Function code for the matrix cofactors() function
 *
 * @copyright  Copyright (c) 2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

/**
 * Returns the cofactors of a matrix or an array.
 *
 * @param Matrix|array $matrix Matrix or an array to treat as a matrix.
 * @return Matrix The new matrix
 * @throws Exception If argument isn't a valid matrix or array.
 */
function cofactors($matrix)
{
    if (is_array($matrix)) {
        $matrix = new Matrix($matrix);
    }
    if (!$matrix instanceof Matrix) {
        throw new Exception('Must be Matrix or array');
    }

    return Functions::cofactors($matrix);
}
matrix/classes/src/functions/determinant.php000064400000001330151162047100015321
0ustar00<?php

/**
 *
 * Function code for the matrix determinant() function
 *
 * @copyright  Copyright (c) 2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

/**
 * Returns the determinant of a matrix or an array.
 *
 * @param Matrix|array $matrix Matrix or an array to treat as a matrix.
 * @return float Matrix determinant
 * @throws Exception If argument isn't a valid matrix or array.
 */
function determinant($matrix)
{
    if (is_array($matrix)) {
        $matrix = new Matrix($matrix);
    }
    if (!$matrix instanceof Matrix) {
        throw new Exception('Must be Matrix or array');
    }

    return Functions::determinant($matrix);
}
matrix/classes/src/functions/diagonal.php000064400000001311151162047100014564
0ustar00<?php

/**
 *
 * Function code for the matrix diagonal() function
 *
 * @copyright  Copyright (c) 2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

/**
 * Returns the diagonal of a matrix or an array.
 *
 * @param Matrix|array $matrix Matrix or an array to treat as a matrix.
 * @return Matrix The new matrix
 * @throws Exception If argument isn't a valid matrix or array.
 */
function diagonal($matrix)
{
    if (is_array($matrix)) {
        $matrix = new Matrix($matrix);
    }
    if (!$matrix instanceof Matrix) {
        throw new Exception('Must be Matrix or array');
    }

    return Functions::diagonal($matrix);
}
matrix/classes/src/functions/identity.php000064400000001316151162047100014644
0ustar00<?php

/**
 *
 * Function code for the matrix identity() function
 *
 * @copyright  Copyright (c) 2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

/**
 * Returns the identity of a matrix or an array.
 *
 * @param Matrix|array $matrix Matrix or an array to treat as a matrix.
 * @return Matrix The identity matrix
 * @throws Exception If argument isn't a valid matrix or array.
 */
function identity($matrix)
{
    if (is_array($matrix)) {
        $matrix = new Matrix($matrix);
    }
    if (!$matrix instanceof Matrix) {
        throw new Exception('Must be Matrix or array');
    }

    return Functions::identity($matrix);
}
matrix/classes/src/functions/inverse.php000064400000001305151162047100014464
0ustar00<?php

/**
 *
 * Function code for the matrix inverse() function
 *
 * @copyright  Copyright (c) 2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

/**
 * Returns the inverse of a matrix or an array.
 *
 * @param Matrix|array $matrix Matrix or an array to treat as a matrix.
 * @return Matrix The new matrix
 * @throws Exception If argument isn't a valid matrix or array.
 */
function inverse($matrix)
{
    if (is_array($matrix)) {
        $matrix = new Matrix($matrix);
    }
    if (!$matrix instanceof Matrix) {
        throw new Exception('Must be Matrix or array');
    }

    return Functions::inverse($matrix);
}
matrix/classes/src/functions/minors.php000064400000001301151162047100014314
0ustar00<?php

/**
 *
 * Function code for the matrix minors() function
 *
 * @copyright  Copyright (c) 2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

/**
 * Returns the minors of a matrix or an array.
 *
 * @param Matrix|array $matrix Matrix or an array to treat as a matrix.
 * @return Matrix The new matrix
 * @throws Exception If argument isn't a valid matrix or array.
 */
function minors($matrix)
{
    if (is_array($matrix)) {
        $matrix = new Matrix($matrix);
    }
    if (!$matrix instanceof Matrix) {
        throw new Exception('Must be Matrix or array');
    }

    return Functions::minors($matrix);
}
matrix/classes/src/functions/trace.php000064400000001305151162047100014107
0ustar00<?php

/**
 *
 * Function code for the matrix trace() function
 *
 * @copyright  Copyright (c) 2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

/**
 * Returns the trace of a matrix or an array.
 *
 * @param Matrix|array $matrix Matrix or an array to treat as a matrix.
 * @return float The trace of the matrix
 * @throws Exception If argument isn't a valid matrix or array.
 */
function trace($matrix)
{
    if (is_array($matrix)) {
        $matrix = new Matrix($matrix);
    }
    if (!$matrix instanceof Matrix) {
        throw new Exception('Must be Matrix or array');
    }

    return Functions::trace($matrix);
}
matrix/classes/src/functions/transpose.php000064400000001324151162047100015030
0ustar00<?php

/**
 *
 * Function code for the matrix transpose() function
 *
 * @copyright  Copyright (c) 2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

/**
 * Returns the transpose of a matrix or an array.
 *
 * @param Matrix|array $matrix Matrix or an array to treat as a matrix.
 * @return Matrix The transposed matrix
 * @throws Exception If argument isn't a valid matrix or array.
 */
function transpose($matrix)
{
    if (is_array($matrix)) {
        $matrix = new Matrix($matrix);
    }
    if (!$matrix instanceof Matrix) {
        throw new Exception('Must be Matrix or array');
    }

    return Functions::transpose($matrix);
}
matrix/classes/src/operations/add.php000064400000001674151162047100013725
0ustar00<?php

/**
 *
 * Function code for the matrix addition operation
 *
 * @copyright  Copyright (c) 2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

use Matrix\Operators\Addition;

/**
 * Adds two or more matrices
 *
 * @param array<int, mixed> $matrixValues The matrices to add
 * @return Matrix
 * @throws Exception
 */
function add(...$matrixValues)
{
    if (count($matrixValues) < 2) {
        throw new Exception('Addition operation requires at least 2
arguments');
    }

    $matrix = array_shift($matrixValues);

    if (is_array($matrix)) {
        $matrix = new Matrix($matrix);
    }
    if (!$matrix instanceof Matrix) {
        throw new Exception('Addition arguments must be Matrix or
array');
    }

    $result = new Addition($matrix);

    foreach ($matrixValues as $matrix) {
        $result->execute($matrix);
    }

    return $result->result();
}
matrix/classes/src/operations/directsum.php000064400000001710151162047100015163
0ustar00<?php

/**
 *
 * Function code for the matrix direct sum operation
 *
 * @copyright  Copyright (c) 2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

use Matrix\Operators\DirectSum;

/**
 * Adds two or more matrices
 *
 * @param array<int, mixed> $matrixValues The matrices to add
 * @return Matrix
 * @throws Exception
 */
function directsum(...$matrixValues)
{
    if (count($matrixValues) < 2) {
        throw new Exception('DirectSum operation requires at least 2
arguments');
    }

    $matrix = array_shift($matrixValues);

    if (is_array($matrix)) {
        $matrix = new Matrix($matrix);
    }
    if (!$matrix instanceof Matrix) {
        throw new Exception('DirectSum arguments must be Matrix or
array');
    }

    $result = new DirectSum($matrix);

    foreach ($matrixValues as $matrix) {
        $result->execute($matrix);
    }

    return $result->result();
}
matrix/classes/src/operations/divideby.php000064400000001723151162047100014767
0ustar00<?php

/**
 *
 * Function code for the matrix division operation
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPComplex)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

use Matrix\Operators\Division;

/**
 * Divides two or more matrix numbers
 *
 * @param array<int, mixed> $matrixValues The matrices to divide
 * @return Matrix
 * @throws Exception
 */
function divideby(...$matrixValues)
{
    if (count($matrixValues) < 2) {
        throw new Exception('Division operation requires at least 2
arguments');
    }

    $matrix = array_shift($matrixValues);

    if (is_array($matrix)) {
        $matrix = new Matrix($matrix);
    }
    if (!$matrix instanceof Matrix) {
        throw new Exception('Division arguments must be Matrix or
array');
    }

    $result = new Division($matrix);

    foreach ($matrixValues as $matrix) {
        $result->execute($matrix);
    }

    return $result->result();
}
matrix/classes/src/operations/divideinto.php000064400000001723151162047100015326
0ustar00<?php

/**
 *
 * Function code for the matrix division operation
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

use Matrix\Operators\Division;

/**
 * Divides two or more matrix numbers
 *
 * @param array<int, mixed> $matrixValues The numbers to divide
 * @return Matrix
 * @throws Exception
 */
function divideinto(...$matrixValues)
{
    if (count($matrixValues) < 2) {
        throw new Exception('Division operation requires at least 2
arguments');
    }

    $matrix = array_shift($matrixValues);

    if (is_array($matrix)) {
        $matrix = new Matrix($matrix);
    }
    if (!$matrix instanceof Matrix) {
        throw new Exception('Division arguments must be Matrix or
array');
    }

    $result = new Division($matrix);

    foreach ($matrixValues as $matrix) {
        $result->execute($matrix);
    }

    return $result->result();
}
matrix/classes/src/operations/multiply.php000064400000001752151162047100015051
0ustar00<?php

/**
 *
 * Function code for the matrix multiplication operation
 *
 * @copyright  Copyright (c) 2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

use Matrix\Operators\Multiplication;

/**
 * Multiplies two or more matrices
 *
 * @param array<int, mixed> $matrixValues The matrices to multiply
 * @return Matrix
 * @throws Exception
 */
function multiply(...$matrixValues)
{
    if (count($matrixValues) < 2) {
        throw new Exception('Multiplication operation requires at
least 2 arguments');
    }

    $matrix = array_shift($matrixValues);

    if (is_array($matrix)) {
        $matrix = new Matrix($matrix);
    }
    if (!$matrix instanceof Matrix) {
        throw new Exception('Multiplication arguments must be Matrix
or array');
    }

    $result = new Multiplication($matrix);

    foreach ($matrixValues as $matrix) {
        $result->execute($matrix);
    }

    return $result->result();
}
matrix/classes/src/operations/subtract.php000064400000001732151162047100015017
0ustar00<?php

/**
 *
 * Function code for the matrix subtraction operation
 *
 * @copyright  Copyright (c) 2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

use Matrix\Operators\Subtraction;

/**
 * Subtracts two or more matrices
 *
 * @param array<int, mixed> $matrixValues The matrices to subtract
 * @return Matrix
 * @throws Exception
 */
function subtract(...$matrixValues)
{
    if (count($matrixValues) < 2) {
        throw new Exception('Subtraction operation requires at least 2
arguments');
    }

    $matrix = array_shift($matrixValues);

    if (is_array($matrix)) {
        $matrix = new Matrix($matrix);
    }
    if (!$matrix instanceof Matrix) {
        throw new Exception('Subtraction arguments must be Matrix or
array');
    }

    $result = new Subtraction($matrix);

    foreach ($matrixValues as $matrix) {
        $result->execute($matrix);
    }

    return $result->result();
}
matrix/classes/src/Operators/Addition.php000064400000003742151162047100014521
0ustar00<?php

namespace Matrix\Operators;

use Matrix\Matrix;
use Matrix\Exception;

class Addition extends Operator
{
    /**
     * Execute the addition
     *
     * @param mixed $value The matrix or numeric value to add to the
current base value
     * @throws Exception If the provided argument is not appropriate for
the operation
     * @return $this The operation object, allowing multiple additions to
be chained
     **/
    public function execute($value)
    {
        if (is_array($value)) {
            $value = new Matrix($value);
        }

        if (is_object($value) && ($value instanceof Matrix)) {
            return $this->addMatrix($value);
        } elseif (is_numeric($value)) {
            return $this->addScalar($value);
        }

        throw new Exception('Invalid argument for addition');
    }

    /**
     * Execute the addition for a scalar
     *
     * @param mixed $value The numeric value to add to the current base
value
     * @return $this The operation object, allowing multiple additions to
be chained
     **/
    protected function addScalar($value)
    {
        for ($row = 0; $row < $this->rows; ++$row) {
            for ($column = 0; $column < $this->columns; ++$column) {
                $this->matrix[$row][$column] += $value;
            }
        }

        return $this;
    }

    /**
     * Execute the addition for a matrix
     *
     * @param Matrix $value The numeric value to add to the current base
value
     * @return $this The operation object, allowing multiple additions to
be chained
     * @throws Exception If the provided argument is not appropriate for
the operation
     **/
    protected function addMatrix(Matrix $value)
    {
        $this->validateMatchingDimensions($value);

        for ($row = 0; $row < $this->rows; ++$row) {
            for ($column = 0; $column < $this->columns; ++$column) {
                $this->matrix[$row][$column] += $value->getValue($row
+ 1, $column + 1);
            }
        }

        return $this;
    }
}
matrix/classes/src/Operators/DirectSum.php000064400000003553151162047100014665
0ustar00<?php

namespace Matrix\Operators;

use Matrix\Matrix;
use Matrix\Exception;

class DirectSum extends Operator
{
    /**
     * Execute the addition
     *
     * @param mixed $value The matrix or numeric value to add to the
current base value
     * @return $this The operation object, allowing multiple additions to
be chained
     * @throws Exception If the provided argument is not appropriate for
the operation
     */
    public function execute($value)
    {
        if (is_array($value)) {
            $value = new Matrix($value);
        }

        if ($value instanceof Matrix) {
            return $this->directSumMatrix($value);
        }

        throw new Exception('Invalid argument for addition');
    }

    /**
     * Execute the direct sum for a matrix
     *
     * @param Matrix $value The numeric value to concatenate/direct sum
with the current base value
     * @return $this The operation object, allowing multiple additions to
be chained
     **/
    private function directSumMatrix($value)
    {
        $originalColumnCount = count($this->matrix[0]);
        $originalRowCount = count($this->matrix);
        $valColumnCount = $value->columns;
        $valRowCount = $value->rows;
        $value = $value->toArray();

        for ($row = 0; $row < $this->rows; ++$row) {
            $this->matrix[$row] = array_merge($this->matrix[$row],
array_fill(0, $valColumnCount, 0));
        }

        $this->matrix = array_merge(
            $this->matrix,
            array_fill(0, $valRowCount, array_fill(0, $originalColumnCount,
0))
        );

        for ($row = $originalRowCount; $row < $originalRowCount +
$valRowCount; ++$row) {
            array_splice(
                $this->matrix[$row],
                $originalColumnCount,
                $valColumnCount,
                $value[$row - $originalRowCount]
            );
        }

        return $this;
    }
}
matrix/classes/src/Operators/Division.php000064400000002125151162047100014544
0ustar00<?php

namespace Matrix\Operators;

use \Matrix\Matrix;
use \Matrix\Functions;
use Matrix\Exception;

class Division extends Multiplication
{
    /**
     * Execute the division
     *
     * @param mixed $value The matrix or numeric value to divide the
current base value by
     * @throws Exception If the provided argument is not appropriate for
the operation
     * @return $this The operation object, allowing multiple divisions to
be chained
     **/
    public function execute($value)
    {
        if (is_array($value)) {
            $value = new Matrix($value);
        }

        if (is_object($value) && ($value instanceof Matrix)) {
            try {
                $value = Functions::inverse($value);
            } catch (Exception $e) {
                throw new Exception('Division can only be calculated
using a matrix with a non-zero determinant');
            }

            return $this->multiplyMatrix($value);
        } elseif (is_numeric($value)) {
            return $this->multiplyScalar(1 / $value);
        }

        throw new Exception('Invalid argument for division');
    }
}
matrix/classes/src/Operators/Multiplication.php000064400000004653151162047100015765
0ustar00<?php

namespace Matrix\Operators;

use Matrix\Matrix;
use \Matrix\Builder;
use Matrix\Exception;

class Multiplication extends Operator
{
    /**
     * Execute the multiplication
     *
     * @param mixed $value The matrix or numeric value to multiply the
current base value by
     * @throws Exception If the provided argument is not appropriate for
the operation
     * @return $this The operation object, allowing multiple
multiplications to be chained
     **/
    public function execute($value)
    {
        if (is_array($value)) {
            $value = new Matrix($value);
        }

        if (is_object($value) && ($value instanceof Matrix)) {
            return $this->multiplyMatrix($value);
        } elseif (is_numeric($value)) {
            return $this->multiplyScalar($value);
        }

        throw new Exception('Invalid argument for
multiplication');
    }

    /**
     * Execute the multiplication for a scalar
     *
     * @param mixed $value The numeric value to multiply with the current
base value
     * @return $this The operation object, allowing multiple mutiplications
to be chained
     **/
    protected function multiplyScalar($value)
    {
        for ($row = 0; $row < $this->rows; ++$row) {
            for ($column = 0; $column < $this->columns; ++$column) {
                $this->matrix[$row][$column] *= $value;
            }
        }

        return $this;
    }

    /**
     * Execute the multiplication for a matrix
     *
     * @param Matrix $value The numeric value to multiply with the current
base value
     * @return $this The operation object, allowing multiple mutiplications
to be chained
     * @throws Exception If the provided argument is not appropriate for
the operation
     **/
    protected function multiplyMatrix(Matrix $value)
    {
        $this->validateReflectingDimensions($value);

        $newRows = $this->rows;
        $newColumns = $value->columns;
        $matrix = Builder::createFilledMatrix(0, $newRows, $newColumns)
            ->toArray();
        for ($row = 0; $row < $newRows; ++$row) {
            for ($column = 0; $column < $newColumns; ++$column) {
                $columnData = $value->getColumns($column +
1)->toArray();
                foreach ($this->matrix[$row] as $key => $valueData) {
                    $matrix[$row][$column] += $valueData *
$columnData[$key][0];
                }
            }
        }
        $this->matrix = $matrix;

        return $this;
    }
}
matrix/classes/src/Operators/Operator.php000064400000003675151162047100014566
0ustar00<?php

namespace Matrix\Operators;

use Matrix\Matrix;
use Matrix\Exception;

abstract class Operator
{
    /**
     * Stored internally as a 2-dimension array of values
     *
     * @property mixed[][] $matrix
     **/
    protected $matrix;

    /**
     * Number of rows in the matrix
     *
     * @property integer $rows
     **/
    protected $rows;

    /**
     * Number of columns in the matrix
     *
     * @property integer $columns
     **/
    protected $columns;

    /**
     * Create an new handler object for the operation
     *
     * @param Matrix $matrix The base Matrix object on which the operation
will be performed
     */
    public function __construct(Matrix $matrix)
    {
        $this->rows = $matrix->rows;
        $this->columns = $matrix->columns;
        $this->matrix = $matrix->toArray();
    }

    /**
     * Compare the dimensions of the matrices being operated on to see if
they are valid for addition/subtraction
     *
     * @param Matrix $matrix The second Matrix object on which the
operation will be performed
     * @throws Exception
     */
    protected function validateMatchingDimensions(Matrix $matrix)
    {
        if (($this->rows != $matrix->rows) || ($this->columns !=
$matrix->columns)) {
            throw new Exception('Matrices have mismatched
dimensions');
        }
    }

    /**
     * Compare the dimensions of the matrices being operated on to see if
they are valid for multiplication/division
     *
     * @param Matrix $matrix The second Matrix object on which the
operation will be performed
     * @throws Exception
     */
    protected function validateReflectingDimensions(Matrix $matrix)
    {
        if ($this->columns != $matrix->rows) {
            throw new Exception('Matrices have mismatched
dimensions');
        }
    }

    /**
     * Return the result of the operation
     *
     * @return Matrix
     */
    public function result()
    {
        return new Matrix($this->matrix);
    }
}
matrix/classes/src/Operators/Subtraction.php000064400000004042151162047100015255
0ustar00<?php

namespace Matrix\Operators;

use Matrix\Matrix;
use Matrix\Exception;

class Subtraction extends Operator
{
    /**
     * Execute the subtraction
     *
     * @param mixed $value The matrix or numeric value to subtract from the
current base value
     * @throws Exception If the provided argument is not appropriate for
the operation
     * @return $this The operation object, allowing multiple subtractions
to be chained
     **/
    public function execute($value)
    {
        if (is_array($value)) {
            $value = new Matrix($value);
        }

        if (is_object($value) && ($value instanceof Matrix)) {
            return $this->subtractMatrix($value);
        } elseif (is_numeric($value)) {
            return $this->subtractScalar($value);
        }

        throw new Exception('Invalid argument for subtraction');
    }

    /**
     * Execute the subtraction for a scalar
     *
     * @param mixed $value The numeric value to subtracted from the current
base value
     * @return $this The operation object, allowing multiple additions to
be chained
     **/
    protected function subtractScalar($value)
    {
        for ($row = 0; $row < $this->rows; ++$row) {
            for ($column = 0; $column < $this->columns; ++$column) {
                $this->matrix[$row][$column] -= $value;
            }
        }

        return $this;
    }

    /**
     * Execute the subtraction for a matrix
     *
     * @param Matrix $value The numeric value to subtract from the current
base value
     * @return $this The operation object, allowing multiple subtractions
to be chained
     * @throws Exception If the provided argument is not appropriate for
the operation
     **/
    protected function subtractMatrix(Matrix $value)
    {
        $this->validateMatchingDimensions($value);

        for ($row = 0; $row < $this->rows; ++$row) {
            for ($column = 0; $column < $this->columns; ++$column) {
                $this->matrix[$row][$column] -= $value->getValue($row
+ 1, $column + 1);
            }
        }

        return $this;
    }
}
matrix/classes/src/Builder.php000064400000003213151162047100012367
0ustar00<?php

/**
 *
 * Class for the creating "special" Matrices
 *
 * @copyright  Copyright (c) 2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

/**
 * Matrix Builder class.
 *
 * @package Matrix
 */
class Builder
{
    /**
     * Create a new matrix of specified dimensions, and filled with a
specified value
     * If the column argument isn't provided, then a square matrix
will be created
     *
     * @param mixed $value
     * @param int $rows
     * @param int|null $columns
     * @return Matrix
     * @throws Exception
     */
    public static function createFilledMatrix($value, $rows, $columns =
null)
    {
        if ($columns === null) {
            $columns = $rows;
        }

        $rows = Matrix::validateRow($rows);
        $columns = Matrix::validateColumn($columns);

        return new Matrix(
            array_fill(
                0,
                $rows,
                array_fill(
                    0,
                    $columns,
                    $value
                )
            )
        );
    }

    /**
     * Create a new identity matrix of specified dimensions
     * This will always be a square matrix, with the number of rows and
columns matching the provided dimension
     *
     * @param int $dimensions
     * @return Matrix
     * @throws Exception
     */
    public static function createIdentityMatrix($dimensions)
    {
        $grid = static::createFilledMatrix(null,
$dimensions)->toArray();

        for ($x = 0; $x < $dimensions; ++$x) {
            $grid[$x][$x] = 1;
        }

        return new Matrix($grid);
    }
}
matrix/classes/src/Exception.php000064400000000357151162047100012745
0ustar00<?php

/**
 * Exception.
 *
 * @copyright  Copyright (c) 2013-2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */
namespace Matrix;

class Exception extends \Exception
{
}
matrix/classes/src/Functions.php000064400000023073151162047100012757
0ustar00<?php

namespace Matrix;

class Functions
{
    /**
     * Calculate the adjoint of the matrix
     *
     * @param Matrix $matrix The matrix whose adjoint we wish to calculate
     * @return Matrix
     *
     * @throws Exception
     */
    private static function getAdjoint(Matrix $matrix)
    {
        return self::transpose(
            self::getCofactors($matrix)
        );
    }

    /**
     * Return the adjoint of this matrix
     * The adjugate, classical adjoint, or adjunct of a square matrix is
the transpose of its cofactor matrix.
     * The adjugate has sometimes been called the "adjoint", but
today the "adjoint" of a matrix normally refers
     *     to its corresponding adjoint operator, which is its conjugate
transpose.
     *
     * @param Matrix $matrix The matrix whose adjoint we wish to calculate
     * @return Matrix
     * @throws Exception
     **/
    public static function adjoint(Matrix $matrix)
    {
        if (!$matrix->isSquare()) {
            throw new Exception('Adjoint can only be calculated for a
square matrix');
        }

        return self::getAdjoint($matrix);
    }

    /**
     * Calculate the cofactors of the matrix
     *
     * @param Matrix $matrix The matrix whose cofactors we wish to
calculate
     * @return Matrix
     *
     * @throws Exception
     */
    private static function getCofactors(Matrix $matrix)
    {
        $cofactors = self::getMinors($matrix);
        $dimensions = $matrix->rows;

        $cof = 1;
        for ($i = 0; $i < $dimensions; ++$i) {
            $cofs = $cof;
            for ($j = 0; $j < $dimensions; ++$j) {
                $cofactors[$i][$j] *= $cofs;
                $cofs = -$cofs;
            }
            $cof = -$cof;
        }

        return new Matrix($cofactors);
    }

    /**
     * Return the cofactors of this matrix
     *
     * @param Matrix $matrix The matrix whose cofactors we wish to
calculate
     * @return Matrix
     *
     * @throws Exception
     */
    public static function cofactors(Matrix $matrix)
    {
        if (!$matrix->isSquare()) {
            throw new Exception('Cofactors can only be calculated for
a square matrix');
        }

        return self::getCofactors($matrix);
    }

    /**
     * @param Matrix $matrix
     * @param int $row
     * @param int $column
     * @return float
     * @throws Exception
     */
    private static function getDeterminantSegment(Matrix $matrix, $row,
$column)
    {
        $tmpMatrix = $matrix->toArray();
        unset($tmpMatrix[$row]);
        array_walk(
            $tmpMatrix,
            function (&$row) use ($column) {
                unset($row[$column]);
            }
        );

        return self::getDeterminant(new Matrix($tmpMatrix));
    }

    /**
     * Calculate the determinant of the matrix
     *
     * @param Matrix $matrix The matrix whose determinant we wish to
calculate
     * @return float
     *
     * @throws Exception
     */
    private static function getDeterminant(Matrix $matrix)
    {
        $dimensions = $matrix->rows;
        $determinant = 0;

        switch ($dimensions) {
            case 1:
                $determinant = $matrix->getValue(1, 1);
                break;
            case 2:
                $determinant = $matrix->getValue(1, 1) *
$matrix->getValue(2, 2) -
                    $matrix->getValue(1, 2) * $matrix->getValue(2,
1);
                break;
            default:
                for ($i = 1; $i <= $dimensions; ++$i) {
                    $det = $matrix->getValue(1, $i) *
self::getDeterminantSegment($matrix, 0, $i - 1);
                    if (($i % 2) == 0) {
                        $determinant -= $det;
                    } else {
                        $determinant += $det;
                    }
                }
                break;
        }

        return $determinant;
    }

    /**
     * Return the determinant of this matrix
     *
     * @param Matrix $matrix The matrix whose determinant we wish to
calculate
     * @return float
     * @throws Exception
     **/
    public static function determinant(Matrix $matrix)
    {
        if (!$matrix->isSquare()) {
            throw new Exception('Determinant can only be calculated
for a square matrix');
        }

        return self::getDeterminant($matrix);
    }

    /**
     * Return the diagonal of this matrix
     *
     * @param Matrix $matrix The matrix whose diagonal we wish to calculate
     * @return Matrix
     * @throws Exception
     **/
    public static function diagonal(Matrix $matrix)
    {
        if (!$matrix->isSquare()) {
            throw new Exception('Diagonal can only be extracted from a
square matrix');
        }

        $dimensions = $matrix->rows;
        $grid = Builder::createFilledMatrix(0, $dimensions, $dimensions)
            ->toArray();

        for ($i = 0; $i < $dimensions; ++$i) {
            $grid[$i][$i] = $matrix->getValue($i + 1, $i + 1);
        }

        return new Matrix($grid);
    }

    /**
     * Return the antidiagonal of this matrix
     *
     * @param Matrix $matrix The matrix whose antidiagonal we wish to
calculate
     * @return Matrix
     * @throws Exception
     **/
    public static function antidiagonal(Matrix $matrix)
    {
        if (!$matrix->isSquare()) {
            throw new Exception('Anti-Diagonal can only be extracted
from a square matrix');
        }

        $dimensions = $matrix->rows;
        $grid = Builder::createFilledMatrix(0, $dimensions, $dimensions)
            ->toArray();

        for ($i = 0; $i < $dimensions; ++$i) {
            $grid[$i][$dimensions - $i - 1] = $matrix->getValue($i + 1,
$dimensions - $i);
        }

        return new Matrix($grid);
    }

    /**
     * Return the identity matrix
     * The identity matrix, or sometimes ambiguously called a unit matrix,
of size n is the n × n square matrix
     *   with ones on the main diagonal and zeros elsewhere
     *
     * @param Matrix $matrix The matrix whose identity we wish to calculate
     * @return Matrix
     * @throws Exception
     **/
    public static function identity(Matrix $matrix)
    {
        if (!$matrix->isSquare()) {
            throw new Exception('Identity can only be created for a
square matrix');
        }

        $dimensions = $matrix->rows;

        return Builder::createIdentityMatrix($dimensions);
    }

    /**
     * Return the inverse of this matrix
     *
     * @param Matrix $matrix The matrix whose inverse we wish to calculate
     * @return Matrix
     * @throws Exception
     **/
    public static function inverse(Matrix $matrix)
    {
        if (!$matrix->isSquare()) {
            throw new Exception('Inverse can only be calculated for a
square matrix');
        }

        $determinant = self::getDeterminant($matrix);
        if ($determinant == 0.0) {
            throw new Exception('Inverse can only be calculated for a
matrix with a non-zero determinant');
        }

        if ($matrix->rows == 1) {
            return new Matrix([[1 / $matrix->getValue(1, 1)]]);
        }

        return self::getAdjoint($matrix)
            ->multiply(1 / $determinant);
    }

    /**
     * Calculate the minors of the matrix
     *
     * @param Matrix $matrix The matrix whose minors we wish to calculate
     * @return array[]
     *
     * @throws Exception
     */
    protected static function getMinors(Matrix $matrix)
    {
        $minors = $matrix->toArray();
        $dimensions = $matrix->rows;
        if ($dimensions == 1) {
            return $minors;
        }

        for ($i = 0; $i < $dimensions; ++$i) {
            for ($j = 0; $j < $dimensions; ++$j) {
                $minors[$i][$j] = self::getDeterminantSegment($matrix, $i,
$j);
            }
        }

        return $minors;
    }

    /**
     * Return the minors of the matrix
     * The minor of a matrix A is the determinant of some smaller square
matrix, cut down from A by removing one or
     *     more of its rows or columns.
     * Minors obtained by removing just one row and one column from square
matrices (first minors) are required for
     *     calculating matrix cofactors, which in turn are useful for
computing both the determinant and inverse of
     *     square matrices.
     *
     * @param Matrix $matrix The matrix whose minors we wish to calculate
     * @return Matrix
     * @throws Exception
     **/
    public static function minors(Matrix $matrix)
    {
        if (!$matrix->isSquare()) {
            throw new Exception('Minors can only be calculated for a
square matrix');
        }

        return new Matrix(self::getMinors($matrix));
    }

    /**
     * Return the trace of this matrix
     * The trace is defined as the sum of the elements on the main diagonal
(the diagonal from the upper left to the lower right)
     *     of the matrix
     *
     * @param Matrix $matrix The matrix whose trace we wish to calculate
     * @return float
     * @throws Exception
     **/
    public static function trace(Matrix $matrix)
    {
        if (!$matrix->isSquare()) {
            throw new Exception('Trace can only be extracted from a
square matrix');
        }

        $dimensions = $matrix->rows;
        $result = 0;
        for ($i = 1; $i <= $dimensions; ++$i) {
            $result += $matrix->getValue($i, $i);
        }

        return $result;
    }

    /**
     * Return the transpose of this matrix
     *
     * @param Matrix $matrix The matrix whose transpose we wish to
calculate
     * @return Matrix
     **/
    public static function transpose(Matrix $matrix)
    {
        $array = array_values(array_merge([null], $matrix->toArray()));
        $grid = call_user_func_array(
            'array_map',
            $array
        );

        return new Matrix($grid);
    }
}
matrix/classes/src/Matrix.php000064400000025255151162047100012257
0ustar00<?php

/**
 *
 * Class for the management of Matrices
 *
 * @copyright  Copyright (c) 2018 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

/**
 * Matrix object.
 *
 * @package Matrix
 *
 * @property-read int $rows The number of rows in the matrix
 * @property-read int $columns The number of columns in the matrix
 * @method Matrix antidiagonal()
 * @method Matrix adjoint()
 * @method Matrix cofactors()
 * @method float determinant()
 * @method Matrix diagonal()
 * @method Matrix identity()
 * @method Matrix inverse()
 * @method Matrix pseudoInverse()
 * @method Matrix minors()
 * @method float trace()
 * @method Matrix transpose()
 * @method Matrix add(...$matrices)
 * @method Matrix subtract(...$matrices)
 * @method Matrix multiply(...$matrices)
 * @method Matrix divideby(...$matrices)
 * @method Matrix divideinto(...$matrices)
 */
class Matrix
{
    protected $rows;
    protected $columns;
    protected $grid = [];

    /*
     * Create a new Matrix object from an array of values
     *
     * @param array $grid
     */
    final public function __construct(array $grid)
    {
        $this->buildFromArray(array_values($grid));
    }

    /*
     * Create a new Matrix object from an array of values
     *
     * @param array $grid
     */
    protected function buildFromArray(array $grid)
    {
        $this->rows = count($grid);
        $columns = array_reduce(
            $grid,
            function ($carry, $value) {
                return max($carry, is_array($value) ? count($value) : 1);
            }
        );
        $this->columns = $columns;

        array_walk(
            $grid,
            function (&$value) use ($columns) {
                if (!is_array($value)) {
                    $value = [$value];
                }
                $value = array_pad(array_values($value), $columns, null);
            }
        );

        $this->grid = $grid;
    }

    /**
     * Validate that a row number is a positive integer
     *
     * @param int $row
     * @return int
     * @throws Exception
     */
    public static function validateRow($row)
    {
        if ((!is_numeric($row)) || (intval($row) < 1)) {
            throw new Exception('Invalid Row');
        }

        return (int)$row;
    }

    /**
     * Validate that a column number is a positive integer
     *
     * @param int $column
     * @return int
     * @throws Exception
     */
    public static function validateColumn($column)
    {
        if ((!is_numeric($column)) || (intval($column) < 1)) {
            throw new Exception('Invalid Column');
        }

        return (int)$column;
    }

    /**
     * Validate that a row number falls within the set of rows for this
matrix
     *
     * @param int $row
     * @return int
     * @throws Exception
     */
    protected function validateRowInRange($row)
    {
        $row = static::validateRow($row);
        if ($row > $this->rows) {
            throw new Exception('Requested Row exceeds matrix
size');
        }

        return $row;
    }

    /**
     * Validate that a column number falls within the set of columns for
this matrix
     *
     * @param int $column
     * @return int
     * @throws Exception
     */
    protected function validateColumnInRange($column)
    {
        $column = static::validateColumn($column);
        if ($column > $this->columns) {
            throw new Exception('Requested Column exceeds matrix
size');
        }

        return $column;
    }

    /**
     * Return a new matrix as a subset of rows from this matrix, starting
at row number $row, and $rowCount rows
     * A $rowCount value of 0 will return all rows of the matrix from $row
     * A negative $rowCount value will return rows until that many rows
from the end of the matrix
     *
     * Note that row numbers start from 1, not from 0
     *
     * @param int $row
     * @param int $rowCount
     * @return static
     * @throws Exception
     */
    public function getRows($row, $rowCount = 1)
    {
        $row = $this->validateRowInRange($row);
        if ($rowCount === 0) {
            $rowCount = $this->rows - $row + 1;
        }

        return new static(array_slice($this->grid, $row - 1,
(int)$rowCount));
    }

    /**
     * Return a new matrix as a subset of columns from this matrix,
starting at column number $column, and $columnCount columns
     * A $columnCount value of 0 will return all columns of the matrix from
$column
     * A negative $columnCount value will return columns until that many
columns from the end of the matrix
     *
     * Note that column numbers start from 1, not from 0
     *
     * @param int $column
     * @param int $columnCount
     * @return Matrix
     * @throws Exception
     */
    public function getColumns($column, $columnCount = 1)
    {
        $column = $this->validateColumnInRange($column);
        if ($columnCount < 1) {
            $columnCount = $this->columns + $columnCount - $column + 1;
        }

        $grid = [];
        for ($i = $column - 1; $i < $column + $columnCount - 1; ++$i) {
            $grid[] = array_column($this->grid, $i);
        }

        return (new static($grid))->transpose();
    }

    /**
     * Return a new matrix as a subset of rows from this matrix, dropping
rows starting at row number $row,
     *     and $rowCount rows
     * A negative $rowCount value will drop rows until that many rows from
the end of the matrix
     * A $rowCount value of 0 will remove all rows of the matrix from $row
     *
     * Note that row numbers start from 1, not from 0
     *
     * @param int $row
     * @param int $rowCount
     * @return static
     * @throws Exception
     */
    public function dropRows($row, $rowCount = 1)
    {
        $this->validateRowInRange($row);
        if ($rowCount === 0) {
            $rowCount = $this->rows - $row + 1;
        }

        $grid = $this->grid;
        array_splice($grid, $row - 1, (int)$rowCount);

        return new static($grid);
    }

    /**
     * Return a new matrix as a subset of columns from this matrix,
dropping columns starting at column number $column,
     *     and $columnCount columns
     * A negative $columnCount value will drop columns until that many
columns from the end of the matrix
     * A $columnCount value of 0 will remove all columns of the matrix from
$column
     *
     * Note that column numbers start from 1, not from 0
     *
     * @param int $column
     * @param int $columnCount
     * @return static
     * @throws Exception
     */
    public function dropColumns($column, $columnCount = 1)
    {
        $this->validateColumnInRange($column);
        if ($columnCount < 1) {
            $columnCount = $this->columns + $columnCount - $column + 1;
        }

        $grid = $this->grid;
        array_walk(
            $grid,
            function (&$row) use ($column, $columnCount) {
                array_splice($row, $column - 1, (int)$columnCount);
            }
        );

        return new static($grid);
    }

    /**
     * Return a value from this matrix, from the "cell"
identified by the row and column numbers
     * Note that row and column numbers start from 1, not from 0
     *
     * @param int $row
     * @param int $column
     * @return mixed
     * @throws Exception
     */
    public function getValue($row, $column)
    {
        $row = $this->validateRowInRange($row);
        $column = $this->validateColumnInRange($column);

        return $this->grid[$row - 1][$column - 1];
    }

    /**
     * Returns a Generator that will yield each row of the matrix in turn
as a vector matrix
     *     or the value of each cell if the matrix is a vector
     *
     * @return \Generator|Matrix[]|mixed[]
     */
    public function rows()
    {
        foreach ($this->grid as $i => $row) {
            yield $i + 1 => ($this->columns == 1)
                ? $row[0]
                : new static([$row]);
        }
    }

    /**
     * Returns a Generator that will yield each column of the matrix in
turn as a vector matrix
     *     or the value of each cell if the matrix is a vector
     *
     * @return \Generator|Matrix[]|mixed[]
     */
    public function columns()
    {
        for ($i = 0; $i < $this->columns; ++$i) {
            yield $i + 1 => ($this->rows == 1)
                ? $this->grid[0][$i]
                : new static(array_column($this->grid, $i));
        }
    }

    /**
     * Identify if the row and column dimensions of this matrix are equal,
     *     i.e. if it is a "square" matrix
     *
     * @return bool
     */
    public function isSquare()
    {
        return $this->rows == $this->columns;
    }

    /**
     * Identify if this matrix is a vector
     *     i.e. if it comprises only a single row or a single column
     *
     * @return bool
     */
    public function isVector()
    {
        return $this->rows == 1 || $this->columns == 1;
    }

    /**
     * Return the matrix as a 2-dimensional array
     *
     * @return array
     */
    public function toArray()
    {
        return $this->grid;
    }

    protected static $getters = [
        'rows',
        'columns',
    ];

    /**
     * Access specific properties as read-only (no setters)
     *
     * @param string $propertyName
     * @return mixed
     * @throws Exception
     */
    public function __get($propertyName)
    {
        $propertyName = strtolower($propertyName);

        // Test for function calls
        if (in_array($propertyName, self::$getters)) {
            return $this->$propertyName;
        }

        throw new Exception('Property does not exist');
    }

    protected static $functions = [
        'antidiagonal',
        'adjoint',
        'cofactors',
        'determinant',
        'diagonal',
        'identity',
        'inverse',
        'minors',
        'trace',
        'transpose',
    ];

    protected static $operations = [
        'add',
        'subtract',
        'multiply',
        'divideby',
        'divideinto',
        'directsum',
    ];

    /**
     * Returns the result of the function call or operation
     *
     * @param string $functionName
     * @param mixed[] $arguments
     * @return Matrix|float
     * @throws Exception
     */
    public function __call($functionName, $arguments)
    {
        $functionName = strtolower(str_replace('_', '',
$functionName));

        if (in_array($functionName, self::$functions) ||
in_array($functionName, self::$operations)) {
            $functionName = "\\" . __NAMESPACE__ .
"\\{$functionName}";
            if (is_callable($functionName)) {
                $arguments = array_values(array_merge([$this],
$arguments));
                return call_user_func_array($functionName, $arguments);
            }
        }
        throw new Exception('Function or Operation does not
exist');
    }
}
matrix/classes/Autoloader.php000064400000002747151162047100012324
0ustar00<?php

namespace Matrix;

/**
 *
 * Autoloader for Matrix classes
 *
 * @package Matrix
 * @copyright  Copyright (c) 2014 Mark Baker
(https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT          MIT
 */
class Autoloader
{
    /**
     * Register the Autoloader with SPL
     *
     */
    public static function Register()
    {
        if (function_exists('__autoload')) {
            //    Register any existing autoloader function with SPL, so we
don't get any clashes
            spl_autoload_register('__autoload');
        }
        //    Register ourselves with SPL
        return spl_autoload_register(['Matrix\\Autoloader',
'Load']);
    }


    /**
     * Autoload a class identified by name
     *
     * @param    string    $pClassName    Name of the object to load
     */
    public static function Load($pClassName)
    {
        if ((class_exists($pClassName, false)) || (strpos($pClassName,
'Matrix\\') !== 0)) {
            // Either already loaded, or not a Matrix class request
            return false;
        }

        $pClassFilePath = __DIR__ . DIRECTORY_SEPARATOR .
                          'src' . DIRECTORY_SEPARATOR .
                          str_replace(['Matrix\\',
'\\'], ['', '/'], $pClassName) .
                          '.php';

        if ((file_exists($pClassFilePath) === false) ||
(is_readable($pClassFilePath) === false)) {
            // Can't load
            return false;
        }
        require($pClassFilePath);
    }
}
matrix/classes/Bootstrap.php000064400000001704151162047100012172
0ustar00<?php

include_once __DIR__ . '/Autoloader.php';

\Matrix\Autoloader::Register();


abstract class FilesystemRegexFilter extends RecursiveRegexIterator
{
    protected $regex;
    public function __construct(RecursiveIterator $it, $regex)
    {
        $this->regex = $regex;
        parent::__construct($it, $regex);
    }
}

class FilenameFilter extends FilesystemRegexFilter
{
    // Filter files against the regex
    public function accept()
    {
        return (!$this->isFile() || preg_match($this->regex,
$this->getFilename()));
    }
}


$srcFolder = __DIR__ . DIRECTORY_SEPARATOR . 'src';
$srcDirectory = new RecursiveDirectoryIterator($srcFolder);

$filteredFileList = new FilenameFilter($srcDirectory,
'/(?:php)$/i');
$filteredFileList = new FilenameFilter($filteredFileList,
'/^(?!.*(Matrix|Exception)\.php).*$/i');

foreach (new RecursiveIteratorIterator($filteredFileList) as $file) {
    if ($file->isFile()) {
        include_once $file;
    }
}
matrix/buildPhar.php000064400000002527151162047100010476 0ustar00<?php

# required: PHP 5.3+ and zlib extension

// ini option check
if (ini_get('phar.readonly')) {
    echo "php.ini: set the 'phar.readonly' option to 0 to
enable phar creation\n";
    exit(1);
}

// output name
$pharName = 'Matrix.phar';

// target folder
$sourceDir = __DIR__ . DIRECTORY_SEPARATOR . 'classes' .
DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR;

// default meta information
$metaData = array(
    'Author'      => 'Mark Baker
<mark@lange.demon.co.uk>',
    'Description' => 'PHP Class for working with Matrix
numbers',
    'Copyright'   => 'Mark Baker (c) 2013-' .
date('Y'),
    'Timestamp'   => time(),
    'Version'     => '0.1.0',
    'Date'        => date('Y-m-d')
);

// cleanup
if (file_exists($pharName)) {
    echo "Removed: {$pharName}\n";
    unlink($pharName);
}

echo "Building phar file...\n";

// the phar object
$phar = new Phar($pharName, null, 'Matrix');
$phar->buildFromDirectory($sourceDir);
$phar->setStub(
<<<'EOT'
<?php
    spl_autoload_register(function ($className) {
        include 'phar://' . $className . '.php';
    });

    try {
        Phar::mapPhar();
    } catch (PharException $e) {
        error_log($e->getMessage());
        exit(1);
    }

    include 'phar://functions/sqrt.php';

    __HALT_COMPILER();
EOT
);
$phar->setMetadata($metaData);
$phar->compressFiles(Phar::GZ);

echo "Complete.\n";

exit();