diff --git a/CHANGELOG.md b/CHANGELOG.md index e5eb7fe..4ac30c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +- 4.1.0 + - Added `softplus()` and `erf()` special functions + - Added `sinh()` and `cosh()` trigonometric functions + - Added reciprocal square root `rsqrt()` function + - 4.0.0 - Data are now backed by a contiguous C buffer instead of PHP array - Added `fromArray()` factory method to build from PHP array diff --git a/benchmarks/Unary/SoftplusMatrixBench.php b/benchmarks/Unary/SoftplusMatrixBench.php new file mode 100644 index 0000000..77c1f44 --- /dev/null +++ b/benchmarks/Unary/SoftplusMatrixBench.php @@ -0,0 +1,62 @@ +a = Matrix::uniform(...$params['size']); + } + + /** + * @return list}> + */ + public function sizes() : Generator + { + yield 'small' => ['size' => [1024, 1024]]; + yield 'medium' => ['size' => [4096, 4096]]; + yield 'large' => ['size' => [8192, 8192]]; + } + + /** + * @Subject + * @Iterations(5) + * @ParamProviders({"sizes"}) + * @OutputTimeUnit("milliseconds", precision=3) + */ + public function benchFused() : void + { + $this->a->softplus(); + } + + /** + * @Subject + * @Iterations(5) + * @ParamProviders({"sizes"}) + * @OutputTimeUnit("milliseconds", precision=3) + */ + public function benchComposed() : void + { + $e = $this->a->exp(); + + $e->add(1.0)->log(); + } +} diff --git a/docs/Matrix.md b/docs/Matrix.md index 20e7dee..5b426f3 100644 --- a/docs/Matrix.md +++ b/docs/Matrix.md @@ -419,12 +419,12 @@ See [Unary](interfaces/unary.md). Each method returns a new `Matrix`. - `abs() : self` — absolute value of each element - `square() : self` — square of the matrix element-wise - `sqrt() : self` — square root of the matrix +- `rsqrt() : self` — reciprocal square root of the matrix - `reciprocal() : self` — element-wise reciprocal of the matrix - `exp() : self` — exponential of the matrix - `expm1() : self` — exponential of each element minus 1 - `log(float $base = M_E) : self` — logarithm of the matrix in the specified base - `log1p() : self` — log of 1 plus each element -- `sigmoid() : self` — element-wise logistic function, `1 / (1 + exp(-x))` - `round(int $precision = 0) : self` — round the elements to a given decimal place (throws `InvalidArgumentException` if `$precision < 0`) - `floor() : self` — round down to the nearest integer - `ceil() : self` — round up to the nearest integer @@ -445,6 +445,8 @@ See [Trigonometric](interfaces/trigonometric.md). Each method returns a new `Mat - `tan()` — tangent of the matrix - `atan()` — arc tangent of the matrix - `tanh() : self` — element-wise hyperbolic tangent +- `sinh() : self` — element-wise hyperbolic sine +- `cosh() : self` — element-wise hyperbolic cosine - `rad2deg()` — convert angles from radians to degrees - `deg2rad()` — convert angles from degrees to radians @@ -466,9 +468,12 @@ See [Reductions](interfaces/reductions.md). For a `Matrix`, row-wise reductions ## Special -See [Special](interfaces/special.md). These preserve the shape of the matrix without being element-wise. +See [Special](interfaces/special.md). `softmax()` preserves the shape of the matrix; `erf()` is element-wise. +- `sigmoid() : self` — element-wise logistic function, `1 / (1 + exp(-x))` +- `softplus() : self` — element-wise softplus, `log(1 + exp(x))` - `softmax() : self` — exponentials normalized so each **row** sums to `1.0`; transpose on either side to normalize each column +- `erf() : self` — element-wise Gaussian error function ## Array Access diff --git a/docs/Vector.md b/docs/Vector.md index 1b73b2c..b18ead8 100644 --- a/docs/Vector.md +++ b/docs/Vector.md @@ -302,12 +302,14 @@ See [Unary](interfaces/unary.md). Each method returns a new `Vector`. - `abs() : self` — absolute value of the vector - `square() : self` — square the vector - `sqrt() : self` — square root of the vector +- `rsqrt() : self` — reciprocal square root of the vector - `reciprocal() : self` — element-wise reciprocal of the vector - `exp() : self` — exponentiate each element - `expm1() : self` — exponential of each element minus 1 - `log(float $base = M_E) : self` — log to the given base of each element - `log1p() : self` — log of 1 plus each element - `sigmoid() : self` — element-wise logistic function, `1 / (1 + exp(-x))` +- `softplus() : self` — element-wise softplus, `log(1 + exp(x))` - `round(int $precision = 0) : self` — round the elements to a given decimal place (throws `InvalidArgumentException` if `$precision < 0`) - `floor() : self` — round down to the nearest integer - `ceil() : self` — round up to the nearest integer @@ -328,6 +330,8 @@ See [Trigonometric](interfaces/trigonometric.md). Each method returns a new `Vec - `tan()` — tangent of the vector - `atan()` — arc tangent of the vector - `tanh() : self` — element-wise hyperbolic tangent +- `sinh() : self` — element-wise hyperbolic sine +- `cosh() : self` — element-wise hyperbolic cosine - `rad2deg()` — convert angles from radians to degrees - `deg2rad()` — convert angles from degrees to radians @@ -348,9 +352,10 @@ See [Reductions](interfaces/reductions.md). For a `Vector` these return scalar ` ## Special -See [Special](interfaces/special.md). These preserve the shape of the vector without being element-wise. +See [Special](interfaces/special.md). `softmax()` preserves the shape of the vector; `erf()` is element-wise. - `softmax() : self` — the exponentials of the vector normalized so they sum to `1.0` +- `erf() : self` — element-wise Gaussian error function ## Array Access diff --git a/docs/index.md b/docs/index.md index 8ee259d..ab7d76c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -55,7 +55,7 @@ Tensor \ | [Unary](interfaces/unary.md) | Element-wise unary functions, including clipping. | | [Trigonometric](interfaces/trigonometric.md) | Element-wise trigonometric functions. | | [Reductions](interfaces/reductions.md) | Aggregate reduction operations, including the statistical summaries. | -| [Special](interfaces/special.md) | Operations that preserve shape without being element-wise, such as `softmax`. | +| [Special](interfaces/special.md) | Operations that fit no other group, such as `softmax` and the error-function `erf`. | ## Decompositions diff --git a/docs/interfaces/special.md b/docs/interfaces/special.md index b8d55a5..aaa15d7 100644 --- a/docs/interfaces/special.md +++ b/docs/interfaces/special.md @@ -6,9 +6,9 @@ Operations that do not belong to any of the other interface groups. ## Overview -`Special` holds the operations that neither pointwise element-wise functions (`Arithmetic`, `Comparable`, `Unary`, `Trigonometric`), nor aggregate reductions (`Reductions`), nor array-like access (`ArrayLike`) can describe. +`Special` holds the operations that neither the basic algebraic and trigonometric families (`Arithmetic`, `Comparable`, `Unary`, `Trigonometric`), aggregate reductions (`Reductions`), nor array-like access (`ArrayLike`) can describe. -`softmax()` is the sole member: it preserves the shape of the tensor, but each element of the output depends on a whole reduction axis rather than on one input element, so it is neither element-wise nor a reduction. +`softmax()` is the only shape-preserving member whose output depends on a whole reduction axis rather than on one input element, so it is neither element-wise nor a reduction. `erf()` is an element-wise error-function transform grouped here so the error-function family stays together, distinct from the basic algebraic operations. ```php interface Special @@ -16,6 +16,21 @@ interface Special ## Methods +### `sigmoid() : mixed` + +Return the element-wise logistic function, `1 / (1 + exp(-x))`. + +A large negative input saturates to exactly `0.0` and a large positive one to +exactly `1.0`, so the result never overflows to an infinity. + +### `softplus() : mixed` + +Return the element-wise softplus, `log(1 + exp(x))`. + +The computation is numerically stable: for a large positive input it reduces to +`x + log1p(0) == x` and for a large negative input to `log1p(0) == 0.0`, so the +result never overflows to an infinity. + ### `softmax() : mixed` Return the softmax of the tensor, i.e. the exponentials of its elements @@ -36,3 +51,10 @@ The maximum of each row is subtracted before exponentiating, so no intermediate can overflow regardless of the magnitude of the input, and a single-element row normalizes to `1.0`. Note the degenerate case this implies: a matrix with a single *column* has one-element rows, so it normalizes to all ones. + +### `erf() : mixed` + +Return the element-wise Gaussian error function. + +A large input saturates to exactly `1.0` or `-1.0` rather than returning an +infinity. diff --git a/docs/interfaces/tensor.md b/docs/interfaces/tensor.md index 1210683..583a772 100644 --- a/docs/interfaces/tensor.md +++ b/docs/interfaces/tensor.md @@ -20,16 +20,15 @@ interface Tensor extends ArrayLike, Arithmetic, Comparable, | [ArrayLike](arraylike.md) | `shape`, `shapeString`, `size`, `map`, `reduce`, `asArray` | | [Arithmetic](arithmetic.md) | `multiply`, `divide`, `add`, `subtract`, `pow`, `mod` | | [Comparable](comparable.md) | `equal`, `notEqual`, `greater`, `greaterEqual`, `less`, `lessEqual` | -| [Unary](unary.md) | `abs`, `square`, `sqrt`, `exp`, `expm1`, `log`, `log1p`, `sigmoid`, `round`, `floor`, `ceil`, `sign`, `negate`, `clip`, `clipLower`, `clipUpper` | -| [Trigonometric](trigonometric.md) | `sin`, `asin`, `cos`, `acos`, `tan`, `atan`, `tanh`, `rad2deg`, `deg2rad` | +| [Unary](unary.md) | `abs`, `square`, `sqrt`, `rsqrt`, `exp`, `expm1`, `log`, `log1p`, `round`, `floor`, `ceil`, `sign`, `negate`, `clip`, `clipLower`, `clipUpper` | +| [Trigonometric](trigonometric.md) | `sin`, `asin`, `cos`, `acos`, `tan`, `atan`, `tanh`, `sinh`, `cosh`, `rad2deg`, `deg2rad` | | [Reductions](reductions.md) | `sum`, `product`, `min`, `max`, `argmin`, `argmax`, `mean`, `variance`, `median`, `quantile` | -| [Special](special.md) | `softmax` | +| [Special](special.md) | `sigmoid`, `softplus`, `softmax`, `erf` | Every group is homogeneous in what it does to the tensor's shape: `Arithmetic`, `Comparable`, `Unary`, and `Trigonometric` are element-wise and preserve it, `Reductions` collapse it, and `ArrayLike` is about access rather than arithmetic. -`Special` is the escape hatch for operations that preserve the shape without being -element-wise. +`Special` is the escape hatch for operations that fit no other group, such as shape-preserving cross-axis operations like `softmax()` and the element-wise error-function family `erf()`. Additionally, because `ArrayLike` extends `ArrayAccess`, `IteratorAggregate`, and `Countable`, every tensor is array-accessible, iterable, and countable. diff --git a/docs/interfaces/trigonometric.md b/docs/interfaces/trigonometric.md index 334953d..213e1dc 100644 --- a/docs/interfaces/trigonometric.md +++ b/docs/interfaces/trigonometric.md @@ -52,3 +52,15 @@ Return the element-wise hyperbolic tangent. A large input saturates to exactly `1.0` or `-1.0` rather than returning an infinity. + +### `sinh() : mixed` + +Return the element-wise hyperbolic sine. + +### `cosh() : mixed` + +Return the element-wise hyperbolic cosine. + +The result is always positive, and `cosh(0) == 1.0`. For a large input it grows +as `exp(|x|) / 2`, so it can overflow to an infinity for sufficiently large +arguments. diff --git a/docs/interfaces/unary.md b/docs/interfaces/unary.md index 8f9f817..59439d1 100644 --- a/docs/interfaces/unary.md +++ b/docs/interfaces/unary.md @@ -26,6 +26,10 @@ Square the tensor. Return the square root of the tensor. +### `rsqrt() : mixed` + +Return the reciprocal square root of the tensor. + ### `reciprocal() : mixed` Return the element-wise reciprocal of the tensor. @@ -49,13 +53,6 @@ Return the logarithm of the tensor in a specified base. Return the log of 1 plus the tensor, i.e. a transform. -### `sigmoid() : mixed` - -Return the element-wise logistic function, `1 / (1 + exp(-x))`. - -A large negative input saturates to exactly `0.0` and a large positive one to -exactly `1.0`, so the result never overflows to an infinity. - ### `round(int $precision = 0) : self` Round the elements in the tensor to a given decimal place. diff --git a/ext/include/unary.c b/ext/include/unary.c index ce6f820..4607bf7 100644 --- a/ext/include/unary.c +++ b/ext/include/unary.c @@ -86,6 +86,7 @@ TENSOR_UNARY_DISPATCH(abs, fabs(va[i])) TENSOR_UNARY_DISPATCH(sqrt, sqrt(va[i])) +TENSOR_UNARY_DISPATCH(rsqrt, 1.0 / sqrt(va[i])) TENSOR_UNARY_DISPATCH(floor, floor(va[i])) TENSOR_UNARY_DISPATCH(ceil, ceil(va[i])) TENSOR_UNARY_DISPATCH(negate, -va[i]) @@ -134,6 +135,7 @@ TENSOR_UNARY(expm1, expm1(va[i])) TENSOR_UNARY(log, log(va[i])) TENSOR_UNARY(log1p, log1p(va[i])) TENSOR_UNARY(sigmoid, 1.0 / (1.0 + exp(-va[i]))) +TENSOR_UNARY(softplus, va[i] > 0.0 ? va[i] + log1p(exp(-va[i])) : log1p(exp(va[i]))) TENSOR_UNARY(sin, sin(va[i])) TENSOR_UNARY(asin, asin(va[i])) TENSOR_UNARY(cos, cos(va[i])) @@ -141,6 +143,9 @@ TENSOR_UNARY(acos, acos(va[i])) TENSOR_UNARY(tan, tan(va[i])) TENSOR_UNARY(atan, atan(va[i])) TENSOR_UNARY(tanh, tanh(va[i])) +TENSOR_UNARY(sinh, sinh(va[i])) +TENSOR_UNARY(cosh, cosh(va[i])) +TENSOR_UNARY(erf, erf(va[i])) #undef TENSOR_UNARY @@ -462,6 +467,7 @@ void tensor_unary_dispatch_sse_init(void) { tensor_abs_route = tensor_abs_sse; tensor_sqrt_route = tensor_sqrt_sse; + tensor_rsqrt_route = tensor_rsqrt_sse; tensor_floor_route = tensor_floor_sse; tensor_ceil_route = tensor_ceil_sse; tensor_negate_route = tensor_negate_sse; @@ -480,6 +486,7 @@ void tensor_unary_dispatch_avx_init(void) { tensor_abs_route = tensor_abs_avx; tensor_sqrt_route = tensor_sqrt_avx; + tensor_rsqrt_route = tensor_rsqrt_avx; tensor_floor_route = tensor_floor_avx; tensor_ceil_route = tensor_ceil_avx; tensor_negate_route = tensor_negate_avx; @@ -498,6 +505,7 @@ void tensor_unary_dispatch_avx512_init(void) { tensor_abs_route = tensor_abs_avx512; tensor_sqrt_route = tensor_sqrt_avx512; + tensor_rsqrt_route = tensor_rsqrt_avx512; tensor_floor_route = tensor_floor_avx512; tensor_ceil_route = tensor_ceil_avx512; tensor_negate_route = tensor_negate_avx512; diff --git a/ext/include/unary.h b/ext/include/unary.h index 778760e..de3c810 100644 --- a/ext/include/unary.h +++ b/ext/include/unary.h @@ -5,13 +5,18 @@ void tensor_abs(zval * return_value, zval * a); void tensor_sqrt(zval * return_value, zval * a); +void tensor_rsqrt(zval * return_value, zval * a); void tensor_exp(zval * return_value, zval * a); void tensor_expm1(zval * return_value, zval * a); void tensor_log(zval * return_value, zval * a); void tensor_log_base(zval * return_value, zval * a, zval * b); void tensor_log1p(zval * return_value, zval * a); void tensor_sigmoid(zval * return_value, zval * a); +void tensor_softplus(zval * return_value, zval * a); void tensor_tanh(zval * return_value, zval * a); +void tensor_sinh(zval * return_value, zval * a); +void tensor_cosh(zval * return_value, zval * a); +void tensor_erf(zval * return_value, zval * a); void tensor_sin(zval * return_value, zval * a); void tensor_asin(zval * return_value, zval * a); void tensor_cos(zval * return_value, zval * a); diff --git a/ext/tensor/matrix.zep.c b/ext/tensor/matrix.zep.c index 003082e..67b7745 100644 --- a/ext/tensor/matrix.zep.c +++ b/ext/tensor/matrix.zep.c @@ -1702,7 +1702,7 @@ PHP_METHOD(Tensor_Matrix, map) zephir_read_property_cached(&_0, this_ptr, _zephir_prop_0, 15, PH_NOISY_CC | PH_READONLY); ZEPHIR_CALL_METHOD(&_1, &_0, "toArray", NULL, 0); zephir_check_call_status(); - ZEPHIR_CALL_FUNCTION(&b, "array_map", NULL, 7, callback, &_1); + ZEPHIR_CALL_FUNCTION(&b, "array_map", NULL, 8, callback, &_1); zephir_check_call_status(); ZEPHIR_INIT_VAR(&buffer); tensor_buffer_from_array(&buffer, &b); @@ -1753,7 +1753,7 @@ PHP_METHOD(Tensor_Matrix, reduce) ZEPHIR_CALL_METHOD(&_1, &_0, "toArray", NULL, 0); zephir_check_call_status(); ZVAL_DOUBLE(&_2, initial); - ZEPHIR_RETURN_CALL_FUNCTION("array_reduce", NULL, 8, &_1, callback, &_2); + ZEPHIR_RETURN_CALL_FUNCTION("array_reduce", NULL, 9, &_1, callback, &_2); zephir_check_call_status(); RETURN_MM(); } @@ -2012,7 +2012,7 @@ PHP_METHOD(Tensor_Matrix, det) ZEPHIR_CALL_METHOD(&_6, &ref, "swaps", NULL, 0); zephir_check_call_status(); ZVAL_DOUBLE(&_7, -1.0); - ZEPHIR_CALL_FUNCTION(&_8, "pow", NULL, 9, &_7, &_6); + ZEPHIR_CALL_FUNCTION(&_8, "pow", NULL, 10, &_7, &_6); zephir_check_call_status(); mul_function(return_value, &pi, &_8); RETURN_MM(); @@ -3669,6 +3669,48 @@ PHP_METHOD(Tensor_Matrix, sqrt) RETURN_MM(); } +/** + * Return the reciprocal square root of the matrix. + * + * @return self + */ +PHP_METHOD(Tensor_Matrix, rsqrt) +{ + zval _0, _1, _2, _3; + zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL; + zend_long ZEPHIR_LAST_CALL_STATUS; + zval *this_ptr = getThis(); + + ZVAL_UNDEF(&_0); + ZVAL_UNDEF(&_1); + ZVAL_UNDEF(&_2); + ZVAL_UNDEF(&_3); + static zend_string *_zephir_prop_0 = NULL; + static zend_string *_zephir_prop_1 = NULL; + static zend_string *_zephir_prop_2 = NULL; + if (UNEXPECTED(!_zephir_prop_0)) { + _zephir_prop_0 = zend_string_init("a", 1, 1); + } + if (UNEXPECTED(!_zephir_prop_1)) { + _zephir_prop_1 = zend_string_init("m", 1, 1); + } + if (UNEXPECTED(!_zephir_prop_2)) { + _zephir_prop_2 = zend_string_init("n", 1, 1); + } + ZEPHIR_METHOD_GLOBALS_PTR = pecalloc(1, sizeof(zephir_method_globals), 0); + zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__); + + object_init_ex(return_value, tensor_matrix_ce); + ZEPHIR_INIT_VAR(&_0); + zephir_read_property_cached(&_1, this_ptr, _zephir_prop_0, 15, PH_NOISY_CC | PH_READONLY); + tensor_rsqrt(&_0, &_1); + zephir_read_property_cached(&_2, this_ptr, _zephir_prop_1, 16, PH_NOISY_CC | PH_READONLY); + zephir_read_property_cached(&_3, this_ptr, _zephir_prop_2, 17, PH_NOISY_CC | PH_READONLY); + ZEPHIR_CALL_METHOD(NULL, return_value, "__construct", NULL, 16, &_0, &_2, &_3); + zephir_check_call_status(); + RETURN_MM(); +} + /** * Return the exponential of the matrix. * @@ -3814,7 +3856,7 @@ PHP_METHOD(Tensor_Matrix, log) ZEPHIR_CONCAT_SSVS(&_3$$3, "Log base must be greater", " than 0, ", &_2$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_0$$3, "__construct", NULL, 2, &_3$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_0$$3, "tensor/matrix.zep", 1400); + zephir_throw_exception_debug(&_0$$3, "tensor/matrix.zep", 1410); ZEPHIR_MM_RESTORE(); return; } @@ -3925,6 +3967,48 @@ PHP_METHOD(Tensor_Matrix, sigmoid) RETURN_MM(); } +/** + * Return the element-wise softplus i.e. log(1 + exp(x)). + * + * @return self + */ +PHP_METHOD(Tensor_Matrix, softplus) +{ + zval _0, _1, _2, _3; + zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL; + zend_long ZEPHIR_LAST_CALL_STATUS; + zval *this_ptr = getThis(); + + ZVAL_UNDEF(&_0); + ZVAL_UNDEF(&_1); + ZVAL_UNDEF(&_2); + ZVAL_UNDEF(&_3); + static zend_string *_zephir_prop_0 = NULL; + static zend_string *_zephir_prop_1 = NULL; + static zend_string *_zephir_prop_2 = NULL; + if (UNEXPECTED(!_zephir_prop_0)) { + _zephir_prop_0 = zend_string_init("a", 1, 1); + } + if (UNEXPECTED(!_zephir_prop_1)) { + _zephir_prop_1 = zend_string_init("m", 1, 1); + } + if (UNEXPECTED(!_zephir_prop_2)) { + _zephir_prop_2 = zend_string_init("n", 1, 1); + } + ZEPHIR_METHOD_GLOBALS_PTR = pecalloc(1, sizeof(zephir_method_globals), 0); + zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__); + + object_init_ex(return_value, tensor_matrix_ce); + ZEPHIR_INIT_VAR(&_0); + zephir_read_property_cached(&_1, this_ptr, _zephir_prop_0, 15, PH_NOISY_CC | PH_READONLY); + tensor_softplus(&_0, &_1); + zephir_read_property_cached(&_2, this_ptr, _zephir_prop_1, 16, PH_NOISY_CC | PH_READONLY); + zephir_read_property_cached(&_3, this_ptr, _zephir_prop_2, 17, PH_NOISY_CC | PH_READONLY); + ZEPHIR_CALL_METHOD(NULL, return_value, "__construct", NULL, 16, &_0, &_2, &_3); + zephir_check_call_status(); + RETURN_MM(); +} + /** * Return the sine of the matrix. * @@ -4219,6 +4303,90 @@ PHP_METHOD(Tensor_Matrix, tanh) RETURN_MM(); } +/** + * Return the element-wise hyperbolic sine of the matrix. + * + * @return self + */ +PHP_METHOD(Tensor_Matrix, sinh) +{ + zval _0, _1, _2, _3; + zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL; + zend_long ZEPHIR_LAST_CALL_STATUS; + zval *this_ptr = getThis(); + + ZVAL_UNDEF(&_0); + ZVAL_UNDEF(&_1); + ZVAL_UNDEF(&_2); + ZVAL_UNDEF(&_3); + static zend_string *_zephir_prop_0 = NULL; + static zend_string *_zephir_prop_1 = NULL; + static zend_string *_zephir_prop_2 = NULL; + if (UNEXPECTED(!_zephir_prop_0)) { + _zephir_prop_0 = zend_string_init("a", 1, 1); + } + if (UNEXPECTED(!_zephir_prop_1)) { + _zephir_prop_1 = zend_string_init("m", 1, 1); + } + if (UNEXPECTED(!_zephir_prop_2)) { + _zephir_prop_2 = zend_string_init("n", 1, 1); + } + ZEPHIR_METHOD_GLOBALS_PTR = pecalloc(1, sizeof(zephir_method_globals), 0); + zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__); + + object_init_ex(return_value, tensor_matrix_ce); + ZEPHIR_INIT_VAR(&_0); + zephir_read_property_cached(&_1, this_ptr, _zephir_prop_0, 15, PH_NOISY_CC | PH_READONLY); + tensor_sinh(&_0, &_1); + zephir_read_property_cached(&_2, this_ptr, _zephir_prop_1, 16, PH_NOISY_CC | PH_READONLY); + zephir_read_property_cached(&_3, this_ptr, _zephir_prop_2, 17, PH_NOISY_CC | PH_READONLY); + ZEPHIR_CALL_METHOD(NULL, return_value, "__construct", NULL, 16, &_0, &_2, &_3); + zephir_check_call_status(); + RETURN_MM(); +} + +/** + * Return the element-wise hyperbolic cosine of the matrix. + * + * @return self + */ +PHP_METHOD(Tensor_Matrix, cosh) +{ + zval _0, _1, _2, _3; + zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL; + zend_long ZEPHIR_LAST_CALL_STATUS; + zval *this_ptr = getThis(); + + ZVAL_UNDEF(&_0); + ZVAL_UNDEF(&_1); + ZVAL_UNDEF(&_2); + ZVAL_UNDEF(&_3); + static zend_string *_zephir_prop_0 = NULL; + static zend_string *_zephir_prop_1 = NULL; + static zend_string *_zephir_prop_2 = NULL; + if (UNEXPECTED(!_zephir_prop_0)) { + _zephir_prop_0 = zend_string_init("a", 1, 1); + } + if (UNEXPECTED(!_zephir_prop_1)) { + _zephir_prop_1 = zend_string_init("m", 1, 1); + } + if (UNEXPECTED(!_zephir_prop_2)) { + _zephir_prop_2 = zend_string_init("n", 1, 1); + } + ZEPHIR_METHOD_GLOBALS_PTR = pecalloc(1, sizeof(zephir_method_globals), 0); + zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__); + + object_init_ex(return_value, tensor_matrix_ce); + ZEPHIR_INIT_VAR(&_0); + zephir_read_property_cached(&_1, this_ptr, _zephir_prop_0, 15, PH_NOISY_CC | PH_READONLY); + tensor_cosh(&_0, &_1); + zephir_read_property_cached(&_2, this_ptr, _zephir_prop_1, 16, PH_NOISY_CC | PH_READONLY); + zephir_read_property_cached(&_3, this_ptr, _zephir_prop_2, 17, PH_NOISY_CC | PH_READONLY); + ZEPHIR_CALL_METHOD(NULL, return_value, "__construct", NULL, 16, &_0, &_2, &_3); + zephir_check_call_status(); + RETURN_MM(); +} + /** * Convert angles from radians to degrees. * @@ -4657,7 +4825,7 @@ PHP_METHOD(Tensor_Matrix, quantile) zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__); zephir_fetch_params(1, 1, 0, &q_param); ZVAL_DOUBLE(&_0, q); - ZEPHIR_CALL_FUNCTION(&_1, "is_finite", NULL, 10, &_0); + ZEPHIR_CALL_FUNCTION(&_1, "is_finite", NULL, 6, &_0); zephir_check_call_status(); if (UNEXPECTED(!zephir_is_true(&_1))) { ZEPHIR_INIT_VAR(&_2$$3); @@ -4666,7 +4834,7 @@ PHP_METHOD(Tensor_Matrix, quantile) ZEPHIR_CONCAT_SS(&_3$$3, "Q must be a finite value", " between 0 and 1."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_3$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 1613); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 1653); ZEPHIR_MM_RESTORE(); return; } @@ -4684,7 +4852,7 @@ PHP_METHOD(Tensor_Matrix, quantile) ZEPHIR_CONCAT_SSVS(&_8$$4, "Q must be between", " 0 and 1, ", &_7$$4, " given."); ZEPHIR_CALL_METHOD(NULL, &_5$$4, "__construct", NULL, 2, &_8$$4); zephir_check_call_status(); - zephir_throw_exception_debug(&_5$$4, "tensor/matrix.zep", 1618); + zephir_throw_exception_debug(&_5$$4, "tensor/matrix.zep", 1658); ZEPHIR_MM_RESTORE(); return; } @@ -4742,6 +4910,48 @@ PHP_METHOD(Tensor_Matrix, softmax) RETURN_MM(); } +/** + * Return the element-wise Gaussian error function. + * + * @return self + */ +PHP_METHOD(Tensor_Matrix, erf) +{ + zval _0, _1, _2, _3; + zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL; + zend_long ZEPHIR_LAST_CALL_STATUS; + zval *this_ptr = getThis(); + + ZVAL_UNDEF(&_0); + ZVAL_UNDEF(&_1); + ZVAL_UNDEF(&_2); + ZVAL_UNDEF(&_3); + static zend_string *_zephir_prop_0 = NULL; + static zend_string *_zephir_prop_1 = NULL; + static zend_string *_zephir_prop_2 = NULL; + if (UNEXPECTED(!_zephir_prop_0)) { + _zephir_prop_0 = zend_string_init("a", 1, 1); + } + if (UNEXPECTED(!_zephir_prop_1)) { + _zephir_prop_1 = zend_string_init("m", 1, 1); + } + if (UNEXPECTED(!_zephir_prop_2)) { + _zephir_prop_2 = zend_string_init("n", 1, 1); + } + ZEPHIR_METHOD_GLOBALS_PTR = pecalloc(1, sizeof(zephir_method_globals), 0); + zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__); + + object_init_ex(return_value, tensor_matrix_ce); + ZEPHIR_INIT_VAR(&_0); + zephir_read_property_cached(&_1, this_ptr, _zephir_prop_0, 15, PH_NOISY_CC | PH_READONLY); + tensor_erf(&_0, &_1); + zephir_read_property_cached(&_2, this_ptr, _zephir_prop_1, 16, PH_NOISY_CC | PH_READONLY); + zephir_read_property_cached(&_3, this_ptr, _zephir_prop_2, 17, PH_NOISY_CC | PH_READONLY); + ZEPHIR_CALL_METHOD(NULL, return_value, "__construct", NULL, 16, &_0, &_2, &_3); + zephir_check_call_status(); + RETURN_MM(); +} + /** * Compute the row variance of the matrix. * @@ -4802,7 +5012,7 @@ PHP_METHOD(Tensor_Matrix, variance) ZEPHIR_CONCAT_SSVS(&_2$$4, "Mean must be a", " column vector ", &_1$$4, " given."); ZEPHIR_CALL_METHOD(NULL, &_0$$4, "__construct", NULL, 2, &_2$$4); zephir_check_call_status(); - zephir_throw_exception_debug(&_0$$4, "tensor/matrix.zep", 1647); + zephir_throw_exception_debug(&_0$$4, "tensor/matrix.zep", 1697); ZEPHIR_MM_RESTORE(); return; } @@ -4822,7 +5032,7 @@ PHP_METHOD(Tensor_Matrix, variance) ZEPHIR_CONCAT_SSVSVS(&_10$$5, "Mean vector must", " have ", &_7$$5, " rows, ", &_9$$5, " given."); ZEPHIR_CALL_METHOD(NULL, &_5$$5, "__construct", NULL, 2, &_10$$5); zephir_check_call_status(); - zephir_throw_exception_debug(&_5$$5, "tensor/matrix.zep", 1653); + zephir_throw_exception_debug(&_5$$5, "tensor/matrix.zep", 1703); ZEPHIR_MM_RESTORE(); return; } @@ -4941,7 +5151,7 @@ PHP_METHOD(Tensor_Matrix, round) ZEPHIR_CONCAT_SSVS(&_3$$3, "Decimal precision cannot", " be less than 0, ", &_2$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_0$$3, "__construct", NULL, 2, &_3$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_0$$3, "tensor/matrix.zep", 1684); + zephir_throw_exception_debug(&_0$$3, "tensor/matrix.zep", 1734); ZEPHIR_MM_RESTORE(); return; } @@ -5178,7 +5388,7 @@ PHP_METHOD(Tensor_Matrix, clip) ZEPHIR_CONCAT_SS(&_1$$3, "Minimum cannot be", " greater than maximum."); ZEPHIR_CALL_METHOD(NULL, &_0$$3, "__construct", NULL, 2, &_1$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_0$$3, "tensor/matrix.zep", 1743); + zephir_throw_exception_debug(&_0$$3, "tensor/matrix.zep", 1793); ZEPHIR_MM_RESTORE(); return; } @@ -5378,7 +5588,7 @@ PHP_METHOD(Tensor_Matrix, augmentAbove) ZEPHIR_CONCAT_SVSVS(&_11$$3, "Matrix A requires", &_8$$3, " columns but Matrix B has ", &_10$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_6$$3, "__construct", NULL, 2, &_11$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_6$$3, "tensor/matrix.zep", 1789); + zephir_throw_exception_debug(&_6$$3, "tensor/matrix.zep", 1839); ZEPHIR_MM_RESTORE(); return; } @@ -5495,7 +5705,7 @@ PHP_METHOD(Tensor_Matrix, augmentBelow) ZEPHIR_CONCAT_SVSVS(&_11$$3, "Matrix A requires", &_8$$3, " columns but Matrix B has ", &_10$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_6$$3, "__construct", NULL, 2, &_11$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_6$$3, "tensor/matrix.zep", 1811); + zephir_throw_exception_debug(&_6$$3, "tensor/matrix.zep", 1861); ZEPHIR_MM_RESTORE(); return; } @@ -5622,7 +5832,7 @@ PHP_METHOD(Tensor_Matrix, augmentLeft) ZEPHIR_CONCAT_SVSVS(&_11$$3, "Matrix A requires", &_8$$3, " rows but Matrix B has ", &_10$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_6$$3, "__construct", NULL, 2, &_11$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_6$$3, "tensor/matrix.zep", 1833); + zephir_throw_exception_debug(&_6$$3, "tensor/matrix.zep", 1883); ZEPHIR_MM_RESTORE(); return; } @@ -5675,7 +5885,7 @@ PHP_METHOD(Tensor_Matrix, augmentLeft) zephir_array_fast_append(&_27$$4, &bufferA); ZEPHIR_CALL_METHOD(&_26$$4, &bufferB, "concat", &_28, 0, &_27$$4); zephir_check_call_status(); - zephir_array_append(&c, &_26$$4, PH_SEPARATE, "tensor/matrix.zep", 1849); + zephir_array_append(&c, &_26$$4, PH_SEPARATE, "tensor/matrix.zep", 1899); } } ZEPHIR_CALL_CE_STATIC(&buffer, tensor_tensorbuffer_ce, "fromBuffers", NULL, 0, &c); @@ -5785,7 +5995,7 @@ PHP_METHOD(Tensor_Matrix, augmentRight) ZEPHIR_CONCAT_SVSVS(&_11$$3, "Matrix A requires", &_8$$3, " rows but Matrix B has ", &_10$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_6$$3, "__construct", NULL, 2, &_11$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_6$$3, "tensor/matrix.zep", 1869); + zephir_throw_exception_debug(&_6$$3, "tensor/matrix.zep", 1919); ZEPHIR_MM_RESTORE(); return; } @@ -5838,7 +6048,7 @@ PHP_METHOD(Tensor_Matrix, augmentRight) zephir_array_fast_append(&_27$$4, &bufferB); ZEPHIR_CALL_METHOD(&_26$$4, &bufferA, "concat", NULL, 0, &_27$$4); zephir_check_call_status(); - zephir_array_append(&c, &_26$$4, PH_SEPARATE, "tensor/matrix.zep", 1885); + zephir_array_append(&c, &_26$$4, PH_SEPARATE, "tensor/matrix.zep", 1935); } } ZEPHIR_CALL_CE_STATIC(&buffer, tensor_tensorbuffer_ce, "fromBuffers", NULL, 0, &c); @@ -5924,7 +6134,7 @@ PHP_METHOD(Tensor_Matrix, repeat) ZEPHIR_CONCAT_SS(&_4$$4, "Chunk length must be", " greater than 0, 0 given."); ZEPHIR_CALL_METHOD(NULL, &_3$$4, "__construct", NULL, 2, &_4$$4); zephir_check_call_status(); - zephir_throw_exception_debug(&_3$$4, "tensor/matrix.zep", 1909); + zephir_throw_exception_debug(&_3$$4, "tensor/matrix.zep", 1959); ZEPHIR_MM_RESTORE(); return; } @@ -6019,7 +6229,7 @@ PHP_METHOD(Tensor_Matrix, multiplyMatrix) ZEPHIR_CONCAT_VSVS(&_5$$3, &_3$$3, " matrix expected but ", &_4$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_5$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 1932); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 1982); ZEPHIR_MM_RESTORE(); return; } @@ -6096,7 +6306,7 @@ PHP_METHOD(Tensor_Matrix, divideMatrix) ZEPHIR_CONCAT_VSVS(&_5$$3, &_3$$3, " matrix expected but ", &_4$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_5$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 1951); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2001); ZEPHIR_MM_RESTORE(); return; } @@ -6173,7 +6383,7 @@ PHP_METHOD(Tensor_Matrix, addMatrix) ZEPHIR_CONCAT_VSVS(&_5$$3, &_3$$3, " matrix expected but ", &_4$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_5$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 1970); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2020); ZEPHIR_MM_RESTORE(); return; } @@ -6250,7 +6460,7 @@ PHP_METHOD(Tensor_Matrix, subtractMatrix) ZEPHIR_CONCAT_VSVS(&_5$$3, &_3$$3, " matrix expected but ", &_4$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_5$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 1989); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2039); ZEPHIR_MM_RESTORE(); return; } @@ -6328,7 +6538,7 @@ PHP_METHOD(Tensor_Matrix, powMatrix) ZEPHIR_CONCAT_VSVS(&_5$$3, &_3$$3, " matrix expected but ", &_4$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_5$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2009); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2059); ZEPHIR_MM_RESTORE(); return; } @@ -6406,7 +6616,7 @@ PHP_METHOD(Tensor_Matrix, modMatrix) ZEPHIR_CONCAT_VSVS(&_5$$3, &_3$$3, " matrix expected but ", &_4$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_5$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2029); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2079); ZEPHIR_MM_RESTORE(); return; } @@ -6484,7 +6694,7 @@ PHP_METHOD(Tensor_Matrix, equalMatrix) ZEPHIR_CONCAT_VSVS(&_5$$3, &_3$$3, " matrix expected but ", &_4$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_5$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2049); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2099); ZEPHIR_MM_RESTORE(); return; } @@ -6561,7 +6771,7 @@ PHP_METHOD(Tensor_Matrix, notEqualMatrix) ZEPHIR_CONCAT_VSVS(&_5$$3, &_3$$3, " matrix expected but ", &_4$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_5$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2068); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2118); ZEPHIR_MM_RESTORE(); return; } @@ -6639,7 +6849,7 @@ PHP_METHOD(Tensor_Matrix, greaterMatrix) ZEPHIR_CONCAT_VSVS(&_5$$3, &_3$$3, " matrix expected but ", &_4$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_5$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2088); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2138); ZEPHIR_MM_RESTORE(); return; } @@ -6717,7 +6927,7 @@ PHP_METHOD(Tensor_Matrix, greaterEqualMatrix) ZEPHIR_CONCAT_VSVS(&_5$$3, &_3$$3, " matrix expected but ", &_4$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_5$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2108); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2158); ZEPHIR_MM_RESTORE(); return; } @@ -6794,7 +7004,7 @@ PHP_METHOD(Tensor_Matrix, lessMatrix) ZEPHIR_CONCAT_VSVS(&_5$$3, &_3$$3, " matrix expected but ", &_4$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_5$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2127); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2177); ZEPHIR_MM_RESTORE(); return; } @@ -6871,7 +7081,7 @@ PHP_METHOD(Tensor_Matrix, lessEqualMatrix) ZEPHIR_CONCAT_VSVS(&_5$$3, &_3$$3, " matrix expected but ", &_4$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_5$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2146); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2196); ZEPHIR_MM_RESTORE(); return; } @@ -6953,7 +7163,7 @@ PHP_METHOD(Tensor_Matrix, multiplyVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " columns but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2166); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2216); ZEPHIR_MM_RESTORE(); return; } @@ -7036,7 +7246,7 @@ PHP_METHOD(Tensor_Matrix, divideVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " columns but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2186); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2236); ZEPHIR_MM_RESTORE(); return; } @@ -7119,7 +7329,7 @@ PHP_METHOD(Tensor_Matrix, addVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " columns but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2206); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2256); ZEPHIR_MM_RESTORE(); return; } @@ -7202,7 +7412,7 @@ PHP_METHOD(Tensor_Matrix, subtractVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " columns but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2226); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2276); ZEPHIR_MM_RESTORE(); return; } @@ -7285,7 +7495,7 @@ PHP_METHOD(Tensor_Matrix, powVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " columns but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2246); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2296); ZEPHIR_MM_RESTORE(); return; } @@ -7368,7 +7578,7 @@ PHP_METHOD(Tensor_Matrix, modVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " columns but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2266); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2316); ZEPHIR_MM_RESTORE(); return; } @@ -7452,7 +7662,7 @@ PHP_METHOD(Tensor_Matrix, equalVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " columns but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2287); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2337); ZEPHIR_MM_RESTORE(); return; } @@ -7535,7 +7745,7 @@ PHP_METHOD(Tensor_Matrix, notEqualVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " columns but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2307); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2357); ZEPHIR_MM_RESTORE(); return; } @@ -7618,7 +7828,7 @@ PHP_METHOD(Tensor_Matrix, greaterVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " columns but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2327); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2377); ZEPHIR_MM_RESTORE(); return; } @@ -7701,7 +7911,7 @@ PHP_METHOD(Tensor_Matrix, greaterEqualVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " columns but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2347); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2397); ZEPHIR_MM_RESTORE(); return; } @@ -7784,7 +7994,7 @@ PHP_METHOD(Tensor_Matrix, lessVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " columns but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2367); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2417); ZEPHIR_MM_RESTORE(); return; } @@ -7868,7 +8078,7 @@ PHP_METHOD(Tensor_Matrix, lessEqualVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " columns but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2388); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2438); ZEPHIR_MM_RESTORE(); return; } @@ -7951,7 +8161,7 @@ PHP_METHOD(Tensor_Matrix, multiplyColumnVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " rows but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2408); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2458); ZEPHIR_MM_RESTORE(); return; } @@ -8034,7 +8244,7 @@ PHP_METHOD(Tensor_Matrix, divideColumnVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " rows but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2428); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2478); ZEPHIR_MM_RESTORE(); return; } @@ -8117,7 +8327,7 @@ PHP_METHOD(Tensor_Matrix, addColumnVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " rows but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2448); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2498); ZEPHIR_MM_RESTORE(); return; } @@ -8200,7 +8410,7 @@ PHP_METHOD(Tensor_Matrix, subtractColumnVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " rows but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2468); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2518); ZEPHIR_MM_RESTORE(); return; } @@ -8283,7 +8493,7 @@ PHP_METHOD(Tensor_Matrix, powColumnVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " rows but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2488); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2538); ZEPHIR_MM_RESTORE(); return; } @@ -8366,7 +8576,7 @@ PHP_METHOD(Tensor_Matrix, modColumnVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " rows but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2508); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2558); ZEPHIR_MM_RESTORE(); return; } @@ -8449,7 +8659,7 @@ PHP_METHOD(Tensor_Matrix, equalColumnVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " rows but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2528); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2578); ZEPHIR_MM_RESTORE(); return; } @@ -8532,7 +8742,7 @@ PHP_METHOD(Tensor_Matrix, notEqualColumnVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " rows but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2548); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2598); ZEPHIR_MM_RESTORE(); return; } @@ -8615,7 +8825,7 @@ PHP_METHOD(Tensor_Matrix, greaterColumnVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " rows but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2568); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2618); ZEPHIR_MM_RESTORE(); return; } @@ -8698,7 +8908,7 @@ PHP_METHOD(Tensor_Matrix, greaterEqualColumnVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " rows but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2588); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2638); ZEPHIR_MM_RESTORE(); return; } @@ -8781,7 +8991,7 @@ PHP_METHOD(Tensor_Matrix, lessColumnVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " rows but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2608); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2658); ZEPHIR_MM_RESTORE(); return; } @@ -8864,7 +9074,7 @@ PHP_METHOD(Tensor_Matrix, lessEqualColumnVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Matrix A expects ", &_4$$3, " rows but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2628); + zephir_throw_exception_debug(&_2$$3, "tensor/matrix.zep", 2678); ZEPHIR_MM_RESTORE(); return; } @@ -9516,7 +9726,7 @@ PHP_METHOD(Tensor_Matrix, offsetSet) Z_PARAM_ZVAL(values) ZEND_PARSE_PARAMETERS_END(); zephir_fetch_params_without_memory_grow(2, 0, &index, &values); - ZEPHIR_THROW_EXCEPTION_DEBUG_STRW(tensor_exceptions_runtimeexception_ce, "Matrix cannot be mutated directly.", "tensor/matrix.zep", 2809); + ZEPHIR_THROW_EXCEPTION_DEBUG_STRW(tensor_exceptions_runtimeexception_ce, "Matrix cannot be mutated directly.", "tensor/matrix.zep", 2859); return; } @@ -9567,7 +9777,7 @@ PHP_METHOD(Tensor_Matrix, offsetUnset) Z_PARAM_ZVAL(index) ZEND_PARSE_PARAMETERS_END(); zephir_fetch_params_without_memory_grow(1, 0, &index); - ZEPHIR_THROW_EXCEPTION_DEBUG_STRW(tensor_exceptions_runtimeexception_ce, "Matrix cannot be mutated directly.", "tensor/matrix.zep", 2833); + ZEPHIR_THROW_EXCEPTION_DEBUG_STRW(tensor_exceptions_runtimeexception_ce, "Matrix cannot be mutated directly.", "tensor/matrix.zep", 2883); return; } @@ -9627,7 +9837,7 @@ PHP_METHOD(Tensor_Matrix, offsetGet) ZEPHIR_CONCAT_SSVS(&_2$$3, "Row offset must be", " an integer, ", &_1$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_0$$3, "__construct", NULL, 2, &_2$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_0$$3, "tensor/matrix.zep", 2847); + zephir_throw_exception_debug(&_0$$3, "tensor/matrix.zep", 2897); ZEPHIR_MM_RESTORE(); return; } @@ -9644,7 +9854,7 @@ PHP_METHOD(Tensor_Matrix, offsetGet) ZEPHIR_CONCAT_SSVS(&_7$$4, "Row offset out of", " bounds, ", &_6$$4, " given."); ZEPHIR_CALL_METHOD(NULL, &_5$$4, "__construct", NULL, 2, &_7$$4); zephir_check_call_status(); - zephir_throw_exception_debug(&_5$$4, "tensor/matrix.zep", 2852); + zephir_throw_exception_debug(&_5$$4, "tensor/matrix.zep", 2902); ZEPHIR_MM_RESTORE(); return; } @@ -9771,30 +9981,30 @@ PHP_METHOD(Tensor_Matrix, __unserialize) zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__); zephir_fetch_params(1, 1, 0, &data_param); zephir_get_arrval(&data, data_param); - zephir_array_fetch_string(&_0, &data, SL("a"), PH_NOISY | PH_READONLY, "tensor/matrix.zep", 2895); + zephir_array_fetch_string(&_0, &data, SL("a"), PH_NOISY | PH_READONLY, "tensor/matrix.zep", 2945); ZVAL_BOOL(&_1, 0); ZEPHIR_CALL_SELF(&a, "fromArray", NULL, 0, &_0, &_1); zephir_check_call_status(); - zephir_array_fetch_string(&_2, &data, SL("m"), PH_NOISY | PH_READONLY, "tensor/matrix.zep", 2897); + zephir_array_fetch_string(&_2, &data, SL("m"), PH_NOISY | PH_READONLY, "tensor/matrix.zep", 2947); ZEPHIR_CALL_METHOD(&_3, &a, "m", NULL, 0); zephir_check_call_status(); _4 = !ZEPHIR_IS_EQUAL(&_2, &_3); if (!(_4)) { - zephir_array_fetch_string(&_5, &data, SL("n"), PH_NOISY | PH_READONLY, "tensor/matrix.zep", 2897); + zephir_array_fetch_string(&_5, &data, SL("n"), PH_NOISY | PH_READONLY, "tensor/matrix.zep", 2947); ZEPHIR_CALL_METHOD(&_6, &a, "n", NULL, 0); zephir_check_call_status(); _4 = !ZEPHIR_IS_EQUAL(&_5, &_6); } if (UNEXPECTED(_4)) { - ZEPHIR_THROW_EXCEPTION_DEBUG_STR(tensor_exceptions_runtimeexception_ce, "Invalid matrix data.", "tensor/matrix.zep", 2898); + ZEPHIR_THROW_EXCEPTION_DEBUG_STR(tensor_exceptions_runtimeexception_ce, "Invalid matrix data.", "tensor/matrix.zep", 2948); return; } ZEPHIR_CALL_METHOD(&_7, &a, "buffer", NULL, 0); zephir_check_call_status(); zephir_update_property_zval_cached(this_ptr, _zephir_prop_0, 15, &_7); - zephir_array_fetch_string(&_8, &data, SL("m"), PH_NOISY | PH_READONLY, "tensor/matrix.zep", 2902); + zephir_array_fetch_string(&_8, &data, SL("m"), PH_NOISY | PH_READONLY, "tensor/matrix.zep", 2952); zephir_update_property_zval_cached(this_ptr, _zephir_prop_1, 16, &_8); - zephir_array_fetch_string(&_9, &data, SL("n"), PH_NOISY | PH_READONLY, "tensor/matrix.zep", 2903); + zephir_array_fetch_string(&_9, &data, SL("n"), PH_NOISY | PH_READONLY, "tensor/matrix.zep", 2953); zephir_update_property_zval_cached(this_ptr, _zephir_prop_2, 17, &_9); ZEPHIR_MM_RESTORE(); } diff --git a/ext/tensor/matrix.zep.h b/ext/tensor/matrix.zep.h index 1e2d74d..008b3a4 100644 --- a/ext/tensor/matrix.zep.h +++ b/ext/tensor/matrix.zep.h @@ -71,11 +71,13 @@ PHP_METHOD(Tensor_Matrix, reciprocal); PHP_METHOD(Tensor_Matrix, abs); PHP_METHOD(Tensor_Matrix, square); PHP_METHOD(Tensor_Matrix, sqrt); +PHP_METHOD(Tensor_Matrix, rsqrt); PHP_METHOD(Tensor_Matrix, exp); PHP_METHOD(Tensor_Matrix, expm1); PHP_METHOD(Tensor_Matrix, log); PHP_METHOD(Tensor_Matrix, log1p); PHP_METHOD(Tensor_Matrix, sigmoid); +PHP_METHOD(Tensor_Matrix, softplus); PHP_METHOD(Tensor_Matrix, sin); PHP_METHOD(Tensor_Matrix, asin); PHP_METHOD(Tensor_Matrix, cos); @@ -83,6 +85,8 @@ PHP_METHOD(Tensor_Matrix, acos); PHP_METHOD(Tensor_Matrix, tan); PHP_METHOD(Tensor_Matrix, atan); PHP_METHOD(Tensor_Matrix, tanh); +PHP_METHOD(Tensor_Matrix, sinh); +PHP_METHOD(Tensor_Matrix, cosh); PHP_METHOD(Tensor_Matrix, rad2deg); PHP_METHOD(Tensor_Matrix, deg2rad); PHP_METHOD(Tensor_Matrix, sum); @@ -95,6 +99,7 @@ PHP_METHOD(Tensor_Matrix, mean); PHP_METHOD(Tensor_Matrix, median); PHP_METHOD(Tensor_Matrix, quantile); PHP_METHOD(Tensor_Matrix, softmax); +PHP_METHOD(Tensor_Matrix, erf); PHP_METHOD(Tensor_Matrix, variance); PHP_METHOD(Tensor_Matrix, covariance); PHP_METHOD(Tensor_Matrix, round); @@ -419,6 +424,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_matrix_sqrt, 0, 0, Tensor\\Matrix, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_matrix_rsqrt, 0, 0, Tensor\\Matrix, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_matrix_exp, 0, 0, Tensor\\Matrix, 0) ZEND_END_ARG_INFO() @@ -435,6 +443,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_matrix_sigmoid, 0, 0, Tensor\\Matrix, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_matrix_softplus, 0, 0, Tensor\\Matrix, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_matrix_sin, 0, 0, Tensor\\Matrix, 0) ZEND_END_ARG_INFO() @@ -456,6 +467,12 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_matrix_tanh, 0, 0, Tensor\\Matrix, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_matrix_sinh, 0, 0, Tensor\\Matrix, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_matrix_cosh, 0, 0, Tensor\\Matrix, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_matrix_rad2deg, 0, 0, Tensor\\Matrix, 0) ZEND_END_ARG_INFO() @@ -493,6 +510,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_matrix_softmax, 0, 0, Tensor\\Matrix, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_matrix_erf, 0, 0, Tensor\\Matrix, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_matrix_variance, 0, 0, Tensor\\ColumnVector, 0) ZEND_ARG_INFO(0, mean) ZEND_END_ARG_INFO() @@ -843,11 +863,13 @@ ZEPHIR_INIT_FUNCS(tensor_matrix_method_entry) { PHP_ME(Tensor_Matrix, abs, arginfo_tensor_matrix_abs, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, square, arginfo_tensor_matrix_square, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, sqrt, arginfo_tensor_matrix_sqrt, ZEND_ACC_PUBLIC) + PHP_ME(Tensor_Matrix, rsqrt, arginfo_tensor_matrix_rsqrt, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, exp, arginfo_tensor_matrix_exp, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, expm1, arginfo_tensor_matrix_expm1, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, log, arginfo_tensor_matrix_log, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, log1p, arginfo_tensor_matrix_log1p, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, sigmoid, arginfo_tensor_matrix_sigmoid, ZEND_ACC_PUBLIC) + PHP_ME(Tensor_Matrix, softplus, arginfo_tensor_matrix_softplus, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, sin, arginfo_tensor_matrix_sin, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, asin, arginfo_tensor_matrix_asin, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, cos, arginfo_tensor_matrix_cos, ZEND_ACC_PUBLIC) @@ -855,6 +877,8 @@ ZEPHIR_INIT_FUNCS(tensor_matrix_method_entry) { PHP_ME(Tensor_Matrix, tan, arginfo_tensor_matrix_tan, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, atan, arginfo_tensor_matrix_atan, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, tanh, arginfo_tensor_matrix_tanh, ZEND_ACC_PUBLIC) + PHP_ME(Tensor_Matrix, sinh, arginfo_tensor_matrix_sinh, ZEND_ACC_PUBLIC) + PHP_ME(Tensor_Matrix, cosh, arginfo_tensor_matrix_cosh, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, rad2deg, arginfo_tensor_matrix_rad2deg, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, deg2rad, arginfo_tensor_matrix_deg2rad, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, sum, arginfo_tensor_matrix_sum, ZEND_ACC_PUBLIC) @@ -867,6 +891,7 @@ ZEPHIR_INIT_FUNCS(tensor_matrix_method_entry) { PHP_ME(Tensor_Matrix, median, arginfo_tensor_matrix_median, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, quantile, arginfo_tensor_matrix_quantile, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, softmax, arginfo_tensor_matrix_softmax, ZEND_ACC_PUBLIC) + PHP_ME(Tensor_Matrix, erf, arginfo_tensor_matrix_erf, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, variance, arginfo_tensor_matrix_variance, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, covariance, arginfo_tensor_matrix_covariance, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Matrix, round, arginfo_tensor_matrix_round, ZEND_ACC_PUBLIC) diff --git a/ext/tensor/special.zep.c b/ext/tensor/special.zep.c index 51f5621..53ad273 100644 --- a/ext/tensor/special.zep.c +++ b/ext/tensor/special.zep.c @@ -19,9 +19,27 @@ ZEPHIR_INIT_CLASS(Tensor_Special) return SUCCESS; } +/** + * Return the element-wise logistic function i.e. 1 / (1 + exp(-x)). + * + * @return mixed + */ +ZEPHIR_DOC_METHOD(Tensor_Special, sigmoid); +/** + * Return the element-wise softplus i.e. log(1 + exp(x)). + * + * @return mixed + */ +ZEPHIR_DOC_METHOD(Tensor_Special, softplus); /** * Return the softmax of the tensor i.e. each row normalized to sum to 1. * * @return mixed */ ZEPHIR_DOC_METHOD(Tensor_Special, softmax); +/** + * Return the element-wise Gaussian error function. + * + * @return mixed + */ +ZEPHIR_DOC_METHOD(Tensor_Special, erf); diff --git a/ext/tensor/special.zep.h b/ext/tensor/special.zep.h index 4637411..ddfd979 100644 --- a/ext/tensor/special.zep.h +++ b/ext/tensor/special.zep.h @@ -3,10 +3,22 @@ extern zend_class_entry *tensor_special_ce; ZEPHIR_INIT_CLASS(Tensor_Special); +ZEND_BEGIN_ARG_INFO_EX(arginfo_tensor_special_sigmoid, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_tensor_special_softplus, 0, 0, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_tensor_special_softmax, 0, 0, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_tensor_special_erf, 0, 0, 0) +ZEND_END_ARG_INFO() + ZEPHIR_INIT_FUNCS(tensor_special_method_entry) { + PHP_ABSTRACT_ME(Tensor_Special, sigmoid, arginfo_tensor_special_sigmoid) + PHP_ABSTRACT_ME(Tensor_Special, softplus, arginfo_tensor_special_softplus) PHP_ABSTRACT_ME(Tensor_Special, softmax, arginfo_tensor_special_softmax) + PHP_ABSTRACT_ME(Tensor_Special, erf, arginfo_tensor_special_erf) PHP_FE_END }; diff --git a/ext/tensor/trigonometric.zep.c b/ext/tensor/trigonometric.zep.c index 06343b3..723997e 100644 --- a/ext/tensor/trigonometric.zep.c +++ b/ext/tensor/trigonometric.zep.c @@ -65,6 +65,18 @@ ZEPHIR_DOC_METHOD(Tensor_Trigonometric, atan); * @return mixed */ ZEPHIR_DOC_METHOD(Tensor_Trigonometric, tanh); +/** + * Return the element-wise hyperbolic sine. + * + * @return mixed + */ +ZEPHIR_DOC_METHOD(Tensor_Trigonometric, sinh); +/** + * Return the element-wise hyperbolic cosine. + * + * @return mixed + */ +ZEPHIR_DOC_METHOD(Tensor_Trigonometric, cosh); /** * Convert angles from radians to degrees. * diff --git a/ext/tensor/trigonometric.zep.h b/ext/tensor/trigonometric.zep.h index 56ce624..668d5c2 100644 --- a/ext/tensor/trigonometric.zep.h +++ b/ext/tensor/trigonometric.zep.h @@ -24,6 +24,12 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_tensor_trigonometric_tanh, 0, 0, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_tensor_trigonometric_sinh, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_tensor_trigonometric_cosh, 0, 0, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_tensor_trigonometric_rad2deg, 0, 0, 0) ZEND_END_ARG_INFO() @@ -38,6 +44,8 @@ ZEPHIR_INIT_FUNCS(tensor_trigonometric_method_entry) { PHP_ABSTRACT_ME(Tensor_Trigonometric, tan, arginfo_tensor_trigonometric_tan) PHP_ABSTRACT_ME(Tensor_Trigonometric, atan, arginfo_tensor_trigonometric_atan) PHP_ABSTRACT_ME(Tensor_Trigonometric, tanh, arginfo_tensor_trigonometric_tanh) + PHP_ABSTRACT_ME(Tensor_Trigonometric, sinh, arginfo_tensor_trigonometric_sinh) + PHP_ABSTRACT_ME(Tensor_Trigonometric, cosh, arginfo_tensor_trigonometric_cosh) PHP_ABSTRACT_ME(Tensor_Trigonometric, rad2deg, arginfo_tensor_trigonometric_rad2deg) PHP_ABSTRACT_ME(Tensor_Trigonometric, deg2rad, arginfo_tensor_trigonometric_deg2rad) PHP_FE_END diff --git a/ext/tensor/unary.zep.c b/ext/tensor/unary.zep.c index 81acfb1..55001c7 100644 --- a/ext/tensor/unary.zep.c +++ b/ext/tensor/unary.zep.c @@ -39,6 +39,12 @@ ZEPHIR_DOC_METHOD(Tensor_Unary, square); * @return mixed */ ZEPHIR_DOC_METHOD(Tensor_Unary, sqrt); +/** + * Return the reciprocal square root of the tensor. + * + * @return mixed + */ +ZEPHIR_DOC_METHOD(Tensor_Unary, rsqrt); /** * Return the exponential of the tensor. * @@ -64,12 +70,6 @@ ZEPHIR_DOC_METHOD(Tensor_Unary, log); * @return mixed */ ZEPHIR_DOC_METHOD(Tensor_Unary, log1p); -/** - * Return the element-wise logistic function i.e. 1 / (1 + exp(-x)). - * - * @return mixed - */ -ZEPHIR_DOC_METHOD(Tensor_Unary, sigmoid); /** * Round the elements in the tensor to a given decimal place. * diff --git a/ext/tensor/unary.zep.h b/ext/tensor/unary.zep.h index 4e75644..52bedc7 100644 --- a/ext/tensor/unary.zep.h +++ b/ext/tensor/unary.zep.h @@ -12,6 +12,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_tensor_unary_sqrt, 0, 0, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_tensor_unary_rsqrt, 0, 0, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_tensor_unary_exp, 0, 0, 0) ZEND_END_ARG_INFO() @@ -25,9 +28,6 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_tensor_unary_log1p, 0, 0, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_tensor_unary_sigmoid, 0, 0, 0) -ZEND_END_ARG_INFO() - ZEND_BEGIN_ARG_INFO_EX(arginfo_tensor_unary_round, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, precision, IS_LONG, 0, "0") ZEND_END_ARG_INFO() @@ -61,11 +61,11 @@ ZEPHIR_INIT_FUNCS(tensor_unary_method_entry) { PHP_ABSTRACT_ME(Tensor_Unary, abs, arginfo_tensor_unary_abs) PHP_ABSTRACT_ME(Tensor_Unary, square, arginfo_tensor_unary_square) PHP_ABSTRACT_ME(Tensor_Unary, sqrt, arginfo_tensor_unary_sqrt) + PHP_ABSTRACT_ME(Tensor_Unary, rsqrt, arginfo_tensor_unary_rsqrt) PHP_ABSTRACT_ME(Tensor_Unary, exp, arginfo_tensor_unary_exp) PHP_ABSTRACT_ME(Tensor_Unary, expm1, arginfo_tensor_unary_expm1) PHP_ABSTRACT_ME(Tensor_Unary, log, arginfo_tensor_unary_log) PHP_ABSTRACT_ME(Tensor_Unary, log1p, arginfo_tensor_unary_log1p) - PHP_ABSTRACT_ME(Tensor_Unary, sigmoid, arginfo_tensor_unary_sigmoid) PHP_ABSTRACT_ME(Tensor_Unary, round, arginfo_tensor_unary_round) PHP_ABSTRACT_ME(Tensor_Unary, floor, arginfo_tensor_unary_floor) PHP_ABSTRACT_ME(Tensor_Unary, ceil, arginfo_tensor_unary_ceil) diff --git a/ext/tensor/vector.zep.c b/ext/tensor/vector.zep.c index 3def1e0..2a46c1e 100644 --- a/ext/tensor/vector.zep.c +++ b/ext/tensor/vector.zep.c @@ -554,24 +554,27 @@ PHP_METHOD(Tensor_Vector, uniform) */ PHP_METHOD(Tensor_Vector, range) { - zval _2$$4, _9$$5; - zend_bool _0, _3; + zval _2$$4, _15$$6; + zend_bool _0, _6, _8, _10; zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL; - zephir_fcall_cache_entry *_6 = NULL; + zephir_fcall_cache_entry *_5 = NULL, *_12 = NULL; zend_long ZEPHIR_LAST_CALL_STATUS; - zval *start_param = NULL, *end_param = NULL, *interval_param = NULL, _4, _5, _7, _10, _11, _12, _1$$4, _8$$5; + zval *start_param = NULL, *end_param = NULL, *interval_param = NULL, _3, _4, _7, _9, _11, _13, _16, _17, _18, _1$$4, _14$$6; double start, end, interval; + ZVAL_UNDEF(&_3); ZVAL_UNDEF(&_4); - ZVAL_UNDEF(&_5); ZVAL_UNDEF(&_7); - ZVAL_UNDEF(&_10); + ZVAL_UNDEF(&_9); ZVAL_UNDEF(&_11); - ZVAL_UNDEF(&_12); + ZVAL_UNDEF(&_13); + ZVAL_UNDEF(&_16); + ZVAL_UNDEF(&_17); + ZVAL_UNDEF(&_18); ZVAL_UNDEF(&_1$$4); - ZVAL_UNDEF(&_8$$5); + ZVAL_UNDEF(&_14$$6); ZVAL_UNDEF(&_2$$4); - ZVAL_UNDEF(&_9$$5); + ZVAL_UNDEF(&_15$$6); ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_DOUBLE(start) Z_PARAM_DOUBLE(end) @@ -604,34 +607,55 @@ PHP_METHOD(Tensor_Vector, range) ZEPHIR_MM_RESTORE(); return; } - _3 = start != end; - if (_3) { - ZVAL_DOUBLE(&_4, (end - start)); - ZEPHIR_CALL_FUNCTION(&_5, "abs", &_6, 6, &_4); + ZVAL_DOUBLE(&_3, start); + ZEPHIR_CALL_FUNCTION(&_4, "is_finite", &_5, 6, &_3); + zephir_check_call_status(); + _6 = !zephir_is_true(&_4); + if (!(_6)) { + ZVAL_DOUBLE(&_3, end); + ZEPHIR_CALL_FUNCTION(&_7, "is_finite", &_5, 6, &_3); zephir_check_call_status(); - ZVAL_DOUBLE(&_4, interval); - ZEPHIR_CALL_FUNCTION(&_7, "abs", &_6, 6, &_4); + _6 = !zephir_is_true(&_7); + } + _8 = _6; + if (!(_8)) { + ZVAL_DOUBLE(&_3, interval); + ZEPHIR_CALL_FUNCTION(&_9, "is_finite", &_5, 6, &_3); zephir_check_call_status(); - _3 = ZEPHIR_LT(&_5, &_7); + _8 = !zephir_is_true(&_9); } - if (UNEXPECTED(_3)) { - ZEPHIR_INIT_VAR(&_8$$5); - object_init_ex(&_8$$5, tensor_exceptions_invalidargumentexception_ce); - ZEPHIR_INIT_VAR(&_9$$5); - ZEPHIR_CONCAT_SS(&_9$$5, "Interval must be smaller", " than the range spanned by the start and end."); - ZEPHIR_CALL_METHOD(NULL, &_8$$5, "__construct", NULL, 2, &_9$$5); + if (UNEXPECTED(_8)) { + ZEPHIR_THROW_EXCEPTION_DEBUG_STR(tensor_exceptions_invalidargumentexception_ce, "Start, end, and interval must be finite.", "tensor/vector.zep", 225); + return; + } + _10 = start != end; + if (_10) { + ZVAL_DOUBLE(&_3, (end - start)); + ZEPHIR_CALL_FUNCTION(&_11, "abs", &_12, 7, &_3); zephir_check_call_status(); - zephir_throw_exception_debug(&_8$$5, "tensor/vector.zep", 226); + ZVAL_DOUBLE(&_3, interval); + ZEPHIR_CALL_FUNCTION(&_13, "abs", &_12, 7, &_3); + zephir_check_call_status(); + _10 = ZEPHIR_LT(&_11, &_13); + } + if (UNEXPECTED(_10)) { + ZEPHIR_INIT_VAR(&_14$$6); + object_init_ex(&_14$$6, tensor_exceptions_invalidargumentexception_ce); + ZEPHIR_INIT_VAR(&_15$$6); + ZEPHIR_CONCAT_SS(&_15$$6, "Interval must be smaller", " than the range spanned by the start and end."); + ZEPHIR_CALL_METHOD(NULL, &_14$$6, "__construct", NULL, 2, &_15$$6); + zephir_check_call_status(); + zephir_throw_exception_debug(&_14$$6, "tensor/vector.zep", 230); ZEPHIR_MM_RESTORE(); return; } object_init_ex(return_value, zend_get_called_scope(execute_data)); - ZEPHIR_INIT_VAR(&_10); - ZVAL_DOUBLE(&_4, start); - ZVAL_DOUBLE(&_11, end); - ZVAL_DOUBLE(&_12, interval); - tensor_range(&_10, &_4, &_11, &_12); - ZEPHIR_CALL_METHOD(NULL, return_value, "__construct", NULL, 3, &_10); + ZEPHIR_INIT_VAR(&_16); + ZVAL_DOUBLE(&_3, start); + ZVAL_DOUBLE(&_17, end); + ZVAL_DOUBLE(&_18, interval); + tensor_range(&_16, &_3, &_17, &_18); + ZEPHIR_CALL_METHOD(NULL, return_value, "__construct", NULL, 3, &_16); zephir_check_call_status(); RETURN_MM(); } @@ -669,7 +693,7 @@ PHP_METHOD(Tensor_Vector, linspace) zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__); zephir_fetch_params(1, 3, 0, &min_param, &max_param, &n_param); if (UNEXPECTED(min > max)) { - ZEPHIR_THROW_EXCEPTION_DEBUG_STR(tensor_exceptions_invalidargumentexception_ce, "Minimum must be less than maximum.", "tensor/vector.zep", 244); + ZEPHIR_THROW_EXCEPTION_DEBUG_STR(tensor_exceptions_invalidargumentexception_ce, "Minimum must be less than maximum.", "tensor/vector.zep", 248); return; } if (UNEXPECTED(n < 2)) { @@ -682,7 +706,7 @@ PHP_METHOD(Tensor_Vector, linspace) ZEPHIR_CONCAT_SSVS(&_3$$4, "Number of elements", " must be greater than 1, ", &_2$$4, " given."); ZEPHIR_CALL_METHOD(NULL, &_0$$4, "__construct", NULL, 2, &_3$$4); zephir_check_call_status(); - zephir_throw_exception_debug(&_0$$4, "tensor/vector.zep", 249); + zephir_throw_exception_debug(&_0$$4, "tensor/vector.zep", 253); ZEPHIR_MM_RESTORE(); return; } @@ -766,7 +790,7 @@ PHP_METHOD(Tensor_Vector, __construct) ZEPHIR_CONCAT_SS(&_2$$3, "Argument must wrap a buffer of", " type double."); ZEPHIR_CALL_METHOD(NULL, &_1$$3, "__construct", NULL, 2, &_2$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_1$$3, "tensor/vector.zep", 276); + zephir_throw_exception_debug(&_1$$3, "tensor/vector.zep", 280); ZEPHIR_MM_RESTORE(); return; } @@ -1025,7 +1049,7 @@ PHP_METHOD(Tensor_Vector, reshape) ZEPHIR_CONCAT_SS(&_2$$3, "The number of rows", " and/or columns cannot be less than 0."); ZEPHIR_CALL_METHOD(NULL, &_1$$3, "__construct", NULL, 2, &_2$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_1$$3, "tensor/vector.zep", 387); + zephir_throw_exception_debug(&_1$$3, "tensor/vector.zep", 391); ZEPHIR_MM_RESTORE(); return; } @@ -1042,7 +1066,7 @@ PHP_METHOD(Tensor_Vector, reshape) ZEPHIR_CONCAT_VSSVS(&_7$$4, &_6$$4, " elements", " are needed but vector only has ", &_5$$4, "."); ZEPHIR_CALL_METHOD(NULL, &_4$$4, "__construct", NULL, 2, &_7$$4); zephir_check_call_status(); - zephir_throw_exception_debug(&_4$$4, "tensor/vector.zep", 394); + zephir_throw_exception_debug(&_4$$4, "tensor/vector.zep", 398); ZEPHIR_MM_RESTORE(); return; } @@ -1114,7 +1138,7 @@ PHP_METHOD(Tensor_Vector, map) zephir_read_property_cached(&_0, this_ptr, _zephir_prop_0, 1, PH_NOISY_CC | PH_READONLY); ZEPHIR_CALL_METHOD(&_1, &_0, "toArray", NULL, 0); zephir_check_call_status(); - ZEPHIR_CALL_FUNCTION(&_2, "array_map", NULL, 7, callback, &_1); + ZEPHIR_CALL_FUNCTION(&_2, "array_map", NULL, 8, callback, &_1); zephir_check_call_status(); ZVAL_BOOL(&_3, 0); ZEPHIR_RETURN_CALL_STATIC("fromArray", NULL, 0, &_2, &_3); @@ -1164,7 +1188,7 @@ PHP_METHOD(Tensor_Vector, reduce) ZEPHIR_CALL_METHOD(&_1, &_0, "toArray", NULL, 0); zephir_check_call_status(); ZVAL_DOUBLE(&_2, initial); - ZEPHIR_RETURN_CALL_FUNCTION("array_reduce", NULL, 8, &_1, callback, &_2); + ZEPHIR_RETURN_CALL_FUNCTION("array_reduce", NULL, 9, &_1, callback, &_2); zephir_check_call_status(); RETURN_MM(); } @@ -1226,7 +1250,7 @@ PHP_METHOD(Tensor_Vector, dot) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A expects ", &_4$$3, " elements but vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 449); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 453); ZEPHIR_MM_RESTORE(); return; } @@ -1315,7 +1339,7 @@ PHP_METHOD(Tensor_Vector, convolve) ZEPHIR_CALL_METHOD(&_0, b, "size", NULL, 0); zephir_check_call_status(); if (UNEXPECTED(ZEPHIR_LT_LONG(&_0, 1))) { - ZEPHIR_THROW_EXCEPTION_DEBUG_STR(tensor_exceptions_invalidargumentexception_ce, "Vector B cannot be empty.", "tensor/vector.zep", 474); + ZEPHIR_THROW_EXCEPTION_DEBUG_STR(tensor_exceptions_invalidargumentexception_ce, "Vector B cannot be empty.", "tensor/vector.zep", 478); return; } if (UNEXPECTED(stride < 1)) { @@ -1328,7 +1352,7 @@ PHP_METHOD(Tensor_Vector, convolve) ZEPHIR_CONCAT_SSVS(&_5$$4, "Stride cannot be", " less than 1, ", &_3$$4, " given."); ZEPHIR_CALL_METHOD(NULL, &_1$$4, "__construct", NULL, 2, &_5$$4); zephir_check_call_status(); - zephir_throw_exception_debug(&_1$$4, "tensor/vector.zep", 479); + zephir_throw_exception_debug(&_1$$4, "tensor/vector.zep", 483); ZEPHIR_MM_RESTORE(); return; } @@ -1342,7 +1366,7 @@ PHP_METHOD(Tensor_Vector, convolve) ZEPHIR_CONCAT_SSVS(&_9$$5, "Padding cannot be", " negative, ", &_8$$5, " given."); ZEPHIR_CALL_METHOD(NULL, &_6$$5, "__construct", NULL, 2, &_9$$5); zephir_check_call_status(); - zephir_throw_exception_debug(&_6$$5, "tensor/vector.zep", 484); + zephir_throw_exception_debug(&_6$$5, "tensor/vector.zep", 488); ZEPHIR_MM_RESTORE(); return; } @@ -1374,7 +1398,7 @@ PHP_METHOD(Tensor_Vector, convolve) ZEPHIR_CONCAT_SSVS(&_21$$6, "Vector B cannot be larger than", " Vector A plus the padding of ", &_20$$6, "."); ZEPHIR_CALL_METHOD(NULL, &_18$$6, "__construct", NULL, 2, &_21$$6); zephir_check_call_status(); - zephir_throw_exception_debug(&_18$$6, "tensor/vector.zep", 494); + zephir_throw_exception_debug(&_18$$6, "tensor/vector.zep", 498); ZEPHIR_MM_RESTORE(); return; } @@ -1587,7 +1611,7 @@ PHP_METHOD(Tensor_Vector, pNorm) ZEPHIR_CONCAT_SSVS(&_3$$3, "P must be greater", " than 0, ", &_2$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_0$$3, "__construct", NULL, 2, &_3$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_0$$3, "tensor/vector.zep", 566); + zephir_throw_exception_debug(&_0$$3, "tensor/vector.zep", 570); ZEPHIR_MM_RESTORE(); return; } @@ -1599,7 +1623,7 @@ PHP_METHOD(Tensor_Vector, pNorm) ZEPHIR_CALL_METHOD(&_7, &_5, "sum", NULL, 0); zephir_check_call_status(); ZVAL_DOUBLE(&_6, zephir_safe_div_double_double(1.0, p)); - ZEPHIR_RETURN_CALL_FUNCTION("pow", NULL, 9, &_7, &_6); + ZEPHIR_RETURN_CALL_FUNCTION("pow", NULL, 10, &_7, &_6); zephir_check_call_status(); RETURN_MM(); } @@ -1680,7 +1704,7 @@ PHP_METHOD(Tensor_Vector, multiply) ZEPHIR_CONCAT_SS(&_2, "Cannot multiply", " vector by the given input."); ZEPHIR_CALL_METHOD(NULL, &_1, "__construct", NULL, 2, &_2); zephir_check_call_status(); - zephir_throw_exception_debug(&_1, "tensor/vector.zep", 606); + zephir_throw_exception_debug(&_1, "tensor/vector.zep", 610); ZEPHIR_MM_RESTORE(); return; } @@ -1737,7 +1761,7 @@ PHP_METHOD(Tensor_Vector, divide) ZEPHIR_CONCAT_SS(&_2, "Cannot divide", " vector by the given input."); ZEPHIR_CALL_METHOD(NULL, &_1, "__construct", NULL, 2, &_2); zephir_check_call_status(); - zephir_throw_exception_debug(&_1, "tensor/vector.zep", 633); + zephir_throw_exception_debug(&_1, "tensor/vector.zep", 637); ZEPHIR_MM_RESTORE(); return; } @@ -1795,7 +1819,7 @@ PHP_METHOD(Tensor_Vector, add) ZEPHIR_CONCAT_SS(&_2, "Cannot add", " vector by the given input."); ZEPHIR_CALL_METHOD(NULL, &_1, "__construct", NULL, 2, &_2); zephir_check_call_status(); - zephir_throw_exception_debug(&_1, "tensor/vector.zep", 661); + zephir_throw_exception_debug(&_1, "tensor/vector.zep", 665); ZEPHIR_MM_RESTORE(); return; } @@ -1853,7 +1877,7 @@ PHP_METHOD(Tensor_Vector, subtract) ZEPHIR_CONCAT_SS(&_2, "Cannot subtract", " vector from the given input."); ZEPHIR_CALL_METHOD(NULL, &_1, "__construct", NULL, 2, &_2); zephir_check_call_status(); - zephir_throw_exception_debug(&_1, "tensor/vector.zep", 689); + zephir_throw_exception_debug(&_1, "tensor/vector.zep", 693); ZEPHIR_MM_RESTORE(); return; } @@ -1911,7 +1935,7 @@ PHP_METHOD(Tensor_Vector, pow) ZEPHIR_CONCAT_SS(&_2, "Cannot raise", " vector to the power of the given input."); ZEPHIR_CALL_METHOD(NULL, &_1, "__construct", NULL, 2, &_2); zephir_check_call_status(); - zephir_throw_exception_debug(&_1, "tensor/vector.zep", 717); + zephir_throw_exception_debug(&_1, "tensor/vector.zep", 721); ZEPHIR_MM_RESTORE(); return; } @@ -1969,7 +1993,7 @@ PHP_METHOD(Tensor_Vector, mod) ZEPHIR_CONCAT_SS(&_2, "Cannot mod", " vector with the given input."); ZEPHIR_CALL_METHOD(NULL, &_1, "__construct", NULL, 2, &_2); zephir_check_call_status(); - zephir_throw_exception_debug(&_1, "tensor/vector.zep", 745); + zephir_throw_exception_debug(&_1, "tensor/vector.zep", 749); ZEPHIR_MM_RESTORE(); return; } @@ -2027,7 +2051,7 @@ PHP_METHOD(Tensor_Vector, equal) ZEPHIR_CONCAT_SS(&_2, "Cannot compare", " vector to the given input."); ZEPHIR_CALL_METHOD(NULL, &_1, "__construct", NULL, 2, &_2); zephir_check_call_status(); - zephir_throw_exception_debug(&_1, "tensor/vector.zep", 773); + zephir_throw_exception_debug(&_1, "tensor/vector.zep", 777); ZEPHIR_MM_RESTORE(); return; } @@ -2085,7 +2109,7 @@ PHP_METHOD(Tensor_Vector, notEqual) ZEPHIR_CONCAT_SS(&_2, "Cannot compare", " vector to the given input."); ZEPHIR_CALL_METHOD(NULL, &_1, "__construct", NULL, 2, &_2); zephir_check_call_status(); - zephir_throw_exception_debug(&_1, "tensor/vector.zep", 801); + zephir_throw_exception_debug(&_1, "tensor/vector.zep", 805); ZEPHIR_MM_RESTORE(); return; } @@ -2143,7 +2167,7 @@ PHP_METHOD(Tensor_Vector, greater) ZEPHIR_CONCAT_SS(&_2, "Cannot compare", " vector to the given input."); ZEPHIR_CALL_METHOD(NULL, &_1, "__construct", NULL, 2, &_2); zephir_check_call_status(); - zephir_throw_exception_debug(&_1, "tensor/vector.zep", 829); + zephir_throw_exception_debug(&_1, "tensor/vector.zep", 833); ZEPHIR_MM_RESTORE(); return; } @@ -2201,7 +2225,7 @@ PHP_METHOD(Tensor_Vector, greaterEqual) ZEPHIR_CONCAT_SS(&_2, "Cannot compare", " vector to the given input."); ZEPHIR_CALL_METHOD(NULL, &_1, "__construct", NULL, 2, &_2); zephir_check_call_status(); - zephir_throw_exception_debug(&_1, "tensor/vector.zep", 857); + zephir_throw_exception_debug(&_1, "tensor/vector.zep", 861); ZEPHIR_MM_RESTORE(); return; } @@ -2259,7 +2283,7 @@ PHP_METHOD(Tensor_Vector, less) ZEPHIR_CONCAT_SS(&_2, "Cannot compare", " vector to the given input."); ZEPHIR_CALL_METHOD(NULL, &_1, "__construct", NULL, 2, &_2); zephir_check_call_status(); - zephir_throw_exception_debug(&_1, "tensor/vector.zep", 885); + zephir_throw_exception_debug(&_1, "tensor/vector.zep", 889); ZEPHIR_MM_RESTORE(); return; } @@ -2317,7 +2341,7 @@ PHP_METHOD(Tensor_Vector, lessEqual) ZEPHIR_CONCAT_SS(&_2, "Cannot compare", " vector to the given input."); ZEPHIR_CALL_METHOD(NULL, &_1, "__construct", NULL, 2, &_2); zephir_check_call_status(); - zephir_throw_exception_debug(&_1, "tensor/vector.zep", 913); + zephir_throw_exception_debug(&_1, "tensor/vector.zep", 917); ZEPHIR_MM_RESTORE(); return; } @@ -2429,6 +2453,36 @@ PHP_METHOD(Tensor_Vector, sqrt) RETURN_MM(); } +/** + * Return the reciprocal square root of the vector. + * + * @return self + */ +PHP_METHOD(Tensor_Vector, rsqrt) +{ + zval _0, _1; + zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL; + zend_long ZEPHIR_LAST_CALL_STATUS; + zval *this_ptr = getThis(); + + ZVAL_UNDEF(&_0); + ZVAL_UNDEF(&_1); + static zend_string *_zephir_prop_0 = NULL; + if (UNEXPECTED(!_zephir_prop_0)) { + _zephir_prop_0 = zend_string_init("a", 1, 1); + } + ZEPHIR_METHOD_GLOBALS_PTR = pecalloc(1, sizeof(zephir_method_globals), 0); + zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__); + + object_init_ex(return_value, zend_get_called_scope(execute_data)); + ZEPHIR_INIT_VAR(&_0); + zephir_read_property_cached(&_1, this_ptr, _zephir_prop_0, 1, PH_NOISY_CC | PH_READONLY); + tensor_rsqrt(&_0, &_1); + ZEPHIR_CALL_METHOD(NULL, return_value, "__construct", NULL, 3, &_0); + zephir_check_call_status(); + RETURN_MM(); +} + /** * Exponentiate each element in the vector. * @@ -2538,7 +2592,7 @@ PHP_METHOD(Tensor_Vector, log) ZEPHIR_CONCAT_SSVS(&_3$$3, "Log base must be greater", " than 0, ", &_2$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_0$$3, "__construct", NULL, 2, &_3$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_0$$3, "tensor/vector.zep", 987); + zephir_throw_exception_debug(&_0$$3, "tensor/vector.zep", 1001); ZEPHIR_MM_RESTORE(); return; } @@ -2621,6 +2675,36 @@ PHP_METHOD(Tensor_Vector, sigmoid) RETURN_MM(); } +/** + * Return the element-wise softplus i.e. log(1 + exp(x)). + * + * @return self + */ +PHP_METHOD(Tensor_Vector, softplus) +{ + zval _0, _1; + zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL; + zend_long ZEPHIR_LAST_CALL_STATUS; + zval *this_ptr = getThis(); + + ZVAL_UNDEF(&_0); + ZVAL_UNDEF(&_1); + static zend_string *_zephir_prop_0 = NULL; + if (UNEXPECTED(!_zephir_prop_0)) { + _zephir_prop_0 = zend_string_init("a", 1, 1); + } + ZEPHIR_METHOD_GLOBALS_PTR = pecalloc(1, sizeof(zephir_method_globals), 0); + zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__); + + object_init_ex(return_value, zend_get_called_scope(execute_data)); + ZEPHIR_INIT_VAR(&_0); + zephir_read_property_cached(&_1, this_ptr, _zephir_prop_0, 1, PH_NOISY_CC | PH_READONLY); + tensor_softplus(&_0, &_1); + ZEPHIR_CALL_METHOD(NULL, return_value, "__construct", NULL, 3, &_0); + zephir_check_call_status(); + RETURN_MM(); +} + /** * Return the sine of this vector. * @@ -2831,6 +2915,66 @@ PHP_METHOD(Tensor_Vector, tanh) RETURN_MM(); } +/** + * Return the element-wise hyperbolic sine of the vector. + * + * @return self + */ +PHP_METHOD(Tensor_Vector, sinh) +{ + zval _0, _1; + zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL; + zend_long ZEPHIR_LAST_CALL_STATUS; + zval *this_ptr = getThis(); + + ZVAL_UNDEF(&_0); + ZVAL_UNDEF(&_1); + static zend_string *_zephir_prop_0 = NULL; + if (UNEXPECTED(!_zephir_prop_0)) { + _zephir_prop_0 = zend_string_init("a", 1, 1); + } + ZEPHIR_METHOD_GLOBALS_PTR = pecalloc(1, sizeof(zephir_method_globals), 0); + zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__); + + object_init_ex(return_value, zend_get_called_scope(execute_data)); + ZEPHIR_INIT_VAR(&_0); + zephir_read_property_cached(&_1, this_ptr, _zephir_prop_0, 1, PH_NOISY_CC | PH_READONLY); + tensor_sinh(&_0, &_1); + ZEPHIR_CALL_METHOD(NULL, return_value, "__construct", NULL, 3, &_0); + zephir_check_call_status(); + RETURN_MM(); +} + +/** + * Return the element-wise hyperbolic cosine of the vector. + * + * @return self + */ +PHP_METHOD(Tensor_Vector, cosh) +{ + zval _0, _1; + zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL; + zend_long ZEPHIR_LAST_CALL_STATUS; + zval *this_ptr = getThis(); + + ZVAL_UNDEF(&_0); + ZVAL_UNDEF(&_1); + static zend_string *_zephir_prop_0 = NULL; + if (UNEXPECTED(!_zephir_prop_0)) { + _zephir_prop_0 = zend_string_init("a", 1, 1); + } + ZEPHIR_METHOD_GLOBALS_PTR = pecalloc(1, sizeof(zephir_method_globals), 0); + zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__); + + object_init_ex(return_value, zend_get_called_scope(execute_data)); + ZEPHIR_INIT_VAR(&_0); + zephir_read_property_cached(&_1, this_ptr, _zephir_prop_0, 1, PH_NOISY_CC | PH_READONLY); + tensor_cosh(&_0, &_1); + ZEPHIR_CALL_METHOD(NULL, return_value, "__construct", NULL, 3, &_0); + zephir_check_call_status(); + RETURN_MM(); +} + /** * Convert angles from radians to degrees. * @@ -3012,7 +3156,7 @@ PHP_METHOD(Tensor_Vector, min) ZEPHIR_CONCAT_SS(&_2$$3, "Cannot compute", " the minimum of an empty vector."); ZEPHIR_CALL_METHOD(NULL, &_1$$3, "__construct", NULL, 2, &_2$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_1$$3, "tensor/vector.zep", 1140); + zephir_throw_exception_debug(&_1$$3, "tensor/vector.zep", 1184); ZEPHIR_MM_RESTORE(); return; } @@ -3068,7 +3212,7 @@ PHP_METHOD(Tensor_Vector, max) ZEPHIR_CONCAT_SS(&_2$$3, "Cannot compute", " the maximum of an empty vector."); ZEPHIR_CALL_METHOD(NULL, &_1$$3, "__construct", NULL, 2, &_2$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_1$$3, "tensor/vector.zep", 1157); + zephir_throw_exception_debug(&_1$$3, "tensor/vector.zep", 1201); ZEPHIR_MM_RESTORE(); return; } @@ -3124,7 +3268,7 @@ PHP_METHOD(Tensor_Vector, argmin) ZEPHIR_CONCAT_SS(&_2$$3, "Cannot compute", " the argmin of an empty vector."); ZEPHIR_CALL_METHOD(NULL, &_1$$3, "__construct", NULL, 2, &_2$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_1$$3, "tensor/vector.zep", 1174); + zephir_throw_exception_debug(&_1$$3, "tensor/vector.zep", 1218); ZEPHIR_MM_RESTORE(); return; } @@ -3180,7 +3324,7 @@ PHP_METHOD(Tensor_Vector, argmax) ZEPHIR_CONCAT_SS(&_2$$3, "Cannot compute", " the argmax of an empty vector."); ZEPHIR_CALL_METHOD(NULL, &_1$$3, "__construct", NULL, 2, &_2$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_1$$3, "tensor/vector.zep", 1191); + zephir_throw_exception_debug(&_1$$3, "tensor/vector.zep", 1235); ZEPHIR_MM_RESTORE(); return; } @@ -3263,7 +3407,7 @@ PHP_METHOD(Tensor_Vector, median) ZEPHIR_CONCAT_SS(&_2$$3, "Cannot compute", " the median of an empty vector."); ZEPHIR_CALL_METHOD(NULL, &_1$$3, "__construct", NULL, 2, &_2$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_1$$3, "tensor/vector.zep", 1218); + zephir_throw_exception_debug(&_1$$3, "tensor/vector.zep", 1262); ZEPHIR_MM_RESTORE(); return; } @@ -3326,7 +3470,7 @@ PHP_METHOD(Tensor_Vector, quantile) zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__); zephir_fetch_params(1, 1, 0, &q_param); ZVAL_DOUBLE(&_0, q); - ZEPHIR_CALL_FUNCTION(&_1, "is_finite", NULL, 10, &_0); + ZEPHIR_CALL_FUNCTION(&_1, "is_finite", NULL, 6, &_0); zephir_check_call_status(); if (UNEXPECTED(!zephir_is_true(&_1))) { ZEPHIR_INIT_VAR(&_2$$3); @@ -3335,7 +3479,7 @@ PHP_METHOD(Tensor_Vector, quantile) ZEPHIR_CONCAT_SS(&_3$$3, "Q must be a finite value", " between 0 and 1."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_3$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1237); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1281); ZEPHIR_MM_RESTORE(); return; } @@ -3353,7 +3497,7 @@ PHP_METHOD(Tensor_Vector, quantile) ZEPHIR_CONCAT_SSVS(&_8$$4, "Q must be", " between 0 and 1, ", &_7$$4, " given."); ZEPHIR_CALL_METHOD(NULL, &_5$$4, "__construct", NULL, 2, &_8$$4); zephir_check_call_status(); - zephir_throw_exception_debug(&_5$$4, "tensor/vector.zep", 1242); + zephir_throw_exception_debug(&_5$$4, "tensor/vector.zep", 1286); ZEPHIR_MM_RESTORE(); return; } @@ -3365,7 +3509,7 @@ PHP_METHOD(Tensor_Vector, quantile) ZEPHIR_CONCAT_SS(&_10$$5, "Cannot compute", " the quantile of an empty vector."); ZEPHIR_CALL_METHOD(NULL, &_9$$5, "__construct", NULL, 2, &_10$$5); zephir_check_call_status(); - zephir_throw_exception_debug(&_9$$5, "tensor/vector.zep", 1247); + zephir_throw_exception_debug(&_9$$5, "tensor/vector.zep", 1291); ZEPHIR_MM_RESTORE(); return; } @@ -3419,6 +3563,36 @@ PHP_METHOD(Tensor_Vector, softmax) RETURN_MM(); } +/** + * Return the element-wise Gaussian error function. + * + * @return self + */ +PHP_METHOD(Tensor_Vector, erf) +{ + zval _0, _1; + zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL; + zend_long ZEPHIR_LAST_CALL_STATUS; + zval *this_ptr = getThis(); + + ZVAL_UNDEF(&_0); + ZVAL_UNDEF(&_1); + static zend_string *_zephir_prop_0 = NULL; + if (UNEXPECTED(!_zephir_prop_0)) { + _zephir_prop_0 = zend_string_init("a", 1, 1); + } + ZEPHIR_METHOD_GLOBALS_PTR = pecalloc(1, sizeof(zephir_method_globals), 0); + zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__); + + object_init_ex(return_value, zend_get_called_scope(execute_data)); + ZEPHIR_INIT_VAR(&_0); + zephir_read_property_cached(&_1, this_ptr, _zephir_prop_0, 1, PH_NOISY_CC | PH_READONLY); + tensor_erf(&_0, &_1); + ZEPHIR_CALL_METHOD(NULL, return_value, "__construct", NULL, 3, &_0); + zephir_check_call_status(); + RETURN_MM(); +} + /** * Return the variance of the vector. * @@ -3474,7 +3648,7 @@ PHP_METHOD(Tensor_Vector, variance) ZEPHIR_CONCAT_SSVS(&_3$$4, "Mean scalar must be", " a floating point number ", &_2$$4, " given."); ZEPHIR_CALL_METHOD(NULL, &_1$$4, "__construct", NULL, 2, &_3$$4); zephir_check_call_status(); - zephir_throw_exception_debug(&_1$$4, "tensor/vector.zep", 1280); + zephir_throw_exception_debug(&_1$$4, "tensor/vector.zep", 1334); ZEPHIR_MM_RESTORE(); return; } @@ -3540,7 +3714,7 @@ PHP_METHOD(Tensor_Vector, round) ZEPHIR_CONCAT_SSVS(&_3$$3, "Decimal precision cannot", " be less than 0, ", &_2$$3, " given."); ZEPHIR_CALL_METHOD(NULL, &_0$$3, "__construct", NULL, 2, &_3$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_0$$3, "tensor/vector.zep", 1304); + zephir_throw_exception_debug(&_0$$3, "tensor/vector.zep", 1358); ZEPHIR_MM_RESTORE(); return; } @@ -3717,7 +3891,7 @@ PHP_METHOD(Tensor_Vector, clip) ZEPHIR_CONCAT_SS(&_1$$3, "Minimum cannot be", " greater than maximum."); ZEPHIR_CALL_METHOD(NULL, &_0$$3, "__construct", NULL, 2, &_1$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_0$$3, "tensor/vector.zep", 1363); + zephir_throw_exception_debug(&_0$$3, "tensor/vector.zep", 1417); ZEPHIR_MM_RESTORE(); return; } @@ -3869,7 +4043,7 @@ PHP_METHOD(Tensor_Vector, multiplyMatrix) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A expects ", &_4$$3, " columns but Matrix B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1403); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1457); ZEPHIR_MM_RESTORE(); return; } @@ -3949,7 +4123,7 @@ PHP_METHOD(Tensor_Vector, divideMatrix) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A expects ", &_4$$3, " columns but Matrix B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1423); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1477); ZEPHIR_MM_RESTORE(); return; } @@ -4029,7 +4203,7 @@ PHP_METHOD(Tensor_Vector, addMatrix) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A expects ", &_4$$3, " columns but Matrix B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1443); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1497); ZEPHIR_MM_RESTORE(); return; } @@ -4109,7 +4283,7 @@ PHP_METHOD(Tensor_Vector, subtractMatrix) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A expects ", &_4$$3, " columns but Matrix B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1463); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1517); ZEPHIR_MM_RESTORE(); return; } @@ -4189,7 +4363,7 @@ PHP_METHOD(Tensor_Vector, powMatrix) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A expects ", &_4$$3, " columns but Matrix B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1483); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1537); ZEPHIR_MM_RESTORE(); return; } @@ -4269,7 +4443,7 @@ PHP_METHOD(Tensor_Vector, modMatrix) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A expects ", &_4$$3, " columns but Matrix B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1503); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1557); ZEPHIR_MM_RESTORE(); return; } @@ -4349,7 +4523,7 @@ PHP_METHOD(Tensor_Vector, equalMatrix) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A expects ", &_4$$3, " columns but Matrix B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1523); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1577); ZEPHIR_MM_RESTORE(); return; } @@ -4429,7 +4603,7 @@ PHP_METHOD(Tensor_Vector, notEqualMatrix) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A expects ", &_4$$3, " columns but Matrix B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1543); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1597); ZEPHIR_MM_RESTORE(); return; } @@ -4509,7 +4683,7 @@ PHP_METHOD(Tensor_Vector, greaterMatrix) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A expects ", &_4$$3, " columns but Matrix B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1563); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1617); ZEPHIR_MM_RESTORE(); return; } @@ -4589,7 +4763,7 @@ PHP_METHOD(Tensor_Vector, greaterEqualMatrix) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A expects ", &_4$$3, " columns but Matrix B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1583); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1637); ZEPHIR_MM_RESTORE(); return; } @@ -4669,7 +4843,7 @@ PHP_METHOD(Tensor_Vector, lessMatrix) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A expects ", &_4$$3, " columns but Matrix B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1603); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1657); ZEPHIR_MM_RESTORE(); return; } @@ -4749,7 +4923,7 @@ PHP_METHOD(Tensor_Vector, lessEqualMatrix) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A expects ", &_4$$3, " columns but Matrix B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1623); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1677); ZEPHIR_MM_RESTORE(); return; } @@ -4826,7 +5000,7 @@ PHP_METHOD(Tensor_Vector, multiplyVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A requires ", &_4$$3, " elements but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1643); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1697); ZEPHIR_MM_RESTORE(); return; } @@ -4899,7 +5073,7 @@ PHP_METHOD(Tensor_Vector, divideVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A requires ", &_4$$3, " elements but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1661); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1715); ZEPHIR_MM_RESTORE(); return; } @@ -4972,7 +5146,7 @@ PHP_METHOD(Tensor_Vector, addVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A requires ", &_4$$3, " elements but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1679); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1733); ZEPHIR_MM_RESTORE(); return; } @@ -5045,7 +5219,7 @@ PHP_METHOD(Tensor_Vector, subtractVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A requires ", &_4$$3, " elements but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1697); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1751); ZEPHIR_MM_RESTORE(); return; } @@ -5118,7 +5292,7 @@ PHP_METHOD(Tensor_Vector, powVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A requires ", &_4$$3, " elements but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1715); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1769); ZEPHIR_MM_RESTORE(); return; } @@ -5191,7 +5365,7 @@ PHP_METHOD(Tensor_Vector, modVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A requires ", &_4$$3, " elements but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1733); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1787); ZEPHIR_MM_RESTORE(); return; } @@ -5265,7 +5439,7 @@ PHP_METHOD(Tensor_Vector, equalVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A requires ", &_4$$3, " elements but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1752); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1806); ZEPHIR_MM_RESTORE(); return; } @@ -5338,7 +5512,7 @@ PHP_METHOD(Tensor_Vector, notEqualVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A requires ", &_4$$3, " elements but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1770); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1824); ZEPHIR_MM_RESTORE(); return; } @@ -5411,7 +5585,7 @@ PHP_METHOD(Tensor_Vector, greaterVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A requires ", &_4$$3, " elements but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1788); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1842); ZEPHIR_MM_RESTORE(); return; } @@ -5484,7 +5658,7 @@ PHP_METHOD(Tensor_Vector, greaterEqualVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A requires ", &_4$$3, " elements but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1806); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1860); ZEPHIR_MM_RESTORE(); return; } @@ -5557,7 +5731,7 @@ PHP_METHOD(Tensor_Vector, lessVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A requires ", &_4$$3, " elements but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1824); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1878); ZEPHIR_MM_RESTORE(); return; } @@ -5630,7 +5804,7 @@ PHP_METHOD(Tensor_Vector, lessEqualVector) ZEPHIR_CONCAT_SVSVS(&_7$$3, "Vector A requires ", &_4$$3, " elements but Vector B has ", &_6$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_2$$3, "__construct", NULL, 2, &_7$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1842); + zephir_throw_exception_debug(&_2$$3, "tensor/vector.zep", 1896); ZEPHIR_MM_RESTORE(); return; } @@ -6130,7 +6304,7 @@ PHP_METHOD(Tensor_Vector, offsetSet) Z_PARAM_ZVAL(values) ZEND_PARSE_PARAMETERS_END(); zephir_fetch_params_without_memory_grow(2, 0, &index, &values); - ZEPHIR_THROW_EXCEPTION_DEBUG_STRW(tensor_exceptions_runtimeexception_ce, "Vector cannot be mutated directly.", "tensor/vector.zep", 1999); + ZEPHIR_THROW_EXCEPTION_DEBUG_STRW(tensor_exceptions_runtimeexception_ce, "Vector cannot be mutated directly.", "tensor/vector.zep", 2053); return; } @@ -6181,7 +6355,7 @@ PHP_METHOD(Tensor_Vector, offsetUnset) Z_PARAM_ZVAL(index) ZEND_PARSE_PARAMETERS_END(); zephir_fetch_params_without_memory_grow(1, 0, &index); - ZEPHIR_THROW_EXCEPTION_DEBUG_STRW(tensor_exceptions_runtimeexception_ce, "Vector cannot be mutated directly.", "tensor/vector.zep", 2023); + ZEPHIR_THROW_EXCEPTION_DEBUG_STRW(tensor_exceptions_runtimeexception_ce, "Vector cannot be mutated directly.", "tensor/vector.zep", 2077); return; } @@ -6239,7 +6413,7 @@ PHP_METHOD(Tensor_Vector, offsetGet) ZEPHIR_CONCAT_SSVS(&_5$$3, "Element not found at", " offset ", &_4$$3, "."); ZEPHIR_CALL_METHOD(NULL, &_3$$3, "__construct", NULL, 2, &_5$$3); zephir_check_call_status(); - zephir_throw_exception_debug(&_3$$3, "tensor/vector.zep", 2037); + zephir_throw_exception_debug(&_3$$3, "tensor/vector.zep", 2091); ZEPHIR_MM_RESTORE(); return; } @@ -6350,21 +6524,21 @@ PHP_METHOD(Tensor_Vector, __unserialize) zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__); zephir_fetch_params(1, 1, 0, &data_param); zephir_get_arrval(&data, data_param); - zephir_array_fetch_string(&_0, &data, SL("a"), PH_NOISY | PH_READONLY, "tensor/vector.zep", 2078); + zephir_array_fetch_string(&_0, &data, SL("a"), PH_NOISY | PH_READONLY, "tensor/vector.zep", 2132); ZVAL_BOOL(&_1, 0); ZEPHIR_CALL_SELF(&a, "fromArray", NULL, 0, &_0, &_1); zephir_check_call_status(); - zephir_array_fetch_string(&_2, &data, SL("n"), PH_NOISY | PH_READONLY, "tensor/vector.zep", 2080); + zephir_array_fetch_string(&_2, &data, SL("n"), PH_NOISY | PH_READONLY, "tensor/vector.zep", 2134); ZEPHIR_CALL_METHOD(&_3, &a, "size", NULL, 0); zephir_check_call_status(); if (UNEXPECTED(!ZEPHIR_IS_EQUAL(&_2, &_3))) { - ZEPHIR_THROW_EXCEPTION_DEBUG_STR(tensor_exceptions_runtimeexception_ce, "Invalid vector data.", "tensor/vector.zep", 2081); + ZEPHIR_THROW_EXCEPTION_DEBUG_STR(tensor_exceptions_runtimeexception_ce, "Invalid vector data.", "tensor/vector.zep", 2135); return; } ZEPHIR_CALL_METHOD(&_4, &a, "buffer", NULL, 0); zephir_check_call_status(); zephir_update_property_zval_cached(this_ptr, _zephir_prop_0, 1, &_4); - zephir_array_fetch_string(&_5, &data, SL("n"), PH_NOISY | PH_READONLY, "tensor/vector.zep", 2085); + zephir_array_fetch_string(&_5, &data, SL("n"), PH_NOISY | PH_READONLY, "tensor/vector.zep", 2139); zephir_update_property_zval_cached(this_ptr, _zephir_prop_1, 2, &_5); ZEPHIR_MM_RESTORE(); } diff --git a/ext/tensor/vector.zep.h b/ext/tensor/vector.zep.h index 191f788..321cb30 100644 --- a/ext/tensor/vector.zep.h +++ b/ext/tensor/vector.zep.h @@ -54,11 +54,13 @@ PHP_METHOD(Tensor_Vector, reciprocal); PHP_METHOD(Tensor_Vector, abs); PHP_METHOD(Tensor_Vector, square); PHP_METHOD(Tensor_Vector, sqrt); +PHP_METHOD(Tensor_Vector, rsqrt); PHP_METHOD(Tensor_Vector, exp); PHP_METHOD(Tensor_Vector, expm1); PHP_METHOD(Tensor_Vector, log); PHP_METHOD(Tensor_Vector, log1p); PHP_METHOD(Tensor_Vector, sigmoid); +PHP_METHOD(Tensor_Vector, softplus); PHP_METHOD(Tensor_Vector, sin); PHP_METHOD(Tensor_Vector, asin); PHP_METHOD(Tensor_Vector, cos); @@ -66,6 +68,8 @@ PHP_METHOD(Tensor_Vector, acos); PHP_METHOD(Tensor_Vector, tan); PHP_METHOD(Tensor_Vector, atan); PHP_METHOD(Tensor_Vector, tanh); +PHP_METHOD(Tensor_Vector, sinh); +PHP_METHOD(Tensor_Vector, cosh); PHP_METHOD(Tensor_Vector, rad2deg); PHP_METHOD(Tensor_Vector, deg2rad); PHP_METHOD(Tensor_Vector, sum); @@ -78,6 +82,7 @@ PHP_METHOD(Tensor_Vector, mean); PHP_METHOD(Tensor_Vector, median); PHP_METHOD(Tensor_Vector, quantile); PHP_METHOD(Tensor_Vector, softmax); +PHP_METHOD(Tensor_Vector, erf); PHP_METHOD(Tensor_Vector, variance); PHP_METHOD(Tensor_Vector, round); PHP_METHOD(Tensor_Vector, floor); @@ -329,6 +334,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_vector_sqrt, 0, 0, Tensor\\Vector, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_vector_rsqrt, 0, 0, Tensor\\Vector, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_vector_exp, 0, 0, Tensor\\Vector, 0) ZEND_END_ARG_INFO() @@ -345,6 +353,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_vector_sigmoid, 0, 0, Tensor\\Vector, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_vector_softplus, 0, 0, Tensor\\Vector, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_vector_sin, 0, 0, Tensor\\Vector, 0) ZEND_END_ARG_INFO() @@ -366,6 +377,12 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_vector_tanh, 0, 0, Tensor\\Vector, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_vector_sinh, 0, 0, Tensor\\Vector, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_vector_cosh, 0, 0, Tensor\\Vector, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_vector_rad2deg, 0, 0, Tensor\\Vector, 0) ZEND_END_ARG_INFO() @@ -403,6 +420,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_vector_softmax, 0, 0, Tensor\\Vector, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_tensor_vector_erf, 0, 0, Tensor\\Vector, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_tensor_vector_variance, 0, 0, IS_DOUBLE, 0) ZEND_ARG_INFO(0, mean) ZEND_END_ARG_INFO() @@ -664,11 +684,13 @@ PHP_ME(Tensor_Vector, transpose, arginfo_tensor_vector_transpose, ZEND_ACC_PUBLI PHP_ME(Tensor_Vector, abs, arginfo_tensor_vector_abs, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, square, arginfo_tensor_vector_square, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, sqrt, arginfo_tensor_vector_sqrt, ZEND_ACC_PUBLIC) + PHP_ME(Tensor_Vector, rsqrt, arginfo_tensor_vector_rsqrt, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, exp, arginfo_tensor_vector_exp, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, expm1, arginfo_tensor_vector_expm1, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, log, arginfo_tensor_vector_log, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, log1p, arginfo_tensor_vector_log1p, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, sigmoid, arginfo_tensor_vector_sigmoid, ZEND_ACC_PUBLIC) + PHP_ME(Tensor_Vector, softplus, arginfo_tensor_vector_softplus, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, sin, arginfo_tensor_vector_sin, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, asin, arginfo_tensor_vector_asin, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, cos, arginfo_tensor_vector_cos, ZEND_ACC_PUBLIC) @@ -676,6 +698,8 @@ PHP_ME(Tensor_Vector, transpose, arginfo_tensor_vector_transpose, ZEND_ACC_PUBLI PHP_ME(Tensor_Vector, tan, arginfo_tensor_vector_tan, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, atan, arginfo_tensor_vector_atan, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, tanh, arginfo_tensor_vector_tanh, ZEND_ACC_PUBLIC) + PHP_ME(Tensor_Vector, sinh, arginfo_tensor_vector_sinh, ZEND_ACC_PUBLIC) + PHP_ME(Tensor_Vector, cosh, arginfo_tensor_vector_cosh, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, rad2deg, arginfo_tensor_vector_rad2deg, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, deg2rad, arginfo_tensor_vector_deg2rad, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, sum, arginfo_tensor_vector_sum, ZEND_ACC_PUBLIC) @@ -688,6 +712,7 @@ PHP_ME(Tensor_Vector, transpose, arginfo_tensor_vector_transpose, ZEND_ACC_PUBLI PHP_ME(Tensor_Vector, median, arginfo_tensor_vector_median, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, quantile, arginfo_tensor_vector_quantile, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, softmax, arginfo_tensor_vector_softmax, ZEND_ACC_PUBLIC) + PHP_ME(Tensor_Vector, erf, arginfo_tensor_vector_erf, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, variance, arginfo_tensor_vector_variance, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, round, arginfo_tensor_vector_round, ZEND_ACC_PUBLIC) PHP_ME(Tensor_Vector, floor, arginfo_tensor_vector_floor, ZEND_ACC_PUBLIC) diff --git a/optimizers/TensorCoshOptimizer.php b/optimizers/TensorCoshOptimizer.php new file mode 100644 index 0000000..0313956 --- /dev/null +++ b/optimizers/TensorCoshOptimizer.php @@ -0,0 +1,76 @@ +processExpectedReturn($context); + + $symbolVariable = $call->getSymbolVariable(); + + if (empty($symbolVariable)) { + throw new CompilerException('Missing symbol variable.'); + } + + if ($symbolVariable->getType() !== 'variable') { + throw new CompilerException( + 'Return value must only be assigned to a dynamic variable.', + $expression + ); + } + + if ($call->mustInitSymbolVariable()) { + $symbolVariable->initVariant($context); + } + + $context->headersManager->add( + 'include/unary', + HeadersManager::POSITION_LAST + ); + + $resolvedParams = $call->getResolvedParams( + $expression['parameters'], + $context, + $expression + ); + + $symbol = $context->backend->getVariableCode($symbolVariable); + + $context->codePrinter->output( + "tensor_cosh($symbol, {$resolvedParams[0]});" + ); + + return new CompiledExpression( + 'variable', + $symbolVariable->getRealName(), + $expression + ); + } +} diff --git a/optimizers/TensorErfOptimizer.php b/optimizers/TensorErfOptimizer.php new file mode 100644 index 0000000..e72b4a7 --- /dev/null +++ b/optimizers/TensorErfOptimizer.php @@ -0,0 +1,76 @@ +processExpectedReturn($context); + + $symbolVariable = $call->getSymbolVariable(); + + if (empty($symbolVariable)) { + throw new CompilerException('Missing symbol variable.'); + } + + if ($symbolVariable->getType() !== 'variable') { + throw new CompilerException( + 'Return value must only be assigned to a dynamic variable.', + $expression + ); + } + + if ($call->mustInitSymbolVariable()) { + $symbolVariable->initVariant($context); + } + + $context->headersManager->add( + 'include/unary', + HeadersManager::POSITION_LAST + ); + + $resolvedParams = $call->getResolvedParams( + $expression['parameters'], + $context, + $expression + ); + + $symbol = $context->backend->getVariableCode($symbolVariable); + + $context->codePrinter->output( + "tensor_erf($symbol, {$resolvedParams[0]});" + ); + + return new CompiledExpression( + 'variable', + $symbolVariable->getRealName(), + $expression + ); + } +} diff --git a/optimizers/TensorRsqrtOptimizer.php b/optimizers/TensorRsqrtOptimizer.php new file mode 100644 index 0000000..85ecebf --- /dev/null +++ b/optimizers/TensorRsqrtOptimizer.php @@ -0,0 +1,76 @@ +processExpectedReturn($context); + + $symbolVariable = $call->getSymbolVariable(); + + if (empty($symbolVariable)) { + throw new CompilerException('Missing symbol variable.'); + } + + if ($symbolVariable->getType() !== 'variable') { + throw new CompilerException( + 'Return value must only be assigned to a dynamic variable.', + $expression + ); + } + + if ($call->mustInitSymbolVariable()) { + $symbolVariable->initVariant($context); + } + + $context->headersManager->add( + 'include/unary', + HeadersManager::POSITION_LAST + ); + + $resolvedParams = $call->getResolvedParams( + $expression['parameters'], + $context, + $expression + ); + + $symbol = $context->backend->getVariableCode($symbolVariable); + + $context->codePrinter->output( + "tensor_rsqrt($symbol, {$resolvedParams[0]});" + ); + + return new CompiledExpression( + 'variable', + $symbolVariable->getRealName(), + $expression + ); + } +} diff --git a/optimizers/TensorSinhOptimizer.php b/optimizers/TensorSinhOptimizer.php new file mode 100644 index 0000000..beb2f17 --- /dev/null +++ b/optimizers/TensorSinhOptimizer.php @@ -0,0 +1,76 @@ +processExpectedReturn($context); + + $symbolVariable = $call->getSymbolVariable(); + + if (empty($symbolVariable)) { + throw new CompilerException('Missing symbol variable.'); + } + + if ($symbolVariable->getType() !== 'variable') { + throw new CompilerException( + 'Return value must only be assigned to a dynamic variable.', + $expression + ); + } + + if ($call->mustInitSymbolVariable()) { + $symbolVariable->initVariant($context); + } + + $context->headersManager->add( + 'include/unary', + HeadersManager::POSITION_LAST + ); + + $resolvedParams = $call->getResolvedParams( + $expression['parameters'], + $context, + $expression + ); + + $symbol = $context->backend->getVariableCode($symbolVariable); + + $context->codePrinter->output( + "tensor_sinh($symbol, {$resolvedParams[0]});" + ); + + return new CompiledExpression( + 'variable', + $symbolVariable->getRealName(), + $expression + ); + } +} diff --git a/optimizers/TensorSoftplusOptimizer.php b/optimizers/TensorSoftplusOptimizer.php new file mode 100644 index 0000000..8a81cad --- /dev/null +++ b/optimizers/TensorSoftplusOptimizer.php @@ -0,0 +1,76 @@ +processExpectedReturn($context); + + $symbolVariable = $call->getSymbolVariable(); + + if (empty($symbolVariable)) { + throw new CompilerException('Missing symbol variable.'); + } + + if ($symbolVariable->getType() !== 'variable') { + throw new CompilerException( + 'Return value must only be assigned to a dynamic variable.', + $expression + ); + } + + if ($call->mustInitSymbolVariable()) { + $symbolVariable->initVariant($context); + } + + $context->headersManager->add( + 'include/unary', + HeadersManager::POSITION_LAST + ); + + $resolvedParams = $call->getResolvedParams( + $expression['parameters'], + $context, + $expression + ); + + $symbol = $context->backend->getVariableCode($symbolVariable); + + $context->codePrinter->output( + "tensor_softplus($symbol, {$resolvedParams[0]});" + ); + + return new CompiledExpression( + 'variable', + $symbolVariable->getRealName(), + $expression + ); + } +} diff --git a/tensor/matrix.zep b/tensor/matrix.zep index 0a35be4..e002c73 100644 --- a/tensor/matrix.zep +++ b/tensor/matrix.zep @@ -1367,6 +1367,16 @@ class Matrix implements Tensor return new self(tensor_sqrt(this->a), this->m, this->n); } + /** + * Return the reciprocal square root of the matrix. + * + * @return self + */ + public function rsqrt() -> + { + return new self(tensor_rsqrt(this->a), this->m, this->n); + } + /** * Return the exponential of the matrix. * @@ -1428,7 +1438,17 @@ class Matrix implements Tensor { return new self(tensor_sigmoid(this->a), this->m, this->n); } - + + /** + * Return the element-wise softplus i.e. log(1 + exp(x)). + * + * @return self + */ + public function softplus() -> + { + return new self(tensor_softplus(this->a), this->m, this->n); + } + /** * Return the sine of the matrix. * @@ -1498,6 +1518,26 @@ class Matrix implements Tensor { return new self(tensor_tanh(this->a), this->m, this->n); } + + /** + * Return the element-wise hyperbolic sine of the matrix. + * + * @return self + */ + public function sinh() -> + { + return new self(tensor_sinh(this->a), this->m, this->n); + } + + /** + * Return the element-wise hyperbolic cosine of the matrix. + * + * @return self + */ + public function cosh() -> + { + return new self(tensor_cosh(this->a), this->m, this->n); + } /** * Convert angles from radians to degrees. @@ -1631,6 +1671,16 @@ class Matrix implements Tensor return new self(tensor_softmax(this->a, this->n), this->m, this->n); } + /** + * Return the element-wise Gaussian error function. + * + * @return self + */ + public function erf() -> + { + return new self(tensor_erf(this->a), this->m, this->n); + } + /** * Compute the row variance of the matrix. * diff --git a/tensor/special.zep b/tensor/special.zep index ef4bc59..2e7b166 100644 --- a/tensor/special.zep +++ b/tensor/special.zep @@ -2,10 +2,31 @@ namespace Tensor; interface Special { + /** + * Return the element-wise logistic function i.e. 1 / (1 + exp(-x)). + * + * @return mixed + */ + public function sigmoid(); + + /** + * Return the element-wise softplus i.e. log(1 + exp(x)). + * + * @return mixed + */ + public function softplus(); + /** * Return the softmax of the tensor i.e. each row normalized to sum to 1. * * @return mixed */ public function softmax(); + + /** + * Return the element-wise Gaussian error function. + * + * @return mixed + */ + public function erf(); } diff --git a/tensor/trigonometric.zep b/tensor/trigonometric.zep index 11819ce..bba609f 100644 --- a/tensor/trigonometric.zep +++ b/tensor/trigonometric.zep @@ -55,6 +55,20 @@ interface Trigonometric */ public function tanh(); + /** + * Return the element-wise hyperbolic sine. + * + * @return mixed + */ + public function sinh(); + + /** + * Return the element-wise hyperbolic cosine. + * + * @return mixed + */ + public function cosh(); + /** * Convert angles from radians to degrees. * diff --git a/tensor/unary.zep b/tensor/unary.zep index 681127c..538f115 100644 --- a/tensor/unary.zep +++ b/tensor/unary.zep @@ -25,6 +25,13 @@ interface Unary */ public function sqrt(); + /** + * Return the reciprocal square root of the tensor. + * + * @return mixed + */ + public function rsqrt(); + /** * Return the exponential of the tensor. * @@ -54,13 +61,6 @@ interface Unary */ public function log1p(); - /** - * Return the element-wise logistic function i.e. 1 / (1 + exp(-x)). - * - * @return mixed - */ - public function sigmoid(); - /** * Round the elements in the tensor to a given decimal place. * diff --git a/tensor/vector.zep b/tensor/vector.zep index 4d38748..1eadbef 100644 --- a/tensor/vector.zep +++ b/tensor/vector.zep @@ -958,6 +958,16 @@ if unlikely !is_finite(start) || !is_finite(end) || !is_finite(interval) { return new static(tensor_sqrt(this->a)); } + /** + * Return the reciprocal square root of the vector. + * + * @return self + */ + public function rsqrt() -> + { + return new static(tensor_rsqrt(this->a)); + } + /** * Exponentiate each element in the vector. * @@ -1018,6 +1028,16 @@ if unlikely !is_finite(start) || !is_finite(end) || !is_finite(interval) { return new static(tensor_sigmoid(this->a)); } + /** + * Return the element-wise softplus i.e. log(1 + exp(x)). + * + * @return self + */ + public function softplus() -> + { + return new static(tensor_softplus(this->a)); + } + /** * Return the sine of this vector. * @@ -1088,6 +1108,26 @@ if unlikely !is_finite(start) || !is_finite(end) || !is_finite(interval) { return new static(tensor_tanh(this->a)); } + /** + * Return the element-wise hyperbolic sine of the vector. + * + * @return self + */ + public function sinh() -> + { + return new static(tensor_sinh(this->a)); + } + + /** + * Return the element-wise hyperbolic cosine of the vector. + * + * @return self + */ + public function cosh() -> + { + return new static(tensor_cosh(this->a)); + } + /** * Convert angles from radians to degrees. * @@ -1269,6 +1309,16 @@ if unlikely !is_finite(start) || !is_finite(end) || !is_finite(interval) { return new static(tensor_softmax(this->a, this->n)); } + /** + * Return the element-wise Gaussian error function. + * + * @return self + */ + public function erf() -> + { + return new static(tensor_erf(this->a)); + } + /** * Return the variance of the vector. * diff --git a/tests/ColumnVectorTest.php b/tests/ColumnVectorTest.php index 6e3be6f..a00c0b1 100644 --- a/tests/ColumnVectorTest.php +++ b/tests/ColumnVectorTest.php @@ -438,6 +438,17 @@ public function sigmoidReturnsColumnVector() : void $this->assertEqualsWithDelta([0.7310585786300049, 0.2689414213699951, 0.5], $b->asArray(), 1e-8); } + /** + * @test + */ + public function softplusReturnsColumnVector() : void + { + $b = ColumnVector::fromArray([1.0, -1.0, 0.0])->softplus(); + + $this->assertInstanceOf(ColumnVector::class, $b); + $this->assertEqualsWithDelta([1.3132616875182, 0.31326168751822, 0.69314718055995], $b->asArray(), 1e-8); + } + /** * @test */ @@ -449,6 +460,50 @@ public function tanhReturnsColumnVector() : void $this->assertEqualsWithDelta([0.76159415595576485, -0.76159415595576485, 0.0], $b->asArray(), 1e-8); } + /** + * @test + */ + public function sinhReturnsColumnVector() : void + { + $b = ColumnVector::fromArray([1.0, -1.0, 0.0])->sinh(); + + $this->assertInstanceOf(ColumnVector::class, $b); + $this->assertEqualsWithDelta([1.1752011936438014, -1.1752011936438014, 0.0], $b->asArray(), 1e-8); + } + + /** + * @test + */ + public function coshReturnsColumnVector() : void + { + $b = ColumnVector::fromArray([1.0, -1.0, 0.0])->cosh(); + + $this->assertInstanceOf(ColumnVector::class, $b); + $this->assertEqualsWithDelta([1.5430806348152437, 1.5430806348152437, 1.0], $b->asArray(), 1e-8); + } + + /** + * @test + */ + public function erfReturnsColumnVector() : void + { + $b = ColumnVector::fromArray([1.0, -1.0, 0.0])->erf(); + + $this->assertInstanceOf(ColumnVector::class, $b); + $this->assertEqualsWithDelta([0.8427007929497148, -0.8427007929497148, 0.0], $b->asArray(), 1e-8); + } + + /** + * @test + */ + public function rsqrtReturnsColumnVector() : void + { + $b = ColumnVector::fromArray([4.0, 9.0, 0.25])->rsqrt(); + + $this->assertInstanceOf(ColumnVector::class, $b); + $this->assertEqualsWithDelta([0.5, 0.3333333333333333, 2.0], $b->asArray(), 1e-8); + } + /** * @test */ diff --git a/tests/MatrixTest.php b/tests/MatrixTest.php index 06fa02b..0f8ef04 100644 --- a/tests/MatrixTest.php +++ b/tests/MatrixTest.php @@ -3476,6 +3476,26 @@ public function sqrt() : void $this->assertEqualsWithDelta($expected->asArray(), $b->asArray(), self::MAX_DELTA); } + /** + * @test + */ + public function rsqrt() : void + { + $a = Matrix::fromArray([ + [4.0, 9.0], + [16.0, 25.0], + ]); + + $b = $a->rsqrt(); + + $expected = Matrix::fromArray([ + [0.5, 0.3333333333333333], + [0.25, 0.2], + ]); + + $this->assertEqualsWithDelta($expected->asArray(), $b->asArray(), self::MAX_DELTA); + } + /** * @test */ @@ -3653,6 +3673,69 @@ public function sigmoidMatchesComposition() : void ); } + /** + * @test + */ + public function softplus() : void + { + $a = Matrix::fromArray([ + [13.0, 1.0, -13.0, 0.5], + [11.0, -1.0, -11.0, -0.5], + [9.0, 0.0, -9.0, 2.5], + ]); + + $b = $a->softplus(); + + $expected = Matrix::fromArray([ + [13.000002260327, 1.3132616875182, 2.2603268524372e-6, 0.97407698418011], + [11.000016701561, 0.31326168751822, 1.6701561318304e-5, 0.47407698418011], + [9.0001234021897, 0.69314718055995, 0.00012340218972334, 2.5788897342925], + ]); + + $this->assertEqualsWithDelta($expected->asArray(), $b->asArray(), self::MAX_DELTA); + } + + /** + * A large positive input must not overflow the exponential that softplus + * evaluates and must saturate to x, and a large negative one to 0. + * + * @test + */ + public function softplusSaturates() : void + { + $a = Matrix::fromArray([ + [-800.0, 800.0, -1000.0], + [-745.0, 745.0, 0.0], + ]); + + $b = $a->softplus()->asArray(); + + $this->assertLessThan(1e-300, $b[0][0]); + $this->assertSame(800.0, $b[0][1]); + $this->assertLessThan(1e-300, $b[0][2]); + $this->assertLessThan(1e-300, $b[1][0]); + $this->assertSame(745.0, $b[1][1]); + $this->assertEqualsWithDelta(log(2.0), $b[1][2], self::MAX_DELTA); + } + + /** + * The fused kernel must agree with the composition it replaces, elementwise. + * + * @test + */ + public function softplusMatchesComposition() : void + { + $a = Matrix::rand(17, 23)->multiply(8.0)->subtract(4.0); + + $e = $a->exp(); + + $this->assertEqualsWithDelta( + $e->add(1.0)->log()->asArray(), + $a->softplus()->asArray(), + self::MAX_DELTA + ); + } + /** * @test */ @@ -3716,6 +3799,88 @@ public function tanhMatchesComposition() : void ); } + /** + * @test + */ + public function sinh() : void + { + $a = Matrix::fromArray([ + [0.0, 1.0, -1.0], + [0.5, -0.5, 2.0], + ]); + + $this->assertSame(0.0, $a->sinh()->asArray()[0][0]); + + $this->assertEqualsWithDelta( + array_map( + static fn (array $row) : array => array_map('sinh', $row), + $a->asArray() + ), + $a->sinh()->asArray(), + self::MAX_DELTA + ); + } + + /** + * The kernel must agree with the exp difference composition it replaces. + * + * @test + */ + public function sinhMatchesComposition() : void + { + $a = Matrix::rand(17, 23)->multiply(0.5)->subtract(0.25); + + $e = $a->exp(); + $em = $a->multiply(-1.0)->exp(); + + $this->assertEqualsWithDelta( + $e->subtract($em)->multiply(0.5)->asArray(), + $a->sinh()->asArray(), + self::MAX_DELTA + ); + } + + /** + * @test + */ + public function cosh() : void + { + $a = Matrix::fromArray([ + [0.0, 1.0, -1.0], + [0.5, -0.5, 2.0], + ]); + + $this->assertSame(1.0, $a->cosh()->asArray()[0][0]); + + $this->assertEqualsWithDelta( + array_map( + static fn (array $row) : array => array_map('cosh', $row), + $a->asArray() + ), + $a->cosh()->asArray(), + self::MAX_DELTA + ); + } + + /** + * The kernel must agree with the exp sum composition it replaces. + * + * @test + */ + public function coshMatchesComposition() : void + { + $a = Matrix::rand(17, 23)->multiply(0.5)->subtract(0.25); + + $e = $a->exp(); + $em = $a->multiply(-1.0)->exp(); + + $this->assertEqualsWithDelta( + $e->add($em)->multiply(0.5)->asArray(), + $a->cosh()->asArray(), + self::MAX_DELTA + ); + } + /** * @test */ @@ -4229,6 +4394,40 @@ public function softmaxDoesNotMutate() : void $this->assertSame($before, $a->asArray()); } + /** + * @test + */ + public function erf() : void + { + $a = Matrix::fromArray([ + [0.0, 1.0, -1.0], + [0.5, -0.5, 2.0], + ]); + + $b = $a->erf(); + + $expected = Matrix::fromArray([ + [0.0, 0.8427007929497148, -0.8427007929497148], + [0.5204998778130465, -0.5204998778130465, 0.9953222650189527], + ]); + + $this->assertEqualsWithDelta($expected->asArray(), $b->asArray(), self::MAX_DELTA); + } + + /** + * A large input saturates to exactly +/-1.0 rather than an infinity. + * + * @test + */ + public function erfSaturates() : void + { + $a = Matrix::fromArray([ + [100.0, -100.0], + ]); + + $this->assertSame([1.0, -1.0], $a->erf()->asArray()[0]); + } + /** * A single row is one group, so it normalizes to one across its width. * diff --git a/tests/SettingsTest.php b/tests/SettingsTest.php index dce14ad..a67b18d 100644 --- a/tests/SettingsTest.php +++ b/tests/SettingsTest.php @@ -116,6 +116,17 @@ public function dispatchedKernelsAreCorrect() : void $va->negate()->asArray(), "negate failed for length {$n}" ); + + $positive = array_values(array_filter($a, fn ($x) => $x > 0.0)); + + if (!empty($positive)) { + $vpos = Vector::fromArray($positive); + $this->assertSame( + array_map(fn ($x) => 1.0 / sqrt($x), $positive), + $vpos->rsqrt()->asArray(), + "rsqrt failed for length {$n}" + ); + } } } diff --git a/tests/VectorTest.php b/tests/VectorTest.php index d161ca5..9b9931a 100644 --- a/tests/VectorTest.php +++ b/tests/VectorTest.php @@ -144,7 +144,7 @@ public function unaryInterfaceSurface() : void 'log1p', 'negate', 'round', - 'sigmoid', + 'rsqrt', 'sign', 'sqrt', 'square', @@ -2173,6 +2173,23 @@ public function sqrt() : void $this->assertEqualsWithDelta($expected->asArray(), $b->asArray(), self::MAX_DELTA); } + /** + * @test + */ + public function rsqrt() : void + { + $a = Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]); + + $b = $a->rsqrt(); + + $expected = Vector::fromArray([ + 0.5, 0.3922322702763681, 0.5872202195147035, 0.22360679774997896, + 0.6201736729460422, 0.28988551782622424, + ]); + + $this->assertEqualsWithDelta($expected->asArray(), $b->asArray(), self::MAX_DELTA); + } + /** * @test */ @@ -2255,6 +2272,59 @@ public function sigmoidMatchesComposition() : void ); } + /** + * @test + */ + public function softplus() : void + { + $a = Vector::fromArray([4.0, 6.5, 2.9, 20.0, 2.6, 11.9]); + + $b = $a->softplus(); + + $expected = Vector::fromArray([ + 4.0181499279178, 6.5015023101598, 2.953562776218, + 20.000000002061, 2.6716446919677, 11.900006790382, + ]); + + $this->assertEqualsWithDelta($expected->asArray(), $b->asArray(), self::MAX_DELTA); + } + + /** + * A large positive input must not overflow the exponential that softplus + * evaluates and must saturate to x, and a large negative one to 0. + * + * @test + */ + public function softplusSaturates() : void + { + $a = Vector::fromArray([-800.0, 800.0, 0.0, -1000.0]); + + $b = $a->softplus()->asArray(); + + $this->assertSame(0.0, $b[0]); + $this->assertSame(800.0, $b[1]); + $this->assertEqualsWithDelta(log(2.0), $b[2], self::MAX_DELTA); + $this->assertSame(0.0, $b[3]); + } + + /** + * The fused kernel must agree with the composition it replaces, elementwise. + * + * @test + */ + public function softplusMatchesComposition() : void + { + $a = Vector::rand(257)->multiply(8.0)->subtract(4.0); + + $e = $a->exp(); + + $this->assertEqualsWithDelta( + $e->add(1.0)->log()->asArray(), + $a->softplus()->asArray(), + self::MAX_DELTA + ); + } + /** * @test */ @@ -2304,6 +2374,76 @@ public function tanhMatchesComposition() : void ); } + /** + * @test + */ + public function sinh() : void + { + $a = Vector::fromArray([0.0, 1.0, -1.0, 0.5, -0.5, 2.0]); + + $this->assertSame(0.0, $a->sinh()->asArray()[0]); + + $this->assertEqualsWithDelta( + array_map('sinh', $a->asArray()), + $a->sinh()->asArray(), + self::MAX_DELTA + ); + } + + /** + * The kernel must agree with the exp difference composition it replaces. + * + * @test + */ + public function sinhMatchesComposition() : void + { + $a = Vector::rand(257)->multiply(0.5)->subtract(0.25); + + $e = $a->exp(); + $em = $a->multiply(-1.0)->exp(); + + $this->assertEqualsWithDelta( + $e->subtract($em)->multiply(0.5)->asArray(), + $a->sinh()->asArray(), + self::MAX_DELTA + ); + } + + /** + * @test + */ + public function cosh() : void + { + $a = Vector::fromArray([0.0, 1.0, -1.0, 0.5, -0.5, 2.0]); + + $this->assertSame(1.0, $a->cosh()->asArray()[0]); + + $this->assertEqualsWithDelta( + array_map('cosh', $a->asArray()), + $a->cosh()->asArray(), + self::MAX_DELTA + ); + } + + /** + * The kernel must agree with the exp sum composition it replaces. + * + * @test + */ + public function coshMatchesComposition() : void + { + $a = Vector::rand(257)->multiply(0.5)->subtract(0.25); + + $e = $a->exp(); + $em = $a->multiply(-1.0)->exp(); + + $this->assertEqualsWithDelta( + $e->add($em)->multiply(0.5)->asArray(), + $a->cosh()->asArray(), + self::MAX_DELTA + ); + } + /** * A vector softmax normalizes the whole vector, as a single row, so the * result sums to one. @@ -2404,6 +2544,36 @@ public function softmaxDoesNotMutate() : void $this->assertSame($before, $a->asArray()); } + /** + * @test + */ + public function erf() : void + { + $a = Vector::fromArray([0.0, 1.0, -1.0, 0.5, -0.5, 2.0, 10.0]); + + $b = $a->erf(); + + $expected = Vector::fromArray([ + 0.0, 0.8427007929497148, -0.8427007929497148, + 0.5204998778130465, -0.5204998778130465, + 0.9953222650189527, 1.0, + ]); + + $this->assertEqualsWithDelta($expected->asArray(), $b->asArray(), self::MAX_DELTA); + } + + /** + * A large input saturates to exactly +/-1.0 rather than an infinity. + * + * @test + */ + public function erfSaturates() : void + { + $a = Vector::fromArray([100.0, -100.0]); + + $this->assertSame([1.0, -1.0], $a->erf()->asArray()); + } + /** * Lengths on both sides of the kernel's block boundary: a single element, a * block narrower than the floor, and one wider than the cap.