NAME
Math::MatrixLUP - Matrix operations and LUP decomposition.
VERSION
Version 0.03
SYNOPSIS
use Math::MatrixLUP;
use Math::AnyNum qw(:overload);
my $A = Math::MatrixLUP->new([
[2, -1, 5, 1],
[3, 2, 2, -6],
[1, 3, 3, -1],
[5, -2, -3, 3],
]);
my $det = $A->determinant;
my $sol = $A->solve([-3, -32, -47, 49]);
my $inv = $A->invert;
my $pow = $A**3;
my $pwm = $A->powmod(100, 10000019);
my $mod = $A % 10007;
DESCRIPTION
Math::MatrixLUP provides generic support for matrix operations and LUP decomposition, allowing any type of numbers inside the matrix, including native Perl numbers and numerical objects provided by other mathematical libraries, such as Math::AnyNum.
The following matrix operations are provided:
matrix-scalar arithmetical operations
matrix multiplication and division
matrix exponentiation
determinant of a square-matrix
inverting a square-matrix
solving a system of linear equations
Math::MatrixLUP objects are immutable.
METHODS
new
Create a new Math::MatrixLUP object, given a 2D array-ref:
my $A = Math::MatrixLUP->new([
[rand,rand,rand],
[rand,rand,rand],
[rand,rand,rand],
]);
identity / I
Returns a nXn identity matrix, given an integer argument:
my $I = Math::MatrixLUP->I(3);
my $I = Math::MatrixLUP->identity(3);
build
Build a new nXm matrix, given two integers and a subroutine reference as arguments:
my $A = Math::MatrixLUP->build($n, $m, sub ($i, $j) {
$i * $j
});
If only one integer is given, it creates a square nXn matrix:
my $B = Math::MatrixLUP->build($n, sub ($i, $j) {
$i**$j
});
The values of i
(row number) and j
(column number) range from [0, n-1]
and [0, m-1]
.
zero
Returns a new nXm matrix with all entries set to 0.
my $A = Math::MatrixLUP->zero(3); # 3x3 zero-matrix
my $A = Math::MatrixLUP->zero(3, 4); # 3x4 zero-matrix
scalar
Returns a new square matrix with the diagonal set a given value.
my $A = Math::MatrixLUP->scalar(3, 42); # 3x3 scalar with value 42
from_rows
A construct method that creates a new matrix, given a list of array-ref rows:
my $A = Math::MatrixLUP->from_rows(
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
);
from_columns
A construct method that creates a new matrix, given a list of array-ref columns:
my $A = Math::MatrixLUP->from_columns(
[1, 4, 7],
[2, 5, 8],
[3, 6, 9],
);
set_row
Returns a new matrix with the n-th (zero-based) row set to the given array-ref of values:
my $B = $A->set_row(0, [1,2,3,4]); # set first row
set_column
Returns a new matrix with the n-th (zero-based) column set to the given array-ref of values:
my $B = $A->set_column(0, [1,2,3,4]); # set first column
row
A constructor method that creates a row vector, given a single array-ref of numbers.
my $row_vector = Math::MatrixLUP->row([1, 4, 4, 8]);
When called on a matrix object, it returns the n-th row (zero-based) as an array-ref.
my $row = $A->row(0); # first row as an array-ref
rows
Returns the rows of the matrix as an array of array-refs.
my @rows = $A->rows;
column
A constructor method that creates a column vector, given a single array-ref of numbers.
my $column_vector = Math::MatrixLUP->column([1, 4, 4, 8]);
When called on a matrix object, it returns the n-th column (zero-based) as an array-ref.
my $col = $A->column(0); # first column as an array-ref
columns
Returns the columns of the matrix as an array of array-refs.
my @columns = $A->columns;
diagonal
A constructor method that creates a diagonal matrix from a single array-ref of numbers.
my $A = Math::MatrixLUP->diagonal([1, 4, 4, 8]);
The matrix is zero filled except for the diagonal, which take the value of the given vector.
When called on a matrix object, it returns the diagonal as an array-ref:
my $diag = $A->diagonal;
anti_diagonal
A constructor method that creates an anti-diagonal matrix from a single array-ref of numbers.
my $A = Math::MatrixLUP->anti_diagonal([1, 4, 4, 8]);
The matrix is zero filled except for the anti-diagonal, which take the value of the given vector.
When called on a matrix object, it returns the anti-diagonal as an array-ref:
my $diag = $A->anti_diagonal;
* Arithmetic operations
neg
Returns a new matrix with all the terms negated.
my $B = -$A;
my $B = $A->neg;
abs
Returns a new matrix with the abs()
function applied to all terms.
my $B = abs($A);
my $B = $A->abs;
floor
Returns a new matrix with the floor()
function applied to all terms.
my $B = $A->floor;
ceil
Returns a new matrix with the ceil()
function applied to all terms.
my $B = $A->ceil;
add
Add two matrices of the same dimensions:
my $C = $A + $B;
my $C = $A->add($B);
If one of the arguments is not a Math::MatrixLUP object, scalar addition is performed:
my $B = $A + $scalar;
sub
Subtract two matrices of the same dimensions:
my $C = $A - $B;
my $C = $A->sub($B);
If one of the arguments is not a Math::MatrixLUP object, scalar subtraction is performed:
my $B = $A - $scalar;
my $B = $scalar - $A;
mul
Multiplication of two matrices, where the number of columns in A equals the number of rows in B.
my $C = $A * $B;
my $C = $A->mul($B);
If one of the arguments is not a Math::MatrixLUP object, scalar multiplication is performed:
my $B = $A * $scalar;
div
Division of two matrices.
my $C = $A / $B;
my $C = $A->div($B);
Defined as:
A/B = A * B^(-1)
If one of the arguments is not a Math::MatrixLUP object, scalar division is performed:
my $B = $A / $scalar;
my $B = $scalar / $A;
mod
Modulo operation.
my $C = $A % $B;
my $C = $A->mod($B);
Defined as:
A mod B = A - B*floor(A/B)
If one of the arguments is not a Math::MatrixLUP object, scalar modulo is performed:
my $B = $A % $scalar;
my $B = $scalar % $A;
pow
Matrix exponentiation, where the exponent is a native integer:
my $B = $A**$n;
my $B = $A->pow($n);
For negative n
, this operation is defined only if the matrix can be inverted.
powmod
Matrix exponentiation modulo m
, where the exponent is an arbitrary large positive integer:
my $B = $A->powmod($n, $m);
For negative n
, this operation is defined only if the matrix can be inverted.
* Bitwise operations
This section includes method for scalar and entrywise matrix bitwise operations.
lsft / rsft / or / xor / and
Bitwise scalar operations:
my $B = $A->lsft(2); # left-shift by 2 applied to each value
my $B = $A->rsft(2); # right-shift by 2 applied to each value
my $B = $A->or(2); # OR 2 applied to each value
my $B = $A->xor(2); # XOR 2 applied to each value
my $B = $A->and(2); # AND 2 applied to each value
Entrywise bitwise operations:
my $C = $A->lsft($B); # entrywise left-shift
my $C = $A->rsft($B); # entrywise right-shift
my $C = $A->or($B); # entrywise OR
my $C = $A->xor($B); # entrywise XOR
my $C = $A->and($B); # entrywise AND
* Transformations
flip
Returns a new matrix with rows and columns flipped.
vflip / vertical_flip
Returns a new matrix with rows flipped.
hflip / horizontal_flip
Returns a new matrix with columns flipped.
transpose
Returns the transposed matrix. This is a new matrix where columns and rows of the self-matrix are swapped.
concat
Concatenates two matrices of same row count. The result is a new matrix.
map
Map each entry of a matrix to a given subroutine callback.
my $B = $A->map(sub { $_**2 }); # new matrix with each entry squared
The subroutine is called with $i
and $j
as arguments, such that $_ = $A->[$i][$j]
.
* Comparisons
eq / ne
Decide if two matrices are equal or not.
$A == $B # true if equal
$A != $B # true if not equal
lt / le / gt / ge / cmp
Compare two matrices, entrywise:
$A < $B # true if A is less than B
$A <= $B # true if A is less than or equal to B
$A > $B # true if A is greater than B
$A >= $B # true if A is greater than or equal to B
$A <=> $B # -1 if A < B, 0 if A == B, 1 if A > B
* Linear algebra
solve
Solve a system of linear equations.
my $A = Math::MatrixLUP->new([
[2, -1, 5, 1],
[3, 2, 2, -6],
[1, 3, 3, -1],
[5, -2, -3, 3],
]);
my $solution = $A->solve([-3, -32, -47, 49]);
say join(', ', @{$solution}); #=> 2, -12, -4, 1
inv / invert
Invert a square matrix.
my $B = $A->inv;
invmod
Invert a square matrix modulo a positive integer.
my $B = $A->invmod($m);
det / determinant
Compute the determinant of a square matrix.
rref
Returns the reduced row echelon form of the self-matrix.
my $B = $A->rref;
decompose
Returns the LUP decomposition of the self matrix.
my ($N, $A, $P) = $matrix->decompose;
There is no need to call this method explicitly. It is called internally automatically and is cached at object-level.
* Other methods
clone
Returns a deep copy of the self-matrix.
size
Returns the dimensions of the matrix (1-based):
my ($rows, $cols) = $A->size;
* Conversions
as_array
Returns the matrix as a 2D array-ref.
stringify
Retruns a stringified version of the self-matrix.
OVERLOADING
The entries of a Math::MatrixLUP object can be accessed as an array-ref:
my $Aij = $A->[$i][$j];
However, modifying the matrix in-place is not recommended, as Math::MatrixLUP uses dynamic caching at object-level in order to avoid recomputing the LUP decomposition multiple times for the same matrix-object.
SEE ALSO
Math::Matrix - Multiply and invert matrices.
Math::GSL::Matrix - Mathematical functions concerning Matrices using the GNU Scientific Library (GSL).
Math::MatrixDecomposition::LU - LU decomposition with partial pivoting of a real matrix.
Math::AnyNum - Arbitrary size precision for integers, rationals, floating-points and complex numbers.
REPOSITORY
https://github.com/trizen/Math-MatrixLUP
REFERENCES
https://en.wikipedia.org/wiki/LU_decomposition
AUTHOR
Daniel Șuteu, <trizen at cpan.org>
COPYRIGHT AND LICENSE
Copyright (C) 2019 Daniel Șuteu
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.22.0 or, at your option, any later version of Perl 5 you may have available.