MDL-71720 lib: Upgrade PHPSpreadSheet to 1.21.0
This commit is contained in:
+1
-1
@@ -4,4 +4,4 @@
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit596026141085fc6d905fff9fde42dc1b::getLoader();
|
||||
return ComposerAutoloaderInit47a82a2b792e78d18b5f54d474d822dc::getLoader();
|
||||
|
||||
+139
-12
@@ -42,21 +42,75 @@ namespace Composer\Autoload;
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var ?string */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<int, string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, string[]>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
/** @var bool */
|
||||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
/** @var bool */
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var bool[]
|
||||
* @psalm-var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var ?string */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var self[]
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param ?string $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
@@ -66,28 +120,47 @@ class ClassLoader
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, array<int, string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[] Array of classname => path
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $classMap Class to filename map
|
||||
* @param string[] $classMap Class to filename map
|
||||
* @psalm-param array<string, string> $classMap
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
@@ -102,9 +175,11 @@ class ClassLoader
|
||||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
* @param string $prefix The prefix
|
||||
* @param string[]|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
@@ -147,11 +222,13 @@ class ClassLoader
|
||||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
@@ -195,8 +272,10 @@ class ClassLoader
|
||||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 base directories
|
||||
* @param string $prefix The prefix
|
||||
* @param string[]|string $paths The PSR-0 base directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
@@ -211,10 +290,12 @@ class ClassLoader
|
||||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
@@ -234,6 +315,8 @@ class ClassLoader
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
@@ -256,6 +339,8 @@ class ClassLoader
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
@@ -276,6 +361,8 @@ class ClassLoader
|
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
@@ -296,25 +383,44 @@ class ClassLoader
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
|
||||
if (null === $this->vendorDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($prepend) {
|
||||
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||
} else {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
|
||||
if (null !== $this->vendorDir) {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return bool|null True if loaded, null otherwise
|
||||
* @return true|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
@@ -323,6 +429,8 @@ class ClassLoader
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -367,6 +475,21 @@ class ClassLoader
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered loaders indexed by their corresponding vendor directories.
|
||||
*
|
||||
* @return self[]
|
||||
*/
|
||||
public static function getRegisteredLoaders()
|
||||
{
|
||||
return self::$registeredLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $ext
|
||||
* @return string|false
|
||||
*/
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
@@ -438,6 +561,10 @@ class ClassLoader
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
* @private
|
||||
*/
|
||||
function includeFile($file)
|
||||
{
|
||||
|
||||
+333
-301
@@ -1,318 +1,350 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <[email protected]>
|
||||
* Jordi Boggiano <[email protected]>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Composer\Semver\VersionParser;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This class is copied in every Composer installed project and available to all
|
||||
*
|
||||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
private static $installed = array (
|
||||
'root' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '70d1b7d67bc280b21f450db41728869bd1bda8d8',
|
||||
'name' => '__root__',
|
||||
),
|
||||
'versions' =>
|
||||
array (
|
||||
'__root__' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '70d1b7d67bc280b21f450db41728869bd1bda8d8',
|
||||
),
|
||||
'ezyang/htmlpurifier' =>
|
||||
array (
|
||||
'pretty_version' => 'v4.13.0',
|
||||
'version' => '4.13.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '08e27c97e4c6ed02f37c5b2b20488046c8d90d75',
|
||||
),
|
||||
'maennchen/zipstream-php' =>
|
||||
array (
|
||||
'pretty_version' => '2.1.0',
|
||||
'version' => '2.1.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'c4c5803cc1f93df3d2448478ef79394a5981cc58',
|
||||
),
|
||||
'markbaker/complex' =>
|
||||
array (
|
||||
'pretty_version' => '2.0.0',
|
||||
'version' => '2.0.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '9999f1432fae467bc93c53f357105b4c31bb994c',
|
||||
),
|
||||
'markbaker/matrix' =>
|
||||
array (
|
||||
'pretty_version' => '2.0.0',
|
||||
'version' => '2.0.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '9567d9c4c519fbe40de01dbd1e4469dbbb66f46a',
|
||||
),
|
||||
'myclabs/php-enum' =>
|
||||
array (
|
||||
'pretty_version' => '1.7.7',
|
||||
'version' => '1.7.7.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'd178027d1e679832db9f38248fcc7200647dc2b7',
|
||||
),
|
||||
'phpoffice/phpspreadsheet' =>
|
||||
array (
|
||||
'pretty_version' => '1.16.0',
|
||||
'version' => '1.16.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '76d4323b85129d0c368149c831a07a3e258b2b50',
|
||||
),
|
||||
'psr/http-client' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621',
|
||||
),
|
||||
'psr/http-factory' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be',
|
||||
),
|
||||
'psr/http-message' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
|
||||
),
|
||||
'psr/simple-cache' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
|
||||
),
|
||||
'symfony/polyfill-mbstring' =>
|
||||
array (
|
||||
'pretty_version' => 'v1.22.0',
|
||||
'version' => '1.22.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'f377a3dd1fde44d37b9831d68dc8dea3ffd28e13',
|
||||
),
|
||||
),
|
||||
);
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private static $canGetVendors;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
private static $installedByVendor = array();
|
||||
|
||||
/**
|
||||
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||
*
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackages()
|
||||
{
|
||||
$packages = array();
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
$packages[] = array_keys($installed['versions']);
|
||||
}
|
||||
|
||||
if (1 === \count($packages)) {
|
||||
return $packages[0];
|
||||
}
|
||||
|
||||
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all package names with a specific type e.g. 'library'
|
||||
*
|
||||
* @param string $type
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackagesByType($type)
|
||||
{
|
||||
$packagesByType = array();
|
||||
|
||||
public static function getInstalledPackages()
|
||||
{
|
||||
return array_keys(self::$installed['versions']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static function isInstalled($packageName)
|
||||
{
|
||||
return isset(self::$installed['versions'][$packageName]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||
{
|
||||
$constraint = $parser->parseConstraints($constraint);
|
||||
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||
|
||||
return $provided->matches($constraint);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static function getVersionRanges($packageName)
|
||||
{
|
||||
if (!isset(self::$installed['versions'][$packageName])) {
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
$ranges = array();
|
||||
if (isset(self::$installed['versions'][$packageName]['pretty_version'])) {
|
||||
$ranges[] = self::$installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
if (array_key_exists('aliases', self::$installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['aliases']);
|
||||
}
|
||||
if (array_key_exists('replaced', self::$installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['replaced']);
|
||||
}
|
||||
if (array_key_exists('provided', self::$installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['provided']);
|
||||
}
|
||||
|
||||
return implode(' || ', $ranges);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static function getVersion($packageName)
|
||||
{
|
||||
if (!isset(self::$installed['versions'][$packageName])) {
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
if (!isset(self::$installed['versions'][$packageName]['version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::$installed['versions'][$packageName]['version'];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static function getPrettyVersion($packageName)
|
||||
{
|
||||
if (!isset(self::$installed['versions'][$packageName])) {
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
if (!isset(self::$installed['versions'][$packageName]['pretty_version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::$installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static function getReference($packageName)
|
||||
{
|
||||
if (!isset(self::$installed['versions'][$packageName])) {
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
if (!isset(self::$installed['versions'][$packageName]['reference'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::$installed['versions'][$packageName]['reference'];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static function getRootPackage()
|
||||
{
|
||||
return self::$installed['root'];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static function getRawData()
|
||||
{
|
||||
return self::$installed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static function reload($data)
|
||||
{
|
||||
self::$installed = $data;
|
||||
}
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
foreach ($installed['versions'] as $name => $package) {
|
||||
if (isset($package['type']) && $package['type'] === $type) {
|
||||
$packagesByType[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $packagesByType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package is installed
|
||||
*
|
||||
* This also returns true if the package name is provided or replaced by another package
|
||||
*
|
||||
* @param string $packageName
|
||||
* @param bool $includeDevRequirements
|
||||
* @return bool
|
||||
*/
|
||||
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (isset($installed['versions'][$packageName])) {
|
||||
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package satisfies a version constraint
|
||||
*
|
||||
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||
*
|
||||
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||
*
|
||||
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||
* @param string $packageName
|
||||
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||
* @return bool
|
||||
*/
|
||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||
{
|
||||
$constraint = $parser->parseConstraints($constraint);
|
||||
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||
|
||||
return $provided->matches($constraint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||
*
|
||||
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||
* whether a given version of a package is installed, and not just whether it exists
|
||||
*
|
||||
* @param string $packageName
|
||||
* @return string Version constraint usable with composer/semver
|
||||
*/
|
||||
public static function getVersionRanges($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ranges = array();
|
||||
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||
}
|
||||
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||
}
|
||||
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||
}
|
||||
|
||||
return implode(' || ', $ranges);
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getPrettyVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||
*/
|
||||
public static function getReference($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['reference'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||
*/
|
||||
public static function getInstallPath($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
$installed = self::getInstalled();
|
||||
|
||||
return $installed[0]['root'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw installed.php data for custom implementations
|
||||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = include __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$installed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
return self::getInstalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets you reload the static array from another file
|
||||
*
|
||||
* This is only useful for complex integrations in which a project needs to use
|
||||
* this class but then also needs to execute another project's autoloader in process,
|
||||
* and wants to ensure both projects have access to their version of installed.php.
|
||||
*
|
||||
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||
* the data it needs from this class, then call reload() with
|
||||
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||
* the project in which it runs can then also use this class safely, without
|
||||
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||
*
|
||||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
self::$installed = $data;
|
||||
self::$installedByVendor = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
if (null === self::$canGetVendors) {
|
||||
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||
}
|
||||
|
||||
$installed = array();
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir];
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
|
||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $installed[count($installed) - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = require __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
$installed[] = self::$installed;
|
||||
|
||||
return $installed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
|
||||
// autoload_files.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'9d8e013a5160a09477beb8e44f8ae97b' => $vendorDir . '/markbaker/matrix/classes/src/functions/adjoint.php',
|
||||
'6e78d1bdea6248d6aa117229efae50f2' => $vendorDir . '/markbaker/matrix/classes/src/functions/antidiagonal.php',
|
||||
'4623d87924d94f5412fe5afbf1cef31d' => $vendorDir . '/markbaker/matrix/classes/src/functions/cofactors.php',
|
||||
'901fd1f6950a637ca85f66b701a45e13' => $vendorDir . '/markbaker/matrix/classes/src/functions/determinant.php',
|
||||
'83057abc0e4acc99ba80154ee5d02a49' => $vendorDir . '/markbaker/matrix/classes/src/functions/diagonal.php',
|
||||
'07b7fd7a434451149b4fd477fca0ce06' => $vendorDir . '/markbaker/matrix/classes/src/functions/identity.php',
|
||||
'c8d43b340583e07ae89f2a3baef2cf89' => $vendorDir . '/markbaker/matrix/classes/src/functions/inverse.php',
|
||||
'499bb10ed7a3aee2ba4c09a31a85e8d1' => $vendorDir . '/markbaker/matrix/classes/src/functions/minors.php',
|
||||
'1cad2e6414d652e8b1c64e8967f6f37d' => $vendorDir . '/markbaker/matrix/classes/src/functions/trace.php',
|
||||
'95a7f134ac17161d07def442b3b737e8' => $vendorDir . '/markbaker/matrix/classes/src/functions/transpose.php',
|
||||
'b3a6bc628377118d4b4b8ba08d1eb949' => $vendorDir . '/markbaker/matrix/classes/src/operations/add.php',
|
||||
'5fef6d0e407f3f8887266dfa4a6c534c' => $vendorDir . '/markbaker/matrix/classes/src/operations/directsum.php',
|
||||
'684ba247e1385946e3babdaa054119de' => $vendorDir . '/markbaker/matrix/classes/src/operations/subtract.php',
|
||||
'aa53dcba601214d17ad405b7c291b7e8' => $vendorDir . '/markbaker/matrix/classes/src/operations/multiply.php',
|
||||
'75c79eb1b25749b05a47976f32b0d8a2' => $vendorDir . '/markbaker/matrix/classes/src/operations/divideby.php',
|
||||
'6ab8ad87a734f276a6bcd5a0fe1289be' => $vendorDir . '/markbaker/matrix/classes/src/operations/divideinto.php',
|
||||
'abede361264e2ae69ec1eee813a101af' => $vendorDir . '/markbaker/complex/classes/src/functions/abs.php',
|
||||
'21a5860fbef5be28db5ddfbc3cca67c4' => $vendorDir . '/markbaker/complex/classes/src/functions/acos.php',
|
||||
'1546e3f9d127f2a9bb2d1b6c31c26ef1' => $vendorDir . '/markbaker/complex/classes/src/functions/acosh.php',
|
||||
'd2516f7f4fba5ea5905f494b4a8262e0' => $vendorDir . '/markbaker/complex/classes/src/functions/acot.php',
|
||||
'4511163d560956219b96882c0980b65e' => $vendorDir . '/markbaker/complex/classes/src/functions/acoth.php',
|
||||
'c361f5616dc2a8da4fa3e137077cd4ea' => $vendorDir . '/markbaker/complex/classes/src/functions/acsc.php',
|
||||
'02d68920fc98da71991ce569c91df0f6' => $vendorDir . '/markbaker/complex/classes/src/functions/acsch.php',
|
||||
'88e19525eae308b4a6aa3419364875d3' => $vendorDir . '/markbaker/complex/classes/src/functions/argument.php',
|
||||
'60e8e2d0827b58bfc904f13957e51849' => $vendorDir . '/markbaker/complex/classes/src/functions/asec.php',
|
||||
'13d2f040713999eab66c359b4d79871d' => $vendorDir . '/markbaker/complex/classes/src/functions/asech.php',
|
||||
'838ab38beb32c68a79d3cd2c007d5a04' => $vendorDir . '/markbaker/complex/classes/src/functions/asin.php',
|
||||
'bb28eccd0f8f008333a1b3c163d604ac' => $vendorDir . '/markbaker/complex/classes/src/functions/asinh.php',
|
||||
'9e483de83558c98f7d3feaa402c78cb3' => $vendorDir . '/markbaker/complex/classes/src/functions/atan.php',
|
||||
'36b74b5b765ded91ee58c8ee3c0e85e3' => $vendorDir . '/markbaker/complex/classes/src/functions/atanh.php',
|
||||
'05c15ee9510da7fd6bf6136f436500c0' => $vendorDir . '/markbaker/complex/classes/src/functions/conjugate.php',
|
||||
'd3208dfbce2505e370788f9f22f6785f' => $vendorDir . '/markbaker/complex/classes/src/functions/cos.php',
|
||||
'141cf1fb3a3046f8b64534b0ebab33ca' => $vendorDir . '/markbaker/complex/classes/src/functions/cosh.php',
|
||||
'be660df75fd0dbe7fa7c03b7434b3294' => $vendorDir . '/markbaker/complex/classes/src/functions/cot.php',
|
||||
'01e31ea298a51bc9e91517e3ce6b9e76' => $vendorDir . '/markbaker/complex/classes/src/functions/coth.php',
|
||||
'803ddd97f7b1da68982a7b087c3476f6' => $vendorDir . '/markbaker/complex/classes/src/functions/csc.php',
|
||||
'3001cdfd101ec3c32da34ee43c2e149b' => $vendorDir . '/markbaker/complex/classes/src/functions/csch.php',
|
||||
'77b2d7629ef2a93fabb8c56754a91051' => $vendorDir . '/markbaker/complex/classes/src/functions/exp.php',
|
||||
'4a4471296dec796c21d4f4b6552396a9' => $vendorDir . '/markbaker/complex/classes/src/functions/inverse.php',
|
||||
'c3e9897e1744b88deb56fcdc39d34d85' => $vendorDir . '/markbaker/complex/classes/src/functions/ln.php',
|
||||
'a83cacf2de942cff288de15a83afd26d' => $vendorDir . '/markbaker/complex/classes/src/functions/log2.php',
|
||||
'6a861dacc9ee2f3061241d4c7772fa21' => $vendorDir . '/markbaker/complex/classes/src/functions/log10.php',
|
||||
'4d2522d968c8ba78d6c13548a1b4200e' => $vendorDir . '/markbaker/complex/classes/src/functions/negative.php',
|
||||
'fd587ca933fc0447fa5ab4843bdd97f7' => $vendorDir . '/markbaker/complex/classes/src/functions/pow.php',
|
||||
'383ef01c62028fc78cd4388082fce3c2' => $vendorDir . '/markbaker/complex/classes/src/functions/rho.php',
|
||||
'150fbd1b95029dc47292da97ecab9375' => $vendorDir . '/markbaker/complex/classes/src/functions/sec.php',
|
||||
'549abd9bae174286d660bdaa07407c68' => $vendorDir . '/markbaker/complex/classes/src/functions/sech.php',
|
||||
'6bfbf5eaea6b17a0ed85cb21ba80370c' => $vendorDir . '/markbaker/complex/classes/src/functions/sin.php',
|
||||
'22efe13f1a497b8e199540ae2d9dc59c' => $vendorDir . '/markbaker/complex/classes/src/functions/sinh.php',
|
||||
'e90135ab8e787795a509ed7147de207d' => $vendorDir . '/markbaker/complex/classes/src/functions/sqrt.php',
|
||||
'bb0a7923ffc6a90919cd64ec54ff06bc' => $vendorDir . '/markbaker/complex/classes/src/functions/tan.php',
|
||||
'2d302f32ce0fd4e433dd91c5bb404a28' => $vendorDir . '/markbaker/complex/classes/src/functions/tanh.php',
|
||||
'24dd4658a952171a4ee79218c4f9fd06' => $vendorDir . '/markbaker/complex/classes/src/functions/theta.php',
|
||||
'e49b7876281d6f5bc39536dde96d1f4a' => $vendorDir . '/markbaker/complex/classes/src/operations/add.php',
|
||||
'47596e02b43cd6da7700134fd08f88cf' => $vendorDir . '/markbaker/complex/classes/src/operations/subtract.php',
|
||||
'883af48563631547925fa4c3b48ead07' => $vendorDir . '/markbaker/complex/classes/src/operations/multiply.php',
|
||||
'f190e3308e6ca23234a2875edc985c03' => $vendorDir . '/markbaker/complex/classes/src/operations/divideby.php',
|
||||
'ac9e33ce6841aa5bf5d16d465a2f03a7' => $vendorDir . '/markbaker/complex/classes/src/operations/divideinto.php',
|
||||
);
|
||||
@@ -5,4 +5,5 @@
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array();
|
||||
return array(
|
||||
);
|
||||
|
||||
@@ -6,13 +6,10 @@ $vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'ZipStream\\' => array($vendorDir . '/maennchen/zipstream-php/src'),
|
||||
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
|
||||
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
|
||||
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'),
|
||||
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
|
||||
'PhpOffice\\PhpSpreadsheet\\' => array($vendorDir . '/phpoffice/phpspreadsheet/src/PhpSpreadsheet'),
|
||||
'MyCLabs\\Enum\\' => array($vendorDir . '/myclabs/php-enum/src'),
|
||||
'Matrix\\' => array($vendorDir . '/markbaker/matrix/classes/src'),
|
||||
'Complex\\' => array($vendorDir . '/markbaker/complex/classes/src'),
|
||||
);
|
||||
|
||||
+5
-23
@@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit596026141085fc6d905fff9fde42dc1b
|
||||
class ComposerAutoloaderInit47a82a2b792e78d18b5f54d474d822dc
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
@@ -24,15 +24,15 @@ class ComposerAutoloaderInit596026141085fc6d905fff9fde42dc1b
|
||||
|
||||
require __DIR__ . '/platform_check.php';
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit596026141085fc6d905fff9fde42dc1b', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit596026141085fc6d905fff9fde42dc1b', 'loadClassLoader'));
|
||||
spl_autoload_register(array('ComposerAutoloaderInit47a82a2b792e78d18b5f54d474d822dc', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit47a82a2b792e78d18b5f54d474d822dc', 'loadClassLoader'));
|
||||
|
||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
||||
if ($useStaticLoader) {
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit596026141085fc6d905fff9fde42dc1b::getInitializer($loader));
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit47a82a2b792e78d18b5f54d474d822dc::getInitializer($loader));
|
||||
} else {
|
||||
$map = require __DIR__ . '/autoload_namespaces.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
@@ -52,24 +52,6 @@ class ComposerAutoloaderInit596026141085fc6d905fff9fde42dc1b
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
if ($useStaticLoader) {
|
||||
$includeFiles = Composer\Autoload\ComposerStaticInit596026141085fc6d905fff9fde42dc1b::$files;
|
||||
} else {
|
||||
$includeFiles = require __DIR__ . '/autoload_files.php';
|
||||
}
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequire596026141085fc6d905fff9fde42dc1b($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
||||
function composerRequire596026141085fc6d905fff9fde42dc1b($fileIdentifier, $file)
|
||||
{
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
require $file;
|
||||
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-97
@@ -4,78 +4,9 @@
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit596026141085fc6d905fff9fde42dc1b
|
||||
class ComposerStaticInit47a82a2b792e78d18b5f54d474d822dc
|
||||
{
|
||||
public static $files = array (
|
||||
'9d8e013a5160a09477beb8e44f8ae97b' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/adjoint.php',
|
||||
'6e78d1bdea6248d6aa117229efae50f2' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/antidiagonal.php',
|
||||
'4623d87924d94f5412fe5afbf1cef31d' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/cofactors.php',
|
||||
'901fd1f6950a637ca85f66b701a45e13' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/determinant.php',
|
||||
'83057abc0e4acc99ba80154ee5d02a49' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/diagonal.php',
|
||||
'07b7fd7a434451149b4fd477fca0ce06' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/identity.php',
|
||||
'c8d43b340583e07ae89f2a3baef2cf89' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/inverse.php',
|
||||
'499bb10ed7a3aee2ba4c09a31a85e8d1' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/minors.php',
|
||||
'1cad2e6414d652e8b1c64e8967f6f37d' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/trace.php',
|
||||
'95a7f134ac17161d07def442b3b737e8' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/transpose.php',
|
||||
'b3a6bc628377118d4b4b8ba08d1eb949' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/add.php',
|
||||
'5fef6d0e407f3f8887266dfa4a6c534c' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/directsum.php',
|
||||
'684ba247e1385946e3babdaa054119de' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/subtract.php',
|
||||
'aa53dcba601214d17ad405b7c291b7e8' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/multiply.php',
|
||||
'75c79eb1b25749b05a47976f32b0d8a2' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/divideby.php',
|
||||
'6ab8ad87a734f276a6bcd5a0fe1289be' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/divideinto.php',
|
||||
'abede361264e2ae69ec1eee813a101af' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/abs.php',
|
||||
'21a5860fbef5be28db5ddfbc3cca67c4' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/acos.php',
|
||||
'1546e3f9d127f2a9bb2d1b6c31c26ef1' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/acosh.php',
|
||||
'd2516f7f4fba5ea5905f494b4a8262e0' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/acot.php',
|
||||
'4511163d560956219b96882c0980b65e' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/acoth.php',
|
||||
'c361f5616dc2a8da4fa3e137077cd4ea' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/acsc.php',
|
||||
'02d68920fc98da71991ce569c91df0f6' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/acsch.php',
|
||||
'88e19525eae308b4a6aa3419364875d3' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/argument.php',
|
||||
'60e8e2d0827b58bfc904f13957e51849' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/asec.php',
|
||||
'13d2f040713999eab66c359b4d79871d' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/asech.php',
|
||||
'838ab38beb32c68a79d3cd2c007d5a04' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/asin.php',
|
||||
'bb28eccd0f8f008333a1b3c163d604ac' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/asinh.php',
|
||||
'9e483de83558c98f7d3feaa402c78cb3' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/atan.php',
|
||||
'36b74b5b765ded91ee58c8ee3c0e85e3' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/atanh.php',
|
||||
'05c15ee9510da7fd6bf6136f436500c0' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/conjugate.php',
|
||||
'd3208dfbce2505e370788f9f22f6785f' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/cos.php',
|
||||
'141cf1fb3a3046f8b64534b0ebab33ca' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/cosh.php',
|
||||
'be660df75fd0dbe7fa7c03b7434b3294' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/cot.php',
|
||||
'01e31ea298a51bc9e91517e3ce6b9e76' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/coth.php',
|
||||
'803ddd97f7b1da68982a7b087c3476f6' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/csc.php',
|
||||
'3001cdfd101ec3c32da34ee43c2e149b' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/csch.php',
|
||||
'77b2d7629ef2a93fabb8c56754a91051' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/exp.php',
|
||||
'4a4471296dec796c21d4f4b6552396a9' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/inverse.php',
|
||||
'c3e9897e1744b88deb56fcdc39d34d85' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/ln.php',
|
||||
'a83cacf2de942cff288de15a83afd26d' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/log2.php',
|
||||
'6a861dacc9ee2f3061241d4c7772fa21' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/log10.php',
|
||||
'4d2522d968c8ba78d6c13548a1b4200e' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/negative.php',
|
||||
'fd587ca933fc0447fa5ab4843bdd97f7' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/pow.php',
|
||||
'383ef01c62028fc78cd4388082fce3c2' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/rho.php',
|
||||
'150fbd1b95029dc47292da97ecab9375' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/sec.php',
|
||||
'549abd9bae174286d660bdaa07407c68' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/sech.php',
|
||||
'6bfbf5eaea6b17a0ed85cb21ba80370c' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/sin.php',
|
||||
'22efe13f1a497b8e199540ae2d9dc59c' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/sinh.php',
|
||||
'e90135ab8e787795a509ed7147de207d' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/sqrt.php',
|
||||
'bb0a7923ffc6a90919cd64ec54ff06bc' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/tan.php',
|
||||
'2d302f32ce0fd4e433dd91c5bb404a28' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/tanh.php',
|
||||
'24dd4658a952171a4ee79218c4f9fd06' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/theta.php',
|
||||
'e49b7876281d6f5bc39536dde96d1f4a' => __DIR__ . '/..' . '/markbaker/complex/classes/src/operations/add.php',
|
||||
'47596e02b43cd6da7700134fd08f88cf' => __DIR__ . '/..' . '/markbaker/complex/classes/src/operations/subtract.php',
|
||||
'883af48563631547925fa4c3b48ead07' => __DIR__ . '/..' . '/markbaker/complex/classes/src/operations/multiply.php',
|
||||
'f190e3308e6ca23234a2875edc985c03' => __DIR__ . '/..' . '/markbaker/complex/classes/src/operations/divideby.php',
|
||||
'ac9e33ce6841aa5bf5d16d465a2f03a7' => __DIR__ . '/..' . '/markbaker/complex/classes/src/operations/divideinto.php',
|
||||
);
|
||||
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'Z' =>
|
||||
array (
|
||||
'ZipStream\\' => 10,
|
||||
),
|
||||
'S' =>
|
||||
array (
|
||||
'Symfony\\Polyfill\\Mbstring\\' => 26,
|
||||
),
|
||||
'P' =>
|
||||
array (
|
||||
'Psr\\SimpleCache\\' => 16,
|
||||
@@ -85,7 +16,6 @@ class ComposerStaticInit596026141085fc6d905fff9fde42dc1b
|
||||
),
|
||||
'M' =>
|
||||
array (
|
||||
'MyCLabs\\Enum\\' => 13,
|
||||
'Matrix\\' => 7,
|
||||
),
|
||||
'C' =>
|
||||
@@ -95,14 +25,6 @@ class ComposerStaticInit596026141085fc6d905fff9fde42dc1b
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'ZipStream\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/maennchen/zipstream-php/src',
|
||||
),
|
||||
'Symfony\\Polyfill\\Mbstring\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
|
||||
),
|
||||
'Psr\\SimpleCache\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/simple-cache/src',
|
||||
@@ -120,10 +42,6 @@ class ComposerStaticInit596026141085fc6d905fff9fde42dc1b
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/phpoffice/phpspreadsheet/src/PhpSpreadsheet',
|
||||
),
|
||||
'MyCLabs\\Enum\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/myclabs/php-enum/src',
|
||||
),
|
||||
'Matrix\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/markbaker/matrix/classes/src',
|
||||
@@ -134,16 +52,6 @@ class ComposerStaticInit596026141085fc6d905fff9fde42dc1b
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixesPsr0 = array (
|
||||
'H' =>
|
||||
array (
|
||||
'HTMLPurifier' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/ezyang/htmlpurifier/library',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
);
|
||||
@@ -151,10 +59,9 @@ class ComposerStaticInit596026141085fc6d905fff9fde42dc1b
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit596026141085fc6d905fff9fde42dc1b::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit596026141085fc6d905fff9fde42dc1b::$prefixDirsPsr4;
|
||||
$loader->prefixesPsr0 = ComposerStaticInit596026141085fc6d905fff9fde42dc1b::$prefixesPsr0;
|
||||
$loader->classMap = ComposerStaticInit596026141085fc6d905fff9fde42dc1b::$classMap;
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit47a82a2b792e78d18b5f54d474d822dc::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit47a82a2b792e78d18b5f54d474d822dc::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInit47a82a2b792e78d18b5f54d474d822dc::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
|
||||
+35
-375
@@ -1,149 +1,18 @@
|
||||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "ezyang/htmlpurifier",
|
||||
"version": "v4.13.0",
|
||||
"version_normalized": "4.13.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ezyang/htmlpurifier.git",
|
||||
"reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
|
||||
"reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd"
|
||||
},
|
||||
"time": "2020-06-29T00:56:53+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"HTMLPurifier": "library/"
|
||||
},
|
||||
"files": [
|
||||
"library/HTMLPurifier.composer.php"
|
||||
],
|
||||
"exclude-from-classmap": [
|
||||
"/library/HTMLPurifier/Language/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-2.1-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Edward Z. Yang",
|
||||
"email": "[email protected]",
|
||||
"homepage": "http://ezyang.com"
|
||||
}
|
||||
],
|
||||
"description": "Standards compliant HTML filter written in PHP",
|
||||
"homepage": "http://htmlpurifier.org/",
|
||||
"keywords": [
|
||||
"html"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/ezyang/htmlpurifier/issues",
|
||||
"source": "https://github.com/ezyang/htmlpurifier/tree/master"
|
||||
},
|
||||
"install-path": "../ezyang/htmlpurifier"
|
||||
},
|
||||
{
|
||||
"name": "maennchen/zipstream-php",
|
||||
"version": "2.1.0",
|
||||
"version_normalized": "2.1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/maennchen/ZipStream-PHP.git",
|
||||
"reference": "c4c5803cc1f93df3d2448478ef79394a5981cc58"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/c4c5803cc1f93df3d2448478ef79394a5981cc58",
|
||||
"reference": "c4c5803cc1f93df3d2448478ef79394a5981cc58",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"myclabs/php-enum": "^1.5",
|
||||
"php": ">= 7.1",
|
||||
"psr/http-message": "^1.0",
|
||||
"symfony/polyfill-mbstring": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-zip": "*",
|
||||
"guzzlehttp/guzzle": ">= 6.3",
|
||||
"mikey179/vfsstream": "^1.6",
|
||||
"phpunit/phpunit": ">= 7.5"
|
||||
},
|
||||
"time": "2020-05-30T13:11:16+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"ZipStream\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Paul Duncan",
|
||||
"email": "[email protected]"
|
||||
},
|
||||
{
|
||||
"name": "Jonatan Männchen",
|
||||
"email": "[email protected]"
|
||||
},
|
||||
{
|
||||
"name": "Jesse Donat",
|
||||
"email": "[email protected]"
|
||||
},
|
||||
{
|
||||
"name": "András Kolesár",
|
||||
"email": "[email protected]"
|
||||
}
|
||||
],
|
||||
"description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
|
||||
"keywords": [
|
||||
"stream",
|
||||
"zip"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/maennchen/ZipStream-PHP/issues",
|
||||
"source": "https://github.com/maennchen/ZipStream-PHP/tree/master"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://opencollective.com/zipstream",
|
||||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"install-path": "../maennchen/zipstream-php"
|
||||
},
|
||||
{
|
||||
"name": "markbaker/complex",
|
||||
"version": "2.0.0",
|
||||
"version_normalized": "2.0.0.0",
|
||||
"version": "3.0.1",
|
||||
"version_normalized": "3.0.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MarkBaker/PHPComplex.git",
|
||||
"reference": "9999f1432fae467bc93c53f357105b4c31bb994c"
|
||||
"reference": "ab8bc271e404909db09ff2d5ffa1e538085c0f22"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/9999f1432fae467bc93c53f357105b4c31bb994c",
|
||||
"reference": "9999f1432fae467bc93c53f357105b4c31bb994c",
|
||||
"url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/ab8bc271e404909db09ff2d5ffa1e538085c0f22",
|
||||
"reference": "ab8bc271e404909db09ff2d5ffa1e538085c0f22",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -152,64 +21,16 @@
|
||||
"require-dev": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
|
||||
"phpcompatibility/php-compatibility": "^9.0",
|
||||
"phpdocumentor/phpdocumentor": "2.*",
|
||||
"phploc/phploc": "^4.0",
|
||||
"phpmd/phpmd": "2.*",
|
||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.3",
|
||||
"sebastian/phpcpd": "^4.0",
|
||||
"squizlabs/php_codesniffer": "^3.4"
|
||||
},
|
||||
"time": "2020-08-26T10:42:07+00:00",
|
||||
"time": "2021-06-29T15:32:53+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Complex\\": "classes/src/"
|
||||
},
|
||||
"files": [
|
||||
"classes/src/functions/abs.php",
|
||||
"classes/src/functions/acos.php",
|
||||
"classes/src/functions/acosh.php",
|
||||
"classes/src/functions/acot.php",
|
||||
"classes/src/functions/acoth.php",
|
||||
"classes/src/functions/acsc.php",
|
||||
"classes/src/functions/acsch.php",
|
||||
"classes/src/functions/argument.php",
|
||||
"classes/src/functions/asec.php",
|
||||
"classes/src/functions/asech.php",
|
||||
"classes/src/functions/asin.php",
|
||||
"classes/src/functions/asinh.php",
|
||||
"classes/src/functions/atan.php",
|
||||
"classes/src/functions/atanh.php",
|
||||
"classes/src/functions/conjugate.php",
|
||||
"classes/src/functions/cos.php",
|
||||
"classes/src/functions/cosh.php",
|
||||
"classes/src/functions/cot.php",
|
||||
"classes/src/functions/coth.php",
|
||||
"classes/src/functions/csc.php",
|
||||
"classes/src/functions/csch.php",
|
||||
"classes/src/functions/exp.php",
|
||||
"classes/src/functions/inverse.php",
|
||||
"classes/src/functions/ln.php",
|
||||
"classes/src/functions/log2.php",
|
||||
"classes/src/functions/log10.php",
|
||||
"classes/src/functions/negative.php",
|
||||
"classes/src/functions/pow.php",
|
||||
"classes/src/functions/rho.php",
|
||||
"classes/src/functions/sec.php",
|
||||
"classes/src/functions/sech.php",
|
||||
"classes/src/functions/sin.php",
|
||||
"classes/src/functions/sinh.php",
|
||||
"classes/src/functions/sqrt.php",
|
||||
"classes/src/functions/tan.php",
|
||||
"classes/src/functions/tanh.php",
|
||||
"classes/src/functions/theta.php",
|
||||
"classes/src/operations/add.php",
|
||||
"classes/src/operations/subtract.php",
|
||||
"classes/src/operations/multiply.php",
|
||||
"classes/src/operations/divideby.php",
|
||||
"classes/src/operations/divideinto.php"
|
||||
]
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@@ -229,27 +50,27 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/MarkBaker/PHPComplex/issues",
|
||||
"source": "https://github.com/MarkBaker/PHPComplex/tree/PHP8"
|
||||
"source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.1"
|
||||
},
|
||||
"install-path": "../markbaker/complex"
|
||||
},
|
||||
{
|
||||
"name": "markbaker/matrix",
|
||||
"version": "2.0.0",
|
||||
"version_normalized": "2.0.0.0",
|
||||
"version": "3.0.0",
|
||||
"version_normalized": "3.0.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MarkBaker/PHPMatrix.git",
|
||||
"reference": "9567d9c4c519fbe40de01dbd1e4469dbbb66f46a"
|
||||
"reference": "c66aefcafb4f6c269510e9ac46b82619a904c576"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/9567d9c4c519fbe40de01dbd1e4469dbbb66f46a",
|
||||
"reference": "9567d9c4c519fbe40de01dbd1e4469dbbb66f46a",
|
||||
"url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/c66aefcafb4f6c269510e9ac46b82619a904c576",
|
||||
"reference": "c66aefcafb4f6c269510e9ac46b82619a904c576",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0"
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
|
||||
@@ -261,31 +82,13 @@
|
||||
"sebastian/phpcpd": "^4.0",
|
||||
"squizlabs/php_codesniffer": "^3.4"
|
||||
},
|
||||
"time": "2020-08-28T17:11:00+00:00",
|
||||
"time": "2021-07-01T19:01:15+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Matrix\\": "classes/src/"
|
||||
},
|
||||
"files": [
|
||||
"classes/src/functions/adjoint.php",
|
||||
"classes/src/functions/antidiagonal.php",
|
||||
"classes/src/functions/cofactors.php",
|
||||
"classes/src/functions/determinant.php",
|
||||
"classes/src/functions/diagonal.php",
|
||||
"classes/src/functions/identity.php",
|
||||
"classes/src/functions/inverse.php",
|
||||
"classes/src/functions/minors.php",
|
||||
"classes/src/functions/trace.php",
|
||||
"classes/src/functions/transpose.php",
|
||||
"classes/src/operations/add.php",
|
||||
"classes/src/operations/directsum.php",
|
||||
"classes/src/operations/subtract.php",
|
||||
"classes/src/operations/multiply.php",
|
||||
"classes/src/operations/divideby.php",
|
||||
"classes/src/operations/divideinto.php"
|
||||
]
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@@ -306,86 +109,23 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/MarkBaker/PHPMatrix/issues",
|
||||
"source": "https://github.com/MarkBaker/PHPMatrix/tree/PHP8"
|
||||
"source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.0"
|
||||
},
|
||||
"install-path": "../markbaker/matrix"
|
||||
},
|
||||
{
|
||||
"name": "myclabs/php-enum",
|
||||
"version": "1.7.7",
|
||||
"version_normalized": "1.7.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/myclabs/php-enum.git",
|
||||
"reference": "d178027d1e679832db9f38248fcc7200647dc2b7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/myclabs/php-enum/zipball/d178027d1e679832db9f38248fcc7200647dc2b7",
|
||||
"reference": "d178027d1e679832db9f38248fcc7200647dc2b7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7",
|
||||
"squizlabs/php_codesniffer": "1.*",
|
||||
"vimeo/psalm": "^3.8"
|
||||
},
|
||||
"time": "2020-11-14T18:14:52+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"MyCLabs\\Enum\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP Enum contributors",
|
||||
"homepage": "https://github.com/myclabs/php-enum/graphs/contributors"
|
||||
}
|
||||
],
|
||||
"description": "PHP Enum implementation",
|
||||
"homepage": "http://github.com/myclabs/php-enum",
|
||||
"keywords": [
|
||||
"enum"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/myclabs/php-enum/issues",
|
||||
"source": "https://github.com/myclabs/php-enum/tree/1.7.7"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/mnapoli",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"install-path": "../myclabs/php-enum"
|
||||
},
|
||||
{
|
||||
"name": "phpoffice/phpspreadsheet",
|
||||
"version": "1.16.0",
|
||||
"version_normalized": "1.16.0.0",
|
||||
"version": "1.21.0",
|
||||
"version_normalized": "1.21.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
|
||||
"reference": "76d4323b85129d0c368149c831a07a3e258b2b50"
|
||||
"reference": "1a359d2ccbb89c05f5dffb32711a95f4afc67964"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/76d4323b85129d0c368149c831a07a3e258b2b50",
|
||||
"reference": "76d4323b85129d0c368149c831a07a3e258b2b50",
|
||||
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/1a359d2ccbb89c05f5dffb32711a95f4afc67964",
|
||||
"reference": "1a359d2ccbb89c05f5dffb32711a95f4afc67964",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -404,22 +144,25 @@
|
||||
"ext-zlib": "*",
|
||||
"ezyang/htmlpurifier": "^4.13",
|
||||
"maennchen/zipstream-php": "^2.1",
|
||||
"markbaker/complex": "^1.5||^2.0",
|
||||
"markbaker/matrix": "^1.2||^2.0",
|
||||
"php": "^7.2||^8.0",
|
||||
"markbaker/complex": "^3.0",
|
||||
"markbaker/matrix": "^3.0",
|
||||
"php": "^7.3 || ^8.0",
|
||||
"psr/http-client": "^1.0",
|
||||
"psr/http-factory": "^1.0",
|
||||
"psr/simple-cache": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"dompdf/dompdf": "^0.8.5",
|
||||
"friendsofphp/php-cs-fixer": "^2.16",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
|
||||
"dompdf/dompdf": "^1.0",
|
||||
"friendsofphp/php-cs-fixer": "^3.2",
|
||||
"jpgraph/jpgraph": "^4.0",
|
||||
"mpdf/mpdf": "^8.0",
|
||||
"phpcompatibility/php-compatibility": "^9.3",
|
||||
"phpunit/phpunit": "^8.5||^9.3",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"tecnickcom/tcpdf": "^6.3"
|
||||
"phpstan/phpstan": "^1.1",
|
||||
"phpstan/phpstan-phpunit": "^1.0",
|
||||
"phpunit/phpunit": "^8.5 || ^9.0",
|
||||
"squizlabs/php_codesniffer": "^3.6",
|
||||
"tecnickcom/tcpdf": "^6.4"
|
||||
},
|
||||
"suggest": {
|
||||
"dompdf/dompdf": "Option for rendering PDF with PDF Writer (doesn't yet support PHP8)",
|
||||
@@ -427,7 +170,7 @@
|
||||
"mpdf/mpdf": "Option for rendering PDF with PDF Writer",
|
||||
"tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer (doesn't yet support PHP8)"
|
||||
},
|
||||
"time": "2020-12-31T18:03:49+00:00",
|
||||
"time": "2022-01-06T11:10:08+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
@@ -473,7 +216,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
|
||||
"source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.16.0"
|
||||
"source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.21.0"
|
||||
},
|
||||
"install-path": "../phpoffice/phpspreadsheet"
|
||||
},
|
||||
@@ -699,89 +442,6 @@
|
||||
"source": "https://github.com/php-fig/simple-cache/tree/master"
|
||||
},
|
||||
"install-path": "../psr/simple-cache"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.22.0",
|
||||
"version_normalized": "1.22.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f377a3dd1fde44d37b9831d68dc8dea3ffd28e13",
|
||||
"reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-mbstring": "For best performance"
|
||||
},
|
||||
"time": "2021-01-07T16:49:33+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.22-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Mbstring\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "[email protected]"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for the Mbstring extension",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"mbstring",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"install-path": "../symfony/polyfill-mbstring"
|
||||
}
|
||||
],
|
||||
"dev": true,
|
||||
|
||||
+107
-120
@@ -1,123 +1,110 @@
|
||||
<?php return array (
|
||||
'root' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'aliases' =>
|
||||
array (
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'pretty_version' => '1.0.0+no-version-set',
|
||||
'version' => '1.0.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => NULL,
|
||||
'name' => '__root__',
|
||||
'dev' => true,
|
||||
),
|
||||
'reference' => '70d1b7d67bc280b21f450db41728869bd1bda8d8',
|
||||
'name' => '__root__',
|
||||
),
|
||||
'versions' =>
|
||||
array (
|
||||
'__root__' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '70d1b7d67bc280b21f450db41728869bd1bda8d8',
|
||||
'versions' => array(
|
||||
'__root__' => array(
|
||||
'pretty_version' => '1.0.0+no-version-set',
|
||||
'version' => '1.0.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => NULL,
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'ezyang/htmlpurifier' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '*',
|
||||
),
|
||||
),
|
||||
'maennchen/zipstream-php' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '*',
|
||||
),
|
||||
),
|
||||
'markbaker/complex' => array(
|
||||
'pretty_version' => '3.0.1',
|
||||
'version' => '3.0.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../markbaker/complex',
|
||||
'aliases' => array(),
|
||||
'reference' => 'ab8bc271e404909db09ff2d5ffa1e538085c0f22',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'markbaker/matrix' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../markbaker/matrix',
|
||||
'aliases' => array(),
|
||||
'reference' => 'c66aefcafb4f6c269510e9ac46b82619a904c576',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'myclabs/php-enum' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '*',
|
||||
),
|
||||
),
|
||||
'phpoffice/phpspreadsheet' => array(
|
||||
'pretty_version' => '1.21.0',
|
||||
'version' => '1.21.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpoffice/phpspreadsheet',
|
||||
'aliases' => array(),
|
||||
'reference' => '1a359d2ccbb89c05f5dffb32711a95f4afc67964',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-client' => array(
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/http-client',
|
||||
'aliases' => array(),
|
||||
'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-factory' => array(
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/http-factory',
|
||||
'aliases' => array(),
|
||||
'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-message' => array(
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/http-message',
|
||||
'aliases' => array(),
|
||||
'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/simple-cache' => array(
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/simple-cache',
|
||||
'aliases' => array(),
|
||||
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-mbstring' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '*',
|
||||
),
|
||||
),
|
||||
),
|
||||
'ezyang/htmlpurifier' =>
|
||||
array (
|
||||
'pretty_version' => 'v4.13.0',
|
||||
'version' => '4.13.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '08e27c97e4c6ed02f37c5b2b20488046c8d90d75',
|
||||
),
|
||||
'maennchen/zipstream-php' =>
|
||||
array (
|
||||
'pretty_version' => '2.1.0',
|
||||
'version' => '2.1.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'c4c5803cc1f93df3d2448478ef79394a5981cc58',
|
||||
),
|
||||
'markbaker/complex' =>
|
||||
array (
|
||||
'pretty_version' => '2.0.0',
|
||||
'version' => '2.0.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '9999f1432fae467bc93c53f357105b4c31bb994c',
|
||||
),
|
||||
'markbaker/matrix' =>
|
||||
array (
|
||||
'pretty_version' => '2.0.0',
|
||||
'version' => '2.0.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '9567d9c4c519fbe40de01dbd1e4469dbbb66f46a',
|
||||
),
|
||||
'myclabs/php-enum' =>
|
||||
array (
|
||||
'pretty_version' => '1.7.7',
|
||||
'version' => '1.7.7.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'd178027d1e679832db9f38248fcc7200647dc2b7',
|
||||
),
|
||||
'phpoffice/phpspreadsheet' =>
|
||||
array (
|
||||
'pretty_version' => '1.16.0',
|
||||
'version' => '1.16.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '76d4323b85129d0c368149c831a07a3e258b2b50',
|
||||
),
|
||||
'psr/http-client' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621',
|
||||
),
|
||||
'psr/http-factory' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be',
|
||||
),
|
||||
'psr/http-message' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
|
||||
),
|
||||
'psr/simple-cache' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
|
||||
),
|
||||
'symfony/polyfill-mbstring' =>
|
||||
array (
|
||||
'pretty_version' => 'v1.22.0',
|
||||
'version' => '1.22.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'f377a3dd1fde44d37b9831d68dc8dea3ffd28e13',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
+2
-2
@@ -4,8 +4,8 @@
|
||||
|
||||
$issues = array();
|
||||
|
||||
if (!(PHP_VERSION_ID >= 70200)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.0". You are running ' . PHP_VERSION . '.';
|
||||
if (!(PHP_VERSION_ID >= 70300)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.0". You are running ' . PHP_VERSION . '.';
|
||||
}
|
||||
|
||||
if ($issues) {
|
||||
|
||||
+49
-32
@@ -3,11 +3,13 @@ PHPComplex
|
||||
|
||||
---
|
||||
|
||||
PHP Class for handling Complex numbers
|
||||
PHP Class Library for working with Complex numbers
|
||||
|
||||
Master: [](http://travis-ci.org/MarkBaker/PHPComplex)
|
||||
[](https://github.com/MarkBaker/PHPComplex/actions)
|
||||
[](https://packagist.org/packages/markbaker/complex)
|
||||
[](https://packagist.org/packages/markbaker/complex)
|
||||
[](https://packagist.org/packages/markbaker/complex)
|
||||
|
||||
Develop: [](http://travis-ci.org/MarkBaker/PHPComplex)
|
||||
|
||||
[](https://xkcd.com/2028/)
|
||||
|
||||
@@ -63,19 +65,37 @@ together with functions for
|
||||
|
||||
---
|
||||
|
||||
# Installation
|
||||
|
||||
```shell
|
||||
composer require markbaker/complex:^3.0
|
||||
```
|
||||
|
||||
# Important BC Note
|
||||
|
||||
If you've previously been using procedural calls to functions and operations using this library, then from version 3.0 you should use [MarkBaker/PHPComplexFunctions](https://github.com/MarkBaker/PHPComplexFunctions) instead (available on packagist as [markbaker/complex-functions](https://packagist.org/packages/markbaker/complex-functions)).
|
||||
|
||||
You'll need to replace `markbaker/complex`in your `composer.json` file with the new library, but otherwise there should be no difference in the namespacing, or in the way that you have called the Complex functions in the past, so no actual code changes are required.
|
||||
|
||||
```shell
|
||||
composer require markbaker/complex-functions:^1.0
|
||||
```
|
||||
|
||||
You should not reference this library (`markbaker/complex`) in your `composer.json`, composer wil take care of that for you.
|
||||
|
||||
# Usage
|
||||
|
||||
To create a new complex object, you can provide either the real, imaginary and suffix parts as individual values, or as an array of values passed passed to the constructor; or a string representing the value. e.g
|
||||
|
||||
```
|
||||
```php
|
||||
$real = 1.23;
|
||||
$imaginary = -4.56;
|
||||
$suffix = 'i';
|
||||
|
||||
$complexObject = new Complex\Complex($real, $imaginary, $suffix);
|
||||
```
|
||||
or
|
||||
```
|
||||
or as an array
|
||||
```php
|
||||
$real = 1.23;
|
||||
$imaginary = -4.56;
|
||||
$suffix = 'i';
|
||||
@@ -84,8 +104,8 @@ $arguments = [$real, $imaginary, $suffix];
|
||||
|
||||
$complexObject = new Complex\Complex($arguments);
|
||||
```
|
||||
or
|
||||
```
|
||||
or as a string
|
||||
```php
|
||||
$complexString = '1.23-4.56i';
|
||||
|
||||
$complexObject = new Complex\Complex($complexString);
|
||||
@@ -98,57 +118,54 @@ This also allows you to chain multiple methods as you would for a fluent interfa
|
||||
|
||||
To perform mathematical operations with Complex values, you can call the appropriate method against a complex value, passing other values as arguments
|
||||
|
||||
```
|
||||
```php
|
||||
$complexString1 = '1.23-4.56i';
|
||||
$complexString2 = '2.34+5.67i';
|
||||
|
||||
$complexObject = new Complex\Complex($complexString1);
|
||||
echo $complexObject->add($complexString2);
|
||||
```
|
||||
or pass all values to the appropriate function
|
||||
```
|
||||
|
||||
or use the static Operation methods
|
||||
```php
|
||||
$complexString1 = '1.23-4.56i';
|
||||
$complexString2 = '2.34+5.67i';
|
||||
|
||||
echo Complex\add($complexString1, $complexString2);
|
||||
echo Complex\Operations::add($complexString1, $complexString2);
|
||||
```
|
||||
If you want to perform the same operation against multiple values (e.g. to add three or more complex numbers), then you can pass multiple arguments to any of the operations.
|
||||
|
||||
You can pass these arguments as Complex objects, or as an array or string that will parse to a complex object.
|
||||
You can pass these arguments as Complex objects, or as an array, or string that will parse to a complex object.
|
||||
|
||||
## Using functions
|
||||
|
||||
When calling any of the available functions for a complex value, you can either call the relevant method for the Complex object
|
||||
```
|
||||
```php
|
||||
$complexString = '1.23-4.56i';
|
||||
|
||||
$complexObject = new Complex\Complex($complexString);
|
||||
echo $complexObject->sinh();
|
||||
```
|
||||
or you can call the function as you would in procedural code, passing the Complex object as an argument
|
||||
|
||||
or use the static Functions methods
|
||||
```php
|
||||
$complexString = '1.23-4.56i';
|
||||
|
||||
echo Complex\Functions::sinh($complexString);
|
||||
```
|
||||
As with operations, you can pass these arguments as Complex objects, or as an array or string that will parse to a complex object.
|
||||
|
||||
|
||||
In the case of the `pow()` function (the only implemented function that requires an additional argument) you need to pass both arguments when calling the function
|
||||
|
||||
```php
|
||||
$complexString = '1.23-4.56i';
|
||||
|
||||
$complexObject = new Complex\Complex($complexString);
|
||||
echo Complex\sinh($complexObject);
|
||||
```
|
||||
When called procedurally using the function, you can pass in the argument as a Complex object, or as an array or string that will parse to a complex object.
|
||||
```
|
||||
$complexString = '1.23-4.56i';
|
||||
|
||||
echo Complex\sinh($complexString);
|
||||
```
|
||||
|
||||
In the case of the `pow()` function (the only implemented function that requires an additional argument) you need to pass both arguments when calling the function procedurally
|
||||
|
||||
```
|
||||
$complexString = '1.23-4.56i';
|
||||
|
||||
$complexObject = new Complex\Complex($complexString);
|
||||
echo Complex\pow($complexObject, 2);
|
||||
echo Complex\Functions::pow($complexObject, 2);
|
||||
```
|
||||
or pass the additional argument when calling the method
|
||||
```
|
||||
```php
|
||||
$complexString = '1.23-4.56i';
|
||||
|
||||
$complexObject = new Complex\Complex($complexString);
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
@@ -186,7 +186,7 @@ class Complex
|
||||
// Set parsed values in our properties
|
||||
$this->realPart = (float) $realPart;
|
||||
$this->imaginaryPart = (float) $imaginaryPart;
|
||||
$this->suffix = strtolower($suffix);
|
||||
$this->suffix = strtolower($suffix ?? '');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,13 +377,11 @@ class Complex
|
||||
|
||||
// Test for function calls
|
||||
if (in_array($functionName, self::$functions, true)) {
|
||||
$functionName = "\\" . __NAMESPACE__ . "\\{$functionName}";
|
||||
return $functionName($this, ...$arguments);
|
||||
return Functions::$functionName($this, ...$arguments);
|
||||
}
|
||||
// Test for operation calls
|
||||
if (in_array($functionName, self::$operations, true)) {
|
||||
$functionName = "\\" . __NAMESPACE__ . "\\{$functionName}";
|
||||
return $functionName($this, ...$arguments);
|
||||
return Operations::$functionName($this, ...$arguments);
|
||||
}
|
||||
throw new Exception('Complex Function or Operation does not exist');
|
||||
}
|
||||
|
||||
@@ -0,0 +1,805 @@
|
||||
<?php
|
||||
|
||||
namespace Complex;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Functions
|
||||
{
|
||||
/**
|
||||
* Returns the absolute value (modulus) of a complex number.
|
||||
* Also known as the rho of the complex number, i.e. the distance/radius
|
||||
* from the centrepoint to the representation of the number in polar coordinates.
|
||||
*
|
||||
* This function is a synonym for rho()
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return float The absolute (or rho) value of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*
|
||||
* @see rho
|
||||
*
|
||||
*/
|
||||
public static function abs($complex): float
|
||||
{
|
||||
return self::rho($complex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse cosine of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse cosine of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function acos($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
$square = clone $complex;
|
||||
$square = Operations::multiply($square, $complex);
|
||||
$invsqrt = new Complex(1.0);
|
||||
$invsqrt = Operations::subtract($invsqrt, $square);
|
||||
$invsqrt = self::sqrt($invsqrt);
|
||||
$adjust = new Complex(
|
||||
$complex->getReal() - $invsqrt->getImaginary(),
|
||||
$complex->getImaginary() + $invsqrt->getReal()
|
||||
);
|
||||
$log = self::ln($adjust);
|
||||
|
||||
return new Complex(
|
||||
$log->getImaginary(),
|
||||
-1 * $log->getReal()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic cosine of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse hyperbolic cosine of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function acosh($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal() && ($complex->getReal() > 1)) {
|
||||
return new Complex(\acosh($complex->getReal()));
|
||||
}
|
||||
|
||||
$acosh = self::acos($complex)
|
||||
->reverse();
|
||||
if ($acosh->getReal() < 0.0) {
|
||||
$acosh = $acosh->invertReal();
|
||||
}
|
||||
|
||||
return $acosh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse cotangent of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse cotangent of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function acot($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
return self::atan(self::inverse($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic cotangent of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse hyperbolic cotangent of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function acoth($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
return self::atanh(self::inverse($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse cosecant of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse cosecant of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function acsc($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return self::asin(self::inverse($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic cosecant of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse hyperbolic cosecant of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function acsch($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return self::asinh(self::inverse($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the argument of a complex number.
|
||||
* Also known as the theta of the complex number, i.e. the angle in radians
|
||||
* from the real axis to the representation of the number in polar coordinates.
|
||||
*
|
||||
* This function is a synonym for theta()
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return float The argument (or theta) value of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*
|
||||
* @see theta
|
||||
*/
|
||||
public static function argument($complex): float
|
||||
{
|
||||
return self::theta($complex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse secant of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse secant of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function asec($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return self::acos(self::inverse($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic secant of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse hyperbolic secant of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function asech($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return self::acosh(self::inverse($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse sine of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse sine of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function asin($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
$square = Operations::multiply($complex, $complex);
|
||||
$invsqrt = new Complex(1.0);
|
||||
$invsqrt = Operations::subtract($invsqrt, $square);
|
||||
$invsqrt = self::sqrt($invsqrt);
|
||||
$adjust = new Complex(
|
||||
$invsqrt->getReal() - $complex->getImaginary(),
|
||||
$invsqrt->getImaginary() + $complex->getReal()
|
||||
);
|
||||
$log = self::ln($adjust);
|
||||
|
||||
return new Complex(
|
||||
$log->getImaginary(),
|
||||
-1 * $log->getReal()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic sine of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse hyperbolic sine of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function asinh($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal() && ($complex->getReal() > 1)) {
|
||||
return new Complex(\asinh($complex->getReal()));
|
||||
}
|
||||
|
||||
$asinh = clone $complex;
|
||||
$asinh = $asinh->reverse()
|
||||
->invertReal();
|
||||
$asinh = self::asin($asinh);
|
||||
|
||||
return $asinh->reverse()
|
||||
->invertImaginary();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse tangent of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse tangent of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function atan($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal()) {
|
||||
return new Complex(\atan($complex->getReal()));
|
||||
}
|
||||
|
||||
$t1Value = new Complex(-1 * $complex->getImaginary(), $complex->getReal());
|
||||
$uValue = new Complex(1, 0);
|
||||
|
||||
$d1Value = clone $uValue;
|
||||
$d1Value = Operations::subtract($d1Value, $t1Value);
|
||||
$d2Value = Operations::add($t1Value, $uValue);
|
||||
$uResult = $d1Value->divideBy($d2Value);
|
||||
$uResult = self::ln($uResult);
|
||||
|
||||
return new Complex(
|
||||
(($uResult->getImaginary() == M_PI) ? -M_PI : $uResult->getImaginary()) * -0.5,
|
||||
$uResult->getReal() * 0.5,
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public static function atanh($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal()) {
|
||||
$real = $complex->getReal();
|
||||
if ($real >= -1.0 && $real <= 1.0) {
|
||||
return new Complex(\atanh($real));
|
||||
} else {
|
||||
return new Complex(\atanh(1 / $real), (($real < 0.0) ? M_PI_2 : -1 * M_PI_2));
|
||||
}
|
||||
}
|
||||
|
||||
$iComplex = clone $complex;
|
||||
$iComplex = $iComplex->invertImaginary()
|
||||
->reverse();
|
||||
return self::atan($iComplex)
|
||||
->invertReal()
|
||||
->reverse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the complex conjugate of a complex number
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The conjugate of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function conjugate($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
return new Complex(
|
||||
$complex->getReal(),
|
||||
-1 * $complex->getImaginary(),
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cosine of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The cosine of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function cos($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal()) {
|
||||
return new Complex(\cos($complex->getReal()));
|
||||
}
|
||||
|
||||
return self::conjugate(
|
||||
new Complex(
|
||||
\cos($complex->getReal()) * \cosh($complex->getImaginary()),
|
||||
\sin($complex->getReal()) * \sinh($complex->getImaginary()),
|
||||
$complex->getSuffix()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic cosine of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The hyperbolic cosine of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function cosh($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal()) {
|
||||
return new Complex(\cosh($complex->getReal()));
|
||||
}
|
||||
|
||||
return new Complex(
|
||||
\cosh($complex->getReal()) * \cos($complex->getImaginary()),
|
||||
\sinh($complex->getReal()) * \sin($complex->getImaginary()),
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cotangent of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The cotangent of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function cot($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return self::inverse(self::tan($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic cotangent of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The hyperbolic cotangent of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function coth($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
return self::inverse(self::tanh($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cosecant of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The cosecant of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function csc($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return self::inverse(self::sin($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic cosecant of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The hyperbolic cosecant of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function csch($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return self::inverse(self::sinh($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exponential of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The exponential of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function exp($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if (($complex->getReal() == 0.0) && (\abs($complex->getImaginary()) == M_PI)) {
|
||||
return new Complex(-1.0, 0.0);
|
||||
}
|
||||
|
||||
$rho = \exp($complex->getReal());
|
||||
|
||||
return new Complex(
|
||||
$rho * \cos($complex->getImaginary()),
|
||||
$rho * \sin($complex->getImaginary()),
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The inverse of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function inverse($complex): Complex
|
||||
{
|
||||
$complex = clone Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
throw new InvalidArgumentException('Division by zero');
|
||||
}
|
||||
|
||||
return $complex->divideInto(1.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the natural logarithm of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The natural logarithm of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws InvalidArgumentException If the real and the imaginary parts are both zero
|
||||
*/
|
||||
public static function ln($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if (($complex->getReal() == 0.0) && ($complex->getImaginary() == 0.0)) {
|
||||
throw new InvalidArgumentException();
|
||||
}
|
||||
|
||||
return new Complex(
|
||||
\log(self::rho($complex)),
|
||||
self::theta($complex),
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base-2 logarithm of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The base-2 logarithm of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws InvalidArgumentException If the real and the imaginary parts are both zero
|
||||
*/
|
||||
public static function log2($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if (($complex->getReal() == 0.0) && ($complex->getImaginary() == 0.0)) {
|
||||
throw new InvalidArgumentException();
|
||||
} elseif (($complex->getReal() > 0.0) && ($complex->getImaginary() == 0.0)) {
|
||||
return new Complex(\log($complex->getReal(), 2), 0.0, $complex->getSuffix());
|
||||
}
|
||||
|
||||
return self::ln($complex)
|
||||
->multiply(\log(Complex::EULER, 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the common logarithm (base 10) of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The common logarithm (base 10) of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws InvalidArgumentException If the real and the imaginary parts are both zero
|
||||
*/
|
||||
public static function log10($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if (($complex->getReal() == 0.0) && ($complex->getImaginary() == 0.0)) {
|
||||
throw new InvalidArgumentException();
|
||||
} elseif (($complex->getReal() > 0.0) && ($complex->getImaginary() == 0.0)) {
|
||||
return new Complex(\log10($complex->getReal()), 0.0, $complex->getSuffix());
|
||||
}
|
||||
|
||||
return self::ln($complex)
|
||||
->multiply(\log10(Complex::EULER));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negative of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The negative value of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*
|
||||
* @see rho
|
||||
*
|
||||
*/
|
||||
public static function negative($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
return new Complex(
|
||||
-1 * $complex->getReal(),
|
||||
-1 * $complex->getImaginary(),
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a complex number raised to a power.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @param float|integer $power The power to raise this value to
|
||||
* @return Complex The complex argument raised to the real power.
|
||||
* @throws Exception If the power argument isn't a valid real
|
||||
*/
|
||||
public static function pow($complex, $power): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if (!is_numeric($power)) {
|
||||
throw new Exception('Power argument must be a real number');
|
||||
}
|
||||
|
||||
if ($complex->getImaginary() == 0.0 && $complex->getReal() >= 0.0) {
|
||||
return new Complex(\pow($complex->getReal(), $power));
|
||||
}
|
||||
|
||||
$rValue = \sqrt(($complex->getReal() * $complex->getReal()) + ($complex->getImaginary() * $complex->getImaginary()));
|
||||
$rPower = \pow($rValue, $power);
|
||||
$theta = $complex->argument() * $power;
|
||||
if ($theta == 0) {
|
||||
return new Complex(1);
|
||||
}
|
||||
|
||||
return new Complex($rPower * \cos($theta), $rPower * \sin($theta), $complex->getSuffix());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the rho of a complex number.
|
||||
* This is the distance/radius from the centrepoint to the representation of the number in polar coordinates.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return float The rho value of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function rho($complex): float
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
return \sqrt(
|
||||
($complex->getReal() * $complex->getReal()) +
|
||||
($complex->getImaginary() * $complex->getImaginary())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the secant of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The secant of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function sec($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
return self::inverse(self::cos($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic secant of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The hyperbolic secant of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function sech($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
return self::inverse(self::cosh($complex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sine of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The sine of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function sin($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal()) {
|
||||
return new Complex(\sin($complex->getReal()));
|
||||
}
|
||||
|
||||
return new Complex(
|
||||
\sin($complex->getReal()) * \cosh($complex->getImaginary()),
|
||||
\cos($complex->getReal()) * \sinh($complex->getImaginary()),
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic sine of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The hyperbolic sine of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function sinh($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal()) {
|
||||
return new Complex(\sinh($complex->getReal()));
|
||||
}
|
||||
|
||||
return new Complex(
|
||||
\sinh($complex->getReal()) * \cos($complex->getImaginary()),
|
||||
\cosh($complex->getReal()) * \sin($complex->getImaginary()),
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square root of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The Square root of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function sqrt($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
$theta = self::theta($complex);
|
||||
$delta1 = \cos($theta / 2);
|
||||
$delta2 = \sin($theta / 2);
|
||||
$rho = \sqrt(self::rho($complex));
|
||||
|
||||
return new Complex($delta1 * $rho, $delta2 * $rho, $complex->getSuffix());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tangent of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The tangent of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function tan($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->isReal()) {
|
||||
return new Complex(\tan($complex->getReal()));
|
||||
}
|
||||
|
||||
$real = $complex->getReal();
|
||||
$imaginary = $complex->getImaginary();
|
||||
$divisor = 1 + \pow(\tan($real), 2) * \pow(\tanh($imaginary), 2);
|
||||
if ($divisor == 0.0) {
|
||||
throw new InvalidArgumentException('Division by zero');
|
||||
}
|
||||
|
||||
return new Complex(
|
||||
\pow(self::sech($imaginary)->getReal(), 2) * \tan($real) / $divisor,
|
||||
\pow(self::sec($real)->getReal(), 2) * \tanh($imaginary) / $divisor,
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic tangent of a complex number.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return Complex The hyperbolic tangent of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
* @throws \InvalidArgumentException If function would result in a division by zero
|
||||
*/
|
||||
public static function tanh($complex): Complex
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
$real = $complex->getReal();
|
||||
$imaginary = $complex->getImaginary();
|
||||
$divisor = \cos($imaginary) * \cos($imaginary) + \sinh($real) * \sinh($real);
|
||||
if ($divisor == 0.0) {
|
||||
throw new InvalidArgumentException('Division by zero');
|
||||
}
|
||||
|
||||
return new Complex(
|
||||
\sinh($real) * \cosh($real) / $divisor,
|
||||
0.5 * \sin(2 * $imaginary) / $divisor,
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the theta of a complex number.
|
||||
* This is the angle in radians from the real axis to the representation of the number in polar coordinates.
|
||||
*
|
||||
* @param Complex|mixed $complex Complex number or a numeric value.
|
||||
* @return float The theta value of the complex argument.
|
||||
* @throws Exception If argument isn't a valid real or complex number.
|
||||
*/
|
||||
public static function theta($complex): float
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0) {
|
||||
if ($complex->isReal()) {
|
||||
return 0.0;
|
||||
} elseif ($complex->getImaginary() < 0.0) {
|
||||
return M_PI / -2;
|
||||
}
|
||||
return M_PI / 2;
|
||||
} elseif ($complex->getReal() > 0.0) {
|
||||
return \atan($complex->getImaginary() / $complex->getReal());
|
||||
} elseif ($complex->getImaginary() < 0.0) {
|
||||
return -(M_PI - \atan(\abs($complex->getImaginary()) / \abs($complex->getReal())));
|
||||
}
|
||||
|
||||
return M_PI - \atan($complex->getImaginary() / \abs($complex->getReal()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
namespace Complex;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Operations
|
||||
{
|
||||
/**
|
||||
* Adds two or more complex numbers
|
||||
*
|
||||
* @param array of string|integer|float|Complex $complexValues The numbers to add
|
||||
* @return Complex
|
||||
*/
|
||||
public static function add(...$complexValues): Complex
|
||||
{
|
||||
if (count($complexValues) < 2) {
|
||||
throw new \Exception('This function requires at least 2 arguments');
|
||||
}
|
||||
|
||||
$base = array_shift($complexValues);
|
||||
$result = clone Complex::validateComplexArgument($base);
|
||||
|
||||
foreach ($complexValues as $complex) {
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($result->isComplex() && $complex->isComplex() &&
|
||||
$result->getSuffix() !== $complex->getSuffix()) {
|
||||
throw new Exception('Suffix Mismatch');
|
||||
}
|
||||
|
||||
$real = $result->getReal() + $complex->getReal();
|
||||
$imaginary = $result->getImaginary() + $complex->getImaginary();
|
||||
|
||||
$result = new Complex(
|
||||
$real,
|
||||
$imaginary,
|
||||
($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides two or more complex numbers
|
||||
*
|
||||
* @param array of string|integer|float|Complex $complexValues The numbers to divide
|
||||
* @return Complex
|
||||
*/
|
||||
public static function divideby(...$complexValues): Complex
|
||||
{
|
||||
if (count($complexValues) < 2) {
|
||||
throw new \Exception('This function requires at least 2 arguments');
|
||||
}
|
||||
|
||||
$base = array_shift($complexValues);
|
||||
$result = clone Complex::validateComplexArgument($base);
|
||||
|
||||
foreach ($complexValues as $complex) {
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($result->isComplex() && $complex->isComplex() &&
|
||||
$result->getSuffix() !== $complex->getSuffix()) {
|
||||
throw new Exception('Suffix Mismatch');
|
||||
}
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
throw new InvalidArgumentException('Division by zero');
|
||||
}
|
||||
|
||||
$delta1 = ($result->getReal() * $complex->getReal()) +
|
||||
($result->getImaginary() * $complex->getImaginary());
|
||||
$delta2 = ($result->getImaginary() * $complex->getReal()) -
|
||||
($result->getReal() * $complex->getImaginary());
|
||||
$delta3 = ($complex->getReal() * $complex->getReal()) +
|
||||
($complex->getImaginary() * $complex->getImaginary());
|
||||
|
||||
$real = $delta1 / $delta3;
|
||||
$imaginary = $delta2 / $delta3;
|
||||
|
||||
$result = new Complex(
|
||||
$real,
|
||||
$imaginary,
|
||||
($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides two or more complex numbers
|
||||
*
|
||||
* @param array of string|integer|float|Complex $complexValues The numbers to divide
|
||||
* @return Complex
|
||||
*/
|
||||
public static function divideinto(...$complexValues): Complex
|
||||
{
|
||||
if (count($complexValues) < 2) {
|
||||
throw new \Exception('This function requires at least 2 arguments');
|
||||
}
|
||||
|
||||
$base = array_shift($complexValues);
|
||||
$result = clone Complex::validateComplexArgument($base);
|
||||
|
||||
foreach ($complexValues as $complex) {
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($result->isComplex() && $complex->isComplex() &&
|
||||
$result->getSuffix() !== $complex->getSuffix()) {
|
||||
throw new Exception('Suffix Mismatch');
|
||||
}
|
||||
if ($result->getReal() == 0.0 && $result->getImaginary() == 0.0) {
|
||||
throw new InvalidArgumentException('Division by zero');
|
||||
}
|
||||
|
||||
$delta1 = ($complex->getReal() * $result->getReal()) +
|
||||
($complex->getImaginary() * $result->getImaginary());
|
||||
$delta2 = ($complex->getImaginary() * $result->getReal()) -
|
||||
($complex->getReal() * $result->getImaginary());
|
||||
$delta3 = ($result->getReal() * $result->getReal()) +
|
||||
($result->getImaginary() * $result->getImaginary());
|
||||
|
||||
$real = $delta1 / $delta3;
|
||||
$imaginary = $delta2 / $delta3;
|
||||
|
||||
$result = new Complex(
|
||||
$real,
|
||||
$imaginary,
|
||||
($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies two or more complex numbers
|
||||
*
|
||||
* @param array of string|integer|float|Complex $complexValues The numbers to multiply
|
||||
* @return Complex
|
||||
*/
|
||||
public static function multiply(...$complexValues): Complex
|
||||
{
|
||||
if (count($complexValues) < 2) {
|
||||
throw new \Exception('This function requires at least 2 arguments');
|
||||
}
|
||||
|
||||
$base = array_shift($complexValues);
|
||||
$result = clone Complex::validateComplexArgument($base);
|
||||
|
||||
foreach ($complexValues as $complex) {
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($result->isComplex() && $complex->isComplex() &&
|
||||
$result->getSuffix() !== $complex->getSuffix()) {
|
||||
throw new Exception('Suffix Mismatch');
|
||||
}
|
||||
|
||||
$real = ($result->getReal() * $complex->getReal()) -
|
||||
($result->getImaginary() * $complex->getImaginary());
|
||||
$imaginary = ($result->getReal() * $complex->getImaginary()) +
|
||||
($result->getImaginary() * $complex->getReal());
|
||||
|
||||
$result = new Complex(
|
||||
$real,
|
||||
$imaginary,
|
||||
($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts two or more complex numbers
|
||||
*
|
||||
* @param array of string|integer|float|Complex $complexValues The numbers to subtract
|
||||
* @return Complex
|
||||
*/
|
||||
public static function subtract(...$complexValues): Complex
|
||||
{
|
||||
if (count($complexValues) < 2) {
|
||||
throw new \Exception('This function requires at least 2 arguments');
|
||||
}
|
||||
|
||||
$base = array_shift($complexValues);
|
||||
$result = clone Complex::validateComplexArgument($base);
|
||||
|
||||
foreach ($complexValues as $complex) {
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($result->isComplex() && $complex->isComplex() &&
|
||||
$result->getSuffix() !== $complex->getSuffix()) {
|
||||
throw new Exception('Suffix Mismatch');
|
||||
}
|
||||
|
||||
$real = $result->getReal() - $complex->getReal();
|
||||
$imaginary = $result->getImaginary() - $complex->getImaginary();
|
||||
|
||||
$result = new Complex(
|
||||
$real,
|
||||
$imaginary,
|
||||
($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?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): float
|
||||
{
|
||||
return rho($complex);
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<?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 = 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()
|
||||
);
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
<?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;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
<?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 = Complex::validateComplexArgument($complex);
|
||||
|
||||
return atan(inverse($complex));
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
<?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 = Complex::validateComplexArgument($complex);
|
||||
|
||||
return atanh(inverse($complex));
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?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 = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return asin(inverse($complex));
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?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 = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return asinh(inverse($complex));
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
<?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): float
|
||||
{
|
||||
return theta($complex);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?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 = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return acos(inverse($complex));
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?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 = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return acosh(inverse($complex));
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
<?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 = 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()
|
||||
);
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?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 = 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();
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<?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 = 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()
|
||||
);
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<?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 = 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();
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
<?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 = Complex::validateComplexArgument($complex);
|
||||
|
||||
return new Complex(
|
||||
$complex->getReal(),
|
||||
-1 * $complex->getImaginary(),
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
<?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 = 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()
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?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 = 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()
|
||||
);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?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 = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return inverse(tan($complex));
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<?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 = Complex::validateComplexArgument($complex);
|
||||
return inverse(tanh($complex));
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?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 = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return inverse(sin($complex));
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?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 = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
return new Complex(INF);
|
||||
}
|
||||
|
||||
return inverse(sinh($complex));
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
<?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 = 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()
|
||||
);
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
<?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
|
||||
{
|
||||
$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);
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?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 = 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()
|
||||
);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?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 = 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));
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?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 = 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));
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
<?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 Complex 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 = Complex::validateComplexArgument($complex);
|
||||
|
||||
return new Complex(
|
||||
-1 * $complex->getReal(),
|
||||
-1 * $complex->getImaginary(),
|
||||
$complex->getSuffix()
|
||||
);
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?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 = 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());
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?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): float
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
return \sqrt(
|
||||
($complex->getReal() * $complex->getReal()) +
|
||||
($complex->getImaginary() * $complex->getImaginary())
|
||||
);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
<?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 = Complex::validateComplexArgument($complex);
|
||||
|
||||
return inverse(cos($complex));
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
<?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 = Complex::validateComplexArgument($complex);
|
||||
|
||||
return inverse(cosh($complex));
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?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 = 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()
|
||||
);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?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 = 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()
|
||||
);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?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 = 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());
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?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 = 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()
|
||||
);
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?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 = 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()
|
||||
);
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<?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): float
|
||||
{
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($complex->getReal() == 0.0) {
|
||||
if ($complex->isReal()) {
|
||||
return 0.0;
|
||||
} elseif ($complex->getImaginary() < 0.0) {
|
||||
return M_PI / -2;
|
||||
}
|
||||
return M_PI / 2;
|
||||
} elseif ($complex->getReal() > 0.0) {
|
||||
return \atan($complex->getImaginary() / $complex->getReal());
|
||||
} elseif ($complex->getImaginary() < 0.0) {
|
||||
return -(M_PI - \atan(\abs($complex->getImaginary()) / \abs($complex->getReal())));
|
||||
}
|
||||
|
||||
return M_PI - \atan($complex->getImaginary() / \abs($complex->getReal()));
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?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): Complex
|
||||
{
|
||||
if (count($complexValues) < 2) {
|
||||
throw new \Exception('This function requires at least 2 arguments');
|
||||
}
|
||||
|
||||
$base = array_shift($complexValues);
|
||||
$result = clone Complex::validateComplexArgument($base);
|
||||
|
||||
foreach ($complexValues as $complex) {
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($result->isComplex() && $complex->isComplex() &&
|
||||
$result->getSuffix() !== $complex->getSuffix()) {
|
||||
throw new Exception('Suffix Mismatch');
|
||||
}
|
||||
|
||||
$real = $result->getReal() + $complex->getReal();
|
||||
$imaginary = $result->getImaginary() + $complex->getImaginary();
|
||||
|
||||
$result = new Complex(
|
||||
$real,
|
||||
$imaginary,
|
||||
($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
-56
@@ -1,56 +0,0 @@
|
||||
<?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): Complex
|
||||
{
|
||||
if (count($complexValues) < 2) {
|
||||
throw new \Exception('This function requires at least 2 arguments');
|
||||
}
|
||||
|
||||
$base = array_shift($complexValues);
|
||||
$result = clone Complex::validateComplexArgument($base);
|
||||
|
||||
foreach ($complexValues as $complex) {
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($result->isComplex() && $complex->isComplex() &&
|
||||
$result->getSuffix() !== $complex->getSuffix()) {
|
||||
throw new Exception('Suffix Mismatch');
|
||||
}
|
||||
if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
|
||||
throw new \InvalidArgumentException('Division by zero');
|
||||
}
|
||||
|
||||
$delta1 = ($result->getReal() * $complex->getReal()) +
|
||||
($result->getImaginary() * $complex->getImaginary());
|
||||
$delta2 = ($result->getImaginary() * $complex->getReal()) -
|
||||
($result->getReal() * $complex->getImaginary());
|
||||
$delta3 = ($complex->getReal() * $complex->getReal()) +
|
||||
($complex->getImaginary() * $complex->getImaginary());
|
||||
|
||||
$real = $delta1 / $delta3;
|
||||
$imaginary = $delta2 / $delta3;
|
||||
|
||||
$result = new Complex(
|
||||
$real,
|
||||
$imaginary,
|
||||
($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
-56
@@ -1,56 +0,0 @@
|
||||
<?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): Complex
|
||||
{
|
||||
if (count($complexValues) < 2) {
|
||||
throw new \Exception('This function requires at least 2 arguments');
|
||||
}
|
||||
|
||||
$base = array_shift($complexValues);
|
||||
$result = clone Complex::validateComplexArgument($base);
|
||||
|
||||
foreach ($complexValues as $complex) {
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($result->isComplex() && $complex->isComplex() &&
|
||||
$result->getSuffix() !== $complex->getSuffix()) {
|
||||
throw new Exception('Suffix Mismatch');
|
||||
}
|
||||
if ($result->getReal() == 0.0 && $result->getImaginary() == 0.0) {
|
||||
throw new \InvalidArgumentException('Division by zero');
|
||||
}
|
||||
|
||||
$delta1 = ($complex->getReal() * $result->getReal()) +
|
||||
($complex->getImaginary() * $result->getImaginary());
|
||||
$delta2 = ($complex->getImaginary() * $result->getReal()) -
|
||||
($complex->getReal() * $result->getImaginary());
|
||||
$delta3 = ($result->getReal() * $result->getReal()) +
|
||||
($result->getImaginary() * $result->getImaginary());
|
||||
|
||||
$real = $delta1 / $delta3;
|
||||
$imaginary = $delta2 / $delta3;
|
||||
|
||||
$result = new Complex(
|
||||
$real,
|
||||
$imaginary,
|
||||
($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
<?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): Complex
|
||||
{
|
||||
if (count($complexValues) < 2) {
|
||||
throw new \Exception('This function requires at least 2 arguments');
|
||||
}
|
||||
|
||||
$base = array_shift($complexValues);
|
||||
$result = clone Complex::validateComplexArgument($base);
|
||||
|
||||
foreach ($complexValues as $complex) {
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($result->isComplex() && $complex->isComplex() &&
|
||||
$result->getSuffix() !== $complex->getSuffix()) {
|
||||
throw new Exception('Suffix Mismatch');
|
||||
}
|
||||
|
||||
$real = ($result->getReal() * $complex->getReal()) -
|
||||
($result->getImaginary() * $complex->getImaginary());
|
||||
$imaginary = ($result->getReal() * $complex->getImaginary()) +
|
||||
($result->getImaginary() * $complex->getReal());
|
||||
|
||||
$result = new Complex(
|
||||
$real,
|
||||
$imaginary,
|
||||
($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
<?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): Complex
|
||||
{
|
||||
if (count($complexValues) < 2) {
|
||||
throw new \Exception('This function requires at least 2 arguments');
|
||||
}
|
||||
|
||||
$base = array_shift($complexValues);
|
||||
$result = clone Complex::validateComplexArgument($base);
|
||||
|
||||
foreach ($complexValues as $complex) {
|
||||
$complex = Complex::validateComplexArgument($complex);
|
||||
|
||||
if ($result->isComplex() && $complex->isComplex() &&
|
||||
$result->getSuffix() !== $complex->getSuffix()) {
|
||||
throw new Exception('Suffix Mismatch');
|
||||
}
|
||||
|
||||
$real = $result->getReal() - $complex->getReal();
|
||||
$imaginary = $result->getImaginary() - $complex->getImaginary();
|
||||
|
||||
$result = new Complex(
|
||||
$real,
|
||||
$imaginary,
|
||||
($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
+1
-52
@@ -16,10 +16,6 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.3",
|
||||
"phpdocumentor/phpdocumentor": "2.*",
|
||||
"phpmd/phpmd": "2.*",
|
||||
"sebastian/phpcpd": "^4.0",
|
||||
"phploc/phploc": "^4.0",
|
||||
"squizlabs/php_codesniffer": "^3.4",
|
||||
"phpcompatibility/php-compatibility": "^9.0",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0"
|
||||
@@ -27,57 +23,10 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Complex\\": "classes/src/"
|
||||
},
|
||||
"files": [
|
||||
"classes/src/functions/abs.php",
|
||||
"classes/src/functions/acos.php",
|
||||
"classes/src/functions/acosh.php",
|
||||
"classes/src/functions/acot.php",
|
||||
"classes/src/functions/acoth.php",
|
||||
"classes/src/functions/acsc.php",
|
||||
"classes/src/functions/acsch.php",
|
||||
"classes/src/functions/argument.php",
|
||||
"classes/src/functions/asec.php",
|
||||
"classes/src/functions/asech.php",
|
||||
"classes/src/functions/asin.php",
|
||||
"classes/src/functions/asinh.php",
|
||||
"classes/src/functions/atan.php",
|
||||
"classes/src/functions/atanh.php",
|
||||
"classes/src/functions/conjugate.php",
|
||||
"classes/src/functions/cos.php",
|
||||
"classes/src/functions/cosh.php",
|
||||
"classes/src/functions/cot.php",
|
||||
"classes/src/functions/coth.php",
|
||||
"classes/src/functions/csc.php",
|
||||
"classes/src/functions/csch.php",
|
||||
"classes/src/functions/exp.php",
|
||||
"classes/src/functions/inverse.php",
|
||||
"classes/src/functions/ln.php",
|
||||
"classes/src/functions/log2.php",
|
||||
"classes/src/functions/log10.php",
|
||||
"classes/src/functions/negative.php",
|
||||
"classes/src/functions/pow.php",
|
||||
"classes/src/functions/rho.php",
|
||||
"classes/src/functions/sec.php",
|
||||
"classes/src/functions/sech.php",
|
||||
"classes/src/functions/sin.php",
|
||||
"classes/src/functions/sinh.php",
|
||||
"classes/src/functions/sqrt.php",
|
||||
"classes/src/functions/tan.php",
|
||||
"classes/src/functions/tanh.php",
|
||||
"classes/src/functions/theta.php",
|
||||
"classes/src/operations/add.php",
|
||||
"classes/src/operations/subtract.php",
|
||||
"classes/src/operations/multiply.php",
|
||||
"classes/src/operations/divideby.php",
|
||||
"classes/src/operations/divideinto.php"
|
||||
]
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"style": "phpcs --report-width=200 --standard=PSR2 --report=summary,full classes/src/ unitTests/classes/src -n",
|
||||
"mess": "phpmd classes/src/ xml codesize,unusedcode,design,naming -n",
|
||||
"lines": "phploc classes/src/ -n",
|
||||
"cpd": "phpcpd classes/src/ -n",
|
||||
"versions": "phpcs --report-width=200 --standard=PHPCompatibility --report=summary,full classes/src/ --runtime-set testVersion 7.2- -n"
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use Complex\Complex as Complex;
|
||||
|
||||
include('../classes/Bootstrap.php');
|
||||
include(__DIR__ . '/../vendor/autoload.php');
|
||||
|
||||
echo 'Create', PHP_EOL;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Complex;
|
||||
|
||||
include('../classes/Bootstrap.php');
|
||||
include(__DIR__ . '/../vendor/autoload.php');
|
||||
|
||||
echo 'Function Examples', PHP_EOL;
|
||||
|
||||
@@ -39,7 +39,7 @@ $functions = array(
|
||||
for ($real = -3.5; $real <= 3.5; $real += 0.5) {
|
||||
for ($imaginary = -3.5; $imaginary <= 3.5; $imaginary += 0.5) {
|
||||
foreach ($functions as $function) {
|
||||
$complexFunction = __NAMESPACE__ . '\\' . $function;
|
||||
$complexFunction = __NAMESPACE__ . '\\Functions::' . $function;
|
||||
$complex = new Complex($real, $imaginary);
|
||||
try {
|
||||
echo $function, '(', $complex, ') = ', $complexFunction($complex), PHP_EOL;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<?php
|
||||
|
||||
use Complex\Complex as Complex;
|
||||
use Complex\Operations;
|
||||
|
||||
include('../classes/Bootstrap.php');
|
||||
include(__DIR__ . '/../vendor/autoload.php');
|
||||
|
||||
$values = [
|
||||
new Complex(123),
|
||||
@@ -16,19 +17,19 @@ foreach ($values as $value) {
|
||||
|
||||
echo 'Addition', PHP_EOL;
|
||||
|
||||
$result = \Complex\add(...$values);
|
||||
$result = Operations::add(...$values);
|
||||
echo '=> ', $result, PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
echo 'Subtraction', PHP_EOL;
|
||||
|
||||
$result = \Complex\subtract(...$values);
|
||||
$result = Operations::subtract(...$values);
|
||||
echo '=> ', $result, PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
echo 'Multiplication', PHP_EOL;
|
||||
|
||||
$result = \Complex\multiply(...$values);
|
||||
$result = Operations::multiply(...$values);
|
||||
echo '=> ', $result, PHP_EOL;
|
||||
|
||||
+96
-46
@@ -5,9 +5,11 @@ PHPMatrix
|
||||
|
||||
PHP Class for handling Matrices
|
||||
|
||||
Master: [](http://travis-ci.org/MarkBaker/PHPMatrix)
|
||||
[](https://github.com/MarkBaker/PHPMatrix/actions)
|
||||
[](https://packagist.org/packages/markbaker/matrix)
|
||||
[](https://packagist.org/packages/markbaker/matrix)
|
||||
[](https://packagist.org/packages/markbaker/matrix)
|
||||
|
||||
Develop: [](http://travis-ci.org/MarkBaker/PHPMatrix)
|
||||
|
||||
[](https://xkcd.com/184/)
|
||||
|
||||
@@ -37,22 +39,54 @@ together with functions for
|
||||
- minors
|
||||
- trace
|
||||
- transpose
|
||||
- solve
|
||||
|
||||
Given Matrices A and B, calculate X for A.X = B
|
||||
|
||||
and classes for
|
||||
|
||||
- Decomposition
|
||||
- LU Decomposition with partial row pivoting,
|
||||
|
||||
such that [P].[A] = [L].[U] and [A] = [P]<sup>|</sup>.[L].[U]
|
||||
- QR Decomposition
|
||||
|
||||
such that [A] = [Q].[R]
|
||||
|
||||
## TO DO
|
||||
|
||||
- power()
|
||||
- EigenValues
|
||||
- EigenVectors
|
||||
- power() function
|
||||
- Decomposition
|
||||
- Cholesky Decomposition
|
||||
- EigenValue Decomposition
|
||||
- EigenValues
|
||||
- EigenVectors
|
||||
|
||||
---
|
||||
|
||||
# Installation
|
||||
|
||||
```shell
|
||||
composer require markbaker/matrix:^3.0
|
||||
```
|
||||
|
||||
# Important BC Note
|
||||
|
||||
If you've previously been using procedural calls to functions and operations using this library, then from version 3.0 you should use [MarkBaker/PHPMatrixFunctions](https://github.com/MarkBaker/PHPMatrixFunctions) instead (available on packagist as [markbaker/matrix-functions](https://packagist.org/packages/markbaker/matrix-functions)).
|
||||
|
||||
You'll need to replace `markbaker/matrix`in your `composer.json` file with the new library, but otherwise there should be no difference in the namespacing, or in the way that you have called the Matrix functions in the past, so no actual code changes are required.
|
||||
|
||||
```shell
|
||||
composer require markbaker/matrix-functions:^1.0
|
||||
```
|
||||
|
||||
You should not reference this library (`markbaker/matrix`) in your `composer.json`, composer wil take care of that for you.
|
||||
|
||||
# Usage
|
||||
|
||||
To create a new Matrix object, provide an array as the constructor argument
|
||||
|
||||
```
|
||||
```php
|
||||
$grid = [
|
||||
[16, 3, 2, 13],
|
||||
[ 5, 10, 11, 8],
|
||||
@@ -63,12 +97,12 @@ $grid = [
|
||||
$matrix = new Matrix\Matrix($grid);
|
||||
```
|
||||
The `Builder` class provides helper methods for creating specific matrices, specifically an identity matrix of a specified size; or a matrix of a specified dimensions, with every cell containing a set value.
|
||||
```
|
||||
$matrix = new Matrix\Builder::createFilledMatrix(1, 5, 3);
|
||||
```php
|
||||
$matrix = Matrix\Builder::createFilledMatrix(1, 5, 3);
|
||||
```
|
||||
Will create a matrix of 5 rows and 3 columns, filled with a `1` in every cell; while
|
||||
```
|
||||
$matrix = new Matrix\Builder::createIdentityMatrix(3);
|
||||
```php
|
||||
$matrix = Matrix\Builder::createIdentityMatrix(3);
|
||||
```
|
||||
will create a 3x3 identity matrix.
|
||||
|
||||
@@ -79,34 +113,34 @@ Matrix objects are immutable: whenever you call a method or pass a grid to a fun
|
||||
|
||||
To perform mathematical operations with Matrices, you can call the appropriate method against a matrix value, passing other values as arguments
|
||||
|
||||
```
|
||||
$matrix1 = new Matrix([
|
||||
```php
|
||||
$matrix1 = new Matrix\Matrix([
|
||||
[2, 7, 6],
|
||||
[9, 5, 1],
|
||||
[4, 3, 8],
|
||||
]);
|
||||
$matrix2 = new Matrix([
|
||||
$matrix2 = new Matrix\Matrix([
|
||||
[1, 2, 3],
|
||||
[4, 5, 6],
|
||||
[7, 8, 9],
|
||||
]);
|
||||
|
||||
echo $matrix1->multiply($matrix2);
|
||||
var_dump($matrix1->multiply($matrix2)->toArray());
|
||||
```
|
||||
or pass all values to the appropriate function
|
||||
```
|
||||
$matrix1 = new Matrix([
|
||||
or pass all values to the appropriate static method
|
||||
```php
|
||||
$matrix1 = new Matrix\Matrix([
|
||||
[2, 7, 6],
|
||||
[9, 5, 1],
|
||||
[4, 3, 8],
|
||||
]);
|
||||
$matrix2 = new Matrix([
|
||||
$matrix2 = new Matrix\Matrix([
|
||||
[1, 2, 3],
|
||||
[4, 5, 6],
|
||||
[7, 8, 9],
|
||||
]);
|
||||
|
||||
echo Matrix\multiply($matrix1, $matrix2);
|
||||
var_dump(Matrix\Operations::multiply($matrix1, $matrix2)->toArray());
|
||||
```
|
||||
You can pass in the arguments as Matrix objects, or as arrays.
|
||||
|
||||
@@ -115,7 +149,7 @@ If you want to perform the same operation against multiple values (e.g. to add t
|
||||
## Using functions
|
||||
|
||||
When calling any of the available functions for a matrix value, you can either call the relevant method for the Matrix object
|
||||
```
|
||||
```php
|
||||
$grid = [
|
||||
[16, 3, 2, 13],
|
||||
[ 5, 10, 11, 8],
|
||||
@@ -127,31 +161,8 @@ $matrix = new Matrix\Matrix($grid);
|
||||
|
||||
echo $matrix->trace();
|
||||
```
|
||||
or you can call the function as you would in procedural code, passing the Matrix object as an argument
|
||||
```
|
||||
$grid = [
|
||||
[16, 3, 2, 13],
|
||||
[ 5, 10, 11, 8],
|
||||
[ 9, 6, 7, 12],
|
||||
[ 4, 15, 14, 1],
|
||||
];
|
||||
|
||||
$matrix = new Matrix\Matrix($grid);
|
||||
echo Matrix\trace($matrix);
|
||||
```
|
||||
When called procedurally using the function, you can pass in the argument as a Matrix object, or as an array.
|
||||
```
|
||||
$grid = [
|
||||
[16, 3, 2, 13],
|
||||
[ 5, 10, 11, 8],
|
||||
[ 9, 6, 7, 12],
|
||||
[ 4, 15, 14, 1],
|
||||
];
|
||||
|
||||
echo Matrix\trace($grid);
|
||||
```
|
||||
As an alternative, it is also possible to call the method directly from the `Functions` class.
|
||||
```
|
||||
or you can call the static method, passing the Matrix object or array as an argument
|
||||
```php
|
||||
$grid = [
|
||||
[16, 3, 2, 13],
|
||||
[ 5, 10, 11, 8],
|
||||
@@ -162,4 +173,43 @@ $grid = [
|
||||
$matrix = new Matrix\Matrix($grid);
|
||||
echo Matrix\Functions::trace($matrix);
|
||||
```
|
||||
Used this way, methods must be called statically, and the argument must be the Matrix object, and cannot be an array.
|
||||
```php
|
||||
$grid = [
|
||||
[16, 3, 2, 13],
|
||||
[ 5, 10, 11, 8],
|
||||
[ 9, 6, 7, 12],
|
||||
[ 4, 15, 14, 1],
|
||||
];
|
||||
|
||||
echo Matrix\Functions::trace($grid);
|
||||
```
|
||||
|
||||
## Decomposition
|
||||
|
||||
The library also provides classes for matrix decomposition. You can access these using
|
||||
```php
|
||||
$grid = [
|
||||
[1, 2],
|
||||
[3, 4],
|
||||
];
|
||||
|
||||
$matrix = new Matrix\Matrix($grid);
|
||||
|
||||
$decomposition = new Matrix\Decomposition\QR($matrix);
|
||||
$Q = $decomposition->getQ();
|
||||
$R = $decomposition->getR();
|
||||
```
|
||||
|
||||
or alternatively us the `Decomposition` factory, identifying which form of decomposition you want to use
|
||||
```php
|
||||
$grid = [
|
||||
[1, 2],
|
||||
[3, 4],
|
||||
];
|
||||
|
||||
$matrix = new Matrix\Matrix($grid);
|
||||
|
||||
$decomposition = Matrix\Decomposition\Decomposition::decomposition(Matrix\Decomposition\Decomposition::QR, $matrix);
|
||||
$Q = $decomposition->getQ();
|
||||
$R = $decomposition->getR();
|
||||
```
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
@@ -21,13 +21,13 @@ 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 mixed $fillValue
|
||||
* @param int $rows
|
||||
* @param int|null $columns
|
||||
* @return Matrix
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function createFilledMatrix($value, $rows, $columns = null)
|
||||
public static function createFilledMatrix($fillValue, $rows, $columns = null)
|
||||
{
|
||||
if ($columns === null) {
|
||||
$columns = $rows;
|
||||
@@ -43,7 +43,7 @@ class Builder
|
||||
array_fill(
|
||||
0,
|
||||
$columns,
|
||||
$value
|
||||
$fillValue
|
||||
)
|
||||
)
|
||||
);
|
||||
@@ -57,9 +57,9 @@ class Builder
|
||||
* @return Matrix
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function createIdentityMatrix($dimensions)
|
||||
public static function createIdentityMatrix($dimensions, $fillValue = null)
|
||||
{
|
||||
$grid = static::createFilledMatrix(null, $dimensions)->toArray();
|
||||
$grid = static::createFilledMatrix($fillValue, $dimensions)->toArray();
|
||||
|
||||
for ($x = 0; $x < $dimensions; ++$x) {
|
||||
$grid[$x][$x] = 1;
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Matrix\Decomposition;
|
||||
|
||||
use Matrix\Exception;
|
||||
use Matrix\Matrix;
|
||||
|
||||
class Decomposition
|
||||
{
|
||||
const LU = 'LU';
|
||||
const QR = 'QR';
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function decomposition($type, Matrix $matrix)
|
||||
{
|
||||
switch (strtoupper($type)) {
|
||||
case self::LU:
|
||||
return new LU($matrix);
|
||||
case self::QR:
|
||||
return new QR($matrix);
|
||||
default:
|
||||
throw new Exception('Invalid Decomposition');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
|
||||
namespace Matrix\Decomposition;
|
||||
|
||||
use Matrix\Exception;
|
||||
use Matrix\Matrix;
|
||||
|
||||
class LU
|
||||
{
|
||||
private $luMatrix;
|
||||
private $rows;
|
||||
private $columns;
|
||||
|
||||
private $pivot = [];
|
||||
|
||||
public function __construct(Matrix $matrix)
|
||||
{
|
||||
$this->luMatrix = $matrix->toArray();
|
||||
$this->rows = $matrix->rows;
|
||||
$this->columns = $matrix->columns;
|
||||
|
||||
$this->buildPivot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get lower triangular factor.
|
||||
*
|
||||
* @return Matrix Lower triangular factor
|
||||
*/
|
||||
public function getL(): Matrix
|
||||
{
|
||||
$lower = [];
|
||||
|
||||
$columns = min($this->rows, $this->columns);
|
||||
for ($row = 0; $row < $this->rows; ++$row) {
|
||||
for ($column = 0; $column < $columns; ++$column) {
|
||||
if ($row > $column) {
|
||||
$lower[$row][$column] = $this->luMatrix[$row][$column];
|
||||
} elseif ($row === $column) {
|
||||
$lower[$row][$column] = 1.0;
|
||||
} else {
|
||||
$lower[$row][$column] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Matrix($lower);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get upper triangular factor.
|
||||
*
|
||||
* @return Matrix Upper triangular factor
|
||||
*/
|
||||
public function getU(): Matrix
|
||||
{
|
||||
$upper = [];
|
||||
|
||||
$rows = min($this->rows, $this->columns);
|
||||
for ($row = 0; $row < $rows; ++$row) {
|
||||
for ($column = 0; $column < $this->columns; ++$column) {
|
||||
if ($row <= $column) {
|
||||
$upper[$row][$column] = $this->luMatrix[$row][$column];
|
||||
} else {
|
||||
$upper[$row][$column] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Matrix($upper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return pivot permutation vector.
|
||||
*
|
||||
* @return Matrix Pivot matrix
|
||||
*/
|
||||
public function getP(): Matrix
|
||||
{
|
||||
$pMatrix = [];
|
||||
|
||||
$pivots = $this->pivot;
|
||||
$pivotCount = count($pivots);
|
||||
foreach ($pivots as $row => $pivot) {
|
||||
$pMatrix[$row] = array_fill(0, $pivotCount, 0);
|
||||
$pMatrix[$row][$pivot] = 1;
|
||||
}
|
||||
|
||||
return new Matrix($pMatrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return pivot permutation vector.
|
||||
*
|
||||
* @return array Pivot vector
|
||||
*/
|
||||
public function getPivot(): array
|
||||
{
|
||||
return $this->pivot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the matrix nonsingular?
|
||||
*
|
||||
* @return bool true if U, and hence A, is nonsingular
|
||||
*/
|
||||
public function isNonsingular(): bool
|
||||
{
|
||||
for ($diagonal = 0; $diagonal < $this->columns; ++$diagonal) {
|
||||
if ($this->luMatrix[$diagonal][$diagonal] === 0.0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function buildPivot(): void
|
||||
{
|
||||
for ($row = 0; $row < $this->rows; ++$row) {
|
||||
$this->pivot[$row] = $row;
|
||||
}
|
||||
|
||||
for ($column = 0; $column < $this->columns; ++$column) {
|
||||
$luColumn = $this->localisedReferenceColumn($column);
|
||||
|
||||
$this->applyTransformations($column, $luColumn);
|
||||
|
||||
$pivot = $this->findPivot($column, $luColumn);
|
||||
if ($pivot !== $column) {
|
||||
$this->pivotExchange($pivot, $column);
|
||||
}
|
||||
|
||||
$this->computeMultipliers($column);
|
||||
|
||||
unset($luColumn);
|
||||
}
|
||||
}
|
||||
|
||||
private function localisedReferenceColumn($column): array
|
||||
{
|
||||
$luColumn = [];
|
||||
|
||||
for ($row = 0; $row < $this->rows; ++$row) {
|
||||
$luColumn[$row] = &$this->luMatrix[$row][$column];
|
||||
}
|
||||
|
||||
return $luColumn;
|
||||
}
|
||||
|
||||
private function applyTransformations($column, array $luColumn): void
|
||||
{
|
||||
for ($row = 0; $row < $this->rows; ++$row) {
|
||||
$luRow = $this->luMatrix[$row];
|
||||
// Most of the time is spent in the following dot product.
|
||||
$kmax = min($row, $column);
|
||||
$sValue = 0.0;
|
||||
for ($kValue = 0; $kValue < $kmax; ++$kValue) {
|
||||
$sValue += $luRow[$kValue] * $luColumn[$kValue];
|
||||
}
|
||||
$luRow[$column] = $luColumn[$row] -= $sValue;
|
||||
}
|
||||
}
|
||||
|
||||
private function findPivot($column, array $luColumn): int
|
||||
{
|
||||
$pivot = $column;
|
||||
for ($row = $column + 1; $row < $this->rows; ++$row) {
|
||||
if (abs($luColumn[$row]) > abs($luColumn[$pivot])) {
|
||||
$pivot = $row;
|
||||
}
|
||||
}
|
||||
|
||||
return $pivot;
|
||||
}
|
||||
|
||||
private function pivotExchange($pivot, $column): void
|
||||
{
|
||||
for ($kValue = 0; $kValue < $this->columns; ++$kValue) {
|
||||
$tValue = $this->luMatrix[$pivot][$kValue];
|
||||
$this->luMatrix[$pivot][$kValue] = $this->luMatrix[$column][$kValue];
|
||||
$this->luMatrix[$column][$kValue] = $tValue;
|
||||
}
|
||||
|
||||
$lValue = $this->pivot[$pivot];
|
||||
$this->pivot[$pivot] = $this->pivot[$column];
|
||||
$this->pivot[$column] = $lValue;
|
||||
}
|
||||
|
||||
private function computeMultipliers($diagonal): void
|
||||
{
|
||||
if (($diagonal < $this->rows) && ($this->luMatrix[$diagonal][$diagonal] != 0.0)) {
|
||||
for ($row = $diagonal + 1; $row < $this->rows; ++$row) {
|
||||
$this->luMatrix[$row][$diagonal] /= $this->luMatrix[$diagonal][$diagonal];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function pivotB(Matrix $B): array
|
||||
{
|
||||
$X = [];
|
||||
foreach ($this->pivot as $rowId) {
|
||||
$row = $B->getRows($rowId + 1)->toArray();
|
||||
$X[] = array_pop($row);
|
||||
}
|
||||
|
||||
return $X;
|
||||
}
|
||||
|
||||
/**
|
||||
* Solve A*X = B.
|
||||
*
|
||||
* @param Matrix $B a Matrix with as many rows as A and any number of columns
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Matrix X so that L*U*X = B(piv,:)
|
||||
*/
|
||||
public function solve(Matrix $B): Matrix
|
||||
{
|
||||
if ($B->rows !== $this->rows) {
|
||||
throw new Exception('Matrix row dimensions are not equal');
|
||||
}
|
||||
|
||||
if ($this->rows !== $this->columns) {
|
||||
throw new Exception('LU solve() only works on square matrices');
|
||||
}
|
||||
|
||||
if (!$this->isNonsingular()) {
|
||||
throw new Exception('Can only perform operation on singular matrix');
|
||||
}
|
||||
|
||||
// Copy right hand side with pivoting
|
||||
$nx = $B->columns;
|
||||
$X = $this->pivotB($B);
|
||||
|
||||
// Solve L*Y = B(piv,:)
|
||||
for ($k = 0; $k < $this->columns; ++$k) {
|
||||
for ($i = $k + 1; $i < $this->columns; ++$i) {
|
||||
for ($j = 0; $j < $nx; ++$j) {
|
||||
$X[$i][$j] -= $X[$k][$j] * $this->luMatrix[$i][$k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Solve U*X = Y;
|
||||
for ($k = $this->columns - 1; $k >= 0; --$k) {
|
||||
for ($j = 0; $j < $nx; ++$j) {
|
||||
$X[$k][$j] /= $this->luMatrix[$k][$k];
|
||||
}
|
||||
for ($i = 0; $i < $k; ++$i) {
|
||||
for ($j = 0; $j < $nx; ++$j) {
|
||||
$X[$i][$j] -= $X[$k][$j] * $this->luMatrix[$i][$k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Matrix($X);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
namespace Matrix\Decomposition;
|
||||
|
||||
use Matrix\Exception;
|
||||
use Matrix\Matrix;
|
||||
|
||||
class QR
|
||||
{
|
||||
private $qrMatrix;
|
||||
private $rows;
|
||||
private $columns;
|
||||
|
||||
private $rDiagonal = [];
|
||||
|
||||
public function __construct(Matrix $matrix)
|
||||
{
|
||||
$this->qrMatrix = $matrix->toArray();
|
||||
$this->rows = $matrix->rows;
|
||||
$this->columns = $matrix->columns;
|
||||
|
||||
$this->decompose();
|
||||
}
|
||||
|
||||
public function getHouseholdVectors(): Matrix
|
||||
{
|
||||
$householdVectors = [];
|
||||
for ($row = 0; $row < $this->rows; ++$row) {
|
||||
for ($column = 0; $column < $this->columns; ++$column) {
|
||||
if ($row >= $column) {
|
||||
$householdVectors[$row][$column] = $this->qrMatrix[$row][$column];
|
||||
} else {
|
||||
$householdVectors[$row][$column] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Matrix($householdVectors);
|
||||
}
|
||||
|
||||
public function getQ(): Matrix
|
||||
{
|
||||
$qGrid = [];
|
||||
|
||||
$rowCount = $this->rows;
|
||||
for ($k = $this->columns - 1; $k >= 0; --$k) {
|
||||
for ($i = 0; $i < $this->rows; ++$i) {
|
||||
$qGrid[$i][$k] = 0.0;
|
||||
}
|
||||
$qGrid[$k][$k] = 1.0;
|
||||
if ($this->columns > $this->rows) {
|
||||
$qGrid = array_slice($qGrid, 0, $this->rows);
|
||||
}
|
||||
|
||||
for ($j = $k; $j < $this->columns; ++$j) {
|
||||
if (isset($this->qrMatrix[$k], $this->qrMatrix[$k][$k]) && $this->qrMatrix[$k][$k] != 0.0) {
|
||||
$s = 0.0;
|
||||
for ($i = $k; $i < $this->rows; ++$i) {
|
||||
$s += $this->qrMatrix[$i][$k] * $qGrid[$i][$j];
|
||||
}
|
||||
$s = -$s / $this->qrMatrix[$k][$k];
|
||||
for ($i = $k; $i < $this->rows; ++$i) {
|
||||
$qGrid[$i][$j] += $s * $this->qrMatrix[$i][$k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
array_walk(
|
||||
$qGrid,
|
||||
function (&$row) use ($rowCount) {
|
||||
$row = array_reverse($row);
|
||||
$row = array_slice($row, 0, $rowCount);
|
||||
}
|
||||
);
|
||||
|
||||
return new Matrix($qGrid);
|
||||
}
|
||||
|
||||
public function getR(): Matrix
|
||||
{
|
||||
$rGrid = [];
|
||||
|
||||
for ($row = 0; $row < $this->columns; ++$row) {
|
||||
for ($column = 0; $column < $this->columns; ++$column) {
|
||||
if ($row < $column) {
|
||||
$rGrid[$row][$column] = $this->qrMatrix[$row][$column] ?? 0.0;
|
||||
} elseif ($row === $column) {
|
||||
$rGrid[$row][$column] = $this->rDiagonal[$row] ?? 0.0;
|
||||
} else {
|
||||
$rGrid[$row][$column] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->columns > $this->rows) {
|
||||
$rGrid = array_slice($rGrid, 0, $this->rows);
|
||||
}
|
||||
|
||||
return new Matrix($rGrid);
|
||||
}
|
||||
|
||||
private function hypo($a, $b): float
|
||||
{
|
||||
if (abs($a) > abs($b)) {
|
||||
$r = $b / $a;
|
||||
$r = abs($a) * sqrt(1 + $r * $r);
|
||||
} elseif ($b != 0.0) {
|
||||
$r = $a / $b;
|
||||
$r = abs($b) * sqrt(1 + $r * $r);
|
||||
} else {
|
||||
$r = 0.0;
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* QR Decomposition computed by Householder reflections.
|
||||
*/
|
||||
private function decompose(): void
|
||||
{
|
||||
for ($k = 0; $k < $this->columns; ++$k) {
|
||||
// Compute 2-norm of k-th column without under/overflow.
|
||||
$norm = 0.0;
|
||||
for ($i = $k; $i < $this->rows; ++$i) {
|
||||
$norm = $this->hypo($norm, $this->qrMatrix[$i][$k]);
|
||||
}
|
||||
if ($norm != 0.0) {
|
||||
// Form k-th Householder vector.
|
||||
if ($this->qrMatrix[$k][$k] < 0.0) {
|
||||
$norm = -$norm;
|
||||
}
|
||||
for ($i = $k; $i < $this->rows; ++$i) {
|
||||
$this->qrMatrix[$i][$k] /= $norm;
|
||||
}
|
||||
$this->qrMatrix[$k][$k] += 1.0;
|
||||
// Apply transformation to remaining columns.
|
||||
for ($j = $k + 1; $j < $this->columns; ++$j) {
|
||||
$s = 0.0;
|
||||
for ($i = $k; $i < $this->rows; ++$i) {
|
||||
$s += $this->qrMatrix[$i][$k] * $this->qrMatrix[$i][$j];
|
||||
}
|
||||
$s = -$s / $this->qrMatrix[$k][$k];
|
||||
for ($i = $k; $i < $this->rows; ++$i) {
|
||||
$this->qrMatrix[$i][$j] += $s * $this->qrMatrix[$i][$k];
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->rDiagonal[$k] = -$norm;
|
||||
}
|
||||
}
|
||||
|
||||
public function isFullRank(): bool
|
||||
{
|
||||
for ($j = 0; $j < $this->columns; ++$j) {
|
||||
if ($this->rDiagonal[$j] == 0.0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Least squares solution of A*X = B.
|
||||
*
|
||||
* @param Matrix $B a Matrix with as many rows as A and any number of columns
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Matrix matrix that minimizes the two norm of Q*R*X-B
|
||||
*/
|
||||
public function solve(Matrix $B): Matrix
|
||||
{
|
||||
if ($B->rows !== $this->rows) {
|
||||
throw new Exception('Matrix row dimensions are not equal');
|
||||
}
|
||||
|
||||
if (!$this->isFullRank()) {
|
||||
throw new Exception('Can only perform this operation on a full-rank matrix');
|
||||
}
|
||||
|
||||
// Compute Y = transpose(Q)*B
|
||||
$Y = $this->getQ()->transpose()
|
||||
->multiply($B);
|
||||
// Solve R*X = Y;
|
||||
return $this->getR()->inverse()
|
||||
->multiply($Y);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Exception.
|
||||
*
|
||||
* @copyright Copyright (c) 2013-2018 Mark Baker (https://github.com/MarkBaker/PHPMatrix)
|
||||
* @license https://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
namespace Matrix;
|
||||
|
||||
class Div0Exception extends Exception
|
||||
{
|
||||
}
|
||||
@@ -4,6 +4,25 @@ namespace Matrix;
|
||||
|
||||
class Functions
|
||||
{
|
||||
/**
|
||||
* Validates an array of matrix, converting an array to a matrix if required.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
private static function validateMatrix($matrix)
|
||||
{
|
||||
if (is_array($matrix)) {
|
||||
$matrix = new Matrix($matrix);
|
||||
}
|
||||
if (!$matrix instanceof Matrix) {
|
||||
throw new Exception('Must be Matrix or array');
|
||||
}
|
||||
|
||||
return $matrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the adjoint of the matrix
|
||||
*
|
||||
@@ -25,12 +44,14 @@ class Functions
|
||||
* 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
|
||||
* @param Matrix|array $matrix The matrix whose adjoint we wish to calculate
|
||||
* @return Matrix
|
||||
* @throws Exception
|
||||
**/
|
||||
public static function adjoint(Matrix $matrix)
|
||||
public static function adjoint($matrix)
|
||||
{
|
||||
$matrix = self::validateMatrix($matrix);
|
||||
|
||||
if (!$matrix->isSquare()) {
|
||||
throw new Exception('Adjoint can only be calculated for a square matrix');
|
||||
}
|
||||
@@ -67,13 +88,15 @@ class Functions
|
||||
/**
|
||||
* Return the cofactors of this matrix
|
||||
*
|
||||
* @param Matrix $matrix The matrix whose cofactors we wish to calculate
|
||||
* @param Matrix|array $matrix The matrix whose cofactors we wish to calculate
|
||||
* @return Matrix
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function cofactors(Matrix $matrix)
|
||||
public static function cofactors($matrix)
|
||||
{
|
||||
$matrix = self::validateMatrix($matrix);
|
||||
|
||||
if (!$matrix->isSquare()) {
|
||||
throw new Exception('Cofactors can only be calculated for a square matrix');
|
||||
}
|
||||
@@ -141,12 +164,14 @@ class Functions
|
||||
/**
|
||||
* Return the determinant of this matrix
|
||||
*
|
||||
* @param Matrix $matrix The matrix whose determinant we wish to calculate
|
||||
* @param Matrix|array $matrix The matrix whose determinant we wish to calculate
|
||||
* @return float
|
||||
* @throws Exception
|
||||
**/
|
||||
public static function determinant(Matrix $matrix)
|
||||
public static function determinant($matrix)
|
||||
{
|
||||
$matrix = self::validateMatrix($matrix);
|
||||
|
||||
if (!$matrix->isSquare()) {
|
||||
throw new Exception('Determinant can only be calculated for a square matrix');
|
||||
}
|
||||
@@ -157,12 +182,14 @@ class Functions
|
||||
/**
|
||||
* Return the diagonal of this matrix
|
||||
*
|
||||
* @param Matrix $matrix The matrix whose diagonal we wish to calculate
|
||||
* @param Matrix|array $matrix The matrix whose diagonal we wish to calculate
|
||||
* @return Matrix
|
||||
* @throws Exception
|
||||
**/
|
||||
public static function diagonal(Matrix $matrix)
|
||||
public static function diagonal($matrix)
|
||||
{
|
||||
$matrix = self::validateMatrix($matrix);
|
||||
|
||||
if (!$matrix->isSquare()) {
|
||||
throw new Exception('Diagonal can only be extracted from a square matrix');
|
||||
}
|
||||
@@ -181,12 +208,14 @@ class Functions
|
||||
/**
|
||||
* Return the antidiagonal of this matrix
|
||||
*
|
||||
* @param Matrix $matrix The matrix whose antidiagonal we wish to calculate
|
||||
* @param Matrix|array $matrix The matrix whose antidiagonal we wish to calculate
|
||||
* @return Matrix
|
||||
* @throws Exception
|
||||
**/
|
||||
public static function antidiagonal(Matrix $matrix)
|
||||
public static function antidiagonal($matrix)
|
||||
{
|
||||
$matrix = self::validateMatrix($matrix);
|
||||
|
||||
if (!$matrix->isSquare()) {
|
||||
throw new Exception('Anti-Diagonal can only be extracted from a square matrix');
|
||||
}
|
||||
@@ -207,12 +236,14 @@ class Functions
|
||||
* 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
|
||||
* @param Matrix|array $matrix The matrix whose identity we wish to calculate
|
||||
* @return Matrix
|
||||
* @throws Exception
|
||||
**/
|
||||
public static function identity(Matrix $matrix)
|
||||
public static function identity($matrix)
|
||||
{
|
||||
$matrix = self::validateMatrix($matrix);
|
||||
|
||||
if (!$matrix->isSquare()) {
|
||||
throw new Exception('Identity can only be created for a square matrix');
|
||||
}
|
||||
@@ -225,19 +256,21 @@ class Functions
|
||||
/**
|
||||
* Return the inverse of this matrix
|
||||
*
|
||||
* @param Matrix $matrix The matrix whose inverse we wish to calculate
|
||||
* @param Matrix|array $matrix The matrix whose inverse we wish to calculate
|
||||
* @return Matrix
|
||||
* @throws Exception
|
||||
**/
|
||||
public static function inverse(Matrix $matrix)
|
||||
public static function inverse($matrix, string $type = 'inverse')
|
||||
{
|
||||
$matrix = self::validateMatrix($matrix);
|
||||
|
||||
if (!$matrix->isSquare()) {
|
||||
throw new Exception('Inverse can only be calculated for a square matrix');
|
||||
throw new Exception(ucfirst($type) . ' 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');
|
||||
throw new Div0Exception(ucfirst($type) . ' can only be calculated for a matrix with a non-zero determinant');
|
||||
}
|
||||
|
||||
if ($matrix->rows == 1) {
|
||||
@@ -281,12 +314,14 @@ class Functions
|
||||
* 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
|
||||
* @param Matrix|array $matrix The matrix whose minors we wish to calculate
|
||||
* @return Matrix
|
||||
* @throws Exception
|
||||
**/
|
||||
public static function minors(Matrix $matrix)
|
||||
public static function minors($matrix)
|
||||
{
|
||||
$matrix = self::validateMatrix($matrix);
|
||||
|
||||
if (!$matrix->isSquare()) {
|
||||
throw new Exception('Minors can only be calculated for a square matrix');
|
||||
}
|
||||
@@ -299,12 +334,14 @@ class Functions
|
||||
* 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
|
||||
* @param Matrix|array $matrix The matrix whose trace we wish to calculate
|
||||
* @return float
|
||||
* @throws Exception
|
||||
**/
|
||||
public static function trace(Matrix $matrix)
|
||||
public static function trace($matrix)
|
||||
{
|
||||
$matrix = self::validateMatrix($matrix);
|
||||
|
||||
if (!$matrix->isSquare()) {
|
||||
throw new Exception('Trace can only be extracted from a square matrix');
|
||||
}
|
||||
@@ -321,11 +358,13 @@ class Functions
|
||||
/**
|
||||
* Return the transpose of this matrix
|
||||
*
|
||||
* @param Matrix $matrix The matrix whose transpose we wish to calculate
|
||||
* @param Matrix|\a $matrix The matrix whose transpose we wish to calculate
|
||||
* @return Matrix
|
||||
**/
|
||||
public static function transpose(Matrix $matrix)
|
||||
public static function transpose($matrix)
|
||||
{
|
||||
$matrix = self::validateMatrix($matrix);
|
||||
|
||||
$array = array_values(array_merge([null], $matrix->toArray()));
|
||||
$grid = call_user_func_array(
|
||||
'array_map',
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
|
||||
namespace Matrix;
|
||||
|
||||
use Generator;
|
||||
use Matrix\Decomposition\LU;
|
||||
use Matrix\Decomposition\QR;
|
||||
|
||||
/**
|
||||
* Matrix object.
|
||||
*
|
||||
@@ -24,7 +28,6 @@ namespace Matrix;
|
||||
* @method Matrix diagonal()
|
||||
* @method Matrix identity()
|
||||
* @method Matrix inverse()
|
||||
* @method Matrix pseudoInverse()
|
||||
* @method Matrix minors()
|
||||
* @method float trace()
|
||||
* @method Matrix transpose()
|
||||
@@ -33,6 +36,7 @@ namespace Matrix;
|
||||
* @method Matrix multiply(...$matrices)
|
||||
* @method Matrix divideby(...$matrices)
|
||||
* @method Matrix divideinto(...$matrices)
|
||||
* @method Matrix directsum(...$matrices)
|
||||
*/
|
||||
class Matrix
|
||||
{
|
||||
@@ -270,11 +274,11 @@ class Matrix
|
||||
|
||||
/**
|
||||
* 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
|
||||
* or the value of each cell if the matrix is a column vector
|
||||
*
|
||||
* @return \Generator|Matrix[]|mixed[]
|
||||
* @return Generator|Matrix[]|mixed[]
|
||||
*/
|
||||
public function rows(): \Generator
|
||||
public function rows(): Generator
|
||||
{
|
||||
foreach ($this->grid as $i => $row) {
|
||||
yield $i + 1 => ($this->columns == 1)
|
||||
@@ -285,11 +289,11 @@ class Matrix
|
||||
|
||||
/**
|
||||
* 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
|
||||
* or the value of each cell if the matrix is a row vector
|
||||
*
|
||||
* @return \Generator|Matrix[]|mixed[]
|
||||
* @return Generator|Matrix[]|mixed[]
|
||||
*/
|
||||
public function columns(): \Generator
|
||||
public function columns(): Generator
|
||||
{
|
||||
for ($i = 0; $i < $this->columns; ++$i) {
|
||||
yield $i + 1 => ($this->rows == 1)
|
||||
@@ -306,7 +310,7 @@ class Matrix
|
||||
*/
|
||||
public function isSquare(): bool
|
||||
{
|
||||
return $this->rows == $this->columns;
|
||||
return $this->rows === $this->columns;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -317,7 +321,7 @@ class Matrix
|
||||
*/
|
||||
public function isVector(): bool
|
||||
{
|
||||
return $this->rows == 1 || $this->columns == 1;
|
||||
return $this->rows === 1 || $this->columns === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -330,6 +334,24 @@ class Matrix
|
||||
return $this->grid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Solve A*X = B.
|
||||
*
|
||||
* @param Matrix $B Right hand side
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Matrix ... Solution if A is square, least squares solution otherwise
|
||||
*/
|
||||
public function solve(Matrix $B): Matrix
|
||||
{
|
||||
if ($this->columns === $this->rows) {
|
||||
return (new LU($this))->solve($B);
|
||||
}
|
||||
|
||||
return (new QR($this))->solve($B);
|
||||
}
|
||||
|
||||
protected static $getters = [
|
||||
'rows',
|
||||
'columns',
|
||||
@@ -355,8 +377,8 @@ class Matrix
|
||||
}
|
||||
|
||||
protected static $functions = [
|
||||
'antidiagonal',
|
||||
'adjoint',
|
||||
'antidiagonal',
|
||||
'cofactors',
|
||||
'determinant',
|
||||
'diagonal',
|
||||
@@ -388,12 +410,13 @@ class Matrix
|
||||
{
|
||||
$functionName = strtolower(str_replace('_', '', $functionName));
|
||||
|
||||
if (in_array($functionName, self::$functions, true) || in_array($functionName, self::$operations, true)) {
|
||||
$functionName = "\\" . __NAMESPACE__ . "\\{$functionName}";
|
||||
if (is_callable($functionName)) {
|
||||
$arguments = array_values(array_merge([$this], $arguments));
|
||||
return call_user_func_array($functionName, $arguments);
|
||||
}
|
||||
// Test for function calls
|
||||
if (in_array($functionName, self::$functions, true)) {
|
||||
return Functions::$functionName($this, ...$arguments);
|
||||
}
|
||||
// Test for operation calls
|
||||
if (in_array($functionName, self::$operations, true)) {
|
||||
return Operations::$functionName($this, ...$arguments);
|
||||
}
|
||||
throw new Exception('Function or Operation does not exist');
|
||||
}
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
namespace Matrix;
|
||||
|
||||
use Matrix\Operators\Addition;
|
||||
use Matrix\Operators\DirectSum;
|
||||
use Matrix\Operators\Division;
|
||||
use Matrix\Operators\Multiplication;
|
||||
use Matrix\Operators\Subtraction;
|
||||
|
||||
class Operations
|
||||
{
|
||||
public static function add(...$matrixValues): Matrix
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
public static function directsum(...$matrixValues): Matrix
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
public static function divideby(...$matrixValues): Matrix
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
public static function divideinto(...$matrixValues): Matrix
|
||||
{
|
||||
if (count($matrixValues) < 2) {
|
||||
throw new Exception('Division operation requires at least 2 arguments');
|
||||
}
|
||||
|
||||
$matrix = array_pop($matrixValues);
|
||||
$matrixValues = array_reverse($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();
|
||||
}
|
||||
|
||||
public static function multiply(...$matrixValues): Matrix
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
public static function subtract(...$matrixValues): Matrix
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
+6
-9
@@ -2,9 +2,10 @@
|
||||
|
||||
namespace Matrix\Operators;
|
||||
|
||||
use Matrix\Div0Exception;
|
||||
use Matrix\Exception;
|
||||
use \Matrix\Matrix;
|
||||
use \Matrix\Functions;
|
||||
use Matrix\Exception;
|
||||
|
||||
class Division extends Multiplication
|
||||
{
|
||||
@@ -15,22 +16,18 @@ class Division extends Multiplication
|
||||
* @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): Operator
|
||||
public function execute($value, string $type = 'division'): Operator
|
||||
{
|
||||
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');
|
||||
}
|
||||
$value = Functions::inverse($value, $type);
|
||||
|
||||
return $this->multiplyMatrix($value);
|
||||
return $this->multiplyMatrix($value, $type);
|
||||
} elseif (is_numeric($value)) {
|
||||
return $this->multiplyScalar(1 / $value);
|
||||
return $this->multiplyScalar(1 / $value, $type);
|
||||
}
|
||||
|
||||
throw new Exception('Invalid argument for division');
|
||||
|
||||
+23
-14
@@ -5,6 +5,7 @@ namespace Matrix\Operators;
|
||||
use Matrix\Matrix;
|
||||
use \Matrix\Builder;
|
||||
use Matrix\Exception;
|
||||
use Throwable;
|
||||
|
||||
class Multiplication extends Operator
|
||||
{
|
||||
@@ -15,19 +16,19 @@ class Multiplication extends Operator
|
||||
* @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): Operator
|
||||
public function execute($value, string $type = 'multiplication'): Operator
|
||||
{
|
||||
if (is_array($value)) {
|
||||
$value = new Matrix($value);
|
||||
}
|
||||
|
||||
if (is_object($value) && ($value instanceof Matrix)) {
|
||||
return $this->multiplyMatrix($value);
|
||||
return $this->multiplyMatrix($value, $type);
|
||||
} elseif (is_numeric($value)) {
|
||||
return $this->multiplyScalar($value);
|
||||
return $this->multiplyScalar($value, $type);
|
||||
}
|
||||
|
||||
throw new Exception('Invalid argument for multiplication');
|
||||
throw new Exception("Invalid argument for $type");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,12 +37,16 @@ class Multiplication extends Operator
|
||||
* @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): Operator
|
||||
protected function multiplyScalar($value, string $type = 'multiplication'): Operator
|
||||
{
|
||||
for ($row = 0; $row < $this->rows; ++$row) {
|
||||
for ($column = 0; $column < $this->columns; ++$column) {
|
||||
$this->matrix[$row][$column] *= $value;
|
||||
try {
|
||||
for ($row = 0; $row < $this->rows; ++$row) {
|
||||
for ($column = 0; $column < $this->columns; ++$column) {
|
||||
$this->matrix[$row][$column] *= $value;
|
||||
}
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
throw new Exception("Invalid argument for $type");
|
||||
}
|
||||
|
||||
return $this;
|
||||
@@ -54,7 +59,7 @@ class Multiplication extends Operator
|
||||
* @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): Operator
|
||||
protected function multiplyMatrix(Matrix $value, string $type = 'multiplication'): Operator
|
||||
{
|
||||
$this->validateReflectingDimensions($value);
|
||||
|
||||
@@ -62,13 +67,17 @@ class Multiplication extends Operator
|
||||
$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];
|
||||
try {
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
throw new Exception("Invalid argument for $type");
|
||||
}
|
||||
$this->matrix = $matrix;
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
<?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): 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);
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
<?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): 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);
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
<?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): 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);
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
<?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): float
|
||||
{
|
||||
if (is_array($matrix)) {
|
||||
$matrix = new Matrix($matrix);
|
||||
}
|
||||
if (!$matrix instanceof Matrix) {
|
||||
throw new Exception('Must be Matrix or array');
|
||||
}
|
||||
|
||||
return Functions::determinant($matrix);
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
<?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): 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);
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
<?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): 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);
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?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): 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);
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?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): 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);
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?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): float
|
||||
{
|
||||
if (is_array($matrix)) {
|
||||
$matrix = new Matrix($matrix);
|
||||
}
|
||||
if (!$matrix instanceof Matrix) {
|
||||
throw new Exception('Must be Matrix or array');
|
||||
}
|
||||
|
||||
return Functions::trace($matrix);
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
<?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): 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);
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<?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): Matrix
|
||||
{
|
||||
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();
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
<?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): Matrix
|
||||
{
|
||||
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();
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
<?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): Matrix
|
||||
{
|
||||
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();
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
<?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): Matrix
|
||||
{
|
||||
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();
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
<?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): Matrix
|
||||
{
|
||||
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();
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
<?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): Matrix
|
||||
{
|
||||
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();
|
||||
}
|
||||
+5
-41
@@ -12,7 +12,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0"
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.3",
|
||||
@@ -27,48 +27,12 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Matrix\\": "classes/src/"
|
||||
},
|
||||
"files": [
|
||||
"classes/src/functions/adjoint.php",
|
||||
"classes/src/functions/antidiagonal.php",
|
||||
"classes/src/functions/cofactors.php",
|
||||
"classes/src/functions/determinant.php",
|
||||
"classes/src/functions/diagonal.php",
|
||||
"classes/src/functions/identity.php",
|
||||
"classes/src/functions/inverse.php",
|
||||
"classes/src/functions/minors.php",
|
||||
"classes/src/functions/trace.php",
|
||||
"classes/src/functions/transpose.php",
|
||||
"classes/src/operations/add.php",
|
||||
"classes/src/operations/directsum.php",
|
||||
"classes/src/operations/subtract.php",
|
||||
"classes/src/operations/multiply.php",
|
||||
"classes/src/operations/divideby.php",
|
||||
"classes/src/operations/divideinto.php"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Matrix\\Test\\": "unitTests/classes/src/"
|
||||
},
|
||||
"files": [
|
||||
"unitTests/classes/src/functions/adjointTest.php",
|
||||
"unitTests/classes/src/functions/antidiagonalTest.php",
|
||||
"unitTests/classes/src/functions/cofactorsTest.php",
|
||||
"unitTests/classes/src/functions/determinantTest.php",
|
||||
"unitTests/classes/src/functions/diagonalTest.php",
|
||||
"unitTests/classes/src/functions/identityTest.php",
|
||||
"unitTests/classes/src/functions/inverseTest.php",
|
||||
"unitTests/classes/src/functions/minorsTest.php",
|
||||
"unitTests/classes/src/functions/traceTest.php",
|
||||
"unitTests/classes/src/functions/transposeTest.php",
|
||||
"unitTests/classes/src/operations/addTest.php",
|
||||
"unitTests/classes/src/operations/directsumTest.php",
|
||||
"unitTests/classes/src/operations/subtractTest.php",
|
||||
"unitTests/classes/src/operations/multiplyTest.php",
|
||||
"unitTests/classes/src/operations/dividebyTest.php",
|
||||
"unitTests/classes/src/operations/divideintoTest.php"
|
||||
]
|
||||
"MatrixTest\\": "unitTests/classes/src/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"style": "phpcs --report-width=200 --standard=PSR2 --report=summary,full classes/src/ unitTests/classes/src -n",
|
||||
@@ -80,4 +44,4 @@
|
||||
"coverage": "phpunit -c phpunit.xml.dist --coverage-text --coverage-html ./build/coverage"
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
}
|
||||
+24
-10
@@ -1,19 +1,33 @@
|
||||
<?php
|
||||
|
||||
include __DIR__ . '/../classes/Bootstrap.php';
|
||||
use Matrix\Matrix;
|
||||
use Matrix\Decomposition\QR;
|
||||
|
||||
$grid1 = [
|
||||
[1, 3, 2],
|
||||
[2, 3, 1],
|
||||
];
|
||||
include __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$grid2 = [
|
||||
[1, 6],
|
||||
$grid = [
|
||||
[0, 1],
|
||||
[-1, 0],
|
||||
];
|
||||
|
||||
$matrix = new Matrix\Matrix($grid1);
|
||||
$targetGrid = [
|
||||
[-1],
|
||||
[2],
|
||||
];
|
||||
|
||||
$new = $matrix->directsum(new Matrix\Matrix($grid2));
|
||||
$matrix = new Matrix($grid);
|
||||
$target = new Matrix($targetGrid);
|
||||
|
||||
var_dump($new);
|
||||
$decomposition = new QR($matrix);
|
||||
|
||||
$X = $decomposition->solve($target);
|
||||
|
||||
echo 'X', PHP_EOL;
|
||||
var_export($X->toArray());
|
||||
echo PHP_EOL;
|
||||
|
||||
$resolve = $matrix->multiply($X);
|
||||
|
||||
echo 'Resolve', PHP_EOL;
|
||||
var_export($resolve->toArray());
|
||||
echo PHP_EOL;
|
||||
|
||||
+227
-4
@@ -5,11 +5,96 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org).
|
||||
|
||||
## Unreleased - TBD
|
||||
## 1.21.0 - 2022-01-06
|
||||
|
||||
### Added
|
||||
|
||||
- Nothing.
|
||||
- Ability to add a picture to the background of the comment. Supports four image formats: png, jpeg, gif, bmp. New `Comment::setSizeAsBackgroundImage()` to change the size of a comment to the size of a background image. [Issue #1547](https://github.com/PHPOffice/PhpSpreadsheet/issues/1547) [PR #2422](https://github.com/PHPOffice/PhpSpreadsheet/pull/2422)
|
||||
- Ability to set default paper size and orientation [PR #2410](https://github.com/PHPOffice/PhpSpreadsheet/pull/2410)
|
||||
- Ability to extend AutoFilter to Maximum Row [PR #2414](https://github.com/PHPOffice/PhpSpreadsheet/pull/2414)
|
||||
|
||||
### Changed
|
||||
|
||||
- Xlsx Writer will evaluate AutoFilter only if it is as yet unevaluated, or has changed since it was last evaluated [PR #2414](https://github.com/PHPOffice/PhpSpreadsheet/pull/2414)
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Nothing
|
||||
|
||||
### Removed
|
||||
|
||||
- Nothing
|
||||
|
||||
### Fixed
|
||||
|
||||
- Rounding in `NumberFormatter` [Issue #2385](https://github.com/PHPOffice/PhpSpreadsheet/issues/2385) [PR #2399](https://github.com/PHPOffice/PhpSpreadsheet/pull/2399)
|
||||
- Support for themes [Issue #2075](https://github.com/PHPOffice/PhpSpreadsheet/issues/2075) [Issue #2387](https://github.com/PHPOffice/PhpSpreadsheet/issues/2387) [PR #2403](https://github.com/PHPOffice/PhpSpreadsheet/pull/2403)
|
||||
- Read spreadsheet with `#` in name [Issue #2405](https://github.com/PHPOffice/PhpSpreadsheet/issues/2405) [PR #2409](https://github.com/PHPOffice/PhpSpreadsheet/pull/2409)
|
||||
- Improve PDF support for page size and orientation [Issue #1691](https://github.com/PHPOffice/PhpSpreadsheet/issues/1691) [PR #2410](https://github.com/PHPOffice/PhpSpreadsheet/pull/2410)
|
||||
- Wildcard handling issues in text match [Issue #2430](https://github.com/PHPOffice/PhpSpreadsheet/issues/2430) [PR #2431](https://github.com/PHPOffice/PhpSpreadsheet/pull/2431)
|
||||
- Respect DataType in `insertNewBefore` [PR #2433](https://github.com/PHPOffice/PhpSpreadsheet/pull/2433)
|
||||
- Handle rows explicitly hidden after AutoFilter [Issue #1641](https://github.com/PHPOffice/PhpSpreadsheet/issues/1641) [PR #2414](https://github.com/PHPOffice/PhpSpreadsheet/pull/2414)
|
||||
- Special characters in image file name [Issue #1470](https://github.com/PHPOffice/PhpSpreadsheet/issues/1470) [Issue #2415](https://github.com/PHPOffice/PhpSpreadsheet/issues/2415) [PR #2416](https://github.com/PHPOffice/PhpSpreadsheet/pull/2416)
|
||||
- Mpdf with very many styles [Issue #2432](https://github.com/PHPOffice/PhpSpreadsheet/issues/2432) [PR #2434](https://github.com/PHPOffice/PhpSpreadsheet/pull/2434)
|
||||
- Name clashes between parsed and unparsed drawings [Issue #1767](https://github.com/PHPOffice/PhpSpreadsheet/issues/1767) [Issue #2396](https://github.com/PHPOffice/PhpSpreadsheet/issues/2396) [PR #2423](https://github.com/PHPOffice/PhpSpreadsheet/pull/2423)
|
||||
- Fill pattern start and end colors [Issue #2441](https://github.com/PHPOffice/PhpSpreadsheet/issues/2441) [PR #2444](https://github.com/PHPOffice/PhpSpreadsheet/pull/2444)
|
||||
- General style specified in wrong case [Issue #2450](https://github.com/PHPOffice/PhpSpreadsheet/issues/2450) [PR #2451](https://github.com/PHPOffice/PhpSpreadsheet/pull/2451)
|
||||
- Null passed to `AutoFilter::setRange()` [Issue #2281](https://github.com/PHPOffice/PhpSpreadsheet/issues/2281) [PR #2454](https://github.com/PHPOffice/PhpSpreadsheet/pull/2454)
|
||||
- Another undefined index in Xls reader (#2470) [Issue #2463](https://github.com/PHPOffice/PhpSpreadsheet/issues/2463) [PR #2470](https://github.com/PHPOffice/PhpSpreadsheet/pull/2470)
|
||||
- Allow single-cell checks on conditional styles, even when the style is configured for a range of cells (#) [PR #2483](https://github.com/PHPOffice/PhpSpreadsheet/pull/2483)
|
||||
|
||||
## 1.20.0 - 2021-11-23
|
||||
|
||||
### Added
|
||||
|
||||
- Xlsx Writer Support for WMF Files [#2339](https://github.com/PHPOffice/PhpSpreadsheet/issues/2339)
|
||||
- Use standard temporary file for internal use of HTMLPurifier [#2383](https://github.com/PHPOffice/PhpSpreadsheet/issues/2383)
|
||||
|
||||
### Changed
|
||||
|
||||
- Drop support for PHP 7.2, according to https://phpspreadsheet.readthedocs.io/en/latest/#php-version-support
|
||||
- Use native typing for objects that were already documented as such
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Nothing
|
||||
|
||||
### Removed
|
||||
|
||||
- Nothing
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed null conversation for strToUpper [#2292](https://github.com/PHPOffice/PhpSpreadsheet/issues/2292)
|
||||
- Fixed Trying to access array offset on value of type null (Xls Reader) [#2315](https://github.com/PHPOffice/PhpSpreadsheet/issues/2315)
|
||||
- Don't corrupt XLSX files containing data validation [#2377](https://github.com/PHPOffice/PhpSpreadsheet/issues/2377)
|
||||
- Non-fixed cells were not updated if shared formula has a fixed cell [#2354](https://github.com/PHPOffice/PhpSpreadsheet/issues/2354)
|
||||
- Declare key of generic ArrayObject
|
||||
- CSV reader better support for boolean values [#2374](https://github.com/PHPOffice/PhpSpreadsheet/pull/2374)
|
||||
- Some ZIP file could not be read [#2376](https://github.com/PHPOffice/PhpSpreadsheet/pull/2376)
|
||||
- Fix regression were hyperlinks could not be read [#2391](https://github.com/PHPOffice/PhpSpreadsheet/pull/2391)
|
||||
- AutoFilter Improvements [#2393](https://github.com/PHPOffice/PhpSpreadsheet/pull/2393)
|
||||
- Don't corrupt file when using chart with fill color [#589](https://github.com/PHPOffice/PhpSpreadsheet/pull/589)
|
||||
- Restore imperfect array formula values in xlsx writer [#2343](https://github.com/PHPOffice/PhpSpreadsheet/pull/2343)
|
||||
- Restore explicit list of changes to PHPExcel migration document [#1546](https://github.com/PHPOffice/PhpSpreadsheet/issues/1546)
|
||||
|
||||
## 1.19.0 - 2021-10-31
|
||||
|
||||
### Added
|
||||
|
||||
- Ability to set style on named range, and validate input to setSelectedCells [Issue #2279](https://github.com/PHPOffice/PhpSpreadsheet/issues/2279) [PR #2280](https://github.com/PHPOffice/PhpSpreadsheet/pull/2280)
|
||||
- Process comments in Sylk file [Issue #2276](https://github.com/PHPOffice/PhpSpreadsheet/issues/2276) [PR #2277](https://github.com/PHPOffice/PhpSpreadsheet/pull/2277)
|
||||
- Addition of Custom Properties to Ods Writer, and 32-bit-safe timestamps for Document Properties [PR #2113](https://github.com/PHPOffice/PhpSpreadsheet/pull/2113)
|
||||
- Added callback to CSV reader to set user-specified defaults for various properties (especially for escape which has a poor PHP-inherited default of backslash which does not correspond with Excel) [PR #2103](https://github.com/PHPOffice/PhpSpreadsheet/pull/2103)
|
||||
- Phase 1 of better namespace handling for Xlsx, resolving many open issues [PR #2173](https://github.com/PHPOffice/PhpSpreadsheet/pull/2173) [PR #2204](https://github.com/PHPOffice/PhpSpreadsheet/pull/2204) [PR #2303](https://github.com/PHPOffice/PhpSpreadsheet/pull/2303)
|
||||
- Add ability to extract images if source is a URL [Issue #1997](https://github.com/PHPOffice/PhpSpreadsheet/issues/1997) [PR #2072](https://github.com/PHPOffice/PhpSpreadsheet/pull/2072)
|
||||
- Support for passing flags in the Reader `load()` and Writer `save()`methods, and through the IOFactory, to set behaviours [PR #2136](https://github.com/PHPOffice/PhpSpreadsheet/pull/2136)
|
||||
- See [documentation](https://phpspreadsheet.readthedocs.io/en/latest/topics/reading-and-writing-to-file/#readerwriter-flags) for details
|
||||
- More flexibility in the StringValueBinder to determine what datatypes should be treated as strings [PR #2138](https://github.com/PHPOffice/PhpSpreadsheet/pull/2138)
|
||||
- Helper class for conversion between css size Units of measure (`px`, `pt`, `pc`, `in`, `cm`, `mm`) [PR #2152](https://github.com/PHPOffice/PhpSpreadsheet/issues/2145)
|
||||
- Allow Row height and Column Width to be set using different units of measure (`px`, `pt`, `pc`, `in`, `cm`, `mm`), rather than only in points or MS Excel column width units [PR #2152](https://github.com/PHPOffice/PhpSpreadsheet/issues/2145)
|
||||
- Ability to stream to an Amazon S3 bucket [Issue #2249](https://github.com/PHPOffice/PhpSpreadsheet/issues/2249)
|
||||
- Provided a Size Helper class to validate size values (pt, px, em) [PR #1694](https://github.com/PHPOffice/PhpSpreadsheet/pull/1694)
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -17,7 +102,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Nothing.
|
||||
- PHP 8.1 will deprecate auto_detect_line_endings. As a result of this change, Csv Reader using some release after PHP8.1 will no longer be able to handle a Csv with Mac line endings.
|
||||
|
||||
### Removed
|
||||
|
||||
@@ -25,8 +110,145 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||
|
||||
### Fixed
|
||||
|
||||
- Unexpected format in Xlsx Timestamp [Issue #2331](https://github.com/PHPOffice/PhpSpreadsheet/issues/2331) [PR #2332](https://github.com/PHPOffice/PhpSpreadsheet/pull/2332)
|
||||
- Corrections for HLOOKUP [Issue #2123](https://github.com/PHPOffice/PhpSpreadsheet/issues/2123) [PR #2330](https://github.com/PHPOffice/PhpSpreadsheet/pull/2330)
|
||||
- Corrections for Xlsx Read Comments [Issue #2316](https://github.com/PHPOffice/PhpSpreadsheet/issues/2316) [PR #2329](https://github.com/PHPOffice/PhpSpreadsheet/pull/2329)
|
||||
- Lowercase Calibri font names [Issue #2273](https://github.com/PHPOffice/PhpSpreadsheet/issues/2273) [PR #2325](https://github.com/PHPOffice/PhpSpreadsheet/pull/2325)
|
||||
- isFormula Referencing Sheet with Space in Title [Issue #2304](https://github.com/PHPOffice/PhpSpreadsheet/issues/2304) [PR #2306](https://github.com/PHPOffice/PhpSpreadsheet/pull/2306)
|
||||
- Xls Reader Fatal Error due to Undefined Offset [Issue #1114](https://github.com/PHPOffice/PhpSpreadsheet/issues/1114) [PR #2308](https://github.com/PHPOffice/PhpSpreadsheet/pull/2308)
|
||||
- Permit Csv Reader delimiter to be set to null [Issue #2287](https://github.com/PHPOffice/PhpSpreadsheet/issues/2287) [PR #2288](https://github.com/PHPOffice/PhpSpreadsheet/pull/2288)
|
||||
- Csv Reader did not handle booleans correctly [PR #2232](https://github.com/PHPOffice/PhpSpreadsheet/pull/2232)
|
||||
- Problems when deleting sheet with local defined name [Issue #2266](https://github.com/PHPOffice/PhpSpreadsheet/issues/2266) [PR #2284](https://github.com/PHPOffice/PhpSpreadsheet/pull/2284)
|
||||
- Worksheet passwords were not always handled correctly [Issue #1897](https://github.com/PHPOffice/PhpSpreadsheet/issues/1897) [PR #2197](https://github.com/PHPOffice/PhpSpreadsheet/pull/2197)
|
||||
- Gnumeric Reader will now distinguish between Created and Modified timestamp [PR #2133](https://github.com/PHPOffice/PhpSpreadsheet/pull/2133)
|
||||
- Xls Reader will now handle MACCENTRALEUROPE with or without hyphen [Issue #549](https://github.com/PHPOffice/PhpSpreadsheet/issues/549) [PR #2213](https://github.com/PHPOffice/PhpSpreadsheet/pull/2213)
|
||||
- Tweaks to input file validation [Issue #1718](https://github.com/PHPOffice/PhpSpreadsheet/issues/1718) [PR #2217](https://github.com/PHPOffice/PhpSpreadsheet/pull/2217)
|
||||
- Html Reader did not handle comments correctly [Issue #2234](https://github.com/PHPOffice/PhpSpreadsheet/issues/2234) [PR #2235](https://github.com/PHPOffice/PhpSpreadsheet/pull/2235)
|
||||
- Apache OpenOffice Uses Unexpected Case for General format [Issue #2239](https://github.com/PHPOffice/PhpSpreadsheet/issues/2239) [PR #2242](https://github.com/PHPOffice/PhpSpreadsheet/pull/2242)
|
||||
- Problems with fraction formatting [Issue #2253](https://github.com/PHPOffice/PhpSpreadsheet/issues/2253) [PR #2254](https://github.com/PHPOffice/PhpSpreadsheet/pull/2254)
|
||||
- Xlsx Reader had problems reading file with no styles.xml or empty styles.xml [Issue #2246](https://github.com/PHPOffice/PhpSpreadsheet/issues/2246) [PR #2247](https://github.com/PHPOffice/PhpSpreadsheet/pull/2247)
|
||||
- Xlsx Reader did not read Data Validation flags correctly [Issue #2224](https://github.com/PHPOffice/PhpSpreadsheet/issues/2224) [PR #2225](https://github.com/PHPOffice/PhpSpreadsheet/pull/2225)
|
||||
- Better handling of empty arguments in Calculation engine [PR #2143](https://github.com/PHPOffice/PhpSpreadsheet/pull/2143)
|
||||
- Many fixes for Autofilter [Issue #2216](https://github.com/PHPOffice/PhpSpreadsheet/issues/2216) [PR #2141](https://github.com/PHPOffice/PhpSpreadsheet/pull/2141) [PR #2162](https://github.com/PHPOffice/PhpSpreadsheet/pull/2162) [PR #2218](https://github.com/PHPOffice/PhpSpreadsheet/pull/2218)
|
||||
- Locale generator will now use Unix line endings even on Windows [Issue #2172](https://github.com/PHPOffice/PhpSpreadsheet/issues/2172) [PR #2174](https://github.com/PHPOffice/PhpSpreadsheet/pull/2174)
|
||||
- Support differences in implementation of Text functions between Excel/Ods/Gnumeric [PR #2151](https://github.com/PHPOffice/PhpSpreadsheet/pull/2151)
|
||||
- Fixes to places where PHP8.1 enforces new or previously unenforced restrictions [PR #2137](https://github.com/PHPOffice/PhpSpreadsheet/pull/2137) [PR #2191](https://github.com/PHPOffice/PhpSpreadsheet/pull/2191) [PR #2231](https://github.com/PHPOffice/PhpSpreadsheet/pull/2231)
|
||||
- Clone for HashTable was incorrect [PR #2130](https://github.com/PHPOffice/PhpSpreadsheet/pull/2130)
|
||||
- Xlsx Reader was not evaluating Document Security Lock correctly [PR #2128](https://github.com/PHPOffice/PhpSpreadsheet/pull/2128)
|
||||
- Error in COUPNCD handling end of month [Issue #2116](https://github.com/PHPOffice/PhpSpreadsheet/issues/2116) [PR #2119](https://github.com/PHPOffice/PhpSpreadsheet/pull/2119)
|
||||
- Xls Writer Parser did not handle concatenation operator correctly [PR #2080](https://github.com/PHPOffice/PhpSpreadsheet/pull/2080)
|
||||
- Xlsx Writer did not handle boolean false correctly [Issue #2082](https://github.com/PHPOffice/PhpSpreadsheet/issues/2082) [PR #2087](https://github.com/PHPOffice/PhpSpreadsheet/pull/2087)
|
||||
- SUM needs to treat invalid strings differently depending on whether they come from a cell or are used as literals [Issue #2042](https://github.com/PHPOffice/PhpSpreadsheet/issues/2042) [PR #2045](https://github.com/PHPOffice/PhpSpreadsheet/pull/2045)
|
||||
- Html reader could have set illegal coordinates when dealing with embedded tables [Issue #2029](https://github.com/PHPOffice/PhpSpreadsheet/issues/2029) [PR #2032](https://github.com/PHPOffice/PhpSpreadsheet/pull/2032)
|
||||
- Documentation for printing gridlines was wrong [PR #2188](https://github.com/PHPOffice/PhpSpreadsheet/pull/2188)
|
||||
- Return Value Error - DatabaseAbstruct::buildQuery() return null but must be string [Issue #2158](https://github.com/PHPOffice/PhpSpreadsheet/issues/2158) [PR #2160](https://github.com/PHPOffice/PhpSpreadsheet/pull/2160)
|
||||
- Xlsx reader not recognize data validations that references another sheet [Issue #1432](https://github.com/PHPOffice/PhpSpreadsheet/issues/1432) [Issue #2149](https://github.com/PHPOffice/PhpSpreadsheet/issues/2149) [PR #2150](https://github.com/PHPOffice/PhpSpreadsheet/pull/2150) [PR #2265](https://github.com/PHPOffice/PhpSpreadsheet/pull/2265)
|
||||
- Don't calculate cell width for autosize columns if a cell contains a null or empty string value [Issue #2165](https://github.com/PHPOffice/PhpSpreadsheet/issues/2165) [PR #2167](https://github.com/PHPOffice/PhpSpreadsheet/pull/2167)
|
||||
- Allow negative interest rate values in a number of the Financial functions (`PPMT()`, `PMT()`, `FV()`, `PV()`, `NPER()`, etc) [Issue #2163](https://github.com/PHPOffice/PhpSpreadsheet/issues/2163) [PR #2164](https://github.com/PHPOffice/PhpSpreadsheet/pull/2164)
|
||||
- Xls Reader changing grey background to black in Excel template [Issue #2147](https://github.com/PHPOffice/PhpSpreadsheet/issues/2147) [PR #2156](https://github.com/PHPOffice/PhpSpreadsheet/pull/2156)
|
||||
- Column width and Row height styles in the Html Reader when the value includes a unit of measure [Issue #2145](https://github.com/PHPOffice/PhpSpreadsheet/issues/2145).
|
||||
- Data Validation flags not set correctly when reading XLSX files [Issue #2224](https://github.com/PHPOffice/PhpSpreadsheet/issues/2224) [PR #2225](https://github.com/PHPOffice/PhpSpreadsheet/pull/2225)
|
||||
- Reading XLSX files without styles.xml throws an exception [Issue #2246](https://github.com/PHPOffice/PhpSpreadsheet/issues/2246)
|
||||
- Improved performance of `Style::applyFromArray()` when applied to several cells [PR #1785](https://github.com/PHPOffice/PhpSpreadsheet/issues/1785).
|
||||
- Improve XLSX parsing speed if no readFilter is applied (again) - [#772](https://github.com/PHPOffice/PhpSpreadsheet/issues/772)
|
||||
|
||||
## 1.18.0 - 2021-05-31
|
||||
|
||||
### Added
|
||||
|
||||
- Enhancements to CSV Reader, allowing options to be set when using `IOFactory::load()` with a callback to set delimiter, enclosure, charset etc [PR #2103](https://github.com/PHPOffice/PhpSpreadsheet/pull/2103) - See [documentation](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/docs/topics/reading-and-writing-to-file.md#csv-comma-separated-values) for details.
|
||||
- Implemented basic AutoFiltering for Ods Reader and Writer [PR #2053](https://github.com/PHPOffice/PhpSpreadsheet/pull/2053)
|
||||
- Implemented basic AutoFiltering for Gnumeric Reader [PR #2055](https://github.com/PHPOffice/PhpSpreadsheet/pull/2055)
|
||||
- Improved support for Row and Column ranges in formulae [Issue #1755](https://github.com/PHPOffice/PhpSpreadsheet/issues/1755) [PR #2028](https://github.com/PHPOffice/PhpSpreadsheet/pull/2028)
|
||||
- Implemented URLENCODE() Web Function
|
||||
- Implemented the CHITEST(), CHISQ.DIST() and CHISQ.INV() and equivalent Statistical functions, for both left- and right-tailed distributions.
|
||||
- Support for ActiveSheet and SelectedCells in the ODS Reader and Writer [PR #1908](https://github.com/PHPOffice/PhpSpreadsheet/pull/1908)
|
||||
- Support for notContainsText Conditional Style in xlsx [Issue #984](https://github.com/PHPOffice/PhpSpreadsheet/issues/984)
|
||||
|
||||
### Changed
|
||||
|
||||
- Use of `nb` rather than `no` as the locale code for Norsk Bokmål.
|
||||
|
||||
### Deprecated
|
||||
|
||||
- All Excel Function implementations in `Calculation\Database`, `Calculation\DateTime`, `Calculation\Engineering`, `Calculation\Financial`, `Calculation\Logical`, `Calculation\LookupRef`, `Calculation\MathTrig`, `Calculation\Statistical`, `Calculation\TextData` and `Calculation\Web` have been moved to dedicated classes for individual functions or groups of related functions. See the docblocks against all the deprecated methods for details of the new methods to call instead. At some point, these old classes will be deleted.
|
||||
|
||||
### Removed
|
||||
|
||||
- Use of `nb` rather than `no` as the locale language code for Norsk Bokmål.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed error in COUPNCD() calculation for end of month [Issue #2116](https://github.com/PHPOffice/PhpSpreadsheet/issues/2116) - [PR #2119](https://github.com/PHPOffice/PhpSpreadsheet/pull/2119)
|
||||
- Resolve default values when a null argument is passed for HLOOKUP(), VLOOKUP() and ADDRESS() functions [Issue #2120](https://github.com/PHPOffice/PhpSpreadsheet/issues/2120) - [PR #2121](https://github.com/PHPOffice/PhpSpreadsheet/pull/2121)
|
||||
- Fixed incorrect R1C1 to A1 subtraction formula conversion (`R[-2]C-R[2]C`) [Issue #2076](https://github.com/PHPOffice/PhpSpreadsheet/pull/2076) [PR #2086](https://github.com/PHPOffice/PhpSpreadsheet/pull/2086)
|
||||
- Correctly handle absolute A1 references when converting to R1C1 format [PR #2060](https://github.com/PHPOffice/PhpSpreadsheet/pull/2060)
|
||||
- Correct default fill style for conditional without a pattern defined [Issue #2035](https://github.com/PHPOffice/PhpSpreadsheet/issues/2035) [PR #2050](https://github.com/PHPOffice/PhpSpreadsheet/pull/2050)
|
||||
- Fixed issue where array key check for existince before accessing arrays in Xlsx.php [PR #1970](https://github.com/PHPOffice/PhpSpreadsheet/pull/1970)
|
||||
- Fixed issue with quoted strings in number format mask rendered with toFormattedString() [Issue 1972#](https://github.com/PHPOffice/PhpSpreadsheet/issues/1972) [PR #1978](https://github.com/PHPOffice/PhpSpreadsheet/pull/1978)
|
||||
- Fixed issue with percentage formats in number format mask rendered with toFormattedString() [Issue 1929#](https://github.com/PHPOffice/PhpSpreadsheet/issues/1929) [PR #1928](https://github.com/PHPOffice/PhpSpreadsheet/pull/1928)
|
||||
- Fixed issue with _ spacing character in number format mask corrupting output from toFormattedString() [Issue 1924#](https://github.com/PHPOffice/PhpSpreadsheet/issues/1924) [PR #1927](https://github.com/PHPOffice/PhpSpreadsheet/pull/1927)
|
||||
- Fix for [Issue #1887](https://github.com/PHPOffice/PhpSpreadsheet/issues/1887) - Lose Track of Selected Cells After Save
|
||||
- Fixed issue with Xlsx@listWorksheetInfo not returning any data
|
||||
- Fixed invalid arguments triggering mb_substr() error in LEFT(), MID() and RIGHT() text functions [Issue #640](https://github.com/PHPOffice/PhpSpreadsheet/issues/640)
|
||||
- Fix for [Issue #1916](https://github.com/PHPOffice/PhpSpreadsheet/issues/1916) - Invalid signature check for XML files
|
||||
- Fix change in `Font::setSize()` behavior for PHP8 [PR #2100](https://github.com/PHPOffice/PhpSpreadsheet/pull/2100)
|
||||
|
||||
## 1.17.1 - 2021-03-01
|
||||
|
||||
### Added
|
||||
|
||||
- Implementation of the Excel `AVERAGEIFS()` functions as part of a restructuring of Database functions and Conditional Statistical functions.
|
||||
- Support for date values and percentages in query parameters for Database functions, and the IF expressions in functions like COUNTIF() and AVERAGEIF(). [#1875](https://github.com/PHPOffice/PhpSpreadsheet/pull/1875)
|
||||
- Support for booleans, and for wildcard text search in query parameters for Database functions, and the IF expressions in functions like COUNTIF() and AVERAGEIF(). [#1876](https://github.com/PHPOffice/PhpSpreadsheet/pull/1876)
|
||||
- Implemented DataBar for conditional formatting in Xlsx, providing read/write and creation of (type, value, direction, fills, border, axis position, color settings) as DataBar options in Excel. [#1754](https://github.com/PHPOffice/PhpSpreadsheet/pull/1754)
|
||||
- Alignment for ODS Writer [#1796](https://github.com/PHPOffice/PhpSpreadsheet/issues/1796)
|
||||
- Basic implementation of the PERMUTATIONA() Statistical Function
|
||||
|
||||
### Changed
|
||||
|
||||
- Formula functions that previously called PHP functions directly are now processed through the Excel Functions classes; resolving issues with PHP8 stricter typing. [#1789](https://github.com/PHPOffice/PhpSpreadsheet/issues/1789)
|
||||
|
||||
The following MathTrig functions are affected:
|
||||
`ABS()`, `ACOS()`, `ACOSH()`, `ASIN()`, `ASINH()`, `ATAN()`, `ATANH()`,
|
||||
`COS()`, `COSH()`, `DEGREES()` (rad2deg), `EXP()`, `LN()` (log), `LOG10()`,
|
||||
`RADIANS()` (deg2rad), `SIN()`, `SINH()`, `SQRT()`, `TAN()`, `TANH()`.
|
||||
|
||||
One TextData function is also affected: `REPT()` (str_repeat).
|
||||
- `formatAsDate` correctly matches language metadata, reverting c55272e
|
||||
- Formulae that previously crashed on sub function call returning excel error value now return said value.
|
||||
The following functions are affected `CUMPRINC()`, `CUMIPMT()`, `AMORLINC()`,
|
||||
`AMORDEGRC()`.
|
||||
- Adapt some function error return value to match excel's error.
|
||||
The following functions are affected `PPMT()`, `IPMT()`.
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Calling many of the Excel formula functions directly rather than through the Calculation Engine.
|
||||
|
||||
The logic for these Functions is now being moved out of the categorised `Database`, `DateTime`, `Engineering`, `Financial`, `Logical`, `LookupRef`, `MathTrig`, `Statistical`, `TextData` and `Web` classes into small, dedicated classes for individual functions or related groups of functions.
|
||||
|
||||
This makes the logic in these classes easier to maintain; and will reduce the memory footprint required to execute formulae when calling these functions.
|
||||
|
||||
### Removed
|
||||
|
||||
- Nothing.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Avoid Duplicate Titles When Reading Multiple HTML Files.[Issue #1823](https://github.com/PHPOffice/PhpSpreadsheet/issues/1823) [PR #1829](https://github.com/PHPOffice/PhpSpreadsheet/pull/1829)
|
||||
- Fixed issue with Worksheet's `getCell()` method when trying to get a cell by defined name. [#1858](https://github.com/PHPOffice/PhpSpreadsheet/issues/1858)
|
||||
- Fix possible endless loop in NumberFormat Masks [#1792](https://github.com/PHPOffice/PhpSpreadsheet/issues/1792)
|
||||
- Fix problem resulting from literal dot inside quotes in number format masks [PR #1830](https://github.com/PHPOffice/PhpSpreadsheet/pull/1830)
|
||||
- Resolve Google Sheets Xlsx charts issue. Google Sheets uses oneCellAnchor positioning and does not include *Cache values in the exported Xlsx [PR #1761](https://github.com/PHPOffice/PhpSpreadsheet/pull/1761)
|
||||
- Fix for Xlsx Chart axis titles mapping to correct X or Y axis label when only one is present [PR #1760](https://github.com/PHPOffice/PhpSpreadsheet/pull/1760)
|
||||
- Fix For Null Exception on ODS Read of Page Settings. [#1772](https://github.com/PHPOffice/PhpSpreadsheet/issues/1772)
|
||||
- Fix Xlsx reader overriding manually set number format with builtin number format [PR #1805](https://github.com/PHPOffice/PhpSpreadsheet/pull/1805)
|
||||
- Fix Xlsx reader cell alignment [PR #1710](https://github.com/PHPOffice/PhpSpreadsheet/pull/1710)
|
||||
- Fix for not yet implemented data-types in Open Document writer [Issue #1674](https://github.com/PHPOffice/PhpSpreadsheet/issues/1674)
|
||||
- Fix XLSX reader when having a corrupt numeric cell data type [PR #1664](https://github.com/phpoffice/phpspreadsheet/pull/1664)
|
||||
- Fix on `CUMPRINC()`, `CUMIPMT()`, `AMORLINC()`, `AMORDEGRC()` usage. When those functions called one of `YEARFRAC()`, `PPMT()`, `IPMT()` and they would get back an error value (represented as a string), trying to use numeral operands (`+`, `/`, `-`, `*`) on said return value and a number (`float or `int`) would fail.
|
||||
|
||||
## 1.16.0 - 2020-12-31
|
||||
|
||||
### Added
|
||||
@@ -39,7 +261,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Nothing.
|
||||
- All Excel Function implementations in `Calculation\Database`, `Calculation\DateTime`, `Calculation\Engineering`, `Calculation\Financial`, `Calculation\Logical`, `Calculation\LookupRef`, `Calculation\MathTrig`, `Calculation\Statistical`, `Calculation\TextData` and `Calculation\Web` have been moved to dedicated classes for individual functions or groups of related functions. See the docblocks against all the deprecated methods for details of the new methods to call instead. At some point, these old classes will be deleted.
|
||||
|
||||
### Removed
|
||||
|
||||
@@ -47,6 +269,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed issue with absolute path in worksheets' Target [PR #1769](https://github.com/PHPOffice/PhpSpreadsheet/pull/1769)
|
||||
- Fix for Xls Reader when SST has a bad length [#1592](https://github.com/PHPOffice/PhpSpreadsheet/issues/1592)
|
||||
- Resolve Xlsx loader issue whe hyperlinks don't have a destination
|
||||
- Resolve issues when printer settings resources IDs clash with drawing IDs
|
||||
|
||||
@@ -9,3 +9,12 @@ If you would like to contribute, here are some notes and guidelines:
|
||||
- All code changes must be validated by `composer check`
|
||||
- [Helpful article about forking](https://help.github.com/articles/fork-a-repo/ "Forking a GitHub repository")
|
||||
- [Helpful article about pull requests](https://help.github.com/articles/using-pull-requests/ "Pull Requests")
|
||||
|
||||
## How to release
|
||||
|
||||
1. Complete CHANGELOG.md and commit
|
||||
2. Create an annotated tag
|
||||
1. `git tag -a 1.2.3`
|
||||
2. Tag subject must be the version number, eg: `1.2.3`
|
||||
3. Tag body must be a copy-paste of the changelog entries
|
||||
3. Push tag with `git push --tags`, GitHub Actions will create a GitHub release automatically
|
||||
|
||||
@@ -1,7 +1,19 @@
|
||||
{
|
||||
"name": "phpoffice/phpspreadsheet",
|
||||
"description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
|
||||
"keywords": ["PHP", "OpenXML", "Excel", "xlsx", "xls", "ods", "gnumeric", "spreadsheet"],
|
||||
"keywords": [
|
||||
"PHP",
|
||||
"OpenXML",
|
||||
"Excel",
|
||||
"xlsx",
|
||||
"xls",
|
||||
"ods",
|
||||
"gnumeric",
|
||||
"spreadsheet"
|
||||
],
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
@@ -29,47 +41,51 @@
|
||||
"check": [
|
||||
"php-cs-fixer fix --ansi --dry-run --diff",
|
||||
"phpcs",
|
||||
"phpunit --color=always"
|
||||
"phpunit --color=always",
|
||||
"phpstan analyse --ansi"
|
||||
],
|
||||
"fix": [
|
||||
"php-cs-fixer fix --ansi"
|
||||
],
|
||||
"versions": [
|
||||
"phpcs --report-width=200 samples/ src/ tests/ --ignore=samples/Header.php --standard=PHPCompatibility --runtime-set testVersion 7.2- -n"
|
||||
"phpcs --report-width=200 samples/ src/ tests/ --ignore=samples/Header.php --standard=PHPCompatibility --runtime-set testVersion 7.3- -n"
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2||^8.0",
|
||||
"php": "^7.3 || ^8.0",
|
||||
"ext-ctype": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-fileinfo": "*",
|
||||
"ext-gd": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-fileinfo": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-SimpleXML": "*",
|
||||
"ext-simplexml": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-xmlreader": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"ext-zip": "*",
|
||||
"ext-zlib": "*",
|
||||
"ezyang/htmlpurifier": "^4.13",
|
||||
"maennchen/zipstream-php": "^2.1",
|
||||
"markbaker/complex": "^1.5||^2.0",
|
||||
"markbaker/matrix": "^1.2||^2.0",
|
||||
"psr/simple-cache": "^1.0",
|
||||
"markbaker/complex": "^3.0",
|
||||
"markbaker/matrix": "^3.0",
|
||||
"psr/http-client": "^1.0",
|
||||
"psr/http-factory": "^1.0",
|
||||
"ezyang/htmlpurifier": "^4.13"
|
||||
"psr/simple-cache": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"dompdf/dompdf": "^0.8.5",
|
||||
"friendsofphp/php-cs-fixer": "^2.16",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
|
||||
"dompdf/dompdf": "^1.0",
|
||||
"friendsofphp/php-cs-fixer": "^3.2",
|
||||
"jpgraph/jpgraph": "^4.0",
|
||||
"mpdf/mpdf": "^8.0",
|
||||
"phpcompatibility/php-compatibility": "^9.3",
|
||||
"phpunit/phpunit": "^8.5||^9.3",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"tecnickcom/tcpdf": "^6.3"
|
||||
"phpstan/phpstan": "^1.1",
|
||||
"phpstan/phpstan-phpunit": "^1.0",
|
||||
"phpunit/phpunit": "^8.5 || ^9.0",
|
||||
"squizlabs/php_codesniffer": "^3.6",
|
||||
"tecnickcom/tcpdf": "^6.4"
|
||||
},
|
||||
"suggest": {
|
||||
"mpdf/mpdf": "Option for rendering PDF with PDF Writer",
|
||||
@@ -84,7 +100,8 @@
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"PhpOffice\\PhpSpreadsheetTests\\": "tests/PhpSpreadsheetTests"
|
||||
"PhpOffice\\PhpSpreadsheetTests\\": "tests/PhpSpreadsheetTests",
|
||||
"PhpOffice\\PhpSpreadsheetInfra\\": "infra"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+887
-652
File diff suppressed because it is too large
Load Diff
Vendored
+79
-247
@@ -2,126 +2,11 @@
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation;
|
||||
|
||||
/**
|
||||
* @deprecated 1.17.0
|
||||
*/
|
||||
class Database
|
||||
{
|
||||
/**
|
||||
* fieldExtract.
|
||||
*
|
||||
* Extracts the column ID to use for the data field.
|
||||
*
|
||||
* @param mixed[] $database The range of cells that makes up the list or database.
|
||||
* A database is a list of related data in which rows of related
|
||||
* information are records, and columns of data are fields. The
|
||||
* first row of the list contains labels for each column.
|
||||
* @param mixed $field Indicates which column is used in the function. Enter the
|
||||
* column label enclosed between double quotation marks, such as
|
||||
* "Age" or "Yield," or a number (without quotation marks) that
|
||||
* represents the position of the column within the list: 1 for
|
||||
* the first column, 2 for the second column, and so on.
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
private static function fieldExtract($database, $field)
|
||||
{
|
||||
$field = strtoupper(Functions::flattenSingleValue($field));
|
||||
$fieldNames = array_map('strtoupper', array_shift($database));
|
||||
|
||||
if (is_numeric($field)) {
|
||||
$keys = array_keys($fieldNames);
|
||||
|
||||
return $keys[$field - 1];
|
||||
}
|
||||
$key = array_search($field, $fieldNames);
|
||||
|
||||
return ($key) ? $key : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* filter.
|
||||
*
|
||||
* Parses the selection criteria, extracts the database rows that match those criteria, and
|
||||
* returns that subset of rows.
|
||||
*
|
||||
* @param mixed[] $database The range of cells that makes up the list or database.
|
||||
* A database is a list of related data in which rows of related
|
||||
* information are records, and columns of data are fields. The
|
||||
* first row of the list contains labels for each column.
|
||||
* @param mixed[] $criteria The range of cells that contains the conditions you specify.
|
||||
* You can use any range for the criteria argument, as long as it
|
||||
* includes at least one column label and at least one cell below
|
||||
* the column label in which you specify a condition for the
|
||||
* column.
|
||||
*
|
||||
* @return array of mixed
|
||||
*/
|
||||
private static function filter($database, $criteria)
|
||||
{
|
||||
$fieldNames = array_shift($database);
|
||||
$criteriaNames = array_shift($criteria);
|
||||
|
||||
// Convert the criteria into a set of AND/OR conditions with [:placeholders]
|
||||
$testConditions = $testValues = [];
|
||||
$testConditionsCount = 0;
|
||||
foreach ($criteriaNames as $key => $criteriaName) {
|
||||
$testCondition = [];
|
||||
$testConditionCount = 0;
|
||||
foreach ($criteria as $row => $criterion) {
|
||||
if ($criterion[$key] > '') {
|
||||
$testCondition[] = '[:' . $criteriaName . ']' . Functions::ifCondition($criterion[$key]);
|
||||
++$testConditionCount;
|
||||
}
|
||||
}
|
||||
if ($testConditionCount > 1) {
|
||||
$testConditions[] = 'OR(' . implode(',', $testCondition) . ')';
|
||||
++$testConditionsCount;
|
||||
} elseif ($testConditionCount == 1) {
|
||||
$testConditions[] = $testCondition[0];
|
||||
++$testConditionsCount;
|
||||
}
|
||||
}
|
||||
|
||||
if ($testConditionsCount > 1) {
|
||||
$testConditionSet = 'AND(' . implode(',', $testConditions) . ')';
|
||||
} elseif ($testConditionsCount == 1) {
|
||||
$testConditionSet = $testConditions[0];
|
||||
}
|
||||
|
||||
// Loop through each row of the database
|
||||
foreach ($database as $dataRow => $dataValues) {
|
||||
// Substitute actual values from the database row for our [:placeholders]
|
||||
$testConditionList = $testConditionSet;
|
||||
foreach ($criteriaNames as $key => $criteriaName) {
|
||||
$k = array_search($criteriaName, $fieldNames);
|
||||
if (isset($dataValues[$k])) {
|
||||
$dataValue = $dataValues[$k];
|
||||
$dataValue = (is_string($dataValue)) ? Calculation::wrapResult(strtoupper($dataValue)) : $dataValue;
|
||||
$testConditionList = str_replace('[:' . $criteriaName . ']', $dataValue, $testConditionList);
|
||||
}
|
||||
}
|
||||
// evaluate the criteria against the row data
|
||||
$result = Calculation::getInstance()->_calculateFormulaValue('=' . $testConditionList);
|
||||
// If the row failed to meet the criteria, remove it from the database
|
||||
if (!$result) {
|
||||
unset($database[$dataRow]);
|
||||
}
|
||||
}
|
||||
|
||||
return $database;
|
||||
}
|
||||
|
||||
private static function getFilteredColumn($database, $field, $criteria)
|
||||
{
|
||||
// reduce the database to a set of rows that match all the criteria
|
||||
$database = self::filter($database, $criteria);
|
||||
// extract an array of values for the requested column
|
||||
$colData = [];
|
||||
foreach ($database as $row) {
|
||||
$colData[] = $row[$field];
|
||||
}
|
||||
|
||||
return $colData;
|
||||
}
|
||||
|
||||
/**
|
||||
* DAVERAGE.
|
||||
*
|
||||
@@ -130,6 +15,11 @@ class Database
|
||||
* Excel Function:
|
||||
* DAVERAGE(database,field,criteria)
|
||||
*
|
||||
* @Deprecated 1.17.0
|
||||
*
|
||||
* @see Database\DAverage::evaluate()
|
||||
* Use the evaluate() method in the Database\DAverage class instead
|
||||
*
|
||||
* @param mixed[] $database The range of cells that makes up the list or database.
|
||||
* A database is a list of related data in which rows of related
|
||||
* information are records, and columns of data are fields. The
|
||||
@@ -145,19 +35,11 @@ class Database
|
||||
* the column label in which you specify a condition for the
|
||||
* column.
|
||||
*
|
||||
* @return float|string
|
||||
* @return null|float|string
|
||||
*/
|
||||
public static function DAVERAGE($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return
|
||||
return Statistical::AVERAGE(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
return Database\DAverage::evaluate($database, $field, $criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,14 +51,16 @@ class Database
|
||||
* Excel Function:
|
||||
* DCOUNT(database,[field],criteria)
|
||||
*
|
||||
* Excel Function:
|
||||
* DAVERAGE(database,field,criteria)
|
||||
* @Deprecated 1.17.0
|
||||
*
|
||||
* @see Database\DCount::evaluate()
|
||||
* Use the evaluate() method in the Database\DCount class instead
|
||||
*
|
||||
* @param mixed[] $database The range of cells that makes up the list or database.
|
||||
* A database is a list of related data in which rows of related
|
||||
* information are records, and columns of data are fields. The
|
||||
* first row of the list contains labels for each column.
|
||||
* @param int|string $field Indicates which column is used in the function. Enter the
|
||||
* @param null|int|string $field Indicates which column is used in the function. Enter the
|
||||
* column label enclosed between double quotation marks, such as
|
||||
* "Age" or "Yield," or a number (without quotation marks) that
|
||||
* represents the position of the column within the list: 1 for
|
||||
@@ -194,15 +78,7 @@ class Database
|
||||
*/
|
||||
public static function DCOUNT($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return
|
||||
return Statistical::COUNT(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
return Database\DCount::evaluate($database, $field, $criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,11 +89,16 @@ class Database
|
||||
* Excel Function:
|
||||
* DCOUNTA(database,[field],criteria)
|
||||
*
|
||||
* @Deprecated 1.17.0
|
||||
*
|
||||
* @see Database\DCountA::evaluate()
|
||||
* Use the evaluate() method in the Database\DCountA class instead
|
||||
*
|
||||
* @param mixed[] $database The range of cells that makes up the list or database.
|
||||
* A database is a list of related data in which rows of related
|
||||
* information are records, and columns of data are fields. The
|
||||
* first row of the list contains labels for each column.
|
||||
* @param int|string $field Indicates which column is used in the function. Enter the
|
||||
* @param null|int|string $field Indicates which column is used in the function. Enter the
|
||||
* column label enclosed between double quotation marks, such as
|
||||
* "Age" or "Yield," or a number (without quotation marks) that
|
||||
* represents the position of the column within the list: 1 for
|
||||
@@ -229,29 +110,10 @@ class Database
|
||||
* column.
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @TODO The field argument is optional. If field is omitted, DCOUNTA counts all records in the
|
||||
* database that match the criteria.
|
||||
*/
|
||||
public static function DCOUNTA($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// reduce the database to a set of rows that match all the criteria
|
||||
$database = self::filter($database, $criteria);
|
||||
// extract an array of values for the requested column
|
||||
$colData = [];
|
||||
foreach ($database as $row) {
|
||||
$colData[] = $row[$field];
|
||||
}
|
||||
|
||||
// Return
|
||||
return Statistical::COUNTA(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
return Database\DCountA::evaluate($database, $field, $criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -263,6 +125,11 @@ class Database
|
||||
* Excel Function:
|
||||
* DGET(database,field,criteria)
|
||||
*
|
||||
* @Deprecated 1.17.0
|
||||
*
|
||||
* @see Database\DGet::evaluate()
|
||||
* Use the evaluate() method in the Database\DGet class instead
|
||||
*
|
||||
* @param mixed[] $database The range of cells that makes up the list or database.
|
||||
* A database is a list of related data in which rows of related
|
||||
* information are records, and columns of data are fields. The
|
||||
@@ -282,18 +149,7 @@ class Database
|
||||
*/
|
||||
public static function DGET($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return
|
||||
$colData = self::getFilteredColumn($database, $field, $criteria);
|
||||
if (count($colData) > 1) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
return $colData[0];
|
||||
return Database\DGet::evaluate($database, $field, $criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -305,6 +161,11 @@ class Database
|
||||
* Excel Function:
|
||||
* DMAX(database,field,criteria)
|
||||
*
|
||||
* @Deprecated 1.17.0
|
||||
*
|
||||
* @see Database\DMax::evaluate()
|
||||
* Use the evaluate() method in the Database\DMax class instead
|
||||
*
|
||||
* @param mixed[] $database The range of cells that makes up the list or database.
|
||||
* A database is a list of related data in which rows of related
|
||||
* information are records, and columns of data are fields. The
|
||||
@@ -324,15 +185,7 @@ class Database
|
||||
*/
|
||||
public static function DMAX($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return
|
||||
return Statistical::MAX(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
return Database\DMax::evaluate($database, $field, $criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -344,6 +197,11 @@ class Database
|
||||
* Excel Function:
|
||||
* DMIN(database,field,criteria)
|
||||
*
|
||||
* @Deprecated 1.17.0
|
||||
*
|
||||
* @see Database\DMin::evaluate()
|
||||
* Use the evaluate() method in the Database\DMin class instead
|
||||
*
|
||||
* @param mixed[] $database The range of cells that makes up the list or database.
|
||||
* A database is a list of related data in which rows of related
|
||||
* information are records, and columns of data are fields. The
|
||||
@@ -363,15 +221,7 @@ class Database
|
||||
*/
|
||||
public static function DMIN($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return
|
||||
return Statistical::MIN(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
return Database\DMin::evaluate($database, $field, $criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -382,6 +232,11 @@ class Database
|
||||
* Excel Function:
|
||||
* DPRODUCT(database,field,criteria)
|
||||
*
|
||||
* @Deprecated 1.17.0
|
||||
*
|
||||
* @see Database\DProduct::evaluate()
|
||||
* Use the evaluate() method in the Database\DProduct class instead
|
||||
*
|
||||
* @param mixed[] $database The range of cells that makes up the list or database.
|
||||
* A database is a list of related data in which rows of related
|
||||
* information are records, and columns of data are fields. The
|
||||
@@ -397,19 +252,11 @@ class Database
|
||||
* the column label in which you specify a condition for the
|
||||
* column.
|
||||
*
|
||||
* @return float
|
||||
* @return float|string
|
||||
*/
|
||||
public static function DPRODUCT($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return
|
||||
return MathTrig::PRODUCT(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
return Database\DProduct::evaluate($database, $field, $criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -421,6 +268,11 @@ class Database
|
||||
* Excel Function:
|
||||
* DSTDEV(database,field,criteria)
|
||||
*
|
||||
* @Deprecated 1.17.0
|
||||
*
|
||||
* @see Database\DStDev::evaluate()
|
||||
* Use the evaluate() method in the Database\DStDev class instead
|
||||
*
|
||||
* @param mixed[] $database The range of cells that makes up the list or database.
|
||||
* A database is a list of related data in which rows of related
|
||||
* information are records, and columns of data are fields. The
|
||||
@@ -440,15 +292,7 @@ class Database
|
||||
*/
|
||||
public static function DSTDEV($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return
|
||||
return Statistical::STDEV(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
return Database\DStDev::evaluate($database, $field, $criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -460,6 +304,11 @@ class Database
|
||||
* Excel Function:
|
||||
* DSTDEVP(database,field,criteria)
|
||||
*
|
||||
* @Deprecated 1.17.0
|
||||
*
|
||||
* @see Database\DStDevP::evaluate()
|
||||
* Use the evaluate() method in the Database\DStDevP class instead
|
||||
*
|
||||
* @param mixed[] $database The range of cells that makes up the list or database.
|
||||
* A database is a list of related data in which rows of related
|
||||
* information are records, and columns of data are fields. The
|
||||
@@ -479,15 +328,7 @@ class Database
|
||||
*/
|
||||
public static function DSTDEVP($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return
|
||||
return Statistical::STDEVP(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
return Database\DStDevP::evaluate($database, $field, $criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -498,6 +339,11 @@ class Database
|
||||
* Excel Function:
|
||||
* DSUM(database,field,criteria)
|
||||
*
|
||||
* @Deprecated 1.17.0
|
||||
*
|
||||
* @see Database\DSum::evaluate()
|
||||
* Use the evaluate() method in the Database\DSum class instead
|
||||
*
|
||||
* @param mixed[] $database The range of cells that makes up the list or database.
|
||||
* A database is a list of related data in which rows of related
|
||||
* information are records, and columns of data are fields. The
|
||||
@@ -513,19 +359,11 @@ class Database
|
||||
* the column label in which you specify a condition for the
|
||||
* column.
|
||||
*
|
||||
* @return float
|
||||
* @return float|string
|
||||
*/
|
||||
public static function DSUM($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return
|
||||
return MathTrig::SUM(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
return Database\DSum::evaluate($database, $field, $criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -537,6 +375,11 @@ class Database
|
||||
* Excel Function:
|
||||
* DVAR(database,field,criteria)
|
||||
*
|
||||
* @Deprecated 1.17.0
|
||||
*
|
||||
* @see Database\DVar::evaluate()
|
||||
* Use the evaluate() method in the Database\DVar class instead
|
||||
*
|
||||
* @param mixed[] $database The range of cells that makes up the list or database.
|
||||
* A database is a list of related data in which rows of related
|
||||
* information are records, and columns of data are fields. The
|
||||
@@ -556,15 +399,7 @@ class Database
|
||||
*/
|
||||
public static function DVAR($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return
|
||||
return Statistical::VARFunc(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
return Database\DVar::evaluate($database, $field, $criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -576,6 +411,11 @@ class Database
|
||||
* Excel Function:
|
||||
* DVARP(database,field,criteria)
|
||||
*
|
||||
* @Deprecated 1.17.0
|
||||
*
|
||||
* @see Database\DVarP::evaluate()
|
||||
* Use the evaluate() method in the Database\DVarP class instead
|
||||
*
|
||||
* @param mixed[] $database The range of cells that makes up the list or database.
|
||||
* A database is a list of related data in which rows of related
|
||||
* information are records, and columns of data are fields. The
|
||||
@@ -595,14 +435,6 @@ class Database
|
||||
*/
|
||||
public static function DVARP($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return
|
||||
return Statistical::VARP(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
return Database\DVarP::evaluate($database, $field, $criteria);
|
||||
}
|
||||
}
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages;
|
||||
|
||||
class DAverage extends DatabaseAbstract
|
||||
{
|
||||
/**
|
||||
* DAVERAGE.
|
||||
*
|
||||
* Averages the values in a column of a list or database that match conditions you specify.
|
||||
*
|
||||
* Excel Function:
|
||||
* DAVERAGE(database,field,criteria)
|
||||
*
|
||||
* @param mixed[] $database The range of cells that makes up the list or database.
|
||||
* A database is a list of related data in which rows of related
|
||||
* information are records, and columns of data are fields. The
|
||||
* first row of the list contains labels for each column.
|
||||
* @param int|string $field Indicates which column is used in the function. Enter the
|
||||
* column label enclosed between double quotation marks, such as
|
||||
* "Age" or "Yield," or a number (without quotation marks) that
|
||||
* represents the position of the column within the list: 1 for
|
||||
* the first column, 2 for the second column, and so on.
|
||||
* @param mixed[] $criteria The range of cells that contains the conditions you specify.
|
||||
* You can use any range for the criteria argument, as long as it
|
||||
* includes at least one column label and at least one cell below
|
||||
* the column label in which you specify a condition for the
|
||||
* column.
|
||||
*
|
||||
* @return null|float|string
|
||||
*/
|
||||
public static function evaluate($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Averages::average(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user