ZMatrix is a high-performance PHP extension for matrix and N-dimensional tensor operations, implemented in C++ with optimizations for parallel processing and BLAS integration.
git clone https://github.com/omegaalfa/zmatrix.git
cd zmatrix
phpize
./configure --enable-zmatrix
make
sudo make install
Add the extension to your php.ini:
extension=zmatrix.so
The ZMatrix extension implements the following functionalities:
ZTensor::zeros()
- Creates a tensor filled with zerosZTensor::ones()
- Creates a tensor filled with onesZTensor::full()
- Creates a tensor filled with a constant valueZTensor::identity()
- Creates an identity matrixZTensor::eye()
- Creates a diagonal matrix with optional offsetZTensor::arange()
- Creates a 1D tensor with values in a rangeZTensor::linspace()
- Creates a 1D tensor with evenly spaced valuesZTensor::logspace()
- Creates a 1D tensor with logarithmically spaced valuesZTensor::random()
- Creates a tensor with uniformly distributed random valuesZTensor::randn()
- Creates a tensor with normally distributed random values
$tensor->ndim()
- Returns the number of dimensions$tensor->shape()
- Returns the shape (dimensions)$tensor->size()
- Returns the total number of elements$tensor->isEmpty()
- Checks whether the tensor is empty$tensor->toArray()
- Converts tensor to PHP array
$tensor->add()
- Element-wise addition$tensor->sub()
- Element-wise subtraction$tensor->mul()
- Element-wise multiplication$tensor->divide()
- Element-wise division$tensor->pow()
- Raises each element to a power$tensor->scalarMultiply()
- Multiplies tensor by scalar$tensor->scalarDivide()
- Divides tensor by scalar$tensor->transpose()
- Matrix transpose (2D only)$tensor->dot()
- Dot product$tensor->matmul()
- Matrix multiplication (2D only)
$tensor->reshape()
- Returns a reshaped view of the tensorZTensor::tile()
- Repeats a tensor vertically
$tensor->sum()
- Sum over axis or globally$tensor->sumtotal()
- Global sum of all elements$tensor->mean()
- Mean of elements$tensor->std()
- Standard deviation (sample)$tensor->min()
- Minimum value$tensor->max()
- Maximum value
$tensor->abs()
- Absolute value$tensor->sigmoid()
- Sigmoid activation$tensor->sigmoidDerivative()
- Derivative of sigmoid$tensor->relu()
- ReLU activation$tensor->reluDerivative()
- Derivative of ReLU$tensor->tanh()
- Tanh activation$tensor->tanhDerivative()
- Derivative of tanh$tensor->leakyRelu()
- Leaky ReLU$tensor->leakyReluDerivative()
- Derivative of Leaky ReLU$tensor->softmax()
- Softmax activation$tensor->softmaxDerivative()
- Derivative of Softmax
ZTensor::arr()
- Creates a tensor from PHP arrayZTensor::safe()
- Same as arr(), returns a ZTensor$tensor->copy()
- Deep copy$tensor->key([...])
- Gets an element from coordinates$tensor->broadcast($bias)
- Adds 1D bias to rows of 2D tensorZTensor::clip($tensor, $min, $max)
- Clamps tensor values within rangeZTensor::minimum($tensor, $value)
- Element-wise min with scalarZTensor::maximum($tensor, $value)
- Element-wise max with scalar$tensor->greater($other)
- Returns 1.0 where $this > $other
ZMatrix offers significant performance improvements over pure PHP implementations:
- Matrix Multiplication: Up to 100x faster than native PHP
- N-dimensional Tensors: Efficient memory layout and computation
- Automatic Parallelism: Uses multiple CPU cores when available (OpenMP or threads)
- BLAS Integration: Optional BLAS acceleration for linear algebra
- Machine Learning
- Numerical Computing
- Image Processing
- Scientific Simulation
- Data Analysis and Statistics
This document provides comprehensive usage examples for all public methods available in the ZTensor PHP extension. The ZTensor class represents a multidimensional tensor implemented in C++ for high-performance mathematical operations.
- Creation and Initialization
- Special Tensors
- Sequence Generation
- Random Number Generation
- Basic Arithmetic Operations
- Linear Algebra
- Mathematical Functions
- Activation Functions
- Statistics and Aggregations
- Comparison and Clipping
- Shape Manipulation
- Special Operations
use ZMatrix\ZTensor;
Create an empty tensor:
$empty = new ZTensor();
echo "Empty tensor: " . ($empty->isEmpty() ? "yes" : "no") . "\n";
Create tensor from 1D array:
$tensor1d = new ZTensor([1, 2, 3, 4, 5]);
print_r($tensor1d->toArray());
Create tensor from 2D array:
$tensor2d = new ZTensor([
[1, 2, 3],
[4, 5, 6]
]);
print_r($tensor2d->toArray());
$safe_tensor = ZTensor::safe([
[1.5, 2.7],
[3.1, 4.9]
]);
print_r($safe_tensor->shape());
$arr_tensor = ZTensor::arr([
[10, 20],
[30, 40],
[50, 60]
]);
print_r($arr_tensor->toArray());
$original = ZTensor::arr([1, 2, 3]);
$copy = $original->copy();
print_r($original->toArray());
print_r($copy->toArray());
$zeros = ZTensor::zeros([2, 3]);
print_r($zeros->toArray());
// Output: [[0, 0, 0], [0, 0, 0]]
$ones = ZTensor::ones([3, 2]);
print_r($ones->toArray());
// Output: [[1, 1], [1, 1], [1, 1]]
$full = ZTensor::full([2, 2], 7.5);
print_r($full->toArray());
// Output: [[7.5, 7.5], [7.5, 7.5]]
$identity = ZTensor::identity(3);
print_r($identity->toArray());
// Output: [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
$eye = ZTensor::eye(3, 4, 1); // 3 rows, 4 columns, upper diagonal
print_r($eye->toArray());
// Output: [[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
Simple range (0 to 4):
$arange1 = ZTensor::arange(5);
print_r($arange1->toArray());
// Output: [0, 1, 2, 3, 4]
Range with start and stop:
$arange2 = ZTensor::arange(2, 8);
print_r($arange2->toArray());
// Output: [2, 3, 4, 5, 6, 7]
Range with step:
$arange3 = ZTensor::arange(0, 10, 2.5);
print_r($arange3->toArray());
// Output: [0, 2.5, 5.0, 7.5]
$linspace = ZTensor::linspace(0, 1, 5);
print_r($linspace->toArray());
// Output: [0, 0.25, 0.5, 0.75, 1.0]
$logspace = ZTensor::logspace(1, 3, 3); // 10^1, 10^2, 10^3
print_r($logspace->toArray());
// Output: [10, 100, 1000]
$random = ZTensor::random([2, 3], 0.0, 10.0);
echo "Random tensor shape: ";
print_r($random->shape());
// Generates random values between 0.0 and 10.0
$randn = ZTensor::randn([2, 2], 0.0, 1.0);
echo "Normal distribution tensor shape: ";
print_r($randn->shape());
// Generates normally distributed random values
$a = ZTensor::arr([[1, 2], [3, 4]]);
$b = ZTensor::arr([[5, 6], [7, 8]]);
$sum = $a->add($b);
print_r($sum->toArray());
// Output: [[6, 8], [10, 12]]
$a = ZTensor::arr([[1, 2], [3, 4]]);
$b = ZTensor::arr([[5, 6], [7, 8]]);
$diff = $a->sub($b);
print_r($diff->toArray());
// Output: [[-4, -4], [-4, -4]]
$a = ZTensor::arr([[1, 2], [3, 4]]);
$b = ZTensor::arr([[5, 6], [7, 8]]);
$product = $a->mul($b);
print_r($product->toArray());
// Output: [[5, 12], [21, 32]]
$a = ZTensor::arr([[10, 20], [30, 40]]);
$b = ZTensor::arr([[2, 4], [5, 8]]);
$division = $a->divide($b);
print_r($division->toArray());
// Output: [[5, 5], [6, 5]]
$a = ZTensor::arr([[1, 2], [3, 4]]);
$scalar_mul = $a->scalarMultiply(2.5);
print_r($scalar_mul->toArray());
// Output: [[2.5, 5], [7.5, 10]]
$a = ZTensor::arr([[4, 8], [12, 16]]);
$scalar_div = $a->scalarDivide(2.0);
print_r($scalar_div->toArray());
// Output: [[2, 4], [6, 8]]
$a = ZTensor::arr([[2, 3], [4, 5]]);
$power = $a->pow(2);
print_r($power->toArray());
// Output: [[4, 9], [16, 25]]
$matrix_a = ZTensor::arr([
[1, 2, 3],
[4, 5, 6]
]);
$matrix_b = ZTensor::arr([
[7, 8],
[9, 10],
[11, 12]
]);
$matrix_product = $matrix_a->matmul($matrix_b);
print_r($matrix_product->toArray());
// Output: [[58, 64], [139, 154]]
$matrix = ZTensor::arr([
[1, 2, 3],
[4, 5, 6]
]);
$transposed = $matrix->transpose();
print_r($transposed->toArray());
// Output: [[1, 4], [2, 5], [3, 6]]
Vector dot product:
$vec1 = ZTensor::arr([1, 2, 3]);
$vec2 = ZTensor::arr([4, 5, 6]);
$dot_product = $vec1->dot($vec2);
echo "Dot product: $dot_product\n";
// Output: 32 (1*4 + 2*5 + 3*6)
Matrix-vector multiplication:
$matrix = ZTensor::arr([[1, 2], [3, 4]]);
$vector = ZTensor::arr([5, 6]);
$result = $matrix->dot($vector);
print_r($result->toArray());
// Output: [17, 39]
$negative = ZTensor::arr([-1, -2, 3, -4]);
$absolute = $negative->abs();
print_r($absolute->toArray());
// Output: [1, 2, 3, 4]
$values = ZTensor::arr([1, 4, 9, 16]);
$sqrt_result = $values->sqrt();
print_r($sqrt_result->toArray());
// Output: [1, 2, 3, 4]
$values = ZTensor::arr([0, 1, 2]);
$exp_result = $values->exp();
print_r($exp_result->toArray());
// Output: [1, 2.718..., 7.389...]
$values = ZTensor::arr([1, 2.718, 7.389]);
$log_result = $values->log();
print_r($log_result->toArray());
// Output: [0, 1, 2] (approximately)
$data = ZTensor::arr([-2, -1, 0, 1, 2]);
$sigmoid_result = $data->sigmoid();
print_r($sigmoid_result->toArray());
// Output: [0.119, 0.269, 0.5, 0.731, 0.881] (approximately)
$sigmoid_values = ZTensor::arr([0.119, 0.269, 0.5, 0.731, 0.881]);
$sigmoid_deriv = $sigmoid_values->sigmoidDerivative();
print_r($sigmoid_deriv->toArray());
// Output: derivative values
$data = ZTensor::arr([-2, -1, 0, 1, 2]);
$relu_result = $data->relu();
print_r($relu_result->toArray());
// Output: [0, 0, 0, 1, 2]
$data = ZTensor::arr([-2, -1, 0, 1, 2]);
$relu_deriv = $data->reluDerivative();
print_r($relu_deriv->toArray());
// Output: [0, 0, 0, 1, 1]
$data = ZTensor::arr([-2, -1, 0, 1, 2]);
$leaky_relu = $data->leakyRelu(0.1);
print_r($leaky_relu->toArray());
// Output: [-0.2, -0.1, 0, 1, 2]
$data = ZTensor::arr([-2, -1, 0, 1, 2]);
$leaky_deriv = $data->leakyReluDerivative(0.1);
print_r($leaky_deriv->toArray());
// Output: [0.1, 0.1, 0.1, 1, 1]
$data = ZTensor::arr([-2, -1, 0, 1, 2]);
$tanh_result = $data->tanh();
print_r($tanh_result->toArray());
// Output: [-0.964, -0.762, 0, 0.762, 0.964] (approximately)
$tanh_values = ZTensor::arr([-0.964, -0.762, 0, 0.762, 0.964]);
$tanh_deriv = $tanh_values->tanhDerivative();
print_r($tanh_deriv->toArray());
// Output: derivative values
$data = ZTensor::arr([
[1, 2, 3],
[4, 5, 6]
]);
$softmax_result = $data->softmax();
print_r($softmax_result->toArray());
// Output: normalized probabilities for each row
$softmax_values = ZTensor::arr([
[0.09, 0.244, 0.665],
[0.09, 0.244, 0.665]
]);
$softmax_deriv = $softmax_values->softmaxDerivative();
print_r($softmax_deriv->toArray());
// Output: derivative values
$tensor = ZTensor::arr([
[1, 2, 3],
[4, 5, 6]
]);
$total_sum = $tensor->sumtotal();
echo "Total sum: $total_sum\n";
// Output: 21
$tensor = ZTensor::arr([1, 2, 3, 4, 5]);
$mean_value = $tensor->mean();
echo "Mean: $mean_value\n";
// Output: 3.0
$tensor = ZTensor::arr([5, 2, 8, 1, 9]);
$min_value = $tensor->min();
echo "Minimum: $min_value\n";
// Output: 1
$tensor = ZTensor::arr([5, 2, 8, 1, 9]);
$max_value = $tensor->max();
echo "Maximum: $max_value\n";
// Output: 9
$tensor = ZTensor::arr([1, 2, 3, 4, 5]);
$std_value = $tensor->std();
echo "Standard deviation: $std_value\n";
// Output: approximately 1.58
$tensor = ZTensor::arr([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]);
$sum_result = ZTensor::zeros([3]);
$tensor->sum($sum_result, 1); // sum along axis 1
print_r($sum_result->toArray());
// Output: [6, 15, 24]
$a = ZTensor::arr([1, 5, 3, 8, 2]);
$b = ZTensor::arr([2, 4, 3, 6, 9]);
$greater_result = $a->greater($b);
print_r($greater_result->toArray());
// Output: [0, 1, 0, 1, 0]
$data = ZTensor::arr([[-2, 5, 10], [0, 15, 1]]);
$clipped = ZTensor::clip($data, 0, 10);
print_r($clipped->toArray());
// Output: [[0, 5, 10], [0, 10, 1]]
$data = ZTensor::arr([1, 5, 3, 8, 2]);
$min_result = ZTensor::minimum($data, 4.0);
print_r($min_result->toArray());
// Output: [1, 4, 3, 4, 2]
$data = ZTensor::arr([1, 5, 3, 8, 2]);
$max_result = ZTensor::maximum($data, 4.0);
print_r($max_result->toArray());
// Output: [4, 5, 4, 8, 4]
$tensor = ZTensor::arr([
[1, 2, 3, 4],
[5, 6, 7, 8]
]);
$shape = $tensor->shape();
print_r($shape);
// Output: [2, 4]
$tensor = ZTensor::arr([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]);
$dimensions = $tensor->ndim();
echo "Number of dimensions: $dimensions\n";
// Output: 3
$tensor = ZTensor::arr([[1, 2, 3], [4, 5, 6]]);
$total_size = $tensor->size();
echo "Total elements: $total_size\n";
// Output: 6
$tensor = ZTensor::arr([1, 2, 3]);
$is_empty = $tensor->isEmpty();
echo "Is empty: " . ($is_empty ? "yes" : "no") . "\n";
// Output: no
$tensor = ZTensor::arr([
[1, 2, 3, 4],
[5, 6, 7, 8]
]);
$reshaped = $tensor->reshape([4, 2]);
print_r($reshaped->toArray());
// Output: [[1, 2], [3, 4], [5, 6], [7, 8]]
$tensor = ZTensor::arr([[1, 2], [3, 4]]);
$php_array = $tensor->toArray();
print_r($php_array);
// Output: [[1, 2], [3, 4]]
$tensor = ZTensor::arr([
[1, 2, 3],
[4, 5, 6]
]);
$element = $tensor->key([1, 2]);
echo "Element at [1,2]: $element\n";
// Output: 6
$matrix = ZTensor::arr([
[1, 2],
[3, 4],
[5, 6]
]);
$bias = ZTensor::arr([10, 20]);
$broadcasted = $matrix->broadcast($bias);
print_r($broadcasted->toArray());
// Output: [[11, 22], [13, 24], [15, 26]]
$tensor = ZTensor::arr([
[1, 2],
[3, 4]
]);
$tiled = ZTensor::tile($tensor, 3);
print_r($tiled->toArray());
// Output: [[1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]]
For issues related to the ZTensor extension itself, please refer to the official repository or documentation provided by the extension maintainers.
Contributions are welcome! Feel free to open issues or submit pull requests.
MIT License. See LICENSE
.