From 34461d495d1d105412b5935165e87ccbfc923485 Mon Sep 17 00:00:00 2001 From: Andrew DalPino Date: Wed, 23 Sep 2026 20:02:46 -0500 Subject: [PATCH 1/2] Update API to match Ext --- CHANGELOG.md | 12 + docs/Matrix.md | 31 +- docs/Vector.md | 35 +- docs/getting-started.md | 4 +- src/ColumnVector.php | 26 +- src/Decompositions/Cholesky.php | 2 +- src/Decompositions/Eigen.php | 4 +- src/Decompositions/LU.php | 6 +- src/Decompositions/SVD.php | 6 +- src/Matrix.php | 249 +++-- src/Reductions/REF.php | 4 +- src/Reductions/RREF.php | 2 +- src/TensorBuffer.php | 95 ++ src/Vector.php | 175 ++-- tests/ColumnVectorTest.php | 206 ++-- tests/Decompositions/CholeskyTest.php | 56 +- tests/Decompositions/EigenTest.php | 40 +- tests/Decompositions/LUTest.php | 64 +- tests/Decompositions/SVDTest.php | 48 +- tests/MatrixTest.php | 1242 +++++++++++++------------ tests/Reductions/REFTest.php | 68 +- tests/Reductions/RREFTest.php | 56 +- tests/VectorTest.php | 640 +++++++------ 23 files changed, 1752 insertions(+), 1319 deletions(-) create mode 100644 src/TensorBuffer.php diff --git a/CHANGELOG.md b/CHANGELOG.md index ed2d87e..896eb5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Change Log +- 4.0.0 + - Made the pure-PHP library byte-compatible with the tensor_ext extension for + `serialize()` / `unserialize()`: `Vector`, `Matrix`, and `ColumnVector` now + implement `__serialize()` and `__unserialize()` so that payloads written by + either implementation can be read by the other. + - Renamed the `build()` / `quick()` factories to `Vector::fromArray(array + $a = [], bool $validate = true)` and `Matrix::fromArray(array $a = [], bool + $validate = true)` to match the Tensor-Ext API. + - Added `Vector::asTensorBuffer()` and `Matrix::asTensorBuffer()` plus a new + `Tensor\TensorBuffer` class exposing `toArray()`, `asBuffer()`, `count()`, + and a bounds-checked `get(int $index)`. + - 3.1.0 - Implemented the singular value decomposition (SVD) in the pure-PHP library - Implemented the Moore-Penrose pseudoinverse in the pure-PHP library via SVD diff --git a/docs/Matrix.md b/docs/Matrix.md index 9addf5a..8bfa672 100644 --- a/docs/Matrix.md +++ b/docs/Matrix.md @@ -27,13 +27,17 @@ Instantiate a matrix directly. - **Throws:** `Tensor\Exceptions\InvalidArgumentException` if rows have unequal column counts - **Note:** Prefer the factory methods below. -### `Matrix::build(array $a = []) : Matrix` +### `Matrix::fromArray(array $a = [], bool $validate = true) : Matrix` -Factory method to build a new matrix from an array, running validation. +Build a matrix from a PHP array of rows, normalising each value to a `float` +and (by default) validating rectangularity and casting non-floats. Pass +`$validate = false` to skip validation for quicker construction, e.g. when +the source is already known to be a well-formed `list>`. -### `Matrix::quick(array $a = []) : Matrix` - -Build a new matrix foregoing any validation for quicker instantiation. +- **Parameters:** + - `$a` — `array>` + - `$validate` — whether to validate rows and cast non-floats to `float` (default `true`) +- **Throws:** `Tensor\Exceptions\InvalidArgumentException` if `$validate = true` and rows have unequal column counts ### `Matrix::identity(int $n) : Matrix` @@ -135,6 +139,23 @@ Return the elements of the matrix in a 2-d array. - **Returns:** `list>` +### `asTensorBuffer() : TensorBuffer` + +Return the underlying elements (flattened in row-major order) wrapped as a +`Tensor` `TensorBuffer`, mirroring the Tensor-Ext surface area. + +- **Returns:** `Tensor\TensorBuffer` + +### `__serialize() : array` + +Return the elements of the matrix as a plain PHP array of rows so that only +the values, and not the object structure, appear in the serialized form. +Output is byte-compatible with the `Tensor-Ext` polyfill. + +### `__unserialize(array $data) : void` + +Restore the matrix from a plain array of rows produced by `__serialize()`. + ### `asVectors() : array` Return each row as a vector in an array. diff --git a/docs/Vector.md b/docs/Vector.md index 45cd0ef..5635406 100644 --- a/docs/Vector.md +++ b/docs/Vector.md @@ -23,18 +23,16 @@ Instantiate a vector directly. - `$validate` — whether to validate and cast elements to floats (default `true`) - **Note:** Prefer the factory methods below. -### `Vector::build(array $a = [])` +### `Vector::fromArray(array $a = [], bool $validate = true)` -Factory method to build a new vector from an array, running validation. +Build a vector from a PHP array of elements, normalising each value to a +`float` and (by default) validating the input. Pass `$validate = false` to +skip validation for quicker construction, e.g. when the source is already +trusted and known to be a `list`. -- **Parameters:** `$a` — `(int|float)[]` -- **Returns:** `mixed` (a `Vector`/`static`) - -### `Vector::quick(array $a = [])` - -Build a vector foregoing any validation for quicker instantiation. - -- **Parameters:** `$a` — `(int|float)[]` +- **Parameters:** + - `$a` — `(int|float)[]` + - `$validate` — whether to cast non-floats to `float` (default `true`) - **Returns:** `mixed` (a `Vector`/`static`) ### `Vector::zeros(int $n) : Vector` @@ -140,6 +138,23 @@ Return the vector as an array. - **Returns:** `list` +### `asTensorBuffer() : TensorBuffer` + +Return the underlying elements wrapped as a `Tensor` `TensorBuffer`, mirroring +the Tensor-Ext surface area. + +- **Returns:** `Tensor\TensorBuffer` + +### `__serialize() : array` + +Return the elements of the vector as a plain PHP array so that only the values, +and not the object structure, appear in the serialized form. Output is +byte-compatible with the `Tensor-Ext` polyfill. + +### `__unserialize(array $data) : void` + +Restore the vector from a plain array of elements produced by `__serialize()`. + ### `asRowMatrix() : Matrix` Return this vector as a 1 x n row matrix. diff --git a/docs/getting-started.md b/docs/getting-started.md index 6f4d300..5cff89b 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -28,13 +28,13 @@ use Tensor\Matrix; use Tensor\Vector; // Build a 2 x 3 matrix. -$a = Matrix::build([ +$a = Matrix::fromArray([ [1.0, 2.0, 3.0], [4.0, 5.0, 6.0], ]); // Build a 3 x 2 matrix. -$b = Matrix::build([ +$b = Matrix::fromArray([ [7.0, 8.0], [9.0, 10.0], [11.0, 12.0], diff --git a/src/ColumnVector.php b/src/ColumnVector.php index 99af6a5..31d7073 100644 --- a/src/ColumnVector.php +++ b/src/ColumnVector.php @@ -42,7 +42,7 @@ public function n() : int */ public function transpose() { - return Vector::quick($this->a); + return Vector::fromArray($this->a, false); } /** @@ -84,7 +84,7 @@ public function multiplyMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -115,7 +115,7 @@ public function divideMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -146,7 +146,7 @@ public function addMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -177,7 +177,7 @@ public function subtractMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -208,7 +208,7 @@ public function powMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -239,7 +239,7 @@ public function modMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -271,7 +271,7 @@ public function equalMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -303,7 +303,7 @@ public function notEqualMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -335,7 +335,7 @@ public function greaterMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -367,7 +367,7 @@ public function greaterEqualMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -399,7 +399,7 @@ public function lessMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -431,6 +431,6 @@ public function lessEqualMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } } diff --git a/src/Decompositions/Cholesky.php b/src/Decompositions/Cholesky.php index 625de10..a2ef3e6 100644 --- a/src/Decompositions/Cholesky.php +++ b/src/Decompositions/Cholesky.php @@ -71,7 +71,7 @@ public static function decompose(Matrix $a) : self } } - $l = Matrix::quick($l); + $l = Matrix::fromArray($l, false); return new self($l); } diff --git a/src/Decompositions/Eigen.php b/src/Decompositions/Eigen.php index ca700a0..d48f17f 100644 --- a/src/Decompositions/Eigen.php +++ b/src/Decompositions/Eigen.php @@ -51,7 +51,7 @@ public static function decompose(Matrix $a, bool $symmetric = false) : self $n = $a->n(); if ($n === 1) { - return new self($a->rowAsVector(0)->asArray(), Matrix::quick([[1.0]])); + return new self($a->rowAsVector(0)->asArray(), Matrix::fromArray([[1.0]], false)); } if ($symmetric) { @@ -83,7 +83,7 @@ public static function decompose(Matrix $a, bool $symmetric = false) : self } } - return new self($d, Matrix::quick($rows)); + return new self($d, Matrix::fromArray($rows, false)); } /** diff --git a/src/Decompositions/LU.php b/src/Decompositions/LU.php index 1b13757..89f9596 100644 --- a/src/Decompositions/LU.php +++ b/src/Decompositions/LU.php @@ -123,9 +123,9 @@ public static function decompose(Matrix $a) : self } return new self( - Matrix::quick($l), - Matrix::quick($u), - Matrix::quick($p) + Matrix::fromArray($l, false), + Matrix::fromArray($u, false), + Matrix::fromArray($p, false) ); } diff --git a/src/Decompositions/SVD.php b/src/Decompositions/SVD.php index fd12464..d8ff4eb 100644 --- a/src/Decompositions/SVD.php +++ b/src/Decompositions/SVD.php @@ -250,9 +250,9 @@ public static function decompose(Matrix $a) : self } return new self( - Matrix::quick($uMatrix), + Matrix::fromArray($uMatrix, false), array_slice($singularValues, 0, $k), - Matrix::quick($vT) + Matrix::fromArray($vT, false) ); } @@ -307,7 +307,7 @@ public function s() : Matrix $s[$i][$i] = $value; } - return Matrix::quick($s); + return Matrix::fromArray($s, false); } /** diff --git a/src/Matrix.php b/src/Matrix.php index 38465a4..a961586 100644 --- a/src/Matrix.php +++ b/src/Matrix.php @@ -53,25 +53,16 @@ class Matrix implements Tensor protected int $n; /** - * Factory method to build a new matrix from an array. - * - * @param array> $a - * @return self - */ - public static function build(array $a = []) : self - { - return new self($a, true); - } - - /** - * Build a new matrix foregoing any validation for quicker instantiation. + * Build a new matrix from an array of arrays, validating that each row + * has equal length and normalising each value to a float by default. * * @param array> $a + * @param bool $validate * @return self */ - public static function quick(array $a = []) : self + public static function fromArray(array $a = [], bool $validate = true) : self { - return new self($a, false); + return new self($a, $validate); } /** @@ -100,7 +91,7 @@ public static function identity(int $n) : self $a[] = $rowA; } - return self::quick($a); + return self::fromArray($a, false); } /** @@ -151,7 +142,7 @@ public static function diagonal(array $elements) : self $a[] = $rowA; } - return self::quick($a); + return self::fromArray($a, false); } /** @@ -175,7 +166,7 @@ public static function fill(float $value, int $m, int $n) : self . " greater than 0, $n given."); } - return self::quick(array_fill(0, $m, array_fill(0, $n, $value))); + return self::fromArray(array_fill(0, $m, array_fill(0, $n, $value)), false); } /** @@ -212,7 +203,7 @@ public static function rand(int $m, int $n) : self $a[] = $rowA; } - return self::quick($a); + return self::fromArray($a, false); } /** @@ -262,7 +253,7 @@ public static function gaussian(int $m, int $n) : self $a[] = $rowA; } - return self::quick($a); + return self::fromArray($a, false); } /** @@ -320,7 +311,7 @@ public static function poisson(int $m, int $n, float $lambda = 1.0) : self $a[] = $rowA; } - return self::quick($a); + return self::fromArray($a, false); } /** @@ -357,7 +348,7 @@ public static function uniform(int $m, int $n) : self $a[] = $rowA; } - return self::quick($a); + return self::fromArray($a, false); } /** @@ -474,7 +465,7 @@ public function rowAsVector(int $index) : Vector */ public function columnAsVector(int $index) : ColumnVector { - return ColumnVector::quick(array_column($this->a, $index)); + return ColumnVector::fromArray(array_column($this->a, $index), false); } /** @@ -496,7 +487,7 @@ public function diagonalAsVector() : Vector $b[] = $rowA[$i]; } - return Vector::quick($b); + return Vector::fromArray($b, false); } /** @@ -516,7 +507,13 @@ public function asArray() : array */ public function asVectors() : array { - return array_map([Vector::class, 'quick'], $this->a); + $vectors = []; + + foreach ($this->a as $row) { + $vectors[] = Vector::fromArray($row, false); + } + + return $vectors; } /** @@ -542,7 +539,7 @@ public function asColumnVectors() : array */ public function flatten() : Vector { - return Vector::quick(array_merge(...$this->a)); + return Vector::fromArray(array_merge(...$this->a), false); } /** @@ -561,7 +558,7 @@ public function map(callable $callback) : self $b[] = array_map($callback, $rowA); } - return self::quick($b); + return self::fromArray($b, false); } /** @@ -604,10 +601,10 @@ public function transpose() : self $b[] = [$row]; } - return self::quick($b); + return self::fromArray($b, false); default: - return self::quick(array_map(null, ...$this->a)); + return self::fromArray(array_map(null, ...$this->a), false); } } @@ -641,7 +638,7 @@ public function inverse() : self $b[] = array_slice($rowA, $this->n); } - return self::quick($b); + return self::fromArray($b, false); } /** @@ -670,7 +667,7 @@ public function pseudoinverse() : self } return $svd->v() - ->matmul(Matrix::quick($sPlus)) + ->matmul(Matrix::fromArray($sPlus, false)) ->matmul($svd->u()->transpose()); } @@ -795,7 +792,7 @@ public function matmul(Matrix $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -876,7 +873,7 @@ public function convolve(Matrix $b, int $stride = 1) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -1465,7 +1462,7 @@ public function log(float $base = M_E) : self $b[] = $rowB; } - return self::quick($b); + return self::fromArray($b, false); } /** @@ -1565,7 +1562,7 @@ public function deg2rad() : self */ public function sum() : ColumnVector { - return ColumnVector::quick(array_map('array_sum', $this->a)); + return ColumnVector::fromArray(array_map('array_sum', $this->a), false); } /** @@ -1575,7 +1572,7 @@ public function sum() : ColumnVector */ public function product() : ColumnVector { - return ColumnVector::quick(array_map('array_product', $this->a)); + return ColumnVector::fromArray(array_map('array_product', $this->a), false); } /** @@ -1585,7 +1582,7 @@ public function product() : ColumnVector */ public function min() : ColumnVector { - return ColumnVector::quick(array_map('min', $this->a)); + return ColumnVector::fromArray(array_map('min', $this->a), false); } /** @@ -1595,7 +1592,7 @@ public function min() : ColumnVector */ public function max() : ColumnVector { - return ColumnVector::quick(array_map('max', $this->a)); + return ColumnVector::fromArray(array_map('max', $this->a), false); } /** @@ -1663,7 +1660,7 @@ public function median() : ColumnVector $b[] = $median; } - return ColumnVector::quick($b); + return ColumnVector::fromArray($b, false); } /** @@ -1702,7 +1699,7 @@ public function quantile(float $q) : ColumnVector $b[] = $t + $remainder * ($rowA[$xHat] - $t); } - return ColumnVector::quick($b); + return ColumnVector::fromArray($b, false); } /** @@ -1755,7 +1752,7 @@ public function round(int $precision = 0) : self $b[] = $rowB; } - return self::quick($b); + return self::fromArray($b, false); } /** @@ -1817,7 +1814,7 @@ public function clip(float $min, float $max) : self $b[] = $rowB; } - return self::quick($b); + return self::fromArray($b, false); } /** @@ -1846,7 +1843,7 @@ public function clipLower(float $min) : self $b[] = $rowB; } - return self::quick($b); + return self::fromArray($b, false); } /** @@ -1875,7 +1872,7 @@ public function clipUpper(float $max) : self $b[] = $rowB; } - return self::quick($b); + return self::fromArray($b, false); } /** @@ -1903,7 +1900,7 @@ public function sign() : self $b[] = $rowB; } - return self::quick($b); + return self::fromArray($b, false); } /** @@ -1925,7 +1922,7 @@ public function negate() : self $b[] = $rowB; } - return self::quick($b); + return self::fromArray($b, false); } /** @@ -1942,7 +1939,7 @@ public function augmentAbove(Matrix $b) : self . " {$this->n} columns but Matrix B has {$b->n()}."); } - return self::quick(array_merge($b->asArray(), $this->a)); + return self::fromArray(array_merge($b->asArray(), $this->a), false); } /** @@ -1959,7 +1956,7 @@ public function augmentBelow(Matrix $b) : self . " {$this->n} columns but Matrix B has {$b->n()}."); } - return self::quick(array_merge($this->a, $b->asArray())); + return self::fromArray(array_merge($this->a, $b->asArray()), false); } /** @@ -1976,7 +1973,7 @@ public function augmentLeft(Matrix $b) : self . " {$this->m} rows but Matrix B has {$b->m()}."); } - return self::quick(array_map('array_merge', $b->asArray(), $this->a)); + return self::fromArray(array_map('array_merge', $b->asArray(), $this->a), false); } /** @@ -1993,7 +1990,7 @@ public function augmentRight(Matrix $b) : self . " {$this->m} rows but Matrix B has {$b->m()}."); } - return self::quick(array_map('array_merge', $this->a, $b->asArray())); + return self::fromArray(array_map('array_merge', $this->a, $b->asArray()), false); } /** @@ -2027,7 +2024,7 @@ public function repeat(int $m, int $n) : self $b = array_merge($b, ...$temp); - return self::quick($b); + return self::fromArray($b, false); } /** @@ -2058,7 +2055,7 @@ public function multiplyMatrix(Matrix $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2089,7 +2086,7 @@ public function divideMatrix(Matrix $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2120,7 +2117,7 @@ public function addMatrix(Matrix $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2151,7 +2148,7 @@ public function subtractMatrix(Matrix $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2182,7 +2179,7 @@ public function powMatrix(Matrix $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2213,7 +2210,7 @@ public function modMatrix(Matrix $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2244,7 +2241,7 @@ public function equalMatrix(Matrix $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2275,7 +2272,7 @@ public function notEqualMatrix(Matrix $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2306,7 +2303,7 @@ public function greaterMatrix(Matrix $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2337,7 +2334,7 @@ public function greaterEqualMatrix(Matrix $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2368,7 +2365,7 @@ public function lessMatrix(Matrix $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2399,7 +2396,7 @@ public function lessEqualMatrix(Matrix $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2430,7 +2427,7 @@ public function multiplyVector(Vector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2461,7 +2458,7 @@ public function divideVector(Vector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2492,7 +2489,7 @@ public function addVector(Vector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2523,7 +2520,7 @@ public function subtractVector(Vector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2554,7 +2551,7 @@ public function powVector(Vector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2585,7 +2582,7 @@ public function modVector(Vector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2616,7 +2613,7 @@ public function equalVector(Vector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2647,7 +2644,7 @@ public function notEqualVector(Vector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2678,7 +2675,7 @@ public function greaterVector(Vector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2709,7 +2706,7 @@ public function greaterEqualVector(Vector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2740,7 +2737,7 @@ public function lessVector(Vector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2771,7 +2768,7 @@ public function lessEqualVector(Vector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2802,7 +2799,7 @@ public function multiplyColumnVector(ColumnVector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2833,7 +2830,7 @@ public function divideColumnVector(ColumnVector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2864,7 +2861,7 @@ public function addColumnVector(ColumnVector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2895,7 +2892,7 @@ public function subtractColumnVector(ColumnVector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2926,7 +2923,7 @@ public function powColumnVector(ColumnVector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2957,7 +2954,7 @@ public function modColumnVector(ColumnVector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -2988,7 +2985,7 @@ public function equalColumnVector(ColumnVector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3019,7 +3016,7 @@ public function notEqualColumnVector(ColumnVector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3050,7 +3047,7 @@ public function greaterColumnVector(ColumnVector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3081,7 +3078,7 @@ public function greaterEqualColumnVector(ColumnVector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3112,7 +3109,7 @@ public function lessColumnVector(ColumnVector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3143,7 +3140,7 @@ public function lessEqualColumnVector(ColumnVector $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3166,7 +3163,7 @@ public function multiplyScalar(float $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3189,7 +3186,7 @@ public function divideScalar(float $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3212,7 +3209,7 @@ public function addScalar(float $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3235,7 +3232,7 @@ public function subtractScalar(float $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3258,7 +3255,7 @@ public function powScalar(float $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3281,7 +3278,7 @@ public function modScalar(float $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3304,7 +3301,7 @@ public function equalScalar(float $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3327,7 +3324,7 @@ public function notEqualScalar(float $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3350,7 +3347,7 @@ public function greaterScalar(float $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3373,7 +3370,7 @@ public function greaterEqualScalar(float $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3396,7 +3393,7 @@ public function lessScalar(float $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3419,7 +3416,7 @@ public function lessEqualScalar(float $b) : self $c[] = $rowC; } - return self::quick($c); + return self::fromArray($c, false); } /** @@ -3470,7 +3467,7 @@ public function offsetUnset($index) : void public function offsetGet($index) : Vector { if (isset($this->a[$index])) { - return Vector::quick($this->a[$index]); + return Vector::fromArray($this->a[$index], false); } throw new InvalidArgumentException("Element not found at offset $index."); @@ -3485,7 +3482,59 @@ public function offsetGet($index) : Vector public function getIterator() : Traversable { foreach ($this->a as $row) { - yield Vector::quick($row); + yield Vector::fromArray($row, false); } } + + /** + * Return the matrix elements as a TensorBuffer holding a single + * contiguous row-major sequence of values. + * + * @internal + * + * @return TensorBuffer + */ + public function asTensorBuffer() : TensorBuffer + { + $flat = []; + + foreach ($this->a as $rowA) { + foreach ($rowA as $valueA) { + $flat[] = $valueA; + } + } + + return new TensorBuffer($flat); + } + + /** + * Return the elements of the matrix as a plain PHP array of rows so + * that only the values, and not the object structure, appear in the + * serialized form. + * + * @return list> + */ + public function __serialize() : array + { + return [ + 'data' => $this->asArray(), + 'm' => $this->m, + 'n' => $this->n, + ]; + } + + /** + * Restore the matrix from the plain array of rows produced by + * __serialize() by rebuilding its internal state and shape. + * + * @param array{data: list>, m: int, n: int} $data + */ + public function __unserialize(array $data) : void + { + $rebuilt = static::fromArray($data['data']); + + $this->a = $rebuilt->asArray(); + $this->m = $data['m']; + $this->n = $data['n']; + } } diff --git a/src/Reductions/REF.php b/src/Reductions/REF.php index f9669c8..2d73fa9 100644 --- a/src/Reductions/REF.php +++ b/src/Reductions/REF.php @@ -105,7 +105,7 @@ public static function gaussianElimination(Matrix $a) : self } } - return new self(Matrix::quick($b), $swaps); + return new self(Matrix::fromArray($b, false), $swaps); } /** @@ -165,7 +165,7 @@ public static function rowReductionMethod(Matrix $a) : self ++$col; } - return new self(Matrix::quick($b), $swaps); + return new self(Matrix::fromArray($b, false), $swaps); } /** diff --git a/src/Reductions/RREF.php b/src/Reductions/RREF.php index b8715d7..4b81399 100644 --- a/src/Reductions/RREF.php +++ b/src/Reductions/RREF.php @@ -101,7 +101,7 @@ public static function reduce(Matrix $a) : self ++$col; } - return new self(Matrix::quick($b)); + return new self(Matrix::fromArray($b, false)); } /** diff --git a/src/TensorBuffer.php b/src/TensorBuffer.php new file mode 100644 index 0000000..1ec5b1c --- /dev/null +++ b/src/TensorBuffer.php @@ -0,0 +1,95 @@ + + */ + protected array $a; + + /** + * @param (int|float)[] $a + */ + public function __construct(array $a = []) + { + if ($a) { + $a = array_values($a); + + foreach ($a as &$valueA) { + if (!is_float($valueA)) { + $valueA = (float) $valueA; + } + } + } + + $this->a = $a; + } + + /** + * Return the buffer as a PHP array. + * + * @return list + */ + public function toArray() : array + { + return $this->a; + } + + /** + * Return the underlying buffer (this polyfill instance). + * + * @return self + */ + public function asBuffer() : self + { + return $this; + } + + /** + * Return the number of elements in the buffer. + * + * @return int + */ + public function count() : int + { + return count($this->a); + } + + /** + * Return the element at the given index. + * + * @param int $index + * @throws InvalidArgumentException + * @return float + */ + public function get(int $index) : float + { + if ($index < 0 || $index >= count($this->a)) { + throw new InvalidArgumentException( + "Element not found at offset $index." + ); + } + + return $this->a[$index]; + } +} diff --git a/src/Vector.php b/src/Vector.php index 2368299..98258e2 100644 --- a/src/Vector.php +++ b/src/Vector.php @@ -40,25 +40,16 @@ class Vector implements Tensor protected int $n; /** - * Factory method to build a new vector from an array. + * Build a new vector from a PHP array of elements, validating and + * normalising each value to a float by default. * * @param (int|float)[] $a - * @return mixed - */ - public static function build(array $a = []) - { - return new static($a, true); - } - - /** - * Build a vector foregoing any validation for quicker instantiation. - * - * @param (int|float)[] $a - * @return mixed + * @param bool $validate + * @return static */ - public static function quick(array $a = []) + public static function fromArray(array $a = [], bool $validate = true) { - return new static($a, false); + return new static($a, $validate); } /** @@ -98,7 +89,7 @@ public static function fill(float $value, int $n) : self . " must be greater than 0, $n given."); } - return static::quick(array_fill(0, $n, $value)); + return static::fromArray(array_fill(0, $n, $value), false); } /** @@ -123,7 +114,7 @@ public static function rand(int $n) : self $a[] = rand() / $max; } - return static::quick($a); + return static::fromArray($a, false); } /** @@ -158,7 +149,7 @@ public static function gaussian(int $n) : self $a = array_slice($a, 0, $n); } - return static::quick($a); + return static::fromArray($a, false); } /** @@ -204,7 +195,7 @@ public static function poisson(int $n, float $lambda = 1.0) : self $a[] = $k - 1.0; } - return static::quick($a); + return static::fromArray($a, false); } /** @@ -229,7 +220,7 @@ public static function uniform(int $n) : self $a[] = rand(-$max, $max) / $max; } - return static::quick($a); + return static::fromArray($a, false); } /** @@ -242,7 +233,7 @@ public static function uniform(int $n) : self */ public static function range(float $start, float $end, float $interval = 1.0) : self { - return static::quick(range($start, $end, $interval)); + return static::fromArray(range($start, $end, $interval), false); } /** @@ -278,7 +269,7 @@ public static function linspace(float $min, float $max, int $n) : self $a[] = $max; - return self::quick($a); + return self::fromArray($a, false); } /** @@ -361,6 +352,16 @@ public function asArray() : array return $this->a; } + /** + * Return the vector elements as a TensorBuffer. + * + * @return TensorBuffer + */ + public function asTensorBuffer() : TensorBuffer + { + return new TensorBuffer($this->a); + } + /** * Return this vector as a row matrix. * @@ -368,7 +369,7 @@ public function asArray() : array */ public function asRowMatrix() : Matrix { - return Matrix::quick([$this->a]); + return Matrix::fromArray([$this->a], false); } /** @@ -384,7 +385,7 @@ public function asColumnMatrix() : Matrix $b[] = [$valueA]; } - return Matrix::quick($b); + return Matrix::fromArray($b, false); } /** @@ -418,7 +419,7 @@ public function reshape(int $m, int $n) : Matrix $b[] = $rowB; } - return Matrix::quick($b); + return Matrix::fromArray($b, false); } /** @@ -428,7 +429,7 @@ public function reshape(int $m, int $n) : Matrix */ public function transpose() { - return ColumnVector::quick($this->a); + return ColumnVector::fromArray($this->a, false); } /** @@ -441,7 +442,7 @@ public function transpose() */ public function map(callable $callback) : self { - return static::quick(array_map($callback, $this->a)); + return static::fromArray(array_map($callback, $this->a), false); } /** @@ -525,7 +526,7 @@ public function outer(Vector $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -569,7 +570,7 @@ public function convolve(Vector $b, int $stride = 1) : self $c[] = $sigma; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -1061,7 +1062,7 @@ public function log(float $base = M_E) : self $b[] = log($valueA, $base); } - return static::quick($b); + return static::fromArray($b, false); } /** @@ -1298,7 +1299,7 @@ public function round(int $precision = 0) : self $b[] = round($valueA, $precision); } - return static::quick($b); + return static::fromArray($b, false); } /** @@ -1355,7 +1356,7 @@ public function clip(float $min, float $max) : self $b[] = $valueA; } - return static::quick($b); + return static::fromArray($b, false); } /** @@ -1378,7 +1379,7 @@ public function clipLower(float $min) : self $b[] = $valueA; } - return static::quick($b); + return static::fromArray($b, false); } /** @@ -1401,7 +1402,7 @@ public function clipUpper(float $max) : self $b[] = $valueA; } - return static::quick($b); + return static::fromArray($b, false); } /** @@ -1423,7 +1424,7 @@ public function sign() : self } } - return static::quick($b); + return static::fromArray($b, false); } /** @@ -1439,7 +1440,7 @@ public function negate() : self $b[] = -$valueA; } - return static::quick($b); + return static::fromArray($b, false); } /** @@ -1468,7 +1469,7 @@ public function multiplyMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -1497,7 +1498,7 @@ public function divideMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -1526,7 +1527,7 @@ public function addMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -1555,7 +1556,7 @@ public function subtractMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -1584,7 +1585,7 @@ public function powMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -1613,7 +1614,7 @@ public function modMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -1642,7 +1643,7 @@ public function equalMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -1671,7 +1672,7 @@ public function notEqualMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -1700,7 +1701,7 @@ public function greaterMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -1729,7 +1730,7 @@ public function greaterEqualMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -1758,7 +1759,7 @@ public function lessMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -1787,7 +1788,7 @@ public function lessEqualMatrix(Matrix $b) : Matrix $c[] = $rowC; } - return Matrix::quick($c); + return Matrix::fromArray($c, false); } /** @@ -1810,7 +1811,7 @@ public function multiplyVector(Vector $b) : self $c[] = $this->a[$i] * $valueB; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -1833,7 +1834,7 @@ public function divideVector(Vector $b) : self $c[] = $this->a[$i] / $valueB; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -1856,7 +1857,7 @@ public function addVector(Vector $b) : self $c[] = $this->a[$i] + $valueB; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -1879,7 +1880,7 @@ public function subtractVector(Vector $b) : self $c[] = $this->a[$i] - $valueB; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -1902,7 +1903,7 @@ public function powVector(Vector $b) : self $c[] = $this->a[$i] ** $valueB; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -1925,7 +1926,7 @@ public function modVector(Vector $b) : self $c[] = $this->a[$i] % $valueB; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -1948,7 +1949,7 @@ public function equalVector(Vector $b) : self $c[] = $this->a[$i] == $valueB ? 1 : 0; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -1971,7 +1972,7 @@ public function notEqualVector(Vector $b) : self $c[] = $this->a[$i] != $valueB ? 1 : 0; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -1994,7 +1995,7 @@ public function greaterVector(Vector $b) : self $c[] = $this->a[$i] > $valueB ? 1 : 0; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -2017,7 +2018,7 @@ public function greaterEqualVector(Vector $b) : self $c[] = $this->a[$i] >= $valueB ? 1 : 0; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -2040,7 +2041,7 @@ public function lessVector(Vector $b) : self $c[] = $this->a[$i] < $valueB ? 1 : 0; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -2063,7 +2064,7 @@ public function lessEqualVector(Vector $b) : self $c[] = $this->a[$i] <= $valueB ? 1 : 0; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -2080,7 +2081,7 @@ public function multiplyScalar(float $b) : self $c[] = $valueA * $b; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -2097,7 +2098,7 @@ public function divideScalar(float $b) : self $c[] = $valueA / $b; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -2114,7 +2115,7 @@ public function addScalar(float $b) : self $c[] = $valueA + $b; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -2131,7 +2132,7 @@ public function subtractScalar(float $b) : self $c[] = $valueA - $b; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -2148,7 +2149,7 @@ public function powScalar(float $b) : self $c[] = $valueA ** $b; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -2165,7 +2166,7 @@ public function modScalar(float $b) : self $c[] = $valueA % $b; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -2182,7 +2183,7 @@ public function equalScalar(float $b) : self $c[] = $valueA == $b ? 1 : 0; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -2199,7 +2200,7 @@ public function notEqualScalar(float $b) : self $c[] = $valueA != $b ? 1 : 0; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -2216,7 +2217,7 @@ public function greaterScalar(float $b) : self $c[] = $valueA > $b ? 1 : 0; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -2233,7 +2234,7 @@ public function greaterEqualScalar(float $b) : self $c[] = $valueA >= $b ? 1 : 0; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -2250,7 +2251,7 @@ public function lessScalar(float $b) : self $c[] = $valueA < $b ? 1 : 0; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -2267,7 +2268,7 @@ public function lessEqualScalar(float $b) : self $c[] = $valueA <= $b ? 1 : 0; } - return static::quick($c); + return static::fromArray($c, false); } /** @@ -2282,7 +2283,7 @@ public function count() : int /** * @param mixed $index - * @param mixed[] $values + * @param mixed $values * @throws RuntimeException */ #[\ReturnTypeWillChange] @@ -2339,4 +2340,32 @@ public function getIterator() : Traversable { return new ArrayIterator($this->a); } + + /** + * Return the elements of the vector as a plain PHP array so that only the + * values, and not the object structure, appear in the serialized form. + * + * @return list + */ + public function __serialize() : array + { + return [ + 'data' => $this->asArray(), + 'n' => $this->n, + ]; + } + + /** + * Restore the vector from the plain array of elements produced by + * __serialize() by rebuilding its internal state. + * + * @param array{data: list, n: int} $data + */ + public function __unserialize(array $data) : void + { + $rebuilt = static::fromArray($data['data']); + + $this->a = $rebuilt->asArray(); + $this->n = $data['n']; + } } diff --git a/tests/ColumnVectorTest.php b/tests/ColumnVectorTest.php index cd6d0e7..6b3a870 100644 --- a/tests/ColumnVectorTest.php +++ b/tests/ColumnVectorTest.php @@ -31,9 +31,9 @@ class ColumnVectorTest extends TestCase /** * @test */ - public function build() : void + public function fromArray() : void { - $vector = ColumnVector::build([-15, 25, 35]); + $vector = ColumnVector::fromArray([-15, 25, 35]); $this->assertInstanceOf(ColumnVector::class, $vector); $this->assertInstanceOf(Tensor::class, $vector); @@ -51,7 +51,7 @@ public function build() : void */ public function shape() : void { - $vector = ColumnVector::quick([-15, 25, 35]); + $vector = ColumnVector::fromArray([-15, 25, 35], false); $this->assertEquals([3], $vector->shape()); } @@ -61,7 +61,7 @@ public function shape() : void */ public function shapeString() : void { - $vector = ColumnVector::quick([-15, 25, 35]); + $vector = ColumnVector::fromArray([-15, 25, 35], false); $this->assertEquals('3', $vector->shapeString()); } @@ -71,7 +71,7 @@ public function shapeString() : void */ public function size() : void { - $vector = ColumnVector::quick([-15, 25, 35]); + $vector = ColumnVector::fromArray([-15, 25, 35], false); $this->assertEquals(3, $vector->size()); } @@ -81,7 +81,7 @@ public function size() : void */ public function m() : void { - $vector = ColumnVector::quick([-15, 25, 35]); + $vector = ColumnVector::fromArray([-15, 25, 35], false); $this->assertEquals(3, $vector->m()); } @@ -91,7 +91,7 @@ public function m() : void */ public function n() : void { - $vector = ColumnVector::quick([-15, 25, 35]); + $vector = ColumnVector::fromArray([-15, 25, 35], false); $this->assertEquals(1, $vector->n()); } @@ -101,21 +101,21 @@ public function n() : void */ public function multiply() : void { - $a = ColumnVector::quick([-15, 25, 35]); + $a = ColumnVector::fromArray([-15, 25, 35], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [6.23, -1, 0.03], [0.01, 2.01, 1], [1.1, 5, -5], - ]); + ], false); $c = $a->multiply($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [-93.45, 15, -0.44999999999999996], [0.25, 50.24999999999999, 25], [38.5, 175, -175], - ]); + ], false); $this->assertEqualsWithDelta($expected, $c, self::MAX_DELTA); } @@ -125,21 +125,21 @@ public function multiply() : void */ public function divide() : void { - $a = ColumnVector::quick([-15, 25, 35]); + $a = ColumnVector::fromArray([-15, 25, 35], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [6.23, -1, 0.03], [0.01, 2.01, 1], [1.1, 5, -5], - ]); + ], false); $c = $a->divide($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [-2.407704654895666, 15, -500.], [2500.0, 12.437810945273633, 25], [31.818181818181817, 7, -7], - ]); + ], false); $this->assertEqualsWithDelta($expected, $c, self::MAX_DELTA); } @@ -149,21 +149,21 @@ public function divide() : void */ public function add() : void { - $a = ColumnVector::quick([-15, 25, 35]); + $a = ColumnVector::fromArray([-15, 25, 35], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [6.23, -1, 0.03], [0.01, 2.01, 1], [1.1, 5, -5], - ]); + ], false); $c = $a->add($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [-8.77, -16, -14.97], [25.01, 27.009999999999998, 26], [36.1, 40, 30], - ]); + ], false); $this->assertEqualsWithDelta($expected, $c, self::MAX_DELTA); } @@ -173,21 +173,21 @@ public function add() : void */ public function subtract() : void { - $a = ColumnVector::quick([-15, 25, 35]); + $a = ColumnVector::fromArray([-15, 25, 35], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [6.23, -1, 0.03], [0.01, 2.01, 1], [1.1, 5, -5], - ]); + ], false); $c = $a->subtract($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [-21.23, -14, -15.03], [24.99, 22.990000000000002, 24], [33.9, 30, 40], - ]); + ], false); $this->assertEqualsWithDelta($expected, $c, self::MAX_DELTA); } @@ -197,21 +197,21 @@ public function subtract() : void */ public function equal() : void { - $a = ColumnVector::quick([-15, 25, 35]); + $a = ColumnVector::fromArray([-15, 25, 35], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [6.23, -1, 0.03], [0.01, 2.01, 1], [1.1, 5, -5], - ]); + ], false); $c = $a->equal($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [0, 0, 0], [0, 0, 0], [0, 0, 0], - ]); + ], false); $this->assertEquals($expected, $c); } @@ -221,21 +221,21 @@ public function equal() : void */ public function notEqual() : void { - $a = ColumnVector::quick([-15, 25, 35]); + $a = ColumnVector::fromArray([-15, 25, 35], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [6.23, -1, 0.03], [0.01, 2.01, 1], [1.1, 5, -5], - ]); + ], false); $c = $a->notEqual($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [1, 1, 1], [1, 1, 1], [1, 1, 1], - ]); + ], false); $this->assertEquals($expected, $c); } @@ -245,21 +245,21 @@ public function notEqual() : void */ public function greater() : void { - $a = ColumnVector::quick([-15, 25, 35]); + $a = ColumnVector::fromArray([-15, 25, 35], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [6.23, -1, 0.03], [0.01, 2.01, 1], [1.1, 5, -5], - ]); + ], false); $c = $a->greater($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [0, 0, 0], [1, 1, 1], [1, 1, 1], - ]); + ], false); $this->assertEquals($expected, $c); } @@ -269,21 +269,21 @@ public function greater() : void */ public function greaterEqual() : void { - $a = ColumnVector::quick([-15, 25, 35]); + $a = ColumnVector::fromArray([-15, 25, 35], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [6.23, -1, 0.03], [0.01, 2.01, 1], [1.1, 5, -5], - ]); + ], false); $c = $a->greaterEqual($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [0, 0, 0], [1, 1, 1], [1, 1, 1], - ]); + ], false); $this->assertEquals($expected, $c); } @@ -293,21 +293,21 @@ public function greaterEqual() : void */ public function less() : void { - $a = ColumnVector::quick([-15, 25, 35]); + $a = ColumnVector::fromArray([-15, 25, 35], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [6.23, -1, 0.03], [0.01, 2.01, 1], [1.1, 5, -5], - ]); + ], false); $c = $a->less($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [1, 1, 1], [0, 0, 0], [0, 0, 0], - ]); + ], false); $this->assertEquals($expected, $c); } @@ -317,21 +317,21 @@ public function less() : void */ public function lessEqual() : void { - $a = ColumnVector::quick([-15, 25, 35]); + $a = ColumnVector::fromArray([-15, 25, 35], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [6.23, -1, 0.03], [0.01, 2.01, 1], [1.1, 5, -5], - ]); + ], false); $c = $a->lessEqual($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [1, 1, 1], [0, 0, 0], [0, 0, 0], - ]); + ], false); $this->assertEquals($expected, $c); } @@ -341,12 +341,12 @@ public function lessEqual() : void */ public function transposeReturnsVector() : void { - $a = ColumnVector::quick([1.0, 2.0, 3.0]); + $a = ColumnVector::fromArray([1.0, 2.0, 3.0], false); $b = $a->transpose(); $this->assertInstanceOf(Vector::class, $b); - $this->assertEquals(Vector::quick([1.0, 2.0, 3.0]), $b); + $this->assertEquals(Vector::fromArray([1.0, 2.0, 3.0], false), $b); } /** @@ -354,7 +354,7 @@ public function transposeReturnsVector() : void */ public function sizes() : void { - $a = ColumnVector::quick([1.0, 2.0, 3.0]); + $a = ColumnVector::fromArray([1.0, 2.0, 3.0], false); $this->assertEquals(3, $a->m()); $this->assertEquals(1, $a->n()); @@ -366,19 +366,19 @@ public function sizes() : void */ public function matmul() : void { - $a = ColumnVector::quick([1.0, 2.0, 3.0]); + $a = ColumnVector::fromArray([1.0, 2.0, 3.0], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [1.0, 2.0, 3.0], - ]); + ], false); $c = $a->matmul($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [1.0, 2.0, 3.0], [2.0, 4.0, 6.0], [3.0, 6.0, 9.0], - ]); + ], false); $this->assertEqualsWithDelta($expected, $c, self::MAX_DELTA); } @@ -390,11 +390,11 @@ public function matmulDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - ColumnVector::quick([1.0, 2.0, 3.0])->matmul(Matrix::quick([ + ColumnVector::fromArray([1.0, 2.0, 3.0], false)->matmul(Matrix::fromArray([ [1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 10.0, 11.0, 12.0], - ])); + ], false)); } /** @@ -402,21 +402,21 @@ public function matmulDimensionMismatchThrows() : void */ public function powMatrix() : void { - $a = ColumnVector::quick([2.0, 3.0, 4.0]); + $a = ColumnVector::fromArray([2.0, 3.0, 4.0], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [1.0, 2.0, 3.0], [1.0, 1.0, 1.0], [2.0, 0.0, 1.0], - ]); + ], false); $c = $a->powMatrix($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [2.0, 4.0, 8.0], [3.0, 3.0, 3.0], [16.0, 1.0, 4.0], - ]); + ], false); $this->assertEqualsWithDelta($expected, $c, self::MAX_DELTA); } @@ -428,10 +428,10 @@ public function powMatrixDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - ColumnVector::quick([1.0, 2.0, 3.0])->powMatrix(Matrix::quick([ + ColumnVector::fromArray([1.0, 2.0, 3.0], false)->powMatrix(Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], - ])); + ], false)); } /** @@ -439,21 +439,21 @@ public function powMatrixDimensionMismatchThrows() : void */ public function modMatrix() : void { - $a = ColumnVector::quick([10.0, 12.0, 15.0]); + $a = ColumnVector::fromArray([10.0, 12.0, 15.0], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [3.0, 4.0, 5.0], [2.0, 3.0, 4.0], [5.0, 6.0, 7.0], - ]); + ], false); $c = $a->modMatrix($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [1.0, 2.0, 0.0], [0.0, 0.0, 0.0], [0.0, 3.0, 1.0], - ]); + ], false); $this->assertEqualsWithDelta($expected, $c, self::MAX_DELTA); } @@ -465,10 +465,10 @@ public function modMatrixDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - ColumnVector::quick([1.0, 2.0, 3.0])->modMatrix(Matrix::quick([ + ColumnVector::fromArray([1.0, 2.0, 3.0], false)->modMatrix(Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], - ])); + ], false)); } /** @@ -478,10 +478,10 @@ public function multiplyMatrixDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - ColumnVector::quick([1.0, 2.0, 3.0])->multiplyMatrix(Matrix::quick([ + ColumnVector::fromArray([1.0, 2.0, 3.0], false)->multiplyMatrix(Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], - ])); + ], false)); } /** @@ -491,9 +491,45 @@ public function divideMatrixDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - ColumnVector::quick([1.0, 2.0, 3.0])->divideMatrix(Matrix::quick([ + ColumnVector::fromArray([1.0, 2.0, 3.0], false)->divideMatrix(Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], - ])); + ], false)); + } + + /** + * @test + */ + public function serializeRoundTripPreservesColumnVector() : void + { + $vector = ColumnVector::fromArray([1.0, 2.0, 3.0]); + + $unserialised = unserialize(serialize($vector)); + + $this->assertInstanceOf(ColumnVector::class, $unserialised); + $this->assertEquals($vector->asArray(), $unserialised->asArray()); + $this->assertEquals($vector->shape(), $unserialised->shape()); + + // The serialised payload must still be a Vector subclass so it stays + // byte-compatible with the Tensor-Ext ColumnVector. + $this->assertStringStartsWith( + 'O:19:"Tensor\\ColumnVector":2:{', + serialize($vector) + ); + } + + /** + * @test + */ + public function asTensorBuffer() : void + { + $vector = ColumnVector::fromArray([1.0, 2.0, 3.0], false); + + $buffer = $vector->asTensorBuffer(); + + $this->assertInstanceOf(\Tensor\TensorBuffer::class, $buffer); + $this->assertEquals([1.0, 2.0, 3.0], $buffer->toArray()); + $this->assertSame(3, $buffer->count()); + $this->assertEquals(3.0, $buffer->get(2)); } } diff --git a/tests/Decompositions/CholeskyTest.php b/tests/Decompositions/CholeskyTest.php index 6dc819d..36d6fed 100644 --- a/tests/Decompositions/CholeskyTest.php +++ b/tests/Decompositions/CholeskyTest.php @@ -25,17 +25,17 @@ class CholeskyTest extends TestCase */ public function decompose2x2() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [9.0, 3.0], [3.0, 5.0], - ]); + ], false); $ch = Cholesky::decompose($a); - $l = Matrix::quick([ + $l = Matrix::fromArray([ [3.0, 0.0], [1.0, 2.0], - ]); + ], false); $expected = new Cholesky($l); @@ -50,19 +50,19 @@ public function decompose2x2() : void */ public function decompose3x3() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [2.0, -1.0, 0.0], [-1.0, 2.0, -1.0], [0.0, -1.0, 2.0], - ]); + ], false); $ch = Cholesky::decompose($a); - $l = Matrix::quick([ + $l = Matrix::fromArray([ [1.4142135623730951, 0, 0], [-0.7071067811865475, 1.224744871391589, 0], [0, -0.8164965809277261, 1.1547005383792515], - ]); + ], false); $expected = new Cholesky($l); @@ -74,11 +74,11 @@ public function decompose3x3() : void */ public function decompose1x1() : void { - $a = Matrix::quick([[9.0]]); + $a = Matrix::fromArray([[9.0]], false); $ch = Cholesky::decompose($a); - $l = Matrix::quick([[3.0]]); + $l = Matrix::fromArray([[3.0]], false); $expected = new Cholesky($l); @@ -90,19 +90,19 @@ public function decompose1x1() : void */ public function decomposeDiagonal() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [4.0, 0.0, 0.0], [0.0, 9.0, 0.0], [0.0, 0.0, 16.0], - ]); + ], false); $ch = Cholesky::decompose($a); - $l = Matrix::quick([ + $l = Matrix::fromArray([ [2.0, 0.0, 0.0], [0.0, 3.0, 0.0], [0.0, 0.0, 4.0], - ]); + ], false); $expected = new Cholesky($l); @@ -116,10 +116,10 @@ public function decomposeNonSquareThrows() : void { $this->expectException(InvalidArgumentException::class); - Cholesky::decompose(Matrix::quick([ + Cholesky::decompose(Matrix::fromArray([ [1.0, 2.0, 3.0], [4.0, 5.0, 6.0], - ])); + ], false)); } /** @@ -129,10 +129,10 @@ public function decomposeIndefiniteThrows() : void { $this->expectException(RuntimeException::class); - Cholesky::decompose(Matrix::quick([ + Cholesky::decompose(Matrix::fromArray([ [1.0, 2.0], [2.0, 1.0], - ])); + ], false)); } /** @@ -142,10 +142,10 @@ public function decomposeZeroPivotThrows() : void { $this->expectException(RuntimeException::class); - Cholesky::decompose(Matrix::quick([ + Cholesky::decompose(Matrix::fromArray([ [0.0, 1.0], [1.0, 1.0], - ])); + ], false)); } /** @@ -155,10 +155,10 @@ public function decomposeSingularThrows() : void { $this->expectException(RuntimeException::class); - Cholesky::decompose(Matrix::quick([ + Cholesky::decompose(Matrix::fromArray([ [1.0, 2.0], [2.0, 4.0], - ])); + ], false)); } /** @@ -166,10 +166,10 @@ public function decomposeSingularThrows() : void */ public function lTIsTranspose() : void { - $l = Matrix::quick([ + $l = Matrix::fromArray([ [3.0, 0.0], [1.0, 2.0], - ]); + ], false); $ch = new Cholesky($l); @@ -181,19 +181,19 @@ public function lTIsTranspose() : void */ public function accessorsReturnMatrices() : void { - $l = Matrix::quick([ + $l = Matrix::fromArray([ [1.0, 0.0], [0.5, 1.0], - ]); + ], false); $ch = new Cholesky($l); $this->assertEquals($l, $ch->l()); - $expectedT = Matrix::quick([ + $expectedT = Matrix::fromArray([ [1.0, 0.5], [0.0, 1.0], - ]); + ], false); $this->assertEqualsWithDelta($expectedT, $ch->lT(), self::MAX_DELTA); } diff --git a/tests/Decompositions/EigenTest.php b/tests/Decompositions/EigenTest.php index efe9104..da67300 100644 --- a/tests/Decompositions/EigenTest.php +++ b/tests/Decompositions/EigenTest.php @@ -24,11 +24,11 @@ class EigenTest extends TestCase */ public function decomposeGeneral3x3() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $eig = Eigen::decompose($a); @@ -52,11 +52,11 @@ public function decomposeGeneral3x3() : void */ public function decomposeSymmetric3x3() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [3.0, -1.0, 0.0], [-1.0, 2.0, -1.0], [0.0, -1.0, 3.0], - ]); + ], false); $eig = Eigen::decompose($a, true); @@ -72,10 +72,10 @@ public function decomposeSymmetric3x3() : void */ public function decomposeSymmetric2x2() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [9.0, 3.0], [3.0, 5.0], - ]); + ], false); $eig = Eigen::decompose($a, true); @@ -89,11 +89,11 @@ public function decomposeSymmetric2x2() : void */ public function decomposeGeneralAndSymmetricAgree() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [3.0, -1.0, 0.0], [-1.0, 2.0, -1.0], [0.0, -1.0, 3.0], - ]); + ], false); $general = Eigen::decompose($a); $symmetric = Eigen::decompose($a, true); @@ -112,7 +112,7 @@ public function decomposeGeneralAndSymmetricAgree() : void */ public function decompose1x1() : void { - $a = Matrix::quick([[9.0]]); + $a = Matrix::fromArray([[9.0]], false); $eig = Eigen::decompose($a); @@ -120,7 +120,7 @@ public function decompose1x1() : void $this->assertEquals([9.0], $eig->eigenvalues()); - $this->assertEqualsWithDelta(Matrix::quick([[1.0]]), $eig->eigenvectors(), self::MAX_DELTA); + $this->assertEqualsWithDelta(Matrix::fromArray([[1.0]], false), $eig->eigenvectors(), self::MAX_DELTA); } /** @@ -128,11 +128,11 @@ public function decompose1x1() : void */ public function decomposeDiagonal() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [2.0, 0.0, 0.0], [0.0, 3.0, 0.0], [0.0, 0.0, 5.0], - ]); + ], false); $eig = Eigen::decompose($a); @@ -148,10 +148,10 @@ public function decomposeNonSquareThrows() : void { $this->expectException(InvalidArgumentException::class); - Eigen::decompose(Matrix::quick([ + Eigen::decompose(Matrix::fromArray([ [1.0, 2.0, 3.0], [4.0, 5.0, 6.0], - ])); + ], false)); } /** @@ -161,11 +161,11 @@ public function constructAndAccess() : void { $eigenvalues = [1.0, 2.0, 3.0]; - $eigenvectors = Matrix::quick([ + $eigenvectors = Matrix::fromArray([ [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0], - ]); + ], false); $eig = new Eigen($eigenvalues, $eigenvectors); @@ -180,10 +180,10 @@ public function constructAndAccess() : void */ public function decomposeComplexPair() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [0.0, -1.0], [1.0, 0.0], - ]); + ], false); $eig = Eigen::decompose($a); @@ -226,11 +226,11 @@ public function decomposeComplexPair() : void */ public function decomposeComplexPairWithReal() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [0.0, -1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 2.0], - ]); + ], false); $eig = Eigen::decompose($a); diff --git a/tests/Decompositions/LUTest.php b/tests/Decompositions/LUTest.php index 3f79c46..e8e6d9e 100644 --- a/tests/Decompositions/LUTest.php +++ b/tests/Decompositions/LUTest.php @@ -25,31 +25,31 @@ class LUTest extends TestCase */ public function decompose3x3() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $lu = LU::decompose($a); - $l = Matrix::quick([ + $l = Matrix::fromArray([ [1.0, 0, 0], [0.18181818181818182, 1.0, 0], [0.9090909090909091, 0.6709677419354838, 1.0], - ]); + ], false); - $u = Matrix::quick([ + $u = Matrix::fromArray([ [22.0, -17.0, 12.0], [0.0, 14.09090909090909, -4.181818181818182], [0.0, 0.0, -17.10322580645161], - ]); + ], false); - $p = Matrix::quick([ + $p = Matrix::fromArray([ [1.0, 0, 0], [0.0, 1.0, 0], [0.0, 0.0, 1.0], - ]); + ], false); $expected = new LU($l, $u, $p); @@ -67,12 +67,12 @@ public function decompose3x3() : void */ public function decomposeRequiresPivoting() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [0.0, 1.0, 0.0, 0.0], [-1.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 2.0], [0.0, 0.0, 3.0, 1.0], - ]); + ], false); $lu = LU::decompose($a); @@ -88,13 +88,13 @@ public function decomposeRequiresPivoting() : void */ public function decompose1x1() : void { - $a = Matrix::quick([[9.0]]); + $a = Matrix::fromArray([[9.0]], false); $lu = LU::decompose($a); - $l = Matrix::quick([[1.0]]); - $u = Matrix::quick([[9.0]]); - $p = Matrix::quick([[1.0]]); + $l = Matrix::fromArray([[1.0]], false); + $u = Matrix::fromArray([[9.0]], false); + $p = Matrix::fromArray([[1.0]], false); $expected = new LU($l, $u, $p); @@ -106,27 +106,27 @@ public function decompose1x1() : void */ public function decomposeDiagonal() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [2.0, 0.0], [0.0, 3.0], - ]); + ], false); $lu = LU::decompose($a); - $l = Matrix::quick([ + $l = Matrix::fromArray([ [1.0, 0.0], [0.0, 1.0], - ]); + ], false); - $u = Matrix::quick([ + $u = Matrix::fromArray([ [2.0, 0.0], [0.0, 3.0], - ]); + ], false); - $p = Matrix::quick([ + $p = Matrix::fromArray([ [1.0, 0.0], [0.0, 1.0], - ]); + ], false); $expected = new LU($l, $u, $p); @@ -140,10 +140,10 @@ public function decomposeNonSquareThrows() : void { $this->expectException(InvalidArgumentException::class); - LU::decompose(Matrix::quick([ + LU::decompose(Matrix::fromArray([ [1.0, 2.0, 3.0], [4.0, 5.0, 6.0], - ])); + ], false)); } /** @@ -153,10 +153,10 @@ public function decomposeSingularThrows() : void { $this->expectException(RuntimeException::class); - LU::decompose(Matrix::quick([ + LU::decompose(Matrix::fromArray([ [1.0, 2.0], [2.0, 4.0], - ])); + ], false)); } /** @@ -164,20 +164,20 @@ public function decomposeSingularThrows() : void */ public function accessorsReturnMatrices() : void { - $l = Matrix::quick([ + $l = Matrix::fromArray([ [1.0, 0.0], [0.5, 1.0], - ]); + ], false); - $u = Matrix::quick([ + $u = Matrix::fromArray([ [2.0, 3.0], [0.0, 4.0], - ]); + ], false); - $p = Matrix::quick([ + $p = Matrix::fromArray([ [0.0, 1.0], [1.0, 0.0], - ]); + ], false); $lu = new LU($l, $u, $p); diff --git a/tests/Decompositions/SVDTest.php b/tests/Decompositions/SVDTest.php index 6c6dd12..f41d4ad 100644 --- a/tests/Decompositions/SVDTest.php +++ b/tests/Decompositions/SVDTest.php @@ -23,11 +23,11 @@ class SVDTest extends TestCase */ public function decomposeSquare3x3() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $svd = SVD::decompose($a); @@ -50,10 +50,10 @@ public function decomposeSquare3x3() : void */ public function decomposeSquare2x2() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], - ]); + ], false); $svd = SVD::decompose($a); @@ -70,12 +70,12 @@ public function decomposeSquare2x2() : void */ public function decomposeTall() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], [5.0, 6.0], [7.0, 8.0], - ]); + ], false); $svd = SVD::decompose($a); @@ -95,10 +95,10 @@ public function decomposeTall() : void */ public function decomposeWide() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 2.0, 3.0], [4.0, 5.0, 6.0], - ]); + ], false); $svd = SVD::decompose($a); @@ -118,7 +118,7 @@ public function decomposeWide() : void */ public function decompose1x1() : void { - $a = Matrix::quick([[9.0]]); + $a = Matrix::fromArray([[9.0]], false); $svd = SVD::decompose($a); @@ -132,10 +132,10 @@ public function decompose1x1() : void */ public function decomposeRankDeficient() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 1.0], [2.0, 2.0], - ]); + ], false); $svd = SVD::decompose($a); @@ -155,11 +155,11 @@ public function decomposeRankDeficient() : void */ public function decomposePreservesTinySingularValues() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 0.0, 0.0], [0.0, 1e-9, 0.0], [0.0, 0.0, 0.0], - ]); + ], false); $svd = SVD::decompose($a); @@ -181,12 +181,12 @@ public function sReturnsPaddedSingularValueMatrix() : void $this->markTestSkipped('Extension tensor is loaded.'); } - $tall = Matrix::quick([ + $tall = Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], [5.0, 6.0], [7.0, 8.0], - ]); + ], false); $svdTall = SVD::decompose($tall); @@ -194,10 +194,10 @@ public function sReturnsPaddedSingularValueMatrix() : void $this->assertEqualsWithDelta($tall, $svdTall->u()->matmul($svdTall->s())->matmul($svdTall->vT()), self::MAX_DELTA); - $wide = Matrix::quick([ + $wide = Matrix::fromArray([ [1.0, 2.0, 3.0], [4.0, 5.0, 6.0], - ]); + ], false); $svdWide = SVD::decompose($wide); @@ -211,17 +211,17 @@ public function sReturnsPaddedSingularValueMatrix() : void */ public function constructAndAccess() : void { - $u = Matrix::quick([ + $u = Matrix::fromArray([ [1.0, 0.0], [0.0, 1.0], - ]); + ], false); $singularValues = [5.0, 3.0]; - $vT = Matrix::quick([ + $vT = Matrix::fromArray([ [1.0, 0.0], [0.0, 1.0], - ]); + ], false); $svd = new SVD($u, $singularValues, $vT); @@ -235,10 +235,10 @@ public function constructAndAccess() : void // The singular value matrix is an m by n matrix with the singular values on the diagonal. $this->assertSame([2, 2], $svd->s()->shape()); - $expectedS = Matrix::quick([ + $expectedS = Matrix::fromArray([ [5.0, 0.0], [0.0, 3.0], - ]); + ], false); $this->assertEqualsWithDelta($expectedS, $svd->s(), self::MAX_DELTA); } @@ -259,6 +259,6 @@ private function reconstruct(SVD $svd, int $m, int $n) : Matrix $s[$i][$i] = $value; } - return $svd->u()->matmul(Matrix::quick($s))->matmul($svd->vT()); + return $svd->u()->matmul(Matrix::fromArray($s, false))->matmul($svd->vT()); } } diff --git a/tests/MatrixTest.php b/tests/MatrixTest.php index ec7fd5e..7fee239 100644 --- a/tests/MatrixTest.php +++ b/tests/MatrixTest.php @@ -39,9 +39,9 @@ class MatrixTest extends TestCase /** * @test */ - public function build() : void + public function fromArray() : void { - $matrix = Matrix::build([ + $matrix = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], @@ -61,9 +61,9 @@ public function build() : void /** * @test */ - public function buildCastsIntegersToFloatsAndPreservesShape() : void + public function fromArrayCastsIntegersToFloatsAndPreservesShape() : void { - $matrix = Matrix::build([ + $matrix = Matrix::fromArray([ [1, 2, 3], [4, 5, 6], ]); @@ -96,12 +96,12 @@ public function identity() : void { $matrix = Matrix::identity(4); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1], - ]); + ], false); $this->assertEquals($expected, $matrix); } @@ -113,10 +113,10 @@ public function zeros() : void { $matrix = Matrix::zeros(2, 4); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [0, 0, 0, 0], [0, 0, 0, 0], - ]); + ], false); $this->assertEquals($expected, $matrix); } @@ -128,12 +128,12 @@ public function ones() : void { $matrix = Matrix::ones(4, 2); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [1, 1], [1, 1], [1, 1], [1, 1], - ]); + ], false); $this->assertEquals($expected, $matrix); } @@ -145,12 +145,12 @@ public function diagonal() : void { $matrix = Matrix::diagonal([0, 1, 4, 5]); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 4, 0], [0, 0, 0, 5], - ]); + ], false); $this->assertEquals($expected, $matrix); } @@ -162,12 +162,12 @@ public function fill() : void { $matrix = Matrix::fill(5, 4, 4); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [5, 5, 5, 5], [5, 5, 5, 5], [5, 5, 5, 5], [5, 5, 5, 5], - ]); + ], false); $this->assertEquals($expected, $matrix); } @@ -239,11 +239,11 @@ public function uniform() : void */ public function shape() : void { - $matrix = Matrix::quick([ + $matrix = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]); + ], false); $this->assertEquals([3, 3], $matrix->shape()); } @@ -253,10 +253,10 @@ public function shape() : void */ public function shapeString() : void { - $matrix = Matrix::quick([ + $matrix = Matrix::fromArray([ [22, -17, 12, 16], [4, 11, -2, 18], - ]); + ], false); $this->assertEquals('2 x 4', $matrix->shapeString()); } @@ -279,19 +279,19 @@ public function isSquare(Matrix $matrix, $expected) : void public function isSquareProvider() : Generator { yield [ - Matrix::quick([ + Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]), + ], false), true, ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22, -17, 12, 16], [4, 11, -2, 18], - ]), + ], false), false, ]; } @@ -301,11 +301,11 @@ public function isSquareProvider() : Generator */ public function size() : void { - $matrix = Matrix::quick([ + $matrix = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]); + ], false); $this->assertEquals(9, $matrix->size()); } @@ -315,11 +315,11 @@ public function size() : void */ public function m() : void { - $matrix = Matrix::quick([ + $matrix = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]); + ], false); $this->assertEquals(3, $matrix->m()); } @@ -329,11 +329,11 @@ public function m() : void */ public function n() : void { - $matrix = Matrix::quick([ + $matrix = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]); + ], false); $this->assertEquals(3, $matrix->n()); } @@ -343,15 +343,15 @@ public function n() : void */ public function rowAsVector() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]); + ], false); $b = $a->rowAsVector(1); - $expected = Vector::quick([4, 11, -2]); + $expected = Vector::fromArray([4, 11, -2], false); $this->assertEquals($expected, $b); } @@ -361,15 +361,15 @@ public function rowAsVector() : void */ public function columnAsVector() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]); + ], false); $b = $a->columnAsVector(1); - $expected = ColumnVector::quick([-17, 11, -6]); + $expected = ColumnVector::fromArray([-17, 11, -6], false); $this->assertEquals($expected, $b); } @@ -379,15 +379,15 @@ public function columnAsVector() : void */ public function diagonalAsVector() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]); + ], false); $b = $a->diagonalAsVector(); - $expected = Vector::quick([22, 11, -9]); + $expected = Vector::fromArray([22, 11, -9], false); $this->assertEquals($expected, $b); } @@ -397,11 +397,11 @@ public function diagonalAsVector() : void */ public function asArray() : void { - $matrix = Matrix::quick([ + $matrix = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]); + ], false); $expected = [ [22, -17, 12], @@ -417,18 +417,18 @@ public function asArray() : void */ public function asVectors() : void { - $matrix = Matrix::quick([ + $matrix = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]); + ], false); $vectors = $matrix->asVectors(); $expected = [ - Vector::quick([22, -17, 12]), - Vector::quick([4, 11, -2]), - Vector::quick([20, -6, -9]), + Vector::fromArray([22, -17, 12], false), + Vector::fromArray([4, 11, -2], false), + Vector::fromArray([20, -6, -9], false), ]; $this->assertEquals($expected, $vectors); @@ -439,18 +439,18 @@ public function asVectors() : void */ public function asColumnVectors() : void { - $matrix = Matrix::quick([ + $matrix = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]); + ], false); $vectors = $matrix->asColumnVectors(); $expected = [ - ColumnVector::quick([22, 4, 20]), - ColumnVector::quick([-17, 11, -6]), - ColumnVector::quick([12, -2, -9]), + ColumnVector::fromArray([22, 4, 20], false), + ColumnVector::fromArray([-17, 11, -6], false), + ColumnVector::fromArray([12, -2, -9], false), ]; $this->assertEquals($expected, $vectors); @@ -461,15 +461,15 @@ public function asColumnVectors() : void */ public function flatten() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]); + ], false); $b = $a->flatten(); - $expected = Vector::quick([22, -17, 12, 4, 11, -2, 20, -6, -9]); + $expected = Vector::fromArray([22, -17, 12, 4, 11, -2, 20, -6, -9], false); $this->assertEquals($expected, $b); } @@ -479,19 +479,19 @@ public function flatten() : void */ public function transpose() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]); + ], false); $b = $a->transpose(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [22, 4, 20], [-17, 11, -6], [12, -2, -9], - ]); + ], false); $this->assertEquals($expected, $b); } @@ -501,19 +501,19 @@ public function transpose() : void */ public function inverse() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]); + ], false); $b = $a->inverse(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [0.02093549603923048, 0.042436816295737464, 0.018483591097698978], [0.0007544322897019996, 0.08261033572236892, -0.017351942663145988], [0.04602036967182196, 0.03923047906450396, -0.05846850245190495], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -525,11 +525,11 @@ public function inverseNonSquareThrows() : void { $this->expectException(InvalidArgumentException::class); - Matrix::quick([ + Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], [5.0, 6.0], - ])->inverse(); + ], false)->inverse(); } /** @@ -540,12 +540,12 @@ public function inverseSingularThrows() : void // Exactly singular (column 3 = column 0 - column 1 + column 2); the // inverse must be rejected rather than return a magnitude ~1e15 matrix // that does not satisfy A * A^-1 = I. - $a = Matrix::quick([ + $a = Matrix::fromArray([ [2.0, 1.0, 0.0, 1.0], [1.0, 2.0, 1.0, 0.0], [0.0, 1.0, 2.0, 1.0], [1.0, 0.0, 1.0, 2.0], - ]); + ], false); $this->expectException(RuntimeException::class); @@ -557,11 +557,11 @@ public function inverseSingularThrows() : void */ public function det() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [4, 6, -12], [1, 3, 5], [-10, -1, 14], - ]); + ], false); $this->assertEqualsWithDelta(-544.0, $a->det(), self::MAX_DELTA); } @@ -573,12 +573,12 @@ public function detSingularIsZero() : void { // Exactly singular (column 3 = column 0 - column 1 + column 2); the // determinant must be ~0 rather than a spurious ~1e-15 value. - $a = Matrix::quick([ + $a = Matrix::fromArray([ [2.0, 1.0, 0.0, 1.0], [1.0, 2.0, 1.0, 0.0], [0.0, 1.0, 2.0, 1.0], [1.0, 0.0, 1.0, 2.0], - ]); + ], false); $this->assertEqualsWithDelta(0.0, $a->det(), self::MAX_DELTA); } @@ -588,11 +588,11 @@ public function detSingularIsZero() : void */ public function trace() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [4, 6, -12], [1, 3, 5], [-10, -1, 14], - ]); + ], false); $this->assertEquals(21.0, $a->trace()); } @@ -615,20 +615,20 @@ public function symmetric(Matrix $matrix, $expected) : void public function symmetricProvider() : Generator { yield [ - Matrix::quick([ + Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]), + ], false), false, ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [1, 5, 2], [5, 1, 3], [2, 3, 1], - ]), + ], false), true, ]; } @@ -638,30 +638,30 @@ public function symmetricProvider() : Generator */ public function rank() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $this->assertEquals(3, $a->rank()); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [1.0, 2.0, 3.0], [4.0, 5.0, 6.0], - ]); + ], false); $this->assertEquals(2, $b->rank()); // Exactly singular (column 3 = column 0 - column 1 + column 2); the // rank must be 3, not 4, even though floating point leaves a ~1e-16 // residual on the diagonal. - $c = Matrix::quick([ + $c = Matrix::fromArray([ [2.0, 1.0, 0.0, 1.0], [1.0, 2.0, 1.0, 0.0], [0.0, 1.0, 2.0, 1.0], [1.0, 0.0, 1.0, 2.0], - ]); + ], false); $this->assertEquals(3, $c->rank()); } @@ -671,28 +671,28 @@ public function rank() : void */ public function fullRank() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $this->assertTrue($a->fullRank()); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [1.0, 2.0, 3.0], [4.0, 5.0, 6.0], - ]); + ], false); $this->assertTrue($b->fullRank()); // Exactly singular 4x4 (see rank() above); fullRank() must be false. - $c = Matrix::quick([ + $c = Matrix::fromArray([ [2.0, 1.0, 0.0, 1.0], [1.0, 2.0, 1.0, 0.0], [0.0, 1.0, 2.0, 1.0], [1.0, 0.0, 1.0, 2.0], - ]); + ], false); $this->assertFalse($c->fullRank()); } @@ -702,19 +702,19 @@ public function fullRank() : void */ public function reciprocal() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->reciprocal(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [0.045454545454545456, -0.058823529411764705, 0.08333333333333333], [0.25, 0.09090909090909091, -0.5], [0.05, -0.16666666666666666, -0.1111111111111111], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -724,11 +724,11 @@ public function reciprocal() : void */ public function map() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $sign = function ($value) { return $value >= 0.0 ? 1 : -1; @@ -736,11 +736,11 @@ public function map() : void $b = $a->map($sign); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [1, -1, 1], [1, 1, -1], [1, -1, -1], - ]); + ], false); $this->assertEquals($expected, $b); } @@ -750,10 +750,10 @@ public function map() : void */ public function reduce() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], - ]); + ], false); $sum = function ($carry, $value) { return $carry + $value; @@ -770,7 +770,7 @@ public function reduce() : void $this->assertEqualsWithDelta(-8.0, $a->reduce($subtract, 2.0), self::MAX_DELTA); // Must match Vector::reduce() for the same data and callback. - $v = Vector::quick([1.0, 2.0, 3.0, 4.0]); + $v = Vector::fromArray([1.0, 2.0, 3.0, 4.0], false); $this->assertEqualsWithDelta($v->reduce($subtract), $a->reduce($subtract), self::MAX_DELTA); } @@ -780,19 +780,19 @@ public function reduce() : void */ public function ref() : void { - $matrix = Matrix::quick([ + $matrix = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $ref = $matrix->ref(); - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22, -17, 12], [0, 14.09090909090909, -4.181818181818182], [0, 0, -17.10322580645161], - ]); + ], false); $expected = new REF($a, 0); @@ -804,19 +804,19 @@ public function ref() : void */ public function rref() : void { - $matrix = Matrix::quick([ + $matrix = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $rref = $matrix->rref(); - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1, 0, 0], [0, 1, 0], [0, 0, 1], - ]); + ], false); $expected = new RREF($a); @@ -828,31 +828,31 @@ public function rref() : void */ public function lu() : void { - $matrix = Matrix::quick([ + $matrix = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $lu = $matrix->lu(); - $l = Matrix::quick([ + $l = Matrix::fromArray([ [1.0, 0, 0], [0.18181818181818182, 1.0, 0], [0.9090909090909091, 0.6709677419354838, 1.0], - ]); + ], false); - $u = Matrix::quick([ + $u = Matrix::fromArray([ [22, -17, 12], [0, 14.09090909090909, -4.181818181818182], [0, 0, -17.10322580645161], - ]); + ], false); - $p = Matrix::quick([ + $p = Matrix::fromArray([ [1, 0, 0], [0, 1, 0], [0, 0, 1], - ]); + ], false); $expected = new LU($l, $u, $p); @@ -864,12 +864,12 @@ public function lu() : void */ public function luMultiPivot() : void { - $matrix = Matrix::quick([ + $matrix = Matrix::fromArray([ [0.0, 1.0, 0.0, 0.0], [-1.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 2.0], [0.0, 0.0, 3.0, 1.0], - ]); + ], false); $lu = $matrix->lu(); @@ -884,12 +884,12 @@ public function luMultiPivot() : void */ public function luNegativePivot() : void { - $matrix = Matrix::quick([ + $matrix = Matrix::fromArray([ [1.0, 2.0, 3.0, 4.0], [-9.0, 1.0, 0.0, 0.0], [0.5, 0.5, 1.0, 1.0], [0.1, 0.2, 0.3, 0.4], - ]); + ], false); $lu = $matrix->lu(); @@ -906,12 +906,12 @@ public function luSingular() : void { $this->expectException(RuntimeException::class); - $matrix = Matrix::quick([ + $matrix = Matrix::fromArray([ [1.0, 2.0, 0.0, 0.0], [0.0, 1.0, 1.0, 0.0], [2.0, 4.0, 0.0, 1.0], [0.0, 1.0, 1.0, 0.0], - ]); + ], false); $matrix->lu(); } @@ -921,19 +921,19 @@ public function luSingular() : void */ public function cholesky() : void { - $matrix = Matrix::quick([ + $matrix = Matrix::fromArray([ [2, -1, 0], [-1, 2, -1], [0, -1, 2], - ]); + ], false); $cholesky = $matrix->cholesky(); - $l = Matrix::quick([ + $l = Matrix::fromArray([ [1.4142135623730951, 0, 0], [-0.7071067811865475, 1.224744871391589, 0], [0, -0.8164965809277261, 1.1547005383792515], - ]); + ], false); $expected = new Cholesky($l); @@ -945,23 +945,23 @@ public function cholesky() : void */ public function matmul() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [13], [11], [9], - ]); + ], false); $c = $a->matmul($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [207], [155], [113], - ]); + ], false); $this->assertEqualsWithDelta($expected, $c, self::MAX_DELTA); } @@ -971,17 +971,17 @@ public function matmul() : void */ public function dotVector() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); - $b = Vector::quick([2, 10, -1]); + $b = Vector::fromArray([2, 10, -1], false); $c = $a->dot($b); - $expected = ColumnVector::quick([-138, 120, -11]); + $expected = ColumnVector::fromArray([-138, 120, -11], false); $this->assertEqualsWithDelta($expected, $c, self::MAX_DELTA); } @@ -991,31 +991,31 @@ public function dotVector() : void */ public function convolve() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [3, 27, 66, 29, 42, 5], [5, 9, 15, 42, 45, 16], [1, 5, 10, 22, 66, 5], [0, 1, 4, 9, 10, 22, 2], [0, 0, 3, 19, 21, 25], [0, 0, 0, 5, 2, 33, 35], - ]); + ], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [0, 0, 1], [0, 1, 0], [1, 0, 0], - ]); + ], false); $c = $a->convolve($b, 1); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [3, 32, 75, 44, 84, 50], [32, 76, 49, 94, 72, 82], [10, 20, 53, 71, 91, 15], [5, 11, 26, 78, 34, 43], [1, 4, 12, 29, 48, 27], [0, 3, 19, 26, 27, 33], - ]); + ], false); $this->assertEqualsWithDelta($expected, $c, self::MAX_DELTA); } @@ -1041,63 +1041,63 @@ public function multiply(Matrix $a, $b, $expected) : void public function multiplyProvider() : Generator { yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [4, 6, -12], [1, 3, 5], [-10, -1, 14], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [88, -102, -144], [4, 33, -10], [-200, 6, -126], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Vector::quick([2, 10, -1]), - Matrix::quick([ + ], false), + Vector::fromArray([2, 10, -1], false), + Matrix::fromArray([ [44, -170, -12], [8, 110, 2], [40, -60, 9], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - ColumnVector::quick([2.5, -1, 4.8]), - Matrix::quick([ + ], false), + ColumnVector::fromArray([2.5, -1, 4.8], false), + Matrix::fromArray([ [55.0, -42.5, 30.], [-4, -11, 2], [96.0, -28.799999999999997, -43.199999999999996], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), + ], false), 2.5, - Matrix::quick([ + Matrix::fromArray([ [55, -42.5, 30], [10.0, 27.5, -5.], [50, -15, -22.5], - ]), + ], false), ]; } @@ -1122,63 +1122,63 @@ public function divide(Matrix $a, $b, $expected) : void public function divideProvider() : Generator { yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [4, 6, -12], [1, 3, 5], [-10, -1, 14], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [5.5, -2.8333333333333335, -1], [4, 3.6666666666666665, -0.4], [-2, 6, -0.6428571428571429], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Vector::quick([2, 10, -1]), - Matrix::quick([ + ], false), + Vector::fromArray([2, 10, -1], false), + Matrix::fromArray([ [11, -1.7, -12], [2, 1.1, 2], [10, -0.6, 9], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - ColumnVector::quick([2.5, -1, 4.8]), - Matrix::quick([ + ], false), + ColumnVector::fromArray([2.5, -1, 4.8], false), + Matrix::fromArray([ [8.8, -6.8, 4.8], [-4, -11, 2], [4.166666666666667, -1.25, -1.875], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), + ], false), 2.0, - Matrix::quick([ + Matrix::fromArray([ [11.0, -8.5, 6.], [2.0, 5.5, -1.], [10.0, -3.0, -4.5], - ]), + ], false), ]; } @@ -1203,63 +1203,63 @@ public function add(Matrix $a, $b, $expected) : void public function addProvider() : Generator { yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [4, 6, -12], [1, 3, 5], [-10, -1, 14], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [26, -11, 0], [5, 14, 3], [10, -7, 5], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Vector::quick([2, 10, -1]), - Matrix::quick([ + ], false), + Vector::fromArray([2, 10, -1], false), + Matrix::fromArray([ [24, -7, 11], [6, 21, -3], [22, 4, -10], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - ColumnVector::quick([2.5, -1, 4.8]), - Matrix::quick([ + ], false), + ColumnVector::fromArray([2.5, -1, 4.8], false), + Matrix::fromArray([ [24.5, -14.5, 14.5], [3, 10, -3], [24.8, -1.2000000000000002, -4.2], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), + ], false), 1.0, - Matrix::quick([ + Matrix::fromArray([ [23, -16, 13], [5, 12, -1], [21, -5, -8], - ]), + ], false), ]; } @@ -1284,63 +1284,63 @@ public function subtract(Matrix $a, $b, $expected) : void public function subtractProvider() : Generator { yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [4, 6, -12], [1, 3, 5], [-10, -1, 14], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [18, -23, 24], [3, 8, -7], [30, -5, -23], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Vector::quick([2, 10, -1]), - Matrix::quick([ + ], false), + Vector::fromArray([2, 10, -1], false), + Matrix::fromArray([ [20, -27, 13], [2, 1, -1], [18, -16, -8], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - ColumnVector::quick([2.5, -1, 4.8]), - Matrix::quick([ + ], false), + ColumnVector::fromArray([2.5, -1, 4.8], false), + Matrix::fromArray([ [19.5, -19.5, 9.5], [5, 12, -1], [15.2, -10.8, -13.8], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), + ], false), 10.0, - Matrix::quick([ + Matrix::fromArray([ [12, -27, 2], [-6, 1, -12], [10, -16, -19], - ]), + ], false), ]; } @@ -1365,49 +1365,49 @@ public function pow(Matrix $a, $b, $expected) : void public function powProvider() : Generator { yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [4, 6, -12], [1, 3, 5], [-10, -1, 14], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [234256, 24137569, 1.1215665478461509E-13], [4, 1331, -32], [9.765625E-14, -0.16666666666666666, 22876792454961], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Vector::quick([2, 10, -1]), - Matrix::quick([ + ], false), + Vector::fromArray([2, 10, -1], false), + Matrix::fromArray([ [484, 2015993900449, 0.08333333333333333], [16, 25937424601, -0.5], [400, 60466176, -0.1111111111111111], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), + ], false), 3.0, - Matrix::quick([ + Matrix::fromArray([ [10648, -4913, 1728], [64, 1331, -8], [8000, -216, -729], - ]), + ], false), ]; } @@ -1432,63 +1432,63 @@ public function mod(Matrix $a, $b, $expected) : void public function modProvider() : Generator { yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [4, 6, -12], [1, 3, 5], [-10, -1, 14], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [2, -5, 0], [0, 2, -2], [0, 0, -9], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Vector::quick([2, 10, -1]), - Matrix::quick([ + ], false), + Vector::fromArray([2, 10, -1], false), + Matrix::fromArray([ [0, -7, 0], [0, 1, 0], [0, -6, 0], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - ColumnVector::quick([2.5, -1, 4.8]), - Matrix::quick([ + ], false), + ColumnVector::fromArray([2.5, -1, 4.8], false), + Matrix::fromArray([ [0, -1, 0], [0, 0, 0], [0, -2, -1] - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), + ], false), 10.0, - Matrix::quick([ + Matrix::fromArray([ [2, -7, 2], [4, 1, -2], [0, -6, -9], - ]), + ], false), ]; } @@ -1513,63 +1513,63 @@ public function equal(Matrix $a, $b, $expected) : void public function equalProvider() : Generator { yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [4, 6, -12], [1, 3, 5], [-10, -1, 14], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [0, 0, 0], [0, 0, 0], [0, 0, 0], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Vector::quick([2, 10, -1]), - Matrix::quick([ + ], false), + Vector::fromArray([2, 10, -1], false), + Matrix::fromArray([ [0, 0, 0], [0, 0, 0], [0, 0, 0], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - ColumnVector::quick([2.5, -1, 4.8]), - Matrix::quick([ + ], false), + ColumnVector::fromArray([2.5, -1, 4.8], false), + Matrix::fromArray([ [0, 0, 0], [0, 0, 0], [0, 0, 0], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), + ], false), 4.0, - Matrix::quick([ + Matrix::fromArray([ [0, 0, 0], [1, 0, 0], [0, 0, 0], - ]), + ], false), ]; } @@ -1594,63 +1594,63 @@ public function notEqual(Matrix $a, $b, $expected) : void public function notEqualProvider() : Generator { yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [4, 6, -12], [1, 3, 5], [-10, -1, 14], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [1, 1, 1], [1, 1, 1], [1, 1, 1], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Vector::quick([2, 10, -1]), - Matrix::quick([ + ], false), + Vector::fromArray([2, 10, -1], false), + Matrix::fromArray([ [1, 1, 1], [1, 1, 1], [1, 1, 1], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - ColumnVector::quick([2.5, -1, 4.8]), - Matrix::quick([ + ], false), + ColumnVector::fromArray([2.5, -1, 4.8], false), + Matrix::fromArray([ [1, 1, 1], [1, 1, 1], [1, 1, 1], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), + ], false), 4.0, - Matrix::quick([ + Matrix::fromArray([ [1, 1, 1], [0, 1, 1], [1, 1, 1], - ]), + ], false), ]; } @@ -1675,63 +1675,63 @@ public function greater(Matrix $a, $b, $expected) : void public function greaterProvider() : Generator { yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [4, 6, -12], [1, 3, 5], [-10, -1, 14], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [1, 0, 1], [1, 1, 0], [1, 0, 0], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Vector::quick([2, 10, -1]), - Matrix::quick([ + ], false), + Vector::fromArray([2, 10, -1], false), + Matrix::fromArray([ [1, 0, 1], [1, 1, 0], [1, 0, 0], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - ColumnVector::quick([2.5, -1, 4.8]), - Matrix::quick([ + ], false), + ColumnVector::fromArray([2.5, -1, 4.8], false), + Matrix::fromArray([ [1, 0, 1], [1, 1, 0], [1, 0, 0], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), + ], false), 4.0, - Matrix::quick([ + Matrix::fromArray([ [1, 0, 1], [0, 1, 0], [1, 0, 0], - ]), + ], false), ]; } @@ -1756,63 +1756,63 @@ public function greaterEqual(Matrix $a, $b, $expected) : void public function greaterEqualProvider() : Generator { yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [4, 6, -12], [1, 3, 5], [-10, -1, 14], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [1, 0, 1], [1, 1, 0], [1, 0, 0], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Vector::quick([2, 10, -1]), - Matrix::quick([ + ], false), + Vector::fromArray([2, 10, -1], false), + Matrix::fromArray([ [1, 0, 1], [1, 1, 0], [1, 0, 0], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - ColumnVector::quick([2.5, -1, 4.8]), - Matrix::quick([ + ], false), + ColumnVector::fromArray([2.5, -1, 4.8], false), + Matrix::fromArray([ [1, 0, 1], [1, 1, 0], [1, 0, 0], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), + ], false), 4.0, - Matrix::quick([ + Matrix::fromArray([ [1, 0, 1], [1, 1, 0], [1, 0, 0], - ]), + ], false), ]; } @@ -1837,63 +1837,63 @@ public function less(Matrix $a, $b, $expected) : void public function lessProvider() : Generator { yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [4, 6, -12], [1, 3, 5], [-10, -1, 14], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [0, 1, 0], [0, 0, 1], [0, 1, 1], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Vector::quick([2, 10, -1]), - Matrix::quick([ + ], false), + Vector::fromArray([2, 10, -1], false), + Matrix::fromArray([ [0, 1, 0], [0, 0, 1], [0, 1, 1], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - ColumnVector::quick([2.5, -1, 4.8]), - Matrix::quick([ + ], false), + ColumnVector::fromArray([2.5, -1, 4.8], false), + Matrix::fromArray([ [0, 1, 0], [0, 0, 1], [0, 1, 1], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), + ], false), 10.0, - Matrix::quick([ + Matrix::fromArray([ [0, 1, 0], [1, 0, 1], [0, 1, 1], - ]), + ], false), ]; } @@ -1918,63 +1918,63 @@ public function lessEqual(Matrix $a, $b, $expected) : void public function lessEqualProvider() : Generator { yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [4, 6, -12], [1, 3, 5], [-10, -1, 14], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [0, 1, 0], [0, 0, 1], [0, 1, 1], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - Vector::quick([2, 10, -1]), - Matrix::quick([ + ], false), + Vector::fromArray([2, 10, -1], false), + Matrix::fromArray([ [0, 1, 0], [0, 0, 1], [0, 1, 1], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), - ColumnVector::quick([2.5, -1, 4.8]), - Matrix::quick([ + ], false), + ColumnVector::fromArray([2.5, -1, 4.8], false), + Matrix::fromArray([ [0, 1, 0], [0, 0, 1], [0, 1, 1], - ]), + ], false), ]; yield [ - Matrix::quick([ + Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]), + ], false), 10.0, - Matrix::quick([ + Matrix::fromArray([ [0, 1, 0], [1, 0, 1], [0, 1, 1], - ]), + ], false), ]; } @@ -1983,19 +1983,19 @@ public function lessEqualProvider() : Generator */ public function abs() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->abs(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [22, 17, 12], [4, 11, 2], [20, 6, 9], - ]); + ], false); $this->assertEquals($expected, $b); } @@ -2005,19 +2005,19 @@ public function abs() : void */ public function square() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->square(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [484, 289, 144], [16, 121, 4], [400, 36, 81], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2027,19 +2027,19 @@ public function square() : void */ public function sqrt() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [13], [11], [9], - ]); + ], false); $b = $a->sqrt(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [3.605551275463989], [3.3166247903554], [3], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2049,19 +2049,19 @@ public function sqrt() : void */ public function exp() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [13], [11], [9], - ]); + ], false); $b = $a->exp(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [442413.3920089205], [59874.14171519778], [8103.08392757538], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2071,19 +2071,19 @@ public function exp() : void */ public function expm1() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [13], [11], [9], - ]); + ], false); $b = $a->expm1(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [442412.3920089205], [59873.14171519782], [8102.083927575384], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2093,19 +2093,19 @@ public function expm1() : void */ public function log() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [13], [11], [9], - ]); + ], false); $b = $a->log(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [2.5649493574615367], [2.3978952727983707], [2.1972245773362196], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2115,19 +2115,19 @@ public function log() : void */ public function log1p() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [13], [11], [9], - ]); + ], false); $b = $a->log1p(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [2.6390573296152584], [2.4849066497880004], [2.302585092994046], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2137,19 +2137,19 @@ public function log1p() : void */ public function sin() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [13], [11], [9], - ]); + ], false); $b = $a->sin(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [0.4201670368266409], [-0.9999902065507035], [0.4121184852417566], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2159,19 +2159,19 @@ public function sin() : void */ public function asin() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [0.32], [-0.5], [0.01], - ]); + ], false); $b = $a->asin(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [0.3257294872946302], [-0.5235987755982989], [0.010000166674167114], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2181,19 +2181,19 @@ public function asin() : void */ public function cos() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [13], [11], [9], - ]); + ], false); $b = $a->cos(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [0.9074467814501962], [0.004425697988050785], [-0.9111302618846769], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2203,19 +2203,19 @@ public function cos() : void */ public function acos() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [0.32], [-0.5], [0.01], - ]); + ], false); $b = $a->acos(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [1.2450668395002664], [2.0943951023931957], [1.5607961601207294], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2225,19 +2225,19 @@ public function acos() : void */ public function tan() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [13], [11], [9], - ]); + ], false); $b = $a->tan(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [0.4630211329364896], [-225.95084645419513], [-0.45231565944180985], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2247,19 +2247,19 @@ public function tan() : void */ public function atan() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [13], [11], [9], - ]); + ], false); $b = $a->atan(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [1.4940244355251187], [1.4801364395941514], [1.460139105621001], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2269,19 +2269,19 @@ public function atan() : void */ public function rad2deg() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [13], [11], [9], - ]); + ], false); $b = $a->rad2deg(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [744.8451336700701], [630.2535746439056], [515.6620156177408], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2291,19 +2291,19 @@ public function rad2deg() : void */ public function deg2rad() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [13], [11], [9], - ]); + ], false); $b = $a->deg2rad(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [0.22689280275926282], [0.19198621771937624], [0.15707963267948966], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2313,15 +2313,15 @@ public function deg2rad() : void */ public function sum() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->sum(); - $expected = ColumnVector::quick([17, 13, 5]); + $expected = ColumnVector::fromArray([17, 13, 5], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2331,15 +2331,15 @@ public function sum() : void */ public function product() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->product(); - $expected = ColumnVector::quick([-4488.0, -88.0, 1080.0]); + $expected = ColumnVector::fromArray([-4488.0, -88.0, 1080.0], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2349,15 +2349,15 @@ public function product() : void */ public function min() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->min(); - $expected = ColumnVector::quick([-17, -2, -9]); + $expected = ColumnVector::fromArray([-17, -2, -9], false); $this->assertEquals($expected, $b); } @@ -2367,15 +2367,15 @@ public function min() : void */ public function max() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->max(); - $expected = ColumnVector::quick([22, 11, 20]); + $expected = ColumnVector::fromArray([22, 11, 20], false); $this->assertEquals($expected, $b); } @@ -2385,15 +2385,15 @@ public function max() : void */ public function mean() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->mean(); - $expected = ColumnVector::quick([5.666666666666667, 4.333333333333333, 1.6666666666666667]); + $expected = ColumnVector::fromArray([5.666666666666667, 4.333333333333333, 1.6666666666666667], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2403,15 +2403,15 @@ public function mean() : void */ public function median() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->median(); - $expected = ColumnVector::quick([12, 4, -6]); + $expected = ColumnVector::fromArray([12, 4, -6], false); $this->assertEquals($expected, $b); } @@ -2421,31 +2421,31 @@ public function median() : void */ public function quantile() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->quantile(0.4); - $expected = ColumnVector::quick([6.200000000000001, 2.8000000000000003, -6.6]); + $expected = ColumnVector::fromArray([6.200000000000001, 2.8000000000000003, -6.6], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); $max = $a->quantile(1.0); - $maxExpected = ColumnVector::quick([22.0, 11.0, 20.0]); + $maxExpected = ColumnVector::fromArray([22.0, 11.0, 20.0], false); $this->assertEqualsWithDelta($maxExpected, $max, self::MAX_DELTA); - $single = Matrix::quick([ + $single = Matrix::fromArray([ [5.0], [3.0], [8.0], - ]); + ], false); - $singleExpected = ColumnVector::quick([5.0, 3.0, 8.0]); + $singleExpected = ColumnVector::fromArray([5.0, 3.0, 8.0], false); $this->assertEqualsWithDelta( $singleExpected, @@ -2459,15 +2459,15 @@ public function quantile() : void */ public function variance() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->variance(); - $expected = ColumnVector::quick([273.55555555555554, 28.222222222222225, 169.55555555555554]); + $expected = ColumnVector::fromArray([273.55555555555554, 28.222222222222225, 169.55555555555554], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2477,14 +2477,14 @@ public function variance() : void */ public function varianceRowNonSquare() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 2.0, 3.0], [10.0, 20.0, 30.0], - ]); + ], false); $b = $a->variance(); - $expected = ColumnVector::quick([0.6666666666666666, 66.66666666666667]); + $expected = ColumnVector::fromArray([0.6666666666666666, 66.66666666666667], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2494,33 +2494,33 @@ public function varianceRowNonSquare() : void */ public function covariance() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->covariance(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [273.55555555555554, -65.55555555555556, 135.2222222222222], [-65.55555555555556, 28.222222222222225, 3.4444444444444406], [135.2222222222222, 3.4444444444444406, 169.55555555555554], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); - $c = Matrix::quick([ + $c = Matrix::fromArray([ [1.0, 2.0, 3.0], [4.0, 5.0, 6.0], - ]); + ], false); $d = $c->covariance(); - $expectedC = Matrix::quick([ + $expectedC = Matrix::fromArray([ [2.0 / 3.0, 2.0 / 3.0], [2.0 / 3.0, 2.0 / 3.0], - ]); + ], false); $this->assertEqualsWithDelta($expectedC, $d, self::MAX_DELTA); } @@ -2530,19 +2530,19 @@ public function covariance() : void */ public function round() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->round(2); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -2552,19 +2552,19 @@ public function round() : void */ public function floor() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->floor(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]); + ], false); $this->assertEquals($expected, $b); } @@ -2574,19 +2574,19 @@ public function floor() : void */ public function ceil() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->ceil(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]); + ], false); $this->assertEquals($expected, $b); } @@ -2596,17 +2596,17 @@ public function ceil() : void */ public function l1Norm() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $this->assertEqualsWithDelta(46.0, $a->l1Norm(), self::MAX_DELTA); } @@ -2616,11 +2616,11 @@ public function l1Norm() : void */ public function l2Norm() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $this->assertEqualsWithDelta(39.68626966596886, $a->l2Norm(), self::MAX_DELTA); } @@ -2630,11 +2630,11 @@ public function l2Norm() : void */ public function infinityNorm() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $this->assertEqualsWithDelta(51.0, $a->infinityNorm(), self::MAX_DELTA); } @@ -2644,11 +2644,11 @@ public function infinityNorm() : void */ public function maxNorm() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $this->assertEqualsWithDelta(22.0, $a->maxNorm(), self::MAX_DELTA); } @@ -2658,19 +2658,19 @@ public function maxNorm() : void */ public function clip() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->clip(0.0, INF); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [22, 0.0, 12], [4, 11, 0.], [20, 0.0, 0.], - ]); + ], false); $this->assertEquals($expected, $b); } @@ -2680,19 +2680,19 @@ public function clip() : void */ public function clipLower() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->clipLower(5.); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [22, 5.0, 12], [5.0, 11, 5.], [20, 5.0, 5.], - ]); + ], false); $this->assertEquals($expected, $b); } @@ -2702,19 +2702,19 @@ public function clipLower() : void */ public function clipUpper() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->clipUpper(16.0); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [16.0, -17.0, 12], [4, 11, -2.0], [16, -6.0, -9.0], - ]); + ], false); $this->assertEquals($expected, $b); } @@ -2724,19 +2724,19 @@ public function clipUpper() : void */ public function sign() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->sign(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [1, -1, 1], [1, 1, -1], [1, -1, -1], - ]); + ], false); $this->assertEquals($expected, $b); } @@ -2746,19 +2746,19 @@ public function sign() : void */ public function negate() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $b = $a->negate(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [-22, 17, -12], [-4, -11, 2], [-20, 6, 9], - ]); + ], false); $this->assertEquals($expected, $b); } @@ -2768,28 +2768,28 @@ public function negate() : void */ public function augmentAbove() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [4, 6, -12], [1, 3, 5], [-10, -1, 14], - ]); + ], false); $c = $a->augmentAbove($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [4, 6, -12], [1, 3, 5], [-10, -1, 14], [22, -17, 12], [4, 11, -2], [20, -6, -9], - ]); + ], false); $this->assertEquals($expected, $c); } @@ -2799,28 +2799,28 @@ public function augmentAbove() : void */ public function augmentBelow() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [4, 6, -12], [1, 3, 5], [-10, -1, 14], - ]); + ], false); $c = $a->augmentBelow($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], [20, -6, -9], [4, 6, -12], [1, 3, 5], [-10, -1, 14], - ]); + ], false); $this->assertEquals($expected, $c); } @@ -2830,25 +2830,25 @@ public function augmentBelow() : void */ public function augmentLeft() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [13], [11], [9], - ]); + ], false); $c = $a->augmentLeft($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [13, 22, -17, 12], [11, 4, 11, -2], [9, 20, -6, -9], - ]); + ], false); $this->assertEquals($expected, $c); } @@ -2858,25 +2858,25 @@ public function augmentLeft() : void */ public function augmentRight() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [13], [11], [9], - ]); + ], false); $c = $a->augmentRight($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [22, -17, 12, 13], [4, 11, -2, 11], [20, -6, -9, 9], - ]); + ], false); $this->assertEquals($expected, $c); } @@ -2886,22 +2886,22 @@ public function augmentRight() : void */ public function repeat() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [13], [11], [9], - ]); + ], false); $b = $a->repeat(1, 3); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [13, 13, 13, 13], [11, 11, 11, 11], [9, 9, 9, 9], [13, 13, 13, 13], [11, 11, 11, 11], [9, 9, 9, 9], - ]); + ], false); $this->assertEquals($expected, $b); } @@ -2943,10 +2943,10 @@ public function detNonSquareThrows() : void { $this->expectException(InvalidArgumentException::class); - Matrix::quick([ + Matrix::fromArray([ [1.0, 2.0, 3.0], [4.0, 5.0, 6.0], - ])->det(); + ], false)->det(); } /** @@ -2956,14 +2956,14 @@ public function matmulDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - Matrix::quick([ + Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], - ])->matmul(Matrix::quick([ + ], false)->matmul(Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], [5.0, 6.0], - ])); + ], false)); } /** @@ -2973,10 +2973,10 @@ public function dotDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - Matrix::quick([ + Matrix::fromArray([ [1.0, 2.0, 3.0], [4.0, 5.0, 6.0], - ])->dot(Vector::quick([1.0, 2.0])); + ], false)->dot(Vector::fromArray([1.0, 2.0], false)); } /** @@ -2986,11 +2986,11 @@ public function augmentAboveDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - Matrix::quick([ + Matrix::fromArray([ [1.0, 2.0], - ])->augmentAbove(Matrix::quick([ + ], false)->augmentAbove(Matrix::fromArray([ [1.0, 2.0, 3.0], - ])); + ], false)); } /** @@ -3000,11 +3000,11 @@ public function augmentBelowDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - Matrix::quick([ + Matrix::fromArray([ [1.0, 2.0], - ])->augmentBelow(Matrix::quick([ + ], false)->augmentBelow(Matrix::fromArray([ [1.0, 2.0, 3.0], - ])); + ], false)); } /** @@ -3014,13 +3014,13 @@ public function augmentLeftDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - Matrix::quick([ + Matrix::fromArray([ [1.0, 2.0], - ])->augmentLeft(Matrix::quick([ + ], false)->augmentLeft(Matrix::fromArray([ [1.0], [2.0], [3.0], - ])); + ], false)); } /** @@ -3030,13 +3030,13 @@ public function augmentRightDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - Matrix::quick([ + Matrix::fromArray([ [1.0, 2.0], - ])->augmentRight(Matrix::quick([ + ], false)->augmentRight(Matrix::fromArray([ [1.0], [2.0], [3.0], - ])); + ], false)); } /** @@ -3046,10 +3046,10 @@ public function offsetSetThrows() : void { $this->expectException(RuntimeException::class); - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], - ]); + ], false); $a[0] = 10.0; } @@ -3061,10 +3061,10 @@ public function offsetUnsetThrows() : void { $this->expectException(RuntimeException::class); - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], - ]); + ], false); unset($a[0][0]); } @@ -3076,10 +3076,10 @@ public function offsetGetOutOfBoundsThrows() : void { $this->expectException(InvalidArgumentException::class); - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], - ]); + ], false); $this->assertInstanceOf(Vector::class, $a[10]); } @@ -3091,10 +3091,10 @@ public function luNonSquareThrows() : void { $this->expectException(InvalidArgumentException::class); - Matrix::quick([ + Matrix::fromArray([ [1.0, 2.0, 3.0], [4.0, 5.0, 6.0], - ])->lu(); + ], false)->lu(); } /** @@ -3104,10 +3104,10 @@ public function choleskyNonSquareThrows() : void { $this->expectException(InvalidArgumentException::class); - Matrix::quick([ + Matrix::fromArray([ [1.0, 2.0, 3.0], [4.0, 5.0, 6.0], - ])->cholesky(); + ], false)->cholesky(); } /** @@ -3115,10 +3115,10 @@ public function choleskyNonSquareThrows() : void */ public function eigReturnsEigen() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], - ]); + ], false); $eig = $a->eig(false); @@ -3144,10 +3144,10 @@ public function eigReturnsEigen() : void */ public function eigSymmetricReturnsEigen() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [9.0, 3.0], [3.0, 5.0], - ]); + ], false); $eig = $a->eig(true); @@ -3165,10 +3165,10 @@ public function svdPurePHP() : void $this->markTestSkipped('Extension tensor is loaded.'); } - $matrix = Matrix::quick([ + $matrix = Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], - ]); + ], false); $svd = $matrix->svd(); @@ -3188,18 +3188,18 @@ public function pseudoinversePurePHP() : void $this->markTestSkipped('Extension tensor is loaded.'); } - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22, -17, 12], [4, 11, -2], - ]); + ], false); $b = $a->pseudoinverse(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [0.03147992432205172, 0.05583000490505223], [-0.009144418751313844, 0.07003713825239999], [0.01266554551187723, -0.0031357298016957483], - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -3209,16 +3209,86 @@ public function pseudoinversePurePHP() : void */ public function pseudoinversePreservesTinySingularValues() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 0.0], [0.0, 1e-9], - ]); + ], false); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [1.0, 0.0], [0.0, 1.0 / 1e-9], - ]); + ], false); $this->assertEqualsWithDelta($expected, $a->pseudoinverse(), self::MAX_DELTA); } + + /** + * @test + */ + public function fromArrayThrowsOnMismatchedRows() : void + { + $this->expectException(InvalidArgumentException::class); + + Matrix::fromArray([[1.0, 2.0], [3.0]]); + } + + /** + * @test + */ + public function asTensorBuffer() : void + { + $matrix = Matrix::fromArray([[1.0, 2.0], [3.0, 4.0]], false); + + $buffer = $matrix->asTensorBuffer(); + + $this->assertInstanceOf(\Tensor\TensorBuffer::class, $buffer); + $this->assertEquals([1.0, 2.0, 3.0, 4.0], $buffer->toArray()); + $this->assertSame(4, $buffer->count()); + $this->assertEquals(4.0, $buffer->get(3)); + $this->assertSame($buffer, $buffer->asBuffer()); + } + + /** + * @test + */ + public function serializeRoundTrip() : void + { + $matrix = Matrix::fromArray([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]); + + $unserialised = unserialize(serialize($matrix)); + + $this->assertInstanceOf(Matrix::class, $unserialised); + $this->assertEquals($matrix->asArray(), $unserialised->asArray()); + $this->assertEquals($matrix->shape(), $unserialised->shape()); + } + + /** + * @test + */ + public function serialisedShapeIsCompatibleWithTensorExt() : void + { + $matrix = Matrix::fromArray([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]); + + // Byte-compatible with the Tensor-Ext native serialisation: the rows + // are emitted under a named "data" key (with "m"/"n") rather than a + // nested "a" property. + $this->assertSame( + 'O:13:"Tensor\\Matrix":3:{s:4:"data";a:2:{i:0;a:3:{i:0;d:1;i:1;d:2;i:2;d:3;}i:1;a:3:{i:0;d:4;i:1;d:5;i:2;d:6;}}s:1:"m";i:2;s:1:"n";i:3;}', + serialize($matrix) + ); + } + + /** + * @test + */ + public function unserializeFromExtPayload() : void + { + // A payload produced identically by the Tensor-Ext polyfill. + $payload = 'O:13:"Tensor\\Matrix":3:{s:4:"data";a:2:{i:0;a:3:{i:0;d:1;i:1;d:2;i:2;d:3;}i:1;a:3:{i:0;d:4;i:1;d:5;i:2;d:6;}}s:1:"m";i:2;s:1:"n";i:3;}'; + + $matrix = unserialize($payload); + + $this->assertEquals([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], $matrix->asArray()); + $this->assertEquals([2, 3], $matrix->shape()); + } } diff --git a/tests/Reductions/REFTest.php b/tests/Reductions/REFTest.php index 2204cca..4bdb249 100644 --- a/tests/Reductions/REFTest.php +++ b/tests/Reductions/REFTest.php @@ -25,19 +25,19 @@ class REFTest extends TestCase */ public function reduce2x2() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], - ]); + ], false); $ref = REF::reduce($a); // Partial pivoting selects the largest magnitude in each column, so the // rows are swapped to bring 3 (col 0) to the top and 4 (col 1) to the right. - $expectedA = Matrix::quick([ + $expectedA = Matrix::fromArray([ [3.0, 4.0], [0.0, 2.0 / 3.0], - ]); + ], false); $this->assertEquals(1, $ref->swaps()); $this->assertEqualsWithDelta($expectedA, $ref->a(), self::MAX_DELTA); @@ -48,19 +48,19 @@ public function reduce2x2() : void */ public function reduce3x3() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [22.0, -17.0, 12.0], [4.0, 11.0, -2.0], [20.0, -6.0, -9.0], - ]); + ], false); $ref = REF::reduce($a); - $expectedA = Matrix::quick([ + $expectedA = Matrix::fromArray([ [22.0, -17.0, 12.0], [0.0, 14.09090909090909, -4.181818181818182], [0.0, 0.0, -17.10322580645161], - ]); + ], false); $this->assertEqualsWithDelta($expectedA, $ref->a(), self::MAX_DELTA); } @@ -70,18 +70,18 @@ public function reduce3x3() : void */ public function reduce2x3Rectangular() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 2.0, 3.0], [4.0, 5.0, 6.0], - ]); + ], false); $ref = REF::reduce($a); // Partial pivoting brings 4 to the top of column 0. - $expectedA = Matrix::quick([ + $expectedA = Matrix::fromArray([ [4.0, 5.0, 6.0], [0.0, 0.75, 1.5], - ]); + ], false); $this->assertEquals(1, $ref->swaps()); $this->assertEqualsWithDelta($expectedA, $ref->a(), self::MAX_DELTA); @@ -93,10 +93,10 @@ public function reduce2x3Rectangular() : void public function reduceRequiresPivoting() : void { // First column is [0, 5] - a row swap is required to pivot. - $a = Matrix::quick([ + $a = Matrix::fromArray([ [0.0, 1.0], [5.0, 2.0], - ]); + ], false); $ref = REF::reduce($a); @@ -104,10 +104,10 @@ public function reduceRequiresPivoting() : void // should be used as the pivot, and the first row below it zeroed. $this->assertGreaterThanOrEqual(1, $ref->swaps()); - $expectedA = Matrix::quick([ + $expectedA = Matrix::fromArray([ [5.0, 2.0], [0.0, 1.0], - ]); + ], false); $this->assertEqualsWithDelta($expectedA, $ref->a(), self::MAX_DELTA); } @@ -117,11 +117,11 @@ public function reduceRequiresPivoting() : void */ public function reduce1x1() : void { - $a = Matrix::quick([[7.0]]); + $a = Matrix::fromArray([[7.0]], false); $ref = REF::reduce($a); - $expectedA = Matrix::quick([[7.0]]); + $expectedA = Matrix::fromArray([[7.0]], false); $this->assertEquals(0, $ref->swaps()); $this->assertEqualsWithDelta($expectedA, $ref->a(), self::MAX_DELTA); @@ -132,18 +132,18 @@ public function reduce1x1() : void */ public function reduceDiagonal() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [2.0, 0.0], [0.0, 3.0], - ]); + ], false); $ref = REF::reduce($a); // Diagonal is already in row echelon form. - $expectedA = Matrix::quick([ + $expectedA = Matrix::fromArray([ [2.0, 0.0], [0.0, 3.0], - ]); + ], false); $this->assertEquals(0, $ref->swaps()); $this->assertEqualsWithDelta($expectedA, $ref->a(), self::MAX_DELTA); @@ -155,10 +155,10 @@ public function reduceDiagonal() : void public function reduceZeroRow() : void { // One zero row at the top, non-zero row at the bottom. - $a = Matrix::quick([ + $a = Matrix::fromArray([ [0.0, 0.0], [1.0, 2.0], - ]); + ], false); $ref = REF::reduce($a); @@ -178,17 +178,17 @@ public function reduceSingularKeepsPivotScale() : void // A rank-1 matrix is singular: Gaussian elimination must fail and the // row reduction fallback must produce the same (non-normalised) REF // convention as Gaussian elimination - the pivot keeps its value. - $a = Matrix::quick([ + $a = Matrix::fromArray([ [2.0, 4.0], [1.0, 2.0], - ]); + ], false); $ref = REF::reduce($a); - $expectedA = Matrix::quick([ + $expectedA = Matrix::fromArray([ [2.0, 4.0], [0.0, 0.0], - ]); + ], false); $this->assertEqualsWithDelta($expectedA, $ref->a(), self::MAX_DELTA); } @@ -200,7 +200,7 @@ public function constructorWithNegativeSwapsThrows() : void { $this->expectException(InvalidArgumentException::class); - new REF(Matrix::quick([[1.0]]), -1); + new REF(Matrix::fromArray([[1.0]], false), -1); } /** @@ -208,7 +208,7 @@ public function constructorWithNegativeSwapsThrows() : void */ public function constructorWithZeroSwaps() : void { - $a = Matrix::quick([[1.0]]); + $a = Matrix::fromArray([[1.0]], false); $ref = new REF($a, 0); @@ -221,10 +221,10 @@ public function constructorWithZeroSwaps() : void */ public function constructorWithPositiveSwaps() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 0.0], [0.0, 1.0], - ]); + ], false); $ref = new REF($a, 2); @@ -248,12 +248,12 @@ public function reduceExactlySingular4x4GaussianThrowsSingularMatrix() : void // pure-PHP gaussian elimination path must detect the tiny residual // (a ~1e-16 diagonal entry) as singular and route through the row // reduction fallback. - $a = Matrix::quick([ + $a = Matrix::fromArray([ [2.0, 1.0, 0.0, 1.0], [1.0, 2.0, 1.0, 0.0], [0.0, 1.0, 2.0, 1.0], [1.0, 0.0, 1.0, 2.0], - ]); + ], false); $this->expectException(SingularMatrix::class); diff --git a/tests/Reductions/RREFTest.php b/tests/Reductions/RREFTest.php index 0aec1da..c57caae 100644 --- a/tests/Reductions/RREFTest.php +++ b/tests/Reductions/RREFTest.php @@ -24,19 +24,19 @@ class RREFTest extends TestCase public function reduceDiagonalIsIdentity() : void { // A non-singular diagonal matrix reduces to the identity. - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 3.0], - ]); + ], false); $rref = RREF::reduce($a); - $expectedA = Matrix::quick([ + $expectedA = Matrix::fromArray([ [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0], - ]); + ], false); $this->assertEqualsWithDelta($expectedA, $rref->a(), self::MAX_DELTA); } @@ -46,17 +46,17 @@ public function reduceDiagonalIsIdentity() : void */ public function reduce2x2() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], - ]); + ], false); $rref = RREF::reduce($a); - $expectedA = Matrix::quick([ + $expectedA = Matrix::fromArray([ [1.0, 0.0], [0.0, 1.0], - ]); + ], false); $this->assertEqualsWithDelta($expectedA, $rref->a(), self::MAX_DELTA); } @@ -66,17 +66,17 @@ public function reduce2x2() : void */ public function reduceDiagonal2x2() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [2.0, 0.0], [0.0, 3.0], - ]); + ], false); $rref = RREF::reduce($a); - $expectedA = Matrix::quick([ + $expectedA = Matrix::fromArray([ [1.0, 0.0], [0.0, 1.0], - ]); + ], false); $this->assertEqualsWithDelta($expectedA, $rref->a(), self::MAX_DELTA); } @@ -86,11 +86,11 @@ public function reduceDiagonal2x2() : void */ public function reduce1x1() : void { - $a = Matrix::quick([[7.0]]); + $a = Matrix::fromArray([[7.0]], false); $rref = RREF::reduce($a); - $this->assertEqualsWithDelta(Matrix::quick([[1.0]]), $rref->a(), self::MAX_DELTA); + $this->assertEqualsWithDelta(Matrix::fromArray([[1.0]], false), $rref->a(), self::MAX_DELTA); } /** @@ -99,17 +99,17 @@ public function reduce1x1() : void public function reduceSingular2x2() : void { // A rank-1 matrix has a zero row and one free variable. - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 2.0], [2.0, 4.0], - ]); + ], false); $rref = RREF::reduce($a); - $expectedA = Matrix::quick([ + $expectedA = Matrix::fromArray([ [1.0, 2.0], [0.0, 0.0], - ]); + ], false); $this->assertEqualsWithDelta($expectedA, $rref->a(), self::MAX_DELTA); @@ -124,17 +124,17 @@ public function reduceSingular2x2() : void public function reduceZeroRow() : void { // A leading zero row is swapped down; the result has a zero row. - $a = Matrix::quick([ + $a = Matrix::fromArray([ [0.0, 0.0], [1.0, 2.0], - ]); + ], false); $rref = RREF::reduce($a); - $expectedA = Matrix::quick([ + $expectedA = Matrix::fromArray([ [1.0, 2.0], [0.0, 0.0], - ]); + ], false); $this->assertEqualsWithDelta($expectedA, $rref->a(), self::MAX_DELTA); } @@ -144,11 +144,11 @@ public function reduceZeroRow() : void */ public function rankMatchesNumberNonZeroRows() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 2.0, 3.0], [2.0, 4.0, 6.0], [4.0, 8.0, 12.0], - ]); + ], false); $rref = RREF::reduce($a); @@ -185,12 +185,12 @@ public function reduceExactlySingular4x4Has3NonZeroRows() : void // RREF must contain exactly three non-zero rows, the fourth being zero. // Before the float-tolerance fix, floating-point residual of ~1e-16 // on the diagonal would cause RREF to report a fourth non-zero row. - $a = Matrix::quick([ + $a = Matrix::fromArray([ [2.0, 1.0, 0.0, 1.0], [1.0, 2.0, 1.0, 0.0], [0.0, 1.0, 2.0, 1.0], [1.0, 0.0, 1.0, 2.0], - ]); + ], false); $rref = RREF::reduce($a); @@ -222,11 +222,11 @@ public function reduceExactlySingular4x4Has3NonZeroRows() : void */ public function accessorsReturnMatrices() : void { - $a = Matrix::quick([ + $a = Matrix::fromArray([ [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0], - ]); + ], false); $rref = new RREF($a); diff --git a/tests/VectorTest.php b/tests/VectorTest.php index 0d7ddd1..8d8fc0d 100644 --- a/tests/VectorTest.php +++ b/tests/VectorTest.php @@ -34,9 +34,9 @@ class VectorTest extends TestCase /** * @test */ - public function build() : void + public function fromArray() : void { - $vector = Vector::build([1, 2, 3, 4, 5]); + $vector = Vector::fromArray([1, 2, 3, 4, 5]); $this->assertInstanceOf(Vector::class, $vector); $this->assertInstanceOf(Tensor::class, $vector); @@ -52,9 +52,9 @@ public function build() : void /** * @test */ - public function buildCastsIntegersToFloats() : void + public function fromArrayCastsIntegersToFloats() : void { - $vector = Vector::build([1, 2, 3, 4, 5]); + $vector = Vector::fromArray([1, 2, 3, 4, 5]); $this->assertSame(5, $vector->size()); @@ -76,7 +76,7 @@ public function zeros() : void { $zeros = Vector::zeros(4); - $expected = Vector::quick([0, 0, 0, 0]); + $expected = Vector::fromArray([0, 0, 0, 0], false); $this->assertEquals($expected, $zeros); } @@ -88,7 +88,7 @@ public function ones() : void { $ones = Vector::ones(4); - $expected = Vector::quick([1, 1, 1, 1]); + $expected = Vector::fromArray([1, 1, 1, 1], false); $this->assertEquals($expected, $ones); } @@ -100,7 +100,7 @@ public function fill() : void { $vector = Vector::fill(16, 4); - $expected = Vector::quick([16, 16, 16, 16]); + $expected = Vector::fromArray([16, 16, 16, 16], false); $this->assertEquals($expected, $vector); } @@ -280,7 +280,7 @@ public function range() : void { $vector = Vector::range(5.0, 12.0, 2.0); - $expected = Vector::quick([5.0, 7.0, 9.0, 11.0]); + $expected = Vector::fromArray([5.0, 7.0, 9.0, 11.0], false); $this->assertEquals($expected, $vector); } @@ -292,10 +292,10 @@ public function linspace() : void { $vector = Vector::linspace(-5.0, 5.0, 10); - $expected = Vector::quick([ + $expected = Vector::fromArray([ -5.0, -3.888888888888889, -2.7777777777777777, -1.6666666666666665, -0.5555555555555554, 0.5555555555555558, 1.666666666666667, 2.777777777777778, 3.8888888888888893, 5.0, - ]); + ], false); $this->assertEquals($expected, $vector); } @@ -317,11 +317,11 @@ public function shape(Vector $vector, array $expected) : void */ public function shapeProvider() : Generator { - yield [Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), [8]]; + yield [Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), [8]]; - yield [Vector::quick([0.25]), [1]]; + yield [Vector::fromArray([0.25], false), [1]]; - yield [Vector::quick([]), [0]]; + yield [Vector::fromArray([], false), [0]]; } /** @@ -329,7 +329,7 @@ public function shapeProvider() : Generator */ public function shapeString() : void { - $vector = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $vector = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $this->assertEquals('8', $vector->shapeString()); } @@ -339,7 +339,7 @@ public function shapeString() : void */ public function size() : void { - $vector = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $vector = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $this->assertEquals(8, $vector->size()); } @@ -349,7 +349,7 @@ public function size() : void */ public function m() : void { - $vector = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $vector = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $this->assertEquals(1, $vector->m()); } @@ -359,7 +359,7 @@ public function m() : void */ public function n() : void { - $vector = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $vector = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $this->assertEquals(8, $vector->n()); } @@ -369,7 +369,7 @@ public function n() : void */ public function asArray() : void { - $vector = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $vector = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $expected = [-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]; @@ -381,13 +381,13 @@ public function asArray() : void */ public function asRowMatrix() : void { - $vector = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $vector = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $matrix = $vector->asRowMatrix(); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], - ]); + ], false); $this->assertEquals($expected, $matrix); } @@ -397,11 +397,11 @@ public function asRowMatrix() : void */ public function asColumnMatrix() : void { - $vector = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $vector = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $matrix = $vector->asColumnMatrix(); - $expected = Matrix::quick([[-15.0], [25.0], [35.0], [-36.0], [-72.0], [89.0], [106.0], [45.0]]); + $expected = Matrix::fromArray([[-15.0], [25.0], [35.0], [-36.0], [-72.0], [89.0], [106.0], [45.0]], false); $this->assertEquals($expected, $matrix); } @@ -411,16 +411,16 @@ public function asColumnMatrix() : void */ public function reshape() : void { - $vector = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $vector = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $matrix = $vector->reshape(4, 2); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [-15.0, 25.0], [35.0, -36.0], [-72.0, 89.0], [106.0, 45.0], - ]); + ], false); $this->assertEquals($expected, $matrix); } @@ -430,11 +430,11 @@ public function reshape() : void */ public function transpose() : void { - $vector = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $vector = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $vector = $vector->transpose(); - $expected = ColumnVector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $expected = ColumnVector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $this->assertEquals($expected, $vector); } @@ -444,7 +444,7 @@ public function transpose() : void */ public function map() : void { - $vector = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $vector = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $sign = function ($value) { return $value >= 0.0 ? 1 : 0; @@ -452,7 +452,7 @@ public function map() : void $vector = $vector->map($sign); - $expected = Vector::quick([0, 1, 1, 0, 0, 1, 1, 1]); + $expected = Vector::fromArray([0, 1, 1, 0, 0, 1, 1, 1], false); $this->assertEquals($expected, $vector); } @@ -462,7 +462,7 @@ public function map() : void */ public function reduce() : void { - $vector = Vector::quick([1.0, 2.0, 3.0]); + $vector = Vector::fromArray([1.0, 2.0, 3.0], false); $sum = function ($carry, $value) { return $carry + $value; @@ -479,7 +479,7 @@ public function reduce() : void $this->assertEqualsWithDelta(-4.0, $vector->reduce($subtract, 2.0), self::MAX_DELTA); // Must match Matrix::reduce() for the same data and callback. - $matrix = Matrix::quick([[1.0, 2.0, 3.0]]); + $matrix = Matrix::fromArray([[1.0, 2.0, 3.0]], false); $this->assertEqualsWithDelta($vector->reduce($subtract), $matrix->reduce($subtract), self::MAX_DELTA); } @@ -489,14 +489,14 @@ public function reduce() : void */ public function reciprocal() : void { - $vector = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $vector = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $vector = $vector->reciprocal(); - $expected = Vector::quick([ + $expected = Vector::fromArray([ -0.06666666666666667, 0.04, 0.02857142857142857, -0.027777777777777776, -0.013888888888888888, 0.011235955056179775, 0.009433962264150943, 0.022222222222222223, - ]); + ], false); $this->assertEqualsWithDelta($expected, $vector, self::MAX_DELTA); } @@ -506,9 +506,9 @@ public function reciprocal() : void */ public function dot() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); - $b = Vector::quick([0.25, 0.1, 2.0, -0.5, -1.0, -3.0, 3.3, 2.0]); + $b = Vector::fromArray([0.25, 0.1, 2.0, -0.5, -1.0, -3.0, 3.3, 2.0], false); $c = $a->dot($b); @@ -517,22 +517,22 @@ public function dot() : void public function matmul() : void { - $a = Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]); + $a = Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [1.1, 0.01, 6.23], [5.0, 2.01, -1.0], [-5.0, 1.0, 0.03], [30.0, 0.02, -0.01], [-0.005, 0.05, -0.5], [-0.001, -1.0, 2.0], - ]); + ], false); $c = $a->matmul($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [622.3751, 4.634999999999993, 40.807], - ]); + ], false); $this->assertEqualsWithDelta($expected, $c, self::MAX_DELTA); } @@ -542,9 +542,9 @@ public function matmul() : void */ public function inner() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); - $b = Vector::quick([0.25, 0.1, 2.0, -0.5, -1.0, -3.0, 3.3, 2.0]); + $b = Vector::fromArray([0.25, 0.1, 2.0, -0.5, -1.0, -3.0, 3.3, 2.0], false); $c = $a->inner($b); @@ -556,13 +556,13 @@ public function inner() : void */ public function outer() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); - $b = Vector::quick([0.25, 0.1, 2.0, -0.5, -1.0, -3.0, 3.3, 2.0]); + $b = Vector::fromArray([0.25, 0.1, 2.0, -0.5, -1.0, -3.0, 3.3, 2.0], false); $c = $a->outer($b); - $expected = Matrix::quick([ + $expected = Matrix::fromArray([ [-3.75, -1.5, -30.0, 7.5, 15.0, 45.0, -49.5, -30.], [6.25, 2.5, 50.0, -12.5, -25.0, -75.0, 82.5, 50.], [8.75, 3.5, 70.0, -17.5, -35.0, -105.0, 115.5, 70.], @@ -571,7 +571,7 @@ public function outer() : void [22.25, 8.9, 178.0, -44.5, -89.0, -267.0, 293.7, 178.], [26.5, 10.600000000000001, 212.0, -53.0, -106.0, -318.0, 349.79999999999995, 212.], [11.25, 4.5, 90.0, -22.5, -45.0, -135.0, 148.5, 90.], - ]); + ], false); $this->assertEqualsWithDelta($expected, $c, self::MAX_DELTA); } @@ -581,16 +581,16 @@ public function outer() : void */ public function convolve() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); - $b = Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]); + $b = Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false); $c = $a->convolve($b, 1); - $expected = Vector::quick([ + $expected = Vector::fromArray([ -60.0, 2.5, 259.0, -144.0, 40.5, 370.1, 462.20000000000005, 10.000000000000114, 1764.3000000000002, 1625.1, 2234.7, 1378.4, 535.5, - ]); + ], false); $this->assertEqualsWithDelta($expected, $c, self::MAX_DELTA); } @@ -616,29 +616,29 @@ public function multiply(Vector $a, $b, $expected) : void public function multiplyProvider() : Generator { yield [ - Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]), - Matrix::quick([ + Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false), + Matrix::fromArray([ [6.23, -1.0, 0.03, -0.01, -0.5, 2.0], [0.01, 2.01, 1.0, 0.02, 0.05, -1.0], [1.1, 5.0, -5.0, 30, -0.005, -0.001], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [24.92, -6.5, 0.087, -0.2, -1.3, 23.8], [0.04, 13.064999999999998, 2.9, 0.4, 0.13, -11.9], [4.4, 32.5, -14.5, 600.0, -0.013000000000000001, -0.0119], - ]), + ], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), - Vector::quick([0.25, 0.1, 2.0, -0.5, -1.0, -3.0, 3.3, 2.0]), - Vector::quick([-3.75, 2.5, 70.0, 18.0, 72.0, -267.0, 349.79999999999995, 90.0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), + Vector::fromArray([0.25, 0.1, 2.0, -0.5, -1.0, -3.0, 3.3, 2.0], false), + Vector::fromArray([-3.75, 2.5, 70.0, 18.0, 72.0, -267.0, 349.79999999999995, 90.0], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), 2.0, - Vector::quick([-30.0, 50.0, 70.0, -72.0, -144.0, 178.0, 212.0, 90.0]), + Vector::fromArray([-30.0, 50.0, 70.0, -72.0, -144.0, 178.0, 212.0, 90.0], false), ]; } @@ -663,29 +663,29 @@ public function divide(Vector $a, $b, $expected) : void public function divideProvider() : Generator { yield [ - Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]), - Matrix::quick([ + Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false), + Matrix::fromArray([ [6.23, -1.0, 0.03, -0.01, -0.5, 2.0], [0.01, 2.01, 1.0, 0.02, 0.05, -1.0], [1.1, 5.0, -5.0, 30, -0.005, -0.001], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [0.6420545746388443, -6.5, 96.66666666666667, -2000.0, -5.2, 5.95], [400.0, 3.2338308457711444, 2.9, 1000.0, 52.0, -11.9], [3.6363636363636362, 1.3, -0.58, 0.6666666666666666, -520.0, -11900.], - ]), + ], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), - Vector::quick([0.25, 0.1, 2.0, -0.5, -1.0, -3.0, 3.3, 2.0]), - Vector::quick([-60.0, 250.0, 17.5, 72.0, 72.0, -29.666666666666668, 32.121212121212125, 22.5]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), + Vector::fromArray([0.25, 0.1, 2.0, -0.5, -1.0, -3.0, 3.3, 2.0], false), + Vector::fromArray([-60.0, 250.0, 17.5, 72.0, 72.0, -29.666666666666668, 32.121212121212125, 22.5], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), 2.0, - Vector::quick([-7.5, 12.5, 17.5, -18.0, -36.0, 44.5, 53, 22.5]), + Vector::fromArray([-7.5, 12.5, 17.5, -18.0, -36.0, 44.5, 53, 22.5], false), ]; } @@ -710,29 +710,29 @@ public function add(Vector $a, $b, $expected) : void public function addProvider() : Generator { yield [ - Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]), - Matrix::quick([ + Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false), + Matrix::fromArray([ [6.23, -1.0, 0.03, -0.01, -0.5, 2.0], [0.01, 2.01, 1.0, 0.02, 0.05, -1.0], [1.1, 5.0, -5.0, 30, -0.005, -0.001], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [10.23, 5.5, 2.9299999999999997, 19.99, 2.1, 13.9], [4.01, 8.51, 3.9, 20.02, 2.65, 10.9], [5.1, 11.5, -2.1, 50.0, 2.595, 11.899000000000001], - ]), + ], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), - Vector::quick([0.25, 0.1, 2.0, -0.5, -1.0, -3.0, 3.3, 2.0]), - Vector::quick([-14.75, 25.1, 37.0, -36.5, -73.0, 86.0, 109.3, 47.0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), + Vector::fromArray([0.25, 0.1, 2.0, -0.5, -1.0, -3.0, 3.3, 2.0], false), + Vector::fromArray([-14.75, 25.1, 37.0, -36.5, -73.0, 86.0, 109.3, 47.0], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), 10.0, - Vector::quick([-5.0, 35.0, 45.0, -26.0, -62.0, 99.0, 116.0, 55.0]), + Vector::fromArray([-5.0, 35.0, 45.0, -26.0, -62.0, 99.0, 116.0, 55.0], false), ]; } @@ -757,29 +757,29 @@ public function subtract(Vector $a, $b, $expected) : void public function subtractProvider() : Generator { yield [ - Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]), - Matrix::quick([ + Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false), + Matrix::fromArray([ [6.23, -1.0, 0.03, -0.01, -0.5, 2.0], [0.01, 2.01, 1.0, 0.02, 0.05, -1.0], [1.1, 5.0, -5.0, 30, -0.005, -0.001], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [-2.2300000000000004, 7.5, 2.87, 20.01, 3.1, 9.9], [3.99, 4.49, 1.9, 19.98, 2.5500000000000003, 12.9], [2.9, 1.5, 7.9, -10.0, 2.605, 11.901], - ]), + ], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), - Vector::quick([0.25, 0.1, 2.0, -0.5, -1.0, -3.0, 3.3, 2.0]), - Vector::quick([-15.25, 24.9, 33.0, -35.5, -71.0, 92.0, 102.7, 43.0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), + Vector::fromArray([0.25, 0.1, 2.0, -0.5, -1.0, -3.0, 3.3, 2.0], false), + Vector::fromArray([-15.25, 24.9, 33.0, -35.5, -71.0, 92.0, 102.7, 43.0], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), 10.0, - Vector::quick([-25.0, 15.0, 25.0, -46.0, -82.0, 79.0, 96.0, 35.0]), + Vector::fromArray([-25.0, 15.0, 25.0, -46.0, -82.0, 79.0, 96.0, 35.0], false), ]; } @@ -804,31 +804,31 @@ public function power(Vector $a, $b, $expected) : void public function powProvider() : Generator { yield [ - Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]), - Matrix::quick([ + Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false), + Matrix::fromArray([ [6.23, -1.0, 0.03, -0.01, -0.5, 2.0], [0.01, 2.01, 1.0, 0.02, 0.05, -1.0], [1.1, 5.0, -5.0, 30, -0.005, -0.001], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [5634.219287100394, 0.15384615384615385, 1.0324569211337775, 0.9704869503929601, 0.6201736729460423, 141.61], [1.013959479790029, 43.048284263459465, 2.9, 1.0617459178549786, 1.0489352187366092, 0.08403361344537814], [4.59479341998814, 11602.90625, 0.004875397277841432, 1.073741824E+39, 0.9952338371484033, 0.9975265256911376], - ]), + ], false), ]; yield [ - Vector::quick([3.0, 6.0, 9.0]), - Vector::quick([3.0, 2.0, 1.0]), - Vector::quick([27.0, 36.0, 9.0]), + Vector::fromArray([3.0, 6.0, 9.0], false), + Vector::fromArray([3.0, 2.0, 1.0], false), + Vector::fromArray([27.0, 36.0, 9.0], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), 4.0, - Vector::quick([ + Vector::fromArray([ 50625, 390625, 1500625, 1679616, 26873856, 62742241, 126247696, 4100625 - ]), + ], false), ]; } @@ -853,29 +853,29 @@ public function equal(Vector $a, $b, $expected) : void public function equalProvider() : Generator { yield [ - Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]), - Matrix::quick([ + Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false), + Matrix::fromArray([ [4.0, -1.0, 0.03, -0.01, -0.5, 2.0], [0.01, 2.01, 1.0, 20.0, 0.05, -1.0], [1.1, 5.0, -5.0, 30, -0.005, 11.9], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1], - ]), + ], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), - Vector::quick([0.25, 0.1, 2.0, -36.0, -1.0, -3.0, 3.3, 2.0]), - Vector::quick([0, 0, 0, 1, 0, 0, 0, 0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), + Vector::fromArray([0.25, 0.1, 2.0, -36.0, -1.0, -3.0, 3.3, 2.0], false), + Vector::fromArray([0, 0, 0, 1, 0, 0, 0, 0], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), 25.0, - Vector::quick([0, 1, 0, 0, 0, 0, 0, 0]), + Vector::fromArray([0, 1, 0, 0, 0, 0, 0, 0], false), ]; } @@ -900,29 +900,29 @@ public function notEqual(Vector $a, $b, $expected) : void public function notEqualProvider() : Generator { yield [ - Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]), - Matrix::quick([ + Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false), + Matrix::fromArray([ [4.0, -1.0, 0.03, -0.01, -0.5, 2.0], [0.01, 2.01, 1.0, 20.0, 0.05, -1.0], [1.1, 5.0, -5.0, 30, -0.005, 11.9], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [0, 1, 1, 1, 1, 1], [1, 1, 1, 0, 1, 1], [1, 1, 1, 1, 1, 0], - ]), + ], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), - Vector::quick([0.25, 0.1, 2.0, -36.0, -1.0, -3.0, 3.3, 2.0]), - Vector::quick([1, 1, 1, 0, 1, 1, 1, 1]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), + Vector::fromArray([0.25, 0.1, 2.0, -36.0, -1.0, -3.0, 3.3, 2.0], false), + Vector::fromArray([1, 1, 1, 0, 1, 1, 1, 1], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), 25.0, - Vector::quick([1, 0, 1, 1, 1, 1, 1, 1]), + Vector::fromArray([1, 0, 1, 1, 1, 1, 1, 1], false), ]; } @@ -933,12 +933,12 @@ public function notEqualMatrixDimensionMismatch() : void { $this->expectException(DimensionalityMismatch::class); - $a = Vector::quick([1.0, 2.0, 3.0]); + $a = Vector::fromArray([1.0, 2.0, 3.0], false); - $b = Matrix::quick([ + $b = Matrix::fromArray([ [1.0, 2.0], [3.0, 4.0], - ]); + ], false); $a->notEqualMatrix($b); } @@ -964,29 +964,29 @@ public function greater(Vector $a, $b, $expected) : void public function greaterProvider() : Generator { yield [ - Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]), - Matrix::quick([ + Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false), + Matrix::fromArray([ [4.0, -1.0, 0.03, -0.01, -0.5, 2.0], [0.01, 2.01, 1.0, 20.0, 0.05, -1.0], [1.1, 5.0, -5.0, 30, -0.005, 11.9], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [0, 1, 1, 1, 1, 1], [1, 1, 1, 0, 1, 1], [1, 1, 1, 0, 1, 0], - ]), + ], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), - Vector::quick([0.25, 0.1, 2.0, -36.0, -1.0, -3.0, 3.3, 2.0]), - Vector::quick([0, 1, 1, 0, 0, 1, 1, 1]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), + Vector::fromArray([0.25, 0.1, 2.0, -36.0, -1.0, -3.0, 3.3, 2.0], false), + Vector::fromArray([0, 1, 1, 0, 0, 1, 1, 1], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), 1.0, - Vector::quick([0, 1, 1, 0, 0, 1, 1, 1]), + Vector::fromArray([0, 1, 1, 0, 0, 1, 1, 1], false), ]; } @@ -1011,29 +1011,29 @@ public function greaterEqual(Vector $a, $b, $expected) : void public function greaterEqualProvider() : Generator { yield [ - Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]), - Matrix::quick([ + Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false), + Matrix::fromArray([ [4.0, -1.0, 0.03, -0.01, -0.5, 2.0], [0.01, 2.01, 1.0, 20.0, 0.05, -1.0], [1.1, 5.0, -5.0, 30, -0.005, 11.9], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 0, 1, 1], - ]), + ], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), - Vector::quick([0.25, 0.1, 2.0, -36.0, -1.0, -3.0, 3.3, 2.0]), - Vector::quick([0, 1, 1, 1, 0, 1, 1, 1]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), + Vector::fromArray([0.25, 0.1, 2.0, -36.0, -1.0, -3.0, 3.3, 2.0], false), + Vector::fromArray([0, 1, 1, 1, 0, 1, 1, 1], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), 25.0, - Vector::quick([0, 1, 1, 0, 0, 1, 1, 1]), + Vector::fromArray([0, 1, 1, 0, 0, 1, 1, 1], false), ]; } @@ -1058,29 +1058,29 @@ public function less(Vector $a, $b, $expected) : void public function lessProvider() : Generator { yield [ - Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]), - Matrix::quick([ + Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false), + Matrix::fromArray([ [4.0, -1.0, 0.03, -0.01, -0.5, 2.0], [0.01, 2.01, 1.0, 20.0, 0.05, -1.0], [1.1, 5.0, -5.0, 30, -0.005, 11.9], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0], - ]), + ], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), - Vector::quick([0.25, 0.1, 2.0, -36.0, -1.0, -3.0, 3.3, 2.0]), - Vector::quick([1, 0, 0, 0, 1, 0, 0, 0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), + Vector::fromArray([0.25, 0.1, 2.0, -36.0, -1.0, -3.0, 3.3, 2.0], false), + Vector::fromArray([1, 0, 0, 0, 1, 0, 0, 0], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), 25.0, - Vector::quick([1, 0, 0, 1, 1, 0, 0, 0]), + Vector::fromArray([1, 0, 0, 1, 1, 0, 0, 0], false), ]; } @@ -1105,30 +1105,30 @@ public function lessEqual(Vector $a, $b, $expected) : void public function lessEqualProvider() : Generator { yield [ - Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]), - Matrix::quick([ + Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false), + Matrix::fromArray([ [4.0, -1.0, 0.03, -0.01, -0.5, 2.0], [0.01, 2.01, 1.0, 20.0, 0.05, -1.0], [1.1, 5.0, -5.0, 30, -0.005, 11.9], - ]), - Matrix::quick([ + ], false), + Matrix::fromArray([ [1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 1, 0, 1], - ]), + ], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), - Vector::quick([0.25, 0.1, 2.0, -36.0, -1.0, -3.0, 3.3, 2.0]), - Vector::quick([1, 0, 0, 1, 1, 0, 0, 0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), + Vector::fromArray([0.25, 0.1, 2.0, -36.0, -1.0, -3.0, 3.3, 2.0], false), + Vector::fromArray([1, 0, 0, 1, 1, 0, 0, 0], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), 25.0, - Vector::quick([1, 1, 0, 1, 1, 0, 0, 0]), + Vector::fromArray([1, 1, 0, 1, 1, 0, 0, 0], false), ]; } @@ -1153,15 +1153,15 @@ public function mod(Vector $a, $b, $expected) : void public function modProvider() : Generator { yield [ - Vector::quick([0.25, 0.1, 2.0, -0.5, -1.0, -3.0, 3.3, 2.0]), - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), - Vector::quick([0, 0, 2, 0, -1, -3, 3, 2]), + Vector::fromArray([0.25, 0.1, 2.0, -0.5, -1.0, -3.0, 3.3, 2.0], false), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), + Vector::fromArray([0, 0, 2, 0, -1, -3, 3, 2], false), ]; yield [ - Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]), + Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false), 4, - Vector::quick([-3, 1, 3, 0, 0, 1, 2, 1]), + Vector::fromArray([-3, 1, 3, 0, 0, 1, 2, 1], false), ]; } @@ -1170,11 +1170,11 @@ public function modProvider() : Generator */ public function abs() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $b = $a->abs(); - $expected = Vector::quick([15, 25, 35, 36, 72, 89, 106, 45]); + $expected = Vector::fromArray([15, 25, 35, 36, 72, 89, 106, 45], false); $this->assertEquals($expected, $b); } @@ -1184,11 +1184,11 @@ public function abs() : void */ public function square() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $b = $a->square(); - $expected = Vector::quick([225, 625, 1225, 1296, 5184, 7921, 11236, 2025]); + $expected = Vector::fromArray([225, 625, 1225, 1296, 5184, 7921, 11236, 2025], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -1198,11 +1198,11 @@ public function square() : void */ public function pow() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $b = $a->pow(3); - $expected = Vector::quick([-3375, 15625, 42875, -46656, -373248, 704969, 1191016, 91125]); + $expected = Vector::fromArray([-3375, 15625, 42875, -46656, -373248, 704969, 1191016, 91125], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -1212,14 +1212,14 @@ public function pow() : void */ public function sqrt() : void { - $a = Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]); + $a = Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false); $b = $a->sqrt(); - $expected = Vector::quick([ + $expected = Vector::fromArray([ 2.0, 2.5495097567963922, 1.70293863659264, 4.47213595499958, 1.61245154965971, 3.449637662132068, - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -1229,14 +1229,14 @@ public function sqrt() : void */ public function exp() : void { - $a = Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]); + $a = Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false); $b = $a->exp(); - $expected = Vector::quick([ + $expected = Vector::fromArray([ 54.598150033144236, 665.1416330443618, 18.17414536944306, 485165195.4097903, 13.463738035001692, 147266.6252405527, - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -1246,14 +1246,14 @@ public function exp() : void */ public function log() : void { - $a = Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]); + $a = Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false); $b = $a->log(); - $expected = Vector::quick([ + $expected = Vector::fromArray([ 1.3862943611198906, 1.8718021769015913, 1.0647107369924282, 2.995732273553991, 0.9555114450274363, 2.4765384001174837, - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -1263,14 +1263,14 @@ public function log() : void */ public function sin() : void { - $a = Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]); + $a = Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false); $b = $a->sin(); - $expected = Vector::quick([ + $expected = Vector::fromArray([ -0.7568024953079282, 0.21511998808781552, 0.23924932921398243, 0.9129452507276277, 0.5155013718214642, -0.6181371122370333, - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -1280,13 +1280,13 @@ public function sin() : void */ public function asin() : void { - $a = Vector::quick([0.1, 0.3, -0.5]); + $a = Vector::fromArray([0.1, 0.3, -0.5], false); $b = $a->asin(); - $expected = Vector::quick([ + $expected = Vector::fromArray([ 0.1001674211615598, 0.3046926540153975, -0.5235987755982989, - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -1296,14 +1296,14 @@ public function asin() : void */ public function cos() : void { - $a = Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]); + $a = Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false); $b = $a->cos(); - $expected = Vector::quick([ + $expected = Vector::fromArray([ -0.6536436208636119, 0.9765876257280235, -0.9709581651495905, 0.40808206181339196, -0.8568887533689473, 0.7860702961410393, - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -1313,13 +1313,13 @@ public function cos() : void */ public function acos() : void { - $a = Vector::quick([0.1, 0.3, -0.5]); + $a = Vector::fromArray([0.1, 0.3, -0.5], false); $b = $a->acos(); - $expected = Vector::quick([ + $expected = Vector::fromArray([ 1.4706289056333368, 1.2661036727794992, 2.0943951023931957, - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -1329,14 +1329,14 @@ public function acos() : void */ public function tan() : void { - $a = Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]); + $a = Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false); $b = $a->tan(); - $expected = Vector::quick([ + $expected = Vector::fromArray([ 1.1578212823495777, 0.22027720034589682, -0.24640539397196634, 2.237160944224742, -0.6015966130897586, -0.7863636563696398, - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -1346,14 +1346,14 @@ public function tan() : void */ public function atan() : void { - $a = Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]); + $a = Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false); $b = $a->atan(); - $expected = Vector::quick([ + $expected = Vector::fromArray([ 1.3258176636680326, 1.4181469983996315, 1.2387368592520112, 1.5208379310729538, 1.2036224929766774, 1.486959684726482, - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -1363,14 +1363,14 @@ public function atan() : void */ public function rad2deg() : void { - $a = Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]); + $a = Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false); $b = $a->rad2deg(); - $expected = Vector::quick([ + $expected = Vector::fromArray([ 229.1831180523293, 372.42256683503507, 166.15776058793872, 1145.9155902616465, 148.96902673401405, 681.8197762056797, - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -1380,14 +1380,14 @@ public function rad2deg() : void */ public function deg2rad() : void { - $a = Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]); + $a = Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false); $b = $a->deg2rad(); - $expected = Vector::quick([ + $expected = Vector::fromArray([ 0.06981317007977318, 0.11344640137963141, 0.05061454830783556, 0.3490658503988659, 0.04537856055185257, 0.2076941809873252, - ]); + ], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -1397,7 +1397,7 @@ public function deg2rad() : void */ public function sum() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $this->assertEqualsWithDelta(177.0, $a->sum(), self::MAX_DELTA); } @@ -1407,7 +1407,7 @@ public function sum() : void */ public function product() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $this->assertEqualsWithDelta(-14442510600000.0, $a->product(), self::MAX_DELTA); } @@ -1417,7 +1417,7 @@ public function product() : void */ public function min() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $this->assertEquals(-72, $a->min()); } @@ -1427,7 +1427,7 @@ public function min() : void */ public function max() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $this->assertEquals(106, $a->max()); } @@ -1437,7 +1437,7 @@ public function max() : void */ public function mean() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $this->assertEqualsWithDelta(22.125, $a->mean(), self::MAX_DELTA); } @@ -1447,7 +1447,7 @@ public function mean() : void */ public function median() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $this->assertEquals(30.0, $a->median()); } @@ -1457,13 +1457,13 @@ public function median() : void */ public function quantile() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $this->assertEqualsWithDelta(30.0, $a->quantile(0.5), self::MAX_DELTA); $this->assertEqualsWithDelta(-72.0, $a->quantile(0.0), self::MAX_DELTA); $this->assertEqualsWithDelta(106.0, $a->quantile(1.0), self::MAX_DELTA); - $single = Vector::quick([5.0]); + $single = Vector::fromArray([5.0], false); $this->assertEqualsWithDelta(5.0, $single->quantile(0.0), self::MAX_DELTA); $this->assertEqualsWithDelta(5.0, $single->quantile(0.5), self::MAX_DELTA); @@ -1475,7 +1475,7 @@ public function quantile() : void */ public function variance() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $this->assertEqualsWithDelta(3227.609375, $a->variance(), self::MAX_DELTA); } @@ -1485,11 +1485,11 @@ public function variance() : void */ public function round() : void { - $a = Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]); + $a = Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false); $b = $a->round(2); - $expected = Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]); + $expected = Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false); $this->assertEqualsWithDelta($expected, $b, self::MAX_DELTA); } @@ -1499,11 +1499,11 @@ public function round() : void */ public function floor() : void { - $a = Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]); + $a = Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false); $b = $a->floor(); - $expected = Vector::quick([4.0, 6.0, 2.0, 20.0, 2.0, 11.0]); + $expected = Vector::fromArray([4.0, 6.0, 2.0, 20.0, 2.0, 11.0], false); $this->assertEquals($expected, $b); } @@ -1513,11 +1513,11 @@ public function floor() : void */ public function ceil() : void { - $a = Vector::quick([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]); + $a = Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9], false); $b = $a->ceil(); - $expected = Vector::quick([4.0, 7.0, 3.0, 20.0, 3.0, 12.0]); + $expected = Vector::fromArray([4.0, 7.0, 3.0, 20.0, 3.0, 12.0], false); $this->assertEquals($expected, $b); } @@ -1527,7 +1527,7 @@ public function ceil() : void */ public function l1Norm() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $this->assertEqualsWithDelta(423.0, $a->l1Norm(), self::MAX_DELTA); } @@ -1537,7 +1537,7 @@ public function l1Norm() : void */ public function l2Norm() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $this->assertEqualsWithDelta(172.4441938715247, $a->l2Norm(), self::MAX_DELTA); } @@ -1547,7 +1547,7 @@ public function l2Norm() : void */ public function pNorm() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $this->assertEqualsWithDelta(135.15554088861361, $a->pNorm(3.0), self::MAX_DELTA); } @@ -1557,7 +1557,7 @@ public function pNorm() : void */ public function maxNorm() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $this->assertEqualsWithDelta(106.0, $a->maxNorm(), self::MAX_DELTA); } @@ -1567,11 +1567,11 @@ public function maxNorm() : void */ public function clip() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $b = $a->clip(0.0, 100); - $expected = Vector::quick([0.0, 25, 35, 0.0, 0.0, 89, 100.0, 45]); + $expected = Vector::fromArray([0.0, 25, 35, 0.0, 0.0, 89, 100.0, 45], false); $this->assertEquals($expected, $b); } @@ -1581,11 +1581,11 @@ public function clip() : void */ public function clipLower() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $b = $a->clipLower(60.0); - $expected = Vector::quick([60.0, 60.0, 60.0, 60.0, 60.0, 89, 106.0, 60.0]); + $expected = Vector::fromArray([60.0, 60.0, 60.0, 60.0, 60.0, 89, 106.0, 60.0], false); $this->assertEquals($expected, $b); } @@ -1595,11 +1595,11 @@ public function clipLower() : void */ public function clipUpper() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $b = $a->clipUpper(50.0); - $expected = Vector::quick([-15.0, 25, 35, -36.0, -72.0, 50.0, 50.0, 45]); + $expected = Vector::fromArray([-15.0, 25, 35, -36.0, -72.0, 50.0, 50.0, 45], false); $this->assertEquals($expected, $b); } @@ -1609,11 +1609,11 @@ public function clipUpper() : void */ public function sign() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $b = $a->sign(); - $expected = Vector::quick([-1, 1, 1, -1, -1, 1, 1, 1]); + $expected = Vector::fromArray([-1, 1, 1, -1, -1, 1, 1, 1], false); $this->assertEquals($expected, $b); } @@ -1623,11 +1623,11 @@ public function sign() : void */ public function negate() : void { - $a = Vector::quick([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0]); + $a = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0, 106.0, 45.0], false); $b = $a->negate(); - $expected = Vector::quick([15, -25, -35, 36, 72, -89, -106, -45]); + $expected = Vector::fromArray([15, -25, -35, 36, 72, -89, -106, -45], false); $this->assertEquals($expected, $b); } @@ -1729,7 +1729,7 @@ public function reshapeSizeMismatchThrows() : void { $this->expectException(InvalidArgumentException::class); - Vector::quick([1.0, 2.0, 3.0, 4.0])->reshape(2, 3); + Vector::fromArray([1.0, 2.0, 3.0, 4.0], false)->reshape(2, 3); } /** @@ -1739,7 +1739,7 @@ public function quantileOutOfRangeThrows() : void { $this->expectException(InvalidArgumentException::class); - Vector::quick([1.0, 2.0, 3.0])->quantile(-0.1); + Vector::fromArray([1.0, 2.0, 3.0], false)->quantile(-0.1); } /** @@ -1749,7 +1749,7 @@ public function quantileAboveOneThrows() : void { $this->expectException(InvalidArgumentException::class); - Vector::quick([1.0, 2.0, 3.0])->quantile(1.1); + Vector::fromArray([1.0, 2.0, 3.0], false)->quantile(1.1); } /** @@ -1759,7 +1759,7 @@ public function pNormNonPositiveThrows() : void { $this->expectException(InvalidArgumentException::class); - Vector::quick([1.0, 2.0, 3.0])->pNorm(0.0); + Vector::fromArray([1.0, 2.0, 3.0], false)->pNorm(0.0); } /** @@ -1769,7 +1769,7 @@ public function dotDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - Vector::quick([1.0, 2.0, 3.0])->dot(Vector::quick([1.0, 2.0])); + Vector::fromArray([1.0, 2.0, 3.0], false)->dot(Vector::fromArray([1.0, 2.0], false)); } /** @@ -1779,7 +1779,7 @@ public function multiplyDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - Vector::quick([1.0, 2.0, 3.0])->multiply(Vector::quick([1.0, 2.0])); + Vector::fromArray([1.0, 2.0, 3.0], false)->multiply(Vector::fromArray([1.0, 2.0], false)); } /** @@ -1789,7 +1789,7 @@ public function divideDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - Vector::quick([1.0, 2.0, 3.0])->divide(Vector::quick([1.0, 2.0])); + Vector::fromArray([1.0, 2.0, 3.0], false)->divide(Vector::fromArray([1.0, 2.0], false)); } /** @@ -1799,7 +1799,7 @@ public function addDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - Vector::quick([1.0, 2.0, 3.0])->add(Vector::quick([1.0, 2.0])); + Vector::fromArray([1.0, 2.0, 3.0], false)->add(Vector::fromArray([1.0, 2.0], false)); } /** @@ -1809,7 +1809,7 @@ public function subtractDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - Vector::quick([1.0, 2.0, 3.0])->subtract(Vector::quick([1.0, 2.0])); + Vector::fromArray([1.0, 2.0, 3.0], false)->subtract(Vector::fromArray([1.0, 2.0], false)); } /** @@ -1819,7 +1819,7 @@ public function powDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - Vector::quick([1.0, 2.0, 3.0])->pow(Vector::quick([1.0, 2.0])); + Vector::fromArray([1.0, 2.0, 3.0], false)->pow(Vector::fromArray([1.0, 2.0], false)); } /** @@ -1829,7 +1829,7 @@ public function modDimensionMismatchThrows() : void { $this->expectException(DimensionalityMismatch::class); - Vector::quick([1.0, 2.0, 3.0])->mod(Vector::quick([1.0, 2.0])); + Vector::fromArray([1.0, 2.0, 3.0], false)->mod(Vector::fromArray([1.0, 2.0], false)); } /** @@ -1850,51 +1850,51 @@ public function arithmeticWithWrongOperandTypeThrows(callable $operation) : void public function wrongOperandTypeProvider() : Generator { yield 'multiply' => [function () { - Vector::quick([1.0, 2.0, 3.0])->multiply('not a valid operand'); + Vector::fromArray([1.0, 2.0, 3.0], false)->multiply('not a valid operand'); }]; yield 'divide' => [function () { - Vector::quick([1.0, 2.0, 3.0])->divide('not a valid operand'); + Vector::fromArray([1.0, 2.0, 3.0], false)->divide('not a valid operand'); }]; yield 'add' => [function () { - Vector::quick([1.0, 2.0, 3.0])->add('not a valid operand'); + Vector::fromArray([1.0, 2.0, 3.0], false)->add('not a valid operand'); }]; yield 'subtract' => [function () { - Vector::quick([1.0, 2.0, 3.0])->subtract('not a valid operand'); + Vector::fromArray([1.0, 2.0, 3.0], false)->subtract('not a valid operand'); }]; yield 'pow' => [function () { - Vector::quick([1.0, 2.0, 3.0])->pow('not a valid operand'); + Vector::fromArray([1.0, 2.0, 3.0], false)->pow('not a valid operand'); }]; yield 'mod' => [function () { - Vector::quick([1.0, 2.0, 3.0])->mod('not a valid operand'); + Vector::fromArray([1.0, 2.0, 3.0], false)->mod('not a valid operand'); }]; yield 'equal' => [function () { - Vector::quick([1.0, 2.0, 3.0])->equal('not a valid operand'); + Vector::fromArray([1.0, 2.0, 3.0], false)->equal('not a valid operand'); }]; yield 'notEqual' => [function () { - Vector::quick([1.0, 2.0, 3.0])->notEqual('not a valid operand'); + Vector::fromArray([1.0, 2.0, 3.0], false)->notEqual('not a valid operand'); }]; yield 'greater' => [function () { - Vector::quick([1.0, 2.0, 3.0])->greater('not a valid operand'); + Vector::fromArray([1.0, 2.0, 3.0], false)->greater('not a valid operand'); }]; yield 'greaterEqual' => [function () { - Vector::quick([1.0, 2.0, 3.0])->greaterEqual('not a valid operand'); + Vector::fromArray([1.0, 2.0, 3.0], false)->greaterEqual('not a valid operand'); }]; yield 'less' => [function () { - Vector::quick([1.0, 2.0, 3.0])->less('not a valid operand'); + Vector::fromArray([1.0, 2.0, 3.0], false)->less('not a valid operand'); }]; yield 'lessEqual' => [function () { - Vector::quick([1.0, 2.0, 3.0])->lessEqual('not a valid operand'); + Vector::fromArray([1.0, 2.0, 3.0], false)->lessEqual('not a valid operand'); }]; } @@ -1905,7 +1905,7 @@ public function convolveStrideLessThanOneThrows() : void { $this->expectException(InvalidArgumentException::class); - Vector::quick([1.0, 2.0, 3.0])->convolve(Vector::quick([1.0, 1.0]), 0); + Vector::fromArray([1.0, 2.0, 3.0], false)->convolve(Vector::fromArray([1.0, 1.0], false), 0); } /** @@ -1915,7 +1915,7 @@ public function convolveKernelLargerThanVectorThrows() : void { $this->expectException(InvalidArgumentException::class); - Vector::quick([1.0, 2.0])->convolve(Vector::quick([1.0, 2.0, 3.0])); + Vector::fromArray([1.0, 2.0], false)->convolve(Vector::fromArray([1.0, 2.0, 3.0], false)); } /** @@ -1925,7 +1925,7 @@ public function offsetSetThrows() : void { $this->expectException(RuntimeException::class); - $a = Vector::quick([1.0, 2.0, 3.0]); + $a = Vector::fromArray([1.0, 2.0, 3.0], false); $a[0] = 4.0; } @@ -1937,7 +1937,7 @@ public function offsetUnsetThrows() : void { $this->expectException(RuntimeException::class); - $a = Vector::quick([1.0, 2.0, 3.0]); + $a = Vector::fromArray([1.0, 2.0, 3.0], false); unset($a[0]); } @@ -1949,8 +1949,114 @@ public function offsetGetOutOfBoundsThrows() : void { $this->expectException(InvalidArgumentException::class); - $a = Vector::quick([1.0, 2.0, 3.0]); + $a = Vector::fromArray([1.0, 2.0, 3.0], false); $this->assertEquals(0.0, $a[10]); } + + /** + * @test + */ + public function asTensorBuffer() : void + { + $vector = Vector::fromArray([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0], false); + + $buffer = $vector->asTensorBuffer(); + + $this->assertInstanceOf(\Tensor\TensorBuffer::class, $buffer); + $this->assertEquals([-15.0, 25.0, 35.0, -36.0, -72.0, 89.0], $buffer->toArray()); + $this->assertSame(6, $buffer->count()); + $this->assertEquals(25.0, $buffer->get(1)); + $this->assertSame($buffer, $buffer->asBuffer()); + } + + /** + * @test + */ + public function tensorBufferGetThrowsOnOutOfBounds() : void + { + $vector = Vector::fromArray([1.0, 2.0, 3.0], false); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Element not found at offset 3.'); + + $vector->asTensorBuffer()->get(3); + } + + /** + * @test + */ + public function asTensorBufferGetThrowOnNegativeIndex() : void + { + $vector = Vector::fromArray([1.0, 2.0, 3.0], false); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Element not found at offset -1.'); + + $vector->asTensorBuffer()->get(-1); + } + + /** + * @test + */ + public function serializeRoundTrip() : void + { + $vector = Vector::fromArray([1.0, 2.0, 3.0, 4.0, 5.0], true); + + $unserialised = unserialize(serialize($vector)); + + $this->assertInstanceOf(Vector::class, $unserialised); + $this->assertEquals($vector, $unserialised); + $this->assertEquals($vector->asArray(), $unserialised->asArray()); + $this->assertEquals($vector->shape(), $unserialised->shape()); + } + + /** + * @test + */ + public function serializeRoundTripWithEmptyVector() : void + { + $vector = Vector::fromArray([], false); + + $unserialised = unserialize(serialize($vector)); + + $this->assertInstanceOf(Vector::class, $unserialised); + $this->assertEquals($vector, $unserialised); + $this->assertEquals([], $unserialised->asArray()); + $this->assertEquals([0], $unserialised->shape()); + } + + /** + * @test + */ + public function serialisedShapeIsCompatibleWithTensorExt() : void + { + $vector = Vector::fromArray([1.0, 2.0, 3.0], true); + + $serialised = serialize($vector); + + // The payload must be byte-compatible with the Tensor-Ext native + // serialisation: the __serialize() payload is emitted as a named "data" + // array (and "n") under the object header (no nested "a" property). + $this->assertSame( + 'O:13:"Tensor\\Vector":2:{s:4:"data";a:3:{i:0;d:1;i:1;d:2;i:2;d:3;}s:1:"n";i:3;}', + $serialised + ); + } + + /** + * @test + */ + public function unserializeFromRawArrayPayload() : void + { + // Simulate an ext-produced payload and verify __unserialize consumes it. + $vector = new Vector([], false); + + // Manually call __unserialize with a payload matching the shape of the + // 4.0 __serialize() output (a "data" array plus the element count "n"). + $vector->__unserialize(['data' => [1.0, 2.0, 3.0], 'n' => 3]); + + $this->assertEquals([1.0, 2.0, 3.0], $vector->asArray()); + $this->assertEquals([3], $vector->shape()); + } } From 96c132625e06b709389cb3d51cf625609859a4f0 Mon Sep 17 00:00:00 2001 From: Andrew DalPino Date: Thu, 24 Sep 2026 18:01:24 -0500 Subject: [PATCH 2/2] Update CHANGELOG --- CHANGELOG.md | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 896eb5a..249dbc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,16 +1,8 @@ # Change Log - 4.0.0 - - Made the pure-PHP library byte-compatible with the tensor_ext extension for - `serialize()` / `unserialize()`: `Vector`, `Matrix`, and `ColumnVector` now - implement `__serialize()` and `__unserialize()` so that payloads written by - either implementation can be read by the other. - - Renamed the `build()` / `quick()` factories to `Vector::fromArray(array - $a = [], bool $validate = true)` and `Matrix::fromArray(array $a = [], bool - $validate = true)` to match the Tensor-Ext API. - - Added `Vector::asTensorBuffer()` and `Matrix::asTensorBuffer()` plus a new - `Tensor\TensorBuffer` class exposing `toArray()`, `asBuffer()`, `count()`, - and a bounds-checked `get(int $index)`. + - Made the pure-PHP library byte-compatible with the tensor_ext extension for `serialize()` / `unserialize()`: `Vector`, `Matrix`, and `ColumnVector` now implement `__serialize()` and `__unserialize()` so that payloads written by either implementation can be read by the other. + - Renamed the `build()` / `quick()` factories to `Vector::fromArray(array $a = [], bool $validate = true)` and `Matrix::fromArray(array $a = [], bool $validate = true)` to match the Tensor-Ext API. - 3.1.0 - Implemented the singular value decomposition (SVD) in the pure-PHP library