Mercurial > repos > deepakjadmin > mayatool3_test2
diff lib/Matrix.pm @ 0:4816e4a8ae95 draft default tip
Uploaded
author | deepakjadmin |
---|---|
date | Wed, 20 Jan 2016 09:23:18 -0500 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/Matrix.pm Wed Jan 20 09:23:18 2016 -0500 @@ -0,0 +1,3164 @@ +package Matrix; +# +# $RCSfile: Matrix.pm,v $ +# $Date: 2015/02/28 20:47:17 $ +# $Revision: 1.16 $ +# +# Author: Manish Sud <msud@san.rr.com> +# +# Copyright (C) 2015 Manish Sud. All rights reserved. +# +# This file is part of MayaChemTools. +# +# MayaChemTools is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 3 of the License, or (at your option) any +# later version. +# +# MayaChemTools is distributed in the hope that it will be useful, but without +# any warranty; without even the implied warranty of merchantability of fitness +# for a particular purpose. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or +# write to the Free Software Foundation Inc., 59 Temple Place, Suite 330, +# Boston, MA, 02111-1307, USA. +# + +use strict; +use Carp; +use Exporter; +use Scalar::Util (); +use Vector; + +use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); + +@ISA = qw(Exporter); +@EXPORT = qw(IsMatrix IdentityMatrix NewFromRows NewFromColumns NewFromDiagonal UnitMatrix ZeroMatrix); +@EXPORT_OK = qw(SetValuePrintFormat); + +%EXPORT_TAGS = ( + all => [@EXPORT, @EXPORT_OK] + ); + +# Setup class variables... +my($ClassName, $ValueFormat, $MatrixPrintStyle); +_InitializeClass(); + +# +# Using the following explicity overloaded operators, Perl automatically generates methods +# for operations with no explicitly defined methods. Autogenerated methods are possible for +# these operators: +# +# o Arithmetic operators: += -= *= /= **= %= ++ -- x= .= +# o Increment and decrement: ++ -- +# +# 'fallback' is set to 'false' to raise exception for all other operators. +# +use overload '""' => 'StringifyMatrix', + + '@{}' => '_MatrixToArrayOperator', + + '+' => '_MatrixAdditionOperator', + '-' => '_MatrixSubtractionOperator', + '*' => '_MatrixMultiplicationOperator', + '/' => '_MatrixDivisionOperator', + '**' => '_MatrixExponentiationOperator', + '%' => '_MatrixModulusOperator', + + 'bool' => '_MatrixBooleanOperator', + '!' => '_MatrixNotBooleanOperator', + + '==' => '_MatrixEqualOperator', + '!=' => '_MatrixNotEqualOperator', + '<' => '_MatrixLessThanOperator', + '<=' => '_MatrixLessThanEqualOperator', + '>' => '_MatrixGreatarThanOperator', + '>=' => '_MatrixGreatarThanEqualOperator', + + 'neg' => '_MatrixNegativeValueOperator', + + 'abs' => '_MatrixAbsoluteValueOperator', + 'exp' => '_MatrixExpNaturalBaseOperator', + 'log' => '_MatrixLogNaturalBaseOperator', + 'sqrt' => '_MatrixSquareRootOperator', + 'cos' => '_MatrixCosineOperator', + 'sin' => '_MatrixSineOperator', + + 'fallback' => undef; + +# Class constructor... +sub new { + my($Class, $NumOfRows, $NumOfCols) = @_; + + # Initialize object... + my $This = {}; + bless $This, ref($Class) || $Class; + $This->_InitializeMatrix($NumOfRows, $NumOfCols); + + return $This; +} + +# Initialize object data... +# +sub _InitializeMatrix { + my($This, $NumOfRows, $NumOfCols) = @_; + + if (!(defined($NumOfRows) && defined($NumOfCols))) { + croak "Error: ${ClassName}->_InitializeMatrix: NumOfRows and NumOfCols must be specified..."; + } + if (!(($NumOfRows > 0) && ($NumOfRows > 0))) { + croak "Error: ${ClassName}->_InitializeMatrix: NumOfRows and NumOfCols must be a positive number..."; + } + # Initialize matrix elements to zero... + @{$This->{Values}} = (); + + my($RowIndex, @EmptyRow); + + @EmptyRow = (); + @EmptyRow = ('0') x $NumOfCols; + + for $RowIndex (0 .. ($NumOfRows - 1)) { + @{$This->{Values}[$RowIndex]} = (); + @{$This->{Values}[$RowIndex]} = @EmptyRow; + } +} + +# Initialize class ... +sub _InitializeClass { + #Class name... + $ClassName = __PACKAGE__; + + # Print style for matrix rows during StringifyMatrix operation. + # Possible values: AllRowsInOneLine, OneRowPerLine + # + $MatrixPrintStyle = "AllRowsInOneLine"; + + # Print format for matrix values... + $ValueFormat = "%g"; +} + +# Get matrix size... +# +sub GetSize { + my($This) = @_; + + return ($This->GetNumOfRows(), $This->GetNumOfColumns()); +} + +# Get matrix dimensions... +# +sub GetDimension { + my($This) = @_; + + return $This->GetSize(); +} + +# Get number of rows in matrix +# +sub GetNumOfRows { + my($This) = @_; + my($NumOfRows); + + # Size of row array... + $NumOfRows = $#{$This->{Values}} + 1; + + return $NumOfRows; +} + +# Get number of columns in matrix +# +sub GetNumOfColumns { + my($This) = @_; + my($NumOfCols); + + # Size of column array for first row assuming sizes of columns are same... + $NumOfCols = $#{$This->{Values}[0]} + 1; + + return $NumOfCols; +} + +# Get reference to array holding matrix values in order to directly manipulate these values... +# +sub GetMatrixValuesReference { + my($This) = @_; + + return \@{$This->{Values}}; +} + +# Copy matrix... +# +sub Copy { + my($This) = @_; + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex, $Matrix); + + # Create a new matrix... + ($NumOfRows, $NumOfCols) = $This->GetSize(); + $Matrix = new Matrix($NumOfRows, $NumOfCols); + + # Set matrix values... + for $RowIndex (0 .. ($NumOfRows -1)) { + for $ColIndex (0 .. ($NumOfCols -1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = $This->{Values}[$RowIndex][$ColIndex]; + } + } + return $Matrix; +} + +# Create a new matrix using rows specified in one of the following formats: +# o List of vector objects +# o References to list of values +# o List of strings containing row values delimited by space +# +# Each row must contain the same number of values. +# +# This functionality can be either invoked as a class function or an +# object method. +# +sub NewFromRows { + my($FirstParameter, @OtherParamaters) = @_; + + if (IsMatrix($FirstParameter)) { + return _NewFromRowsOrColumns('FromRows', @OtherParamaters); + } + else { + return _NewFromRowsOrColumns('FromRows', @_); + } +} + +# Create a new matrix using columns specified in one of the following formats: +# o List of vector objects +# o References to list of values +# o List of strings containing columns values delimited by space +# +# Each columns must contain the same number of values. +# +# This functionality can be either invoked as a class function or an +# object method. +# +sub NewFromColumns { + my($FirstParameter, @OtherParamaters) = @_; + + if (IsMatrix($FirstParameter)) { + return _NewFromRowsOrColumns('FromColumns', @OtherParamaters); + } + else { + return _NewFromRowsOrColumns('FromColumns', @_); + } +} + +# Create a new matrix using diagonal values specified in one of the following formats: +# o A vector object +# o Reference to list of values +# o Strings containing diagonal values delimited by space +# +# This functionality can be either invoked as a class function or an +# object method. +# +sub NewFromDiagonal { + my($FirstParameter, @OtherParamaters) = @_; + + if (IsMatrix($FirstParameter)) { + return _NewFromDiagonal(@OtherParamaters); + } + else { + return _NewFromDiagonal(@_); + } +} + +# Create a new matrix using diagonal values specified in one of the following formats: +# o A vector object +# o Reference to list of values +# o Strings containing diagonal values delimited by space +# +sub _NewFromDiagonal { + my(@SpecifiedDiagonalValues) = @_; + my($ErrorMsgPrefix, $CheckSizes, $CombineValues, $ValuesRefs, $DiagonalValuesRef); + + $ErrorMsgPrefix = "Error: ${ClassName}::_NewFromDiagonal"; + if (!@SpecifiedDiagonalValues) { + croak "$ErrorMsgPrefix: No diagonal values specified..."; + } + + # Collect specified diagonal values... + $CheckSizes = 0; $CombineValues = 1; + $ValuesRefs = _ProcessSpecifiedMatrixValues($ErrorMsgPrefix, $CheckSizes, $CombineValues, @SpecifiedDiagonalValues); + $DiagonalValuesRef = $ValuesRefs->[0]; + + # Create a new matrix... + my($Matrix, $NumOfRows, $NumOfCols, $RowIndex); + + $NumOfRows = @{$DiagonalValuesRef}; + $NumOfCols = $NumOfRows; + + $Matrix = new Matrix($NumOfRows, $NumOfCols); + + # Set diagonal values... + for $RowIndex (0 .. ($NumOfRows - 1)) { + $Matrix->{Values}[$RowIndex][$RowIndex] = $DiagonalValuesRef->[$RowIndex]; + } + + return $Matrix; +} + +# Create a new matrix using rows or columns specified in one of the following formats: +# o List of vector objects +# o References to list of values +# o List of strings containing row values delimited by space +# +# Each row or column must contain the same number of values. +# +sub _NewFromRowsOrColumns { + my($Mode, @SpecifiedValues) = @_; + + if ($Mode !~ /^(FromRows|FromColumns)$/i) { + croak "Error: ${ClassName}::_NewFromRowsOrColumns: Unknown mode: $Mode..."; + } + my($ErrorMsgPrefix, $CheckSizes, $CombineValues, $ValuesRefs); + + # Retrieve information about specified values and make sure similar number of values + # are specified for each row or column... + if ($Mode =~ /^FromRows$/i) { + $ErrorMsgPrefix = "Error: ${ClassName}::_NewFromRows"; + } + else { + $ErrorMsgPrefix = "Error: ${ClassName}::_NewFromColumns"; + } + $CheckSizes = 1; $CombineValues = 0; + $ValuesRefs = _ProcessSpecifiedMatrixValues($ErrorMsgPrefix, $CheckSizes, $CombineValues, @SpecifiedValues); + + # Create a new matrix... + my($Matrix, $NumOfRows, $NumOfCols, $RowIndex, $ColIndex, $RowMode, $Value); + + if ($Mode =~ /^FromRows$/i) { + $NumOfRows = scalar @{$ValuesRefs}; + $NumOfCols = scalar @{$ValuesRefs->[0]}; + $RowMode = 1; + } + elsif ($Mode =~ /^FromColumns$/i) { + $NumOfRows = scalar @{$ValuesRefs->[0]}; + $NumOfCols = scalar @{$ValuesRefs}; + $RowMode = 0; + } + $Matrix = new Matrix($NumOfRows, $NumOfCols); + + # Setup matrix values... + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Value = $RowMode ? $ValuesRefs->[$RowIndex]->[$ColIndex]: $ValuesRefs->[$ColIndex]->[$RowIndex]; + $Matrix->{Values}[$RowIndex][$ColIndex] = $Value; + } + } + + return $Matrix; +} + +# Process specified matrix values in any of the following supported formats: +# +# o List of vector objects +# o References to list of values +# o List of strings containing row values delimited by space +# +# And return a reference to an array containing references to arrays with specified values. +# +# Value of CombineValuesStatus determines whether all the values specified are combined +# into one array and return its reference as the only entry in the array being returned. +# +sub _ProcessSpecifiedMatrixValues { + my($ErrorMsgPrefix, $CheckSizesStatus, $CombineValuesStatus, @SpecifiedValues) = @_; + my($Value, $TypeOfValue, @ValuesRefs); + + @ValuesRefs = (); + if (!@SpecifiedValues) { + croak "$ErrorMsgPrefix: No values specified..."; + } + + # Collect values... + for $Value (@SpecifiedValues) { + $TypeOfValue = ref $Value; + + if (Vector::IsVector($Value)) { + # Feference to vector object... + my($ValuesRef); + $ValuesRef = $Value->GetValues(); + if (!@{$ValuesRef}) { + croak "$ErrorMsgPrefix: Specified vector object must contain some values..."; + } + push @ValuesRefs, $ValuesRef; + } + elsif ($TypeOfValue =~ /^ARRAY/) { + # Refernece to an array... + if (!@{$Value}) { + croak "$ErrorMsgPrefix: Specified array reference must contain some values..."; + } + push @ValuesRefs, $Value; + } + elsif ($TypeOfValue eq '') { + # String value... + my(@Values); + @Values = split(' ', $Value); + if (!@Values) { + croak "$ErrorMsgPrefix: Specified string must contain some values..."; + } + push @ValuesRefs, \@Values; + } + else { + croak "$ErrorMsgPrefix: Value format, $TypeOfValue, of a specified value to be added to matrix object is not supported..."; + } + } + + # Combine all specified values into one array... + if ($CombineValuesStatus) { + my($ValuesRef, @Values); + + @Values = (); + for $ValuesRef (@ValuesRefs) { + push @Values, @{$ValuesRef}; + } + @ValuesRefs = (); + push @ValuesRefs, \@Values; + } + + # Make sure reference to all specified value arrays contain the same number of values... + if ($CheckSizesStatus) { + my($Index, $FirstValueSize); + $FirstValueSize = $#{$ValuesRefs[0]}; + for $Index (1 .. $#ValuesRefs) { + if ($FirstValueSize != $#{$ValuesRefs[$Index]}) { + croak "$ErrorMsgPrefix: Number of values in each specified value type to be added to matrix object must be same..."; + } + } + } + + return \@ValuesRefs; +} + +# Create a new zero matrix of specified size or default size of 3 x 3. +# +# This functionality can be either invoked as a class function or an +# object method. +# +sub ZeroMatrix (;$$$) { + my($FirstParameter, $SecondParameter, $ThirdParameter) = @_; + my($This, $NumOfRows, $NumOfCols, $Matrix); + + $This = undef; + if (defined($FirstParameter) && IsMatrix($FirstParameter)) { + ($This, $NumOfRows, $NumOfCols) = ($FirstParameter, $SecondParameter, $ThirdParameter); + } + else { + ($This, $NumOfRows, $NumOfCols) = (undef, $FirstParameter, $SecondParameter); + } + ($NumOfRows, $NumOfCols) = (defined($NumOfRows) && defined($NumOfCols)) ? ($NumOfRows, $NumOfCols) : (3, 3); + + # Set up a new zero matrix + $Matrix = new Matrix($NumOfRows, $NumOfCols); + + return $Matrix; +} + +# Create a new unit matrix of specified size or default size of 3 x 3. +# +# This functionality can be either invoked as a class function or an +# object method. +# +sub UnitMatrix (;$$$) { + my($FirstParameter, $SecondParameter, $ThirdParameter) = @_; + my($This, $NumOfRows, $NumOfCols, $Matrix, $RowIndex); + + $This = undef; + if (defined($FirstParameter) && IsMatrix($FirstParameter)) { + ($This, $NumOfRows, $NumOfCols) = ($FirstParameter, $SecondParameter, $ThirdParameter); + } + else { + ($This, $NumOfRows, $NumOfCols) = (undef, $FirstParameter, $SecondParameter); + } + ($NumOfRows, $NumOfCols) = (defined($NumOfRows) && defined($NumOfCols)) ? ($NumOfRows, $NumOfCols) : (3, 3); + + # Set up a new zero matrix + $Matrix = new Matrix($NumOfRows, $NumOfCols); + + if ($NumOfRows != $NumOfCols) { + carp "Warning: ${ClassName}::UnitMatrix: Specified matrix, $NumOfRows x $NumOfCols, is not a square matrix..."; + } + + # Initialize diagonal elements to 1... + for $RowIndex (0 .. ($NumOfRows - 1)) { + $Matrix->{Values}[$RowIndex][$RowIndex] = 1.0; + } + + return $Matrix; +} + +# Identity matrix of specified size or size 3 x 3... +# +sub IdentityMatrix (;$$$) { + my($FirstParameter, $SecondParameter, $ThirdParameter) = @_; + + return UnitMatrix($FirstParameter, $SecondParameter, $ThirdParameter); +} + +# Set all matrix values to 0s... +# +sub Zero { + my($This) = @_; + + return $This->SetAllValues(0.0); +} + +# Set all matrix values to 1s... +# +sub One { + my($This) = @_; + + return $This->SetAllValues(1.0); +} + +# Get a matrix value with row and column indicies starting from 0... +# +sub GetValue { + my($This, $RowIndex, $ColIndex, $SkipIndexCheck) = @_; + + if ($SkipIndexCheck) { + $This->_GetValue($RowIndex, $ColIndex); + } + + $This->_ValidateRowAndColumnIndicies("Error: ${ClassName}::GetValue", $RowIndex, $ColIndex); + + return $This->_GetValue($RowIndex, $ColIndex); +} + +# Get a matrix value... +# +sub _GetValue { + my($This, $RowIndex, $ColIndex) = @_; + + return $This->{Values}[$RowIndex][$ColIndex]; +} + +# Set a matrix value with row and column indicies starting from 0... +# +sub SetValue { + my($This, $RowIndex, $ColIndex, $Value, $SkipIndexCheck) = @_; + + if ($SkipIndexCheck) { + $This->_SetValue($RowIndex, $ColIndex, $Value); + } + + $This->_ValidateRowAndColumnIndicies("Error: ${ClassName}::SetValue", $RowIndex, $ColIndex); + + return $This->_SetValue($RowIndex, $ColIndex, $Value); +} + +# Set a matrix value... +# +sub _SetValue { + my($This, $RowIndex, $ColIndex, $Value) = @_; + + $This->{Values}[$RowIndex][$ColIndex] = $Value; + + return $This; +} + +# Set all matrix values to a specified value... +# +sub SetAllValues { + my($This, $Value) = @_; + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $This->{Values}[$RowIndex][$ColIndex] = $Value; + } + } + return $This; +} + +# Set values of a row in a matrix value with row index starting from 0... +# +sub SetRowValues { + my($This, $RowIndex, @SpecifiedValues) = @_; + my($NumOfRows, $NumOfCols, $ColIndex, $ErrorMsgPrefix, $CheckSizes, $CombineValues, $ValuesRefs, $RowValuesRef, $NumOfRowValues); + + $ErrorMsgPrefix = "Error: ${ClassName}->SetRowValues"; + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + $This->_ValidateRowIndex($ErrorMsgPrefix, $RowIndex); + + # Collect specified row values... + $CheckSizes = 0; $CombineValues = 1; + $ValuesRefs = _ProcessSpecifiedMatrixValues($ErrorMsgPrefix, $CheckSizes, $CombineValues, @SpecifiedValues); + $RowValuesRef = $ValuesRefs->[0]; + + # Check number of specified row values... + $NumOfRowValues = @{$RowValuesRef}; + if ($NumOfRowValues != $NumOfCols) { + croak "$ErrorMsgPrefix: Number of specified row values, $NumOfRowValues, must be equal to number of row values, $NumOfCols, in matrix..."; + } + + # Set row values... + for $ColIndex (0 .. ($NumOfRowValues - 1)) { + $This->{Values}[$RowIndex][$ColIndex] = $RowValuesRef->[$ColIndex]; + } + return $This; +} + +# Add new row values to a matrix... +# +sub AddRowValues { + my($This, @SpecifiedValues) = @_; + my($NumOfRows, $NumOfCols, $RowIndex, $ErrorMsgPrefix, $CheckSizes, $CombineValues, $RowValueRef, $RowValuesRefs, $NumOfNewRows, $NumOfNewCols); + + $ErrorMsgPrefix = "Error: ${ClassName}->AddRowValues"; + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + # Collect specified row values... + $CheckSizes = 1; $CombineValues = 0; + $RowValuesRefs = _ProcessSpecifiedMatrixValues($ErrorMsgPrefix, $CheckSizes, $CombineValues, @SpecifiedValues); + + # Check number of specified row values... + $NumOfNewRows = scalar @{$RowValuesRefs}; + $NumOfNewCols = scalar @{$RowValuesRefs->[0]}; + + if ($NumOfNewCols != $NumOfCols) { + croak "$ErrorMsgPrefix: Number of values in each specified row, $NumOfNewCols, must be equal to number of row values, $NumOfCols, in matrix..."; + } + + # Add each row to the matrix... + $RowIndex = $NumOfRows - 1; + for $RowValueRef (@{$RowValuesRefs}) { + $RowIndex++; + @{$This->{Values}[$RowIndex]} = @{$RowValueRef}; + } + + return $This; +} + +# Get values of a row in matrix as an array. In scalar context, number of row +# values is returned... +# +sub GetRowValues { + my($This, $RowIndex) = @_; + + return $This->_GetRowOrColumnValues('AsArray', 'FromRow', $RowIndex); +} + +# Get values of a row in matrix as a vector object... +# +sub GetRowValuesAsVector { + my($This, $RowIndex) = @_; + + return $This->_GetRowOrColumnValues('AsVector', 'FromRow', $RowIndex); +} + +# Get values of a row as row matrix object... +# +sub GetRowValuesAsRowMatrix { + my($This, $RowIndex) = @_; + + return $This->_GetRowOrColumnValues('AsRowMatrix', 'FromRow', $RowIndex); +} + +# Get values of a row as column matrix object... +# +sub GetRowValuesAsColumnMatrix { + my($This, $RowIndex) = @_; + + return $This->_GetRowOrColumnValues('AsColumnMatrix', 'FromRow', $RowIndex); +} + +# Get values of a row in matrix as a space delimited string... +# +sub GetRowValuesAsString { + my($This, $RowIndex) = @_; + + return $This->_GetRowOrColumnValues('AsString', 'FromRow', $RowIndex); +} + +# Set values of a column in a matrix value with row index starting from 0... +# +sub SetColumnValues { + my($This, $ColIndex, @SpecifiedValues) = @_; + my($NumOfRows, $NumOfCols, $RowIndex, $ErrorMsgPrefix, $CheckSizes, $CombineValues, $ValuesRefs, $ColValuesRef, $NumOfColValues); + + $ErrorMsgPrefix = "Error: ${ClassName}->SetColumnValues"; + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + $This->_ValidateColumnIndex($ErrorMsgPrefix, $ColIndex); + + # Collect specified row values... + $CheckSizes = 0; $CombineValues = 1; + $ValuesRefs = _ProcessSpecifiedMatrixValues($ErrorMsgPrefix, $CheckSizes, $CombineValues, @SpecifiedValues); + $ColValuesRef = $ValuesRefs->[0]; + + # Check number of specified col values... + $NumOfColValues = @{$ColValuesRef}; + if ($NumOfColValues != $NumOfRows) { + croak "$ErrorMsgPrefix: Number of specified col values, $NumOfColValues, must be equal to number of column values, $NumOfRows, in matrix..."; + } + + # Set col values... + for $RowIndex (0 .. ($NumOfColValues - 1)) { + $This->{Values}[$RowIndex][$ColIndex] = $ColValuesRef->[$RowIndex]; + } + return $This; +} + +# Add new column values to a matrix... +# +sub AddColumnValues { + my($This, @SpecifiedValues) = @_; + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex, $ErrorMsgPrefix, $CheckSizes, $CombineValues, $ColValueRef, $ColValuesRefs, $NumOfNewRows, $NumOfNewCols); + + $ErrorMsgPrefix = "Error: ${ClassName}->AddColumnValues"; + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + # Collect specified column values... + $CheckSizes = 1; $CombineValues = 0; + $ColValuesRefs = _ProcessSpecifiedMatrixValues($ErrorMsgPrefix, $CheckSizes, $CombineValues, @SpecifiedValues); + + # Check number of specified column values... + $NumOfNewCols = scalar @{$ColValuesRefs}; + $NumOfNewRows = scalar @{$ColValuesRefs->[0]}; + + if ($NumOfNewRows != $NumOfRows) { + croak "$ErrorMsgPrefix: Number of values in each specified column, $NumOfNewRows, must be equal to number of column values, $NumOfRows, in matrix..."; + } + + # Add each column to the matrix... + $ColIndex = $NumOfCols - 1; + for $ColValueRef (@{$ColValuesRefs}) { + $ColIndex++; + for $RowIndex (0 .. ($NumOfCols - 1)) { + $This->{Values}[$RowIndex][$ColIndex] = $ColValueRef->[$RowIndex]; + } + } + + return $This; +} + +# Get values of a column in matrix as an array. In scalar context, number of column +# values is returned... +# +sub GetColumnValues { + my($This, $ColIndex) = @_; + + return $This->_GetRowOrColumnValues('AsArray', 'FromColumn', $ColIndex); +} + +# Get values of a column in matrix as a vector object... +# +sub GetColumnValuesAsVector { + my($This, $ColIndex) = @_; + + return $This->_GetRowOrColumnValues('AsVector', 'FromColumn', $ColIndex); +} + +# Get values of a column as row matrix object... +# +sub GetColumnValuesAsRowMatrix { + my($This, $ColIndex) = @_; + + return $This->_GetRowOrColumnValues('AsRowMatrix', 'FromColumn', $ColIndex); +} + +# Get values of a column as column matrix object... +# +sub GetColumnValuesAsColumnMatrix { + my($This, $ColIndex) = @_; + + return $This->_GetRowOrColumnValues('AsColumnMatrix', 'FromColumn', $ColIndex); +} + +# Get values of a column in matrix as a space delimited string... +# +sub GetColumnValuesAsString { + my($This, $ColIndex) = @_; + + return $This->_GetRowOrColumnValues('AsString', 'FromColumn', $ColIndex); +} + +# Get row or column values... +# +sub _GetRowOrColumnValues { + my($This, $Mode, $ValueMode, $ValueModeIndex) = @_; + + if ($Mode !~ /^(AsArray|AsVector|AsRowMatrix|AsColumnMatrix|AsString)$/i) { + croak "Error: ${ClassName}->_GetRowOrColumnValues: Unknown mode, $Mode, specified..."; + } + if ($ValueMode !~ /^(FromRow|FromColumn)$/i) { + croak "Error: ${ClassName}->_GetRowOrColumnValues: Unknown value mode, $ValueMode, specified..."; + } + + # Setup error message prefix... + my($ErrorMsgPrefix); + + $ErrorMsgPrefix = "${ClassName}->_GetRowOrColumnValues"; + if ($ValueMode =~ /^FromRow$/i) { + $ErrorMsgPrefix = "Error: ${ClassName}->GetRowValues${Mode}"; + } + elsif ($ValueMode =~ /^FromColumn$/i) { + $ErrorMsgPrefix = "Error: ${ClassName}->GetColumnValues${Mode}"; + } + + # Validate specified index and collect values... + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex, @Values); + + @Values = (); + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + if ($ValueMode =~ /^FromRow$/i) { + $RowIndex = $ValueModeIndex; + $This->_ValidateRowIndex($ErrorMsgPrefix, $RowIndex); + + for $ColIndex (0 .. ($NumOfCols - 1)) { + push @Values, $This->{Values}[$RowIndex][$ColIndex]; + } + } + elsif ($ValueMode =~ /^FromColumn$/i) { + $ColIndex = $ValueModeIndex; + $This->_ValidateColumnIndex($ErrorMsgPrefix, $ColIndex); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + push @Values, $This->{Values}[$RowIndex][$ColIndex]; + } + } + + # Return values... + if ($Mode =~ /^AsRowMatrix$/i) { + return NewFromRows(\@Values); + } + elsif ($Mode =~ /^AsColumnMatrix$/i) { + return NewFromColumns(\@Values); + } + elsif ($Mode =~ /^AsVector$/i) { + return new Vector(@Values); + } + elsif ($Mode =~ /^AsString$/i) { + return join(' ', @Values); + } + else { + return wantarray ? @Values : scalar @Values; + } +} + +# Set values of the diagonal in a square matrix... +# +sub SetDiagonalValues { + my($This, @SpecifiedDiagonalValues) = @_; + my($ErrorMsgPrefix, $NumOfRows, $NumOfCols, $RowIndex, $CheckSizes, $CombineValues, $ValuesRefs, $NumOfDiagonalValues, $DiagonalValuesRef); + + $ErrorMsgPrefix = "Error: ${ClassName}->SetDiagonalValues"; + if (!@SpecifiedDiagonalValues) { + croak "$ErrorMsgPrefix: No diagonal values specified..."; + } + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + if ($NumOfRows != $NumOfCols) { + croak "Error: $ErrorMsgPrefix: Specified matrix, $NumOfRows x $NumOfCols, is not a square matrix..."; + } + + # Collect specified diagonal values... + $CheckSizes = 0; $CombineValues = 1; + $ValuesRefs = _ProcessSpecifiedMatrixValues($ErrorMsgPrefix, $CheckSizes, $CombineValues, @SpecifiedDiagonalValues); + $DiagonalValuesRef = $ValuesRefs->[0]; + $NumOfDiagonalValues = @{$DiagonalValuesRef}; + + if ($NumOfDiagonalValues != $NumOfRows) { + croak "Error: $ErrorMsgPrefix: Number of specified diagonal values, $NumOfDiagonalValues, must be equal to number of rows, $NumOfRows, in square matrix..."; + } + + # Set diagonal values... + for $RowIndex (0 .. ($NumOfRows - 1)) { + $This->{Values}[$RowIndex][$RowIndex] = $DiagonalValuesRef->[$RowIndex]; + } + + return $This; +} + +# Get values of the diagonal in a square matrix as an array. In scalar context, number of +# diagonal values is returned... +# +sub GetDiagonalValues { + my($This) = @_; + + return $This->_GetDiagonalValues('AsArray'); +} + +# Get values of the diagonal in a square matrix as vector object... +# +sub GetDiagonalValuesAsVector { + my($This) = @_; + + return $This->_GetDiagonalValues('AsVector'); +} + +# Get values of the diagonal in a square matrix as row matrix object +# +sub GetDiagonalValuesAsRowMatrix { + my($This) = @_; + + return $This->_GetDiagonalValues('AsRowMatrix'); +} + +# Get values of the diagonal in a square matrix as column matrix object +# +sub GetDiagonalValuesAsColumnMatrix { + my($This) = @_; + + return $This->_GetDiagonalValues('AsColumnMatrix'); +} + +# Get values of the diagonal in a square matrix as a space delimited string... +# +sub GetDiagonalValuesAsString { + my($This) = @_; + + return $This->_GetDiagonalValues('AsString'); +} + +# Get diagonal values... +sub _GetDiagonalValues { + my($This, $Mode) = @_; + + if ($Mode !~ /^(AsArray|AsVector|AsRowMatrix|AsColumnMatrix|AsString)$/i) { + croak "Error: ${ClassName}->_GetDiagonalValues: Unknown mode, $Mode, specified..."; + } + + # Make sure it's a square matrix... + my($NumOfRows, $NumOfCols, $ErrorMsgPrefix); + + $ErrorMsgPrefix = "${ClassName}->_GetDiagonalValues${Mode}"; + ($NumOfRows, $NumOfCols) = $This->GetSize(); + if ($NumOfRows != $NumOfCols) { + croak "Error: $ErrorMsgPrefix: Specified matrix, $NumOfRows x $NumOfCols, is not a square matrix..."; + } + + # Collect values... + my($RowIndex, @Values); + @Values = (); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + push @Values, $This->{Values}[$RowIndex][$RowIndex]; + } + + # Return values... + if ($Mode =~ /^AsRowMatrix$/i) { + return NewFromRows(\@Values); + } + elsif ($Mode =~ /^AsColumnMatrix$/i) { + return NewFromColumns(\@Values); + } + elsif ($Mode =~ /^AsVector$/i) { + return new Vector(@Values); + } + elsif ($Mode =~ /^AsString$/i) { + return join(' ', @Values); + } + else { + return wantarray ? @Values : scalar @Values; + } +} + +# Is it a square matrix? +# +sub IsSquare { + my($This) = @_; + my($NumOfRows, $NumOfCols) = $This->GetSize(); + + return ($NumOfRows == $NumOfCols) ? 1 : 0; +} + +# Is it a unit matrix? +# +# A matrix is a unit matrix: +# o It's a square matrix +# o All its diagonal elements are ones and its off-diagonal elements are zeros +# +sub IsUnit { + my($This) = @_; + + # Is is a square matrix? + if (!$This->IsSquare()) { + return 0; + } + + # Check matrix values... + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex, $ExpectedValue); + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $ExpectedValue = ($RowIndex == $ColIndex) ? 1.0 : 0.0; + if ($This->{Values}[$RowIndex][$ColIndex] != $ExpectedValue) { + return 0; + } + } + } + return 1; +} + +# Is it an identity matrix? +# +sub IsIdentity { + my($This) = @_; + + return $This->IsUnit(); +} + +# Is it a diagonal matrix? +# +# A matrix is a diagonal matrix: +# o It's a square matrix +# o All its off-diagonal elements are zeros and its diagonal elements may or may not +# be zeros +# +# +sub IsDiagonal { + my($This) = @_; + + # Is is a square matrix? + if (!$This->IsSquare()) { + return 0; + } + + # Check off-diagonal matrix values... + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + COLINDEX: for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($RowIndex == $ColIndex) { + next COLINDEX; + } + if ($This->{Values}[$RowIndex][$ColIndex] != 0.0) { + return 0; + } + } + } + return 1; +} + +# Is it a lower bidiagonal matrix? +# +# A matrix is a lower bidiagonal matrix: +# o It's a square matrix +# o All its main diagonal and lower diagonal elements are non-zeros and all its +# other elements are zeros +# +sub IsLowerBiDiagonal { + my($This) = @_; + + # Is is a square matrix? + if (!$This->IsSquare()) { + return 0; + } + + # Check matrix values... + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex, $Value); + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Value = $This->{Values}[$RowIndex][$ColIndex]; + if ($RowIndex == $ColIndex) { + # Main diagonal... + if ($Value == 0.0) { + return 0; + } + } + elsif ($RowIndex == ($ColIndex + 1)) { + # Lower diagonal... + if ($Value == 0.0) { + return 0; + } + } + else { + # Other elements... + if ($Value != 0.0) { + return 0; + } + } + } + } + return 1; +} + +# Is it an upper bidiagonal matrix? +# +# A matrix is an upper bidiagonal matrix: +# o It's a square matrix +# o All its main diagonal and upper diagonal elements are non-zeros and all its +# other elements are zeros +# +sub IsUpperBiDiagonal { + my($This) = @_; + + # Is is a square matrix? + if (!$This->IsSquare()) { + return 0; + } + # Check matrix values... + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex, $Value); + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Value = $This->{Values}[$RowIndex][$ColIndex]; + if ($RowIndex == $ColIndex) { + # Main diagonal... + if ($Value == 0.0) { + return 0; + } + } + elsif ($RowIndex == ($ColIndex - 1)) { + # Upper diagonal... + if ($Value == 0.0) { + return 0; + } + } + else { + # Other elements... + if ($Value != 0.0) { + return 0; + } + } + } + } + return 1; +} + +# Is it a bidiagonal matrix? +# +# A matrix is a bidiagonal matrix: +# +sub IsBiDiagonal { + my($This) = @_; + + return ($This->IsUpperBiDiagonal() || $This->IsLowerBiDiagonal()) ? 1 : 0; +} + +# Is it a tridiagonal matrix? +# +# A matrix is a tribidiagonal matrix: +# o It's a square matrix +# o All its main diagonal, upper diagonal, and lower diagonal elements are non-zeros and all its +# other elements are zeros +# +# +sub IsTriDiagonal { + my($This) = @_; + + # Is is a square matrix? + if (!$This->IsSquare()) { + return 0; + } + + # Check matrix values... + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex, $Value); + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Value = $This->{Values}[$RowIndex][$ColIndex]; + if ($RowIndex == $ColIndex) { + # Main diagonal... + if ($Value == 0.0) { + return 0; + } + } + elsif ($RowIndex == ($ColIndex - 1)) { + # Upper diagonal... + if ($Value == 0.0) { + return 0; + } + } + elsif ($RowIndex == ($ColIndex + 1)) { + # Lower diagonal... + if ($Value == 0.0) { + return 0; + } + } + else { + # Other elements... + if ($Value != 0.0) { + return 0; + } + } + } + } + return 1; +} + +# Is it a lower triangular matrix? +# +# A matrix is a lower triangular matrix: +# o It's a square matrix +# o All its entries above the main diagonal are zero +# +sub IsLowerTriangular { + my($This) = @_; + + return $This->_IsLowerTriangularMatrix(); +} + +# Is it a left triangular matrix? +# +# A matrix is a left triangular matrix: +# o It's a square matrix +# o All its entries above the main diagonal are zero +# +sub IsLeftTriangular { + my($This) = @_; + + return $This->IsLowerTriangular(); +} + +# Is it a strictly lower triangular matrix? +# +# A matrix is a strictly lower triangular matrix: +# o It's a square matrix +# o All its entries on and above the main diagonal are zero +# +sub IsStrictlyLowerTriangular { + my($This) = @_; + my($DiagonalValue); + + $DiagonalValue = 0; + + return $This->_IsLowerTriangularMatrix($DiagonalValue); +} + +# Is it an unit lower triangular matrix? +# +# A matrix is an unit lower triangular matrix: +# o It's a square matrix +# o All its entries main diagonal are one +# o All its entries above the main diagonal are zero +# +sub IsUnitLowerTriangular { + my($This) = @_; + my($DiagonalValue); + + $DiagonalValue = 1; + + return $This->_IsLowerTriangularMatrix($DiagonalValue); +} + +# Is it a lower unitriangular matrix? +# +sub IsLowerUniTriangular { + my($This) = @_; + + return $This->IsUnitLowerTriangular(); +} + +# Is it a lower triangular, strictly lower triangular, or unit lower triangular matrix? +# +sub _IsLowerTriangularMatrix { + my($This, $DiagonalValue) = @_; + + # Is is a square matrix? + if (!$This->IsSquare()) { + return 0; + } + # Check matrix values... + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex, $CheckDiagonalValues); + + $CheckDiagonalValues = defined($DiagonalValue) ? 1 : 0; + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($CheckDiagonalValues && $RowIndex == $ColIndex) { + # Main diagonal... + if ($This->{Values}[$RowIndex][$ColIndex] != $DiagonalValue) { + return 0; + } + } + elsif ($RowIndex < $ColIndex) { + # Elemens above the main diagonal... + if ($This->{Values}[$RowIndex][$ColIndex] != 0.0) { + return 0; + } + } + } + } + return 1; +} + +# Is it an upper triangular matrix? +# +# A matrix is an upper triangular matrix: +# o It's a square matrix +# o All its entries below the main diagonal are zero +# +sub IsUpperTriangular { + my($This) = @_; + + return $This->_IsUpperTriangularMatrix(); +} + +# Is it a right triangular matrix? +# +# A matrix is a right triangular matrix: +# o It's a square matrix +# o All its entries below the main diagonal are zero +# +sub IsRightTriangular { + my($This) = @_; + + return $This->IsUpperTriangular(); +} + +# Is it a strictly upper triangular matrix? +# +# A matrix is a strictly upper triangular matrix: +# o It's a square matrix +# o All its entries on and below the main diagonal are zero +# +sub IsStrictlyUpperTriangular { + my($This) = @_; + my($DiagonalValue); + + $DiagonalValue = 0; + + return $This->_IsUpperTriangularMatrix($DiagonalValue); +} + +# Is it a unit upper triangular matrix? +# +# A matrix is an unit upper triangular matrix: +# o It's a square matrix +# o All its entries main diagonal are one +# o All its entries below the main diagonal are zero +# +sub IsUnitUpperTriangular { + my($This) = @_; + my($DiagonalValue); + + $DiagonalValue = 1; + + return $This->_IsUpperTriangularMatrix($DiagonalValue); +} + +# Is it a upper unitriangular matrix? +# +sub IsUpperUniTriangular { + my($This) = @_; + + return $This->IsUnitUpperTriangular(); +} + +# Is it an upper triangular, strictly upper triangular, or unit upper triangular matrix? +# +sub _IsUpperTriangularMatrix { + my($This, $DiagonalValue) = @_; + + # Is is a square matrix? + if (!$This->IsSquare()) { + return 0; + } + # Check matrix values... + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex, $CheckDiagonalValues); + + $CheckDiagonalValues = defined($DiagonalValue) ? 1 : 0; + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($CheckDiagonalValues && $RowIndex == $ColIndex) { + # Main diagonal... + if ($This->{Values}[$RowIndex][$ColIndex] != $DiagonalValue) { + return 0; + } + } + elsif ($RowIndex > $ColIndex) { + # Elemens below the main diagonal... + if ($This->{Values}[$RowIndex][$ColIndex] != 0.0) { + return 0; + } + } + } + } + return 1; +} + +# Is it a symmetrix matrix? +# +# A matrix is a symmetric matrix: +# o It's a square matrix +# o Its elements are symmetric with respect to main diagonal. In other words, +# elements below the main diagonal are equal to the elements above the main +# diagonal. +# +# Transpose of a symmetric matrix equals the matrix itself. +# +sub IsSymmetric { + my($This) = @_; + + # Is is a square matrix? + if (!$This->IsSquare()) { + return 0; + } + + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($RowIndex - 1)) { + if ($This->{Values}[$RowIndex][$ColIndex] != $This->{Values}[$ColIndex][$RowIndex]) { + return 0; + } + } + } + return 1; +} + +# Is it a anti symmetrix matrix? +# +# A matrix is an anti symmetric matrix: +# o It's a square matrix +# o Its elements are asymmetric with respect to main diagonal. In other words, +# elements below the main diagonal are equal to the negative of elements above +# the main diagonal. +# +# Transpose of a anti symmetric matrix equals the negative of the matrix. +# +sub IsAntiSymmetric { + my($This) = @_; + + # Is is a square matrix? + if (!$This->IsSquare()) { + return 0; + } + + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($RowIndex - 1)) { + if ($This->{Values}[$RowIndex][$ColIndex] != -$This->{Values}[$ColIndex][$RowIndex]) { + return 0; + } + } + } + return 1; +} + +# Is it a skew symmetrix matrix? +# +# It's another name for AnitSymmetricMatrix. +# +sub IsSkewSymmetric { + my($This) = @_; + + return $This->IsAntiSymmetric(); +} + +# Is it a positive matrix with all its values >= zero? +# +sub IsPositive { + my($This) = @_; + + # Check matrix values... + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($This->{Values}[$RowIndex][$ColIndex] < 0.0) { + return 0; + } + } + } + return 1; +} + +# Is it a positive matrix with all its values <= zero? +# +sub IsNegative { + my($This) = @_; + + return $This->IsPositive() ? 0 : 1; +} + +# Transpose the matrix by swaping rows with columns... +# +sub Transpose { + my($This) = @_; + my($Matrix, $NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + # Create the transpose matrix of size $NumOfCols x $NumOfRows + # + ($NumOfRows, $NumOfCols) = $This->GetSize(); + $Matrix = new Matrix($NumOfCols, $NumOfRows); + + # Swap rows and columns... + for $RowIndex (0 .. ($NumOfCols - 1)) { + for $ColIndex (0 .. ($NumOfRows - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = $This->{Values}[$ColIndex][$RowIndex]; + } + } + return $Matrix; +} + +# Is it a matrix object? +sub IsMatrix ($) { + my($Object) = @_; + + return _IsMatrix($Object); +} + +# Set value print format for an individual object or the whole class during StringifyMatrix operation... +sub SetValuePrintFormat ($;$) { + my($FirstParameter, $SecondParameter) = @_; + + if ((@_ == 2) && (_IsMatrix($FirstParameter))) { + # Set value print format for the specific object... + my($This, $ValuePrintFormat) = ($FirstParameter, $SecondParameter); + + $This->{ValueFormat} = $ValuePrintFormat; + } + else { + # Set value print format for the class... + my($ValuePrintFormat) = ($FirstParameter); + + $ValueFormat = $ValuePrintFormat; + } +} + +# Set print style for matrix rows for an individual object or the whole class during StringifyMatrix +# operation. +# +# Possible values: AllRowsInOneLine, OneRowPerLine. Default: AllRowsInOneLine +# +sub SetMatrixPrintStyle ($;$) { + my($FirstParameter, $SecondParameter) = @_; + + if ((@_ == 2) && (_IsMatrix($FirstParameter))) { + # Set value print format for the specific object... + my($This, $MatrixPrintStyleValue) = ($FirstParameter, $SecondParameter); + + if ($MatrixPrintStyleValue !~ /^(AllRowsInOneLine|OneRowPerLine)$/i) { + croak "Error: ${ClassName}->SetMatrixPrintStyle: Specified MatrixPrintStyle, $MatrixPrintStyleValue, is not valid. Supported values: AllRowsInOneLine, OneRowPerLine..."; + } + + $This->{MatrixPrintStyle} = $MatrixPrintStyleValue; + } + else { + # Set value print format for the class... + my($MatrixPrintStyleValue) = ($FirstParameter); + + if ($MatrixPrintStyleValue !~ /^(AllRowsInOneLine|OneRowPerLine)$/i) { + croak "Error: ${ClassName}::SetMatrixPrintStyle: Specified MatrixPrintStyle, $MatrixPrintStyleValue, is not valid. Supported values: AllRowsInOneLine, OneRowPerLine..."; + } + + $MatrixPrintStyle = $MatrixPrintStyleValue; + } +} + +# Is it a matrix object? +# +sub _IsMatrix { + my($Object) = @_; + + return (Scalar::Util::blessed($Object) && $Object->isa($ClassName)) ? 1 : 0; +} + +# Make sure it's a matrix reference... +# +sub _ValidateMatrix { + my($ErrorMsg, $Matrix) = @_; + + if (!_IsMatrix($Matrix)) { + croak "Error: ${ClassName}->${ErrorMsg}: Object must be a matrix..."; + } +} + +# Make sure both row and column indicies are valid... +# +sub _ValidateRowAndColumnIndicies { + my($This, $ErrorMsgPrefix, $RowIndex, $ColumnIndex) = @_; + + $This->_ValidateRowIndex($ErrorMsgPrefix, $RowIndex); + $This->_ValidateColumnIndex($ErrorMsgPrefix, $ColumnIndex); + + return $This; +} + +# Make sure it's a valid row index... +# +sub _ValidateRowIndex { + my($This, $ErrorMsgPrefix, $RowIndex) = @_; + my($NumOfRows); + + if (!defined $RowIndex) { + croak "$ErrorMsgPrefix: RowIndex must be defined..."; + } + $NumOfRows = $This->GetNumOfRows(); + if ($RowIndex < 0 || $RowIndex >= $NumOfRows) { + croak "$ErrorMsgPrefix: RowIndex value $RowIndex must be >= 0 and < $NumOfRows, NumOfRows, in matrix..."; + } + return $This; +} + +# Make sure it's a valid column index... +# +sub _ValidateColumnIndex { + my($This, $ErrorMsgPrefix, $ColIndex) = @_; + my($NumOfCols); + + if (!defined $ColIndex) { + croak "$ErrorMsgPrefix: ColIndex must be defined..."; + } + $NumOfCols = $This->GetNumOfColumns(); + if ($ColIndex < 0 || $ColIndex >= $NumOfCols) { + croak "$ErrorMsgPrefix: ColIndex value $ColIndex must be >= 0 and < $NumOfCols, NumOfCols, in matrix..."; + } + return $This; +} + +# +# Matrix addition operator supports two addition modes: +# . Addition of two matrices by adding corresponding matrix values +# . Addition of a scalar value to matrix values ($Matrix + 1) +# +# Caveats: +# . Addition of a matrix to scalar is not allowed (1 + $Matrix) +# +sub _MatrixAdditionOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $ErrorMsg); + + $ErrorMsg = "_MatrixAdditionOperator: Matrix addition failed"; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_); + + my($Matrix, $NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + $Matrix = new Matrix($NumOfRows, $NumOfCols); + + if ($OtherIsMatrix) { + # $OrderFlipped is set to false for two matrices... + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = $This->{Values}[$RowIndex][$ColIndex] + $Other->{Values}[$RowIndex][$ColIndex]; + } + } + } + else { + # Scalar addition... + if ($OrderFlipped) { + croak "Error: ${ClassName}->${ErrorMsg}: First object must be a matrix..."; + } + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = $This->{Values}[$RowIndex][$ColIndex] + $Other; + } + } + } + return $Matrix; +} + +# +# Matrix subtraction operator supports two subtraction modes: +# . Subtraction of two matrices by subtracting corresponding matrix values +# . Subtraction of a scalar value from matrix values ($Matrix - 1) +# +# Caveats: +# . Subtraction of a matrix from scalar is not allowed (1 - $Matrix) +# +sub _MatrixSubtractionOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $ErrorMsg); + + $ErrorMsg = "_MatrixSubtractionOperator: Matrix subtraction failed"; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_); + + my($Matrix, $NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + $Matrix = new Matrix($NumOfRows, $NumOfCols); + + if ($OtherIsMatrix) { + # $OrderFlipped is set to false for two matrices... + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = $This->{Values}[$RowIndex][$ColIndex] - $Other->{Values}[$RowIndex][$ColIndex]; + } + } + } + else { + # Scalar subtraction... + if ($OrderFlipped) { + croak "Error: ${ClassName}->${ErrorMsg}: First object must be a matrix..."; + } + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = $This->{Values}[$RowIndex][$ColIndex] - $Other; + } + } + } + return $Matrix; +} + +# +# Matrix multiplication operator supports two multiplication modes: +# . Multiplication of two matrices +# . Multiplication of matrix values by a scalar ($Matrix * 1) +# +# Caveats: +# . Multiplication of a scalar by a is not allowed (1 * $Matrix) +# +sub _MatrixMultiplicationOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $ErrorMsg, $CheckSizes); + + $ErrorMsg = "_MatrixMultiplicationOperator: Matrix multiplication failed"; + $CheckSizes = 0; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_, $CheckSizes); + + my($Matrix); + + if ($OtherIsMatrix) { + # $OrderFlipped is set to false for two matrices... + my($NumOfRows1, $NumOfCols1, $RowIndex1, $ColIndex1, $NumOfRows2, $NumOfCols2, $ColIndex2, $Value, $RowColIndex); + + ($NumOfRows1, $NumOfCols1) = $This->GetSize(); + ($NumOfRows2, $NumOfCols2) = $Other->GetSize(); + + if ($NumOfCols1 != $NumOfRows2) { + croak "Error: ${ClassName}->${ErrorMsg}: NumOfCols in first matrix of size $NumOfRows1 x $NumOfCols1 must be equal to NumOfRows in second matrix of size $NumOfRows2 x $NumOfCols2..."; + } + + $Matrix = new Matrix($NumOfRows1, $NumOfCols2); + + for $RowIndex1 (0 .. ($NumOfRows1 - 1)) { + for $ColIndex2 (0 .. ($NumOfCols2 - 1)) { + $Value = 0; + for $RowColIndex (0 .. ($NumOfCols1 - 1)) { + $Value += $This->{Values}[$RowIndex1][$RowColIndex] * $Other->[$RowColIndex][$ColIndex2]; + } + $Matrix->{Values}[$RowIndex1][$ColIndex2] = $Value; + } + } + } + else { + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + $Matrix = new Matrix($NumOfRows, $NumOfCols); + # Scalar subtraction... + if ($OrderFlipped) { + croak "Error: ${ClassName}->${ErrorMsg}: First object must be a matrix..."; + } + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = $This->{Values}[$RowIndex][$ColIndex] * $Other; + } + } + } + return $Matrix; +} + +# +# Matrix division operator supports two division modes: +# . Division of two matrices by dividing corresponding matrix values +# . Division matrix values by a scalar($Matrix/2) +# +# Caveats: +# . Division of scalar value by a matrix is not allowed (2/$Matrix) +# +sub _MatrixDivisionOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $ErrorMsg); + + $ErrorMsg = "_MatrixDivisionOperator: Matrix division failed"; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_); + + my($Matrix, $NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + $Matrix = new Matrix($NumOfRows, $NumOfCols); + + if ($OtherIsMatrix) { + # $OrderFlipped is set to false for two matrices... + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = $This->{Values}[$RowIndex][$ColIndex] / $Other->{Values}[$RowIndex][$ColIndex]; + } + } + } + else { + # Scalar subtraction... + if ($OrderFlipped) { + croak "Error: ${ClassName}->${ErrorMsg}: First object must be a matrix..."; + } + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = $This->{Values}[$RowIndex][$ColIndex] / $Other; + } + } + } + return $Matrix; +} + +# +# Matrix exponentiation operator supports two division modes: +# . Exponent of two matrices by exponentiation of corresponding matrix values +# . Exponentiation matrix values by a scalar ($Matrix ** 2) +# +# Caveats: +# . Exponentiation of scalar value by a matrix is not allowed (2 ** $Matrix) +# +sub _MatrixExponentiationOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $ErrorMsg); + + $ErrorMsg = "_MatrixExponentiationOperator: Matrix exponentiation failed"; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_); + + my($Matrix, $NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + $Matrix = new Matrix($NumOfRows, $NumOfCols); + + if ($OtherIsMatrix) { + # $OrderFlipped is set to false for two matrices... + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = $This->{Values}[$RowIndex][$ColIndex] ** $Other->{Values}[$RowIndex][$ColIndex]; + } + } + } + else { + # Scalar subtraction... + if ($OrderFlipped) { + croak "Error: ${ClassName}->${ErrorMsg}: First object must be a matrix..."; + } + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = $This->{Values}[$RowIndex][$ColIndex] ** $Other; + } + } + } + return $Matrix; +} + +# +# Matrix modulus operator supports two division modes: +# . Modulus of two matrices by taking modulus between corresponding matrix values +# . Modulus of matrix values by a scalar ($Matrix % 2) +# +# Caveats: +# . Modulus of scalar value by a matrix is not allowed (2 % $Matrix) +# +sub _MatrixModulusOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $ErrorMsg); + + $ErrorMsg = "_MatrixModulusOperator: Matrix modulus failed"; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_); + + my($Matrix, $NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + $Matrix = new Matrix($NumOfRows, $NumOfCols); + + if ($OtherIsMatrix) { + # $OrderFlipped is set to false for two matrices... + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = $This->{Values}[$RowIndex][$ColIndex] % $Other->{Values}[$RowIndex][$ColIndex]; + } + } + } + else { + # Scalar subtraction... + if ($OrderFlipped) { + croak "Error: ${ClassName}->${ErrorMsg}: First object must be a matrix..."; + } + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = $This->{Values}[$RowIndex][$ColIndex] % $Other; + } + } + } + return $Matrix; +} + +# +# Matrix booelan operator checks whether a matrix contains at least one non-zero +# value... +# +sub _MatrixBooleanOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $ErrorMsg); + + $ErrorMsg = "_MatrixBooleanOperator: Matrix boolean operation failed"; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_); + + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($This->{Values}[$RowIndex][$ColIndex] != 0.0) { + return 1; + } + } + } + return 0; +} + +# +# Matrix not booelan operator checks whether a matrix contains only zero values... +# value... +# +sub _MatrixNotBooleanOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $ErrorMsg); + + $ErrorMsg = "_MatrixNotBooleanOperator: Matrix not boolean operation failed"; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_); + + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($This->{Values}[$RowIndex][$ColIndex] != 0.0) { + return 0; + } + } + } + return 1; +} + +# +# Matrix equal operator supports two modes: +# . Comparison of corresponding values in two matrices +# . Comparing matrix values to a scalar ($Matrix == 2) +# +# Caveats: +# . Comparison of a scalar to matrix values is not allowed (2 == $Matrix) +# +sub _MatrixEqualOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $CheckMatrixSizes, $ErrorMsg); + + $ErrorMsg = "_MatrixEqualOperator: Matrix equal failed"; + $CheckMatrixSizes = 0; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_, $CheckMatrixSizes); + + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + if ($OtherIsMatrix) { + # $OrderFlipped is set to false for two matrices... + my($OtherNumOfRows, $OtherNumOfCols); + + # Check sizes... + ($OtherNumOfRows, $OtherNumOfCols) = $Other->GetSize(); + if (!($NumOfRows == $OtherNumOfRows && $NumOfCols == $OtherNumOfCols)) { + return 0; + } + + # Check values... + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($This->{Values}[$RowIndex][$ColIndex] != $Other->{Values}[$RowIndex][$ColIndex]) { + return 0; + } + } + } + } + else { + # Scalar comparison... + if ($OrderFlipped) { + croak "Error: ${ClassName}->${ErrorMsg}: First object must be a matrix..."; + } + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($This->{Values}[$RowIndex][$ColIndex] != $Other) { + return 0; + } + } + } + } + return 1; +} + +# +# Matrix not equal operator supports two modes: +# . Comparison of corresponding values in two matrices +# . Comparing matrix values to a scalar ($Matrix != 2) +# +# Caveats: +# . Comparison of a scalar to matrix values is not allowed (2 != $Matrix) +# +sub _MatrixNotEqualOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $CheckMatrixSizes, $ErrorMsg); + + $ErrorMsg = "_MatrixNotEqualOperator: Matrix not equal failed"; + $CheckMatrixSizes = 0; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_, $CheckMatrixSizes); + + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + if ($OtherIsMatrix) { + # $OrderFlipped is set to false for two matrices... + my($OtherNumOfRows, $OtherNumOfCols); + + # Check sizes... + ($OtherNumOfRows, $OtherNumOfCols) = $Other->GetSize(); + if (!($NumOfRows == $OtherNumOfRows && $NumOfCols == $OtherNumOfCols)) { + return 1; + } + + # Check values... + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($This->{Values}[$RowIndex][$ColIndex] == $Other->{Values}[$RowIndex][$ColIndex]) { + return 0; + } + } + } + } + else { + # Scalar comparison... + if ($OrderFlipped) { + croak "Error: ${ClassName}->${ErrorMsg}: First object must be a matrix..."; + } + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($This->{Values}[$RowIndex][$ColIndex] == $Other) { + return 0; + } + } + } + } + return 1; +} + +# +# Matrix less than operator supports two modes: +# . Comparison of corresponding values in two matrices +# . Comparing matrix values to a scalar ($Matrix < 2) +# +# Caveats: +# . Comparison of a scalar to matrix values is not allowed (2 < $Matrix) +# +sub _MatrixLessThanOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $CheckMatrixSizes, $ErrorMsg); + + $ErrorMsg = "_MatrixLessThanOperator: Matrix less than failed"; + $CheckMatrixSizes = 0; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_, $CheckMatrixSizes); + + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + if ($OtherIsMatrix) { + # $OrderFlipped is set to false for two matrices... + my($OtherNumOfRows, $OtherNumOfCols); + + # Check sizes... + ($OtherNumOfRows, $OtherNumOfCols) = $Other->GetSize(); + if (!($NumOfRows == $OtherNumOfRows && $NumOfCols == $OtherNumOfCols)) { + return 0; + } + + # Check values... + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($This->{Values}[$RowIndex][$ColIndex] >= $Other->{Values}[$RowIndex][$ColIndex]) { + return 0; + } + } + } + } + else { + # Scalar comparison... + if ($OrderFlipped) { + croak "Error: ${ClassName}->${ErrorMsg}: First object must be a matrix..."; + } + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($This->{Values}[$RowIndex][$ColIndex] >= $Other) { + return 0; + } + } + } + } + return 1; +} + +# +# Matrix less than equal operator supports two modes: +# . Comparion of corresponding values in two matrices +# . Comparing matrix values to a scalar ($Matrix <= 2) +# +# Caveats: +# . Comparison of a scalar to matrix values is not allowed (2 <= $Matrix) +# +sub _MatrixLessThanEqualOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $CheckMatrixSizes, $ErrorMsg); + + $ErrorMsg = "_MatrixLessThanEqualOperator: Matrix less than equal failed"; + $CheckMatrixSizes = 0; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_, $CheckMatrixSizes); + + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + if ($OtherIsMatrix) { + # $OrderFlipped is set to false for two matrices... + my($OtherNumOfRows, $OtherNumOfCols); + + # Check sizes... + ($OtherNumOfRows, $OtherNumOfCols) = $Other->GetSize(); + if (!($NumOfRows == $OtherNumOfRows && $NumOfCols == $OtherNumOfCols)) { + return 0; + } + + # Check values... + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($This->{Values}[$RowIndex][$ColIndex] > $Other->{Values}[$RowIndex][$ColIndex]) { + return 0; + } + } + } + } + else { + # Scalar comparison... + if ($OrderFlipped) { + croak "Error: ${ClassName}->${ErrorMsg}: First object must be a matrix..."; + } + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($This->{Values}[$RowIndex][$ColIndex] > $Other) { + return 0; + } + } + } + } + return 1; +} + +# +# Matrix greatar than operator supports two modes: +# . Comparison of corresponding values in two matrices +# . Comparing matrix values to a scalar ($Matrix > 2) +# +# Caveats: +# . Comparison of a scalar to matrix values is not allowed (2 > $Matrix) +# +sub _MatrixGreatarThanOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $CheckMatrixSizes, $ErrorMsg); + + $ErrorMsg = "_MatrixGreatarThanOperator: Matrix greatar than failed"; + $CheckMatrixSizes = 0; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_, $CheckMatrixSizes); + + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + if ($OtherIsMatrix) { + # $OrderFlipped is set to false for two matrices... + my($OtherNumOfRows, $OtherNumOfCols); + + # Check sizes... + ($OtherNumOfRows, $OtherNumOfCols) = $Other->GetSize(); + if (!($NumOfRows == $OtherNumOfRows && $NumOfCols == $OtherNumOfCols)) { + return 0; + } + + # Check values... + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($This->{Values}[$RowIndex][$ColIndex] <= $Other->{Values}[$RowIndex][$ColIndex]) { + return 0; + } + } + } + } + else { + # Scalar comparison... + if ($OrderFlipped) { + croak "Error: ${ClassName}->${ErrorMsg}: First object must be a matrix..."; + } + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($This->{Values}[$RowIndex][$ColIndex] <= $Other) { + return 0; + } + } + } + } + return 1; +} + +# +# Matrix greatar than equal operator supports two modes: +# . Comparison of corresponding values in two matrices +# . Comparing matrix values to a scalar ($Matrix >= 2) +# +# Caveats: +# . Comparison of a scalar to matrix values is not allowed (2 >= $Matrix) +# +sub _MatrixGreatarThanEqualOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $CheckMatrixSizes, $ErrorMsg); + + $ErrorMsg = "_MatrixGreatarThanEqualOperator: Matrix greatar than equal failed"; + $CheckMatrixSizes = 0; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_, $CheckMatrixSizes); + + my($NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + if ($OtherIsMatrix) { + # $OrderFlipped is set to false for two matrices... + my($OtherNumOfRows, $OtherNumOfCols); + + # Check sizes... + ($OtherNumOfRows, $OtherNumOfCols) = $Other->GetSize(); + if (!($NumOfRows == $OtherNumOfRows && $NumOfCols == $OtherNumOfCols)) { + return 0; + } + + # Check values... + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($This->{Values}[$RowIndex][$ColIndex] < $Other->{Values}[$RowIndex][$ColIndex]) { + return 0; + } + } + } + } + else { + # Scalar comparison... + if ($OrderFlipped) { + croak "Error: ${ClassName}->${ErrorMsg}: First object must be a matrix..."; + } + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + if ($This->{Values}[$RowIndex][$ColIndex] < $Other) { + return 0; + } + } + } + } + return 1; +} + +# +# Matrix negative value operator returns a matrix with values corresponding to +# negative values of a matrix +# +sub _MatrixNegativeValueOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $ErrorMsg); + + $ErrorMsg = "_MatrixNegativeValueOperator: Matrix negative value operation failed"; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_); + + my($Matrix, $NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + $Matrix = new Matrix($NumOfRows, $NumOfCols); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = - $This->{Values}[$RowIndex][$ColIndex]; + } + } + return $Matrix; +} + +# +# Matrix absolute value operator returns a matrix with values corresponding to +# absolute values of a matrix +# +sub _MatrixAbsoluteValueOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $ErrorMsg); + + $ErrorMsg = "_MatrixAbsoluteValueOperator: Matrix absolute value operation failed"; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_); + + my($Matrix, $NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + $Matrix = new Matrix($NumOfRows, $NumOfCols); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = abs $This->{Values}[$RowIndex][$ColIndex]; + } + } + return $Matrix; +} + +# +# Matrix exp natural base operator returns a matrix with values corresponding to +# e raised to the power of values in a matrix +# +sub _MatrixExpNaturalBaseOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $ErrorMsg); + + $ErrorMsg = "_MatrixExpNaturalBaseOperator: Matrix exp operation failed"; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_); + + my($Matrix, $NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + $Matrix = new Matrix($NumOfRows, $NumOfCols); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = exp $This->{Values}[$RowIndex][$ColIndex]; + } + } + return $Matrix; +} + +# +# Matrix log natural base operator returns a matrix with values corresponding to +# log of values in a matrix +# +sub _MatrixLogNaturalBaseOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $ErrorMsg); + + $ErrorMsg = "_MatrixLogNaturalBaseOperator: Matrix log operation failed"; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_); + + my($Matrix, $NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + $Matrix = new Matrix($NumOfRows, $NumOfCols); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = log $This->{Values}[$RowIndex][$ColIndex]; + } + } + return $Matrix; +} + +# +# Matrix square root operator returns a matrix with values corresponding to +# sqrt of values in a matrix +# +sub _MatrixSquareRootOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $ErrorMsg); + + $ErrorMsg = "_MatrixSquareRootOperator: Matrix sqrt operation failed"; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_); + + my($Matrix, $NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + $Matrix = new Matrix($NumOfRows, $NumOfCols); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = sqrt $This->{Values}[$RowIndex][$ColIndex]; + } + } + return $Matrix; +} + +# +# Matrix sine root operator returns a matrix with values corresponding to +# sin of values in a matrix +# +sub _MatrixSineOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $ErrorMsg); + + $ErrorMsg = "_MatrixSineOperator: Matrix sin operation failed"; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_); + + my($Matrix, $NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + $Matrix = new Matrix($NumOfRows, $NumOfCols); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = sin $This->{Values}[$RowIndex][$ColIndex]; + } + } + return $Matrix; +} + +# +# Matrix cosine root operator returns a matrix with values corresponding to +# cos of values in a matrix +# +sub _MatrixCosineOperator { + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $ErrorMsg); + + $ErrorMsg = "_MatrixCosineOperator: Matrix cos operation failed"; + ($This, $Other, $OrderFlipped, $OtherIsMatrix) = _ProcessOverloadedOperatorParameters($ErrorMsg, @_); + + my($Matrix, $NumOfRows, $NumOfCols, $RowIndex, $ColIndex); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + $Matrix = new Matrix($NumOfRows, $NumOfCols); + + for $RowIndex (0 .. ($NumOfRows - 1)) { + for $ColIndex (0 .. ($NumOfCols - 1)) { + $Matrix->{Values}[$RowIndex][$ColIndex] = cos $This->{Values}[$RowIndex][$ColIndex]; + } + } + return $Matrix; +} + +# Turn matrix into array for @{$Matrix} operation... +# +sub _MatrixToArrayOperator { + my($This) = @_; + + return \@{$This->{Values}}; +} + +# Always return true in boolean context... +# +sub _BoolifyMatrix { + my($This) = @_; + + return 1; +} + +# Process parameters passed to overloaded operators... +# +# For uninary operators, $SecondParameter is not defined. +sub _ProcessOverloadedOperatorParameters { + my($ErrorMsg, $FirstParameter, $SecondParameter, $ParametersOrderStatus, $CheckMatrixSizesStatus) = @_; + my($This, $Other, $OrderFlipped, $OtherIsMatrix, $CheckMatrixSizes); + + ($This, $Other) = ($FirstParameter, $SecondParameter); + $OrderFlipped = (defined($ParametersOrderStatus) && $ParametersOrderStatus) ? 1 : 0; + $CheckMatrixSizes = (defined $CheckMatrixSizesStatus) ? $CheckMatrixSizesStatus : 1; + + _ValidateMatrix($ErrorMsg, $This); + + $OtherIsMatrix = 0; + if (defined($Other) && (ref $Other)) { + # Make sure $Other is a matrix... + _ValidateMatrix($ErrorMsg, $Other); + if ($CheckMatrixSizes) { + _ValidateMatrixSizesAreEqual($ErrorMsg, $This, $Other); + } + $OtherIsMatrix = 1; + } + return ($This, $Other, $OrderFlipped, $OtherIsMatrix); +} + +# Make sure size of the two matrices contain the same number of values... +sub _ValidateMatrixSizesAreEqual { + my($ErrorMsg, $Matrix1, $Matrix2) = @_; + my($NumOfRows1, $NumOfCols1, $NumOfRows2, $NumOfCols2); + + ($NumOfRows1, $NumOfCols1) = $Matrix1->GetSize(); + ($NumOfRows2, $NumOfCols2) = $Matrix2->GetSize(); + + if (!($NumOfRows1 == $NumOfRows2 && $NumOfCols1 == $NumOfCols2)) { + croak "Error: ${ClassName}->${ErrorMsg}: Size of the matrices must be same..."; + } +} + +# Return a string containing matrix values... +# +sub StringifyMatrix { + my($This) = @_; + my($MatrixString, $MatrixPrintStyleValue, $PrintFormat, $AllRowsInOneLine, $FormatString, $NumOfRows, $NumOfCols, $RowIndex, $RowNum, $RowString, @ValuesFormat); + + ($NumOfRows, $NumOfCols) = $This->GetSize(); + + $MatrixPrintStyleValue = (exists $This->{MatrixPrintStyle}) ? $This->{MatrixPrintStyle} : $MatrixPrintStyle; + $AllRowsInOneLine = ($MatrixPrintStyleValue =~ /^AllRowsInOneLine$/i) ? 1 : 0; + + $PrintFormat = (exists $This->{ValueFormat}) ? $This->{ValueFormat} : $ValueFormat; + + @ValuesFormat = ($PrintFormat) x $NumOfCols; + $FormatString = join ' ', @ValuesFormat; + + $MatrixString = sprintf "<Size: $NumOfRows x $NumOfCols;"; + if ($AllRowsInOneLine) { + $MatrixString .= sprintf " Values:"; + } + else { + $MatrixString .= sprintf " Values:\n"; + } + + $RowNum = 0; + for $RowIndex (0 .. ($NumOfRows -1)) { + $RowNum++; + $RowString = sprintf "Row${RowNum}:[$FormatString]", @{$This->{Values}[$RowIndex]}; + if ($AllRowsInOneLine) { + $MatrixString .= " $RowString"; + } + else { + $MatrixString .= "$RowString\n"; + } + } + $MatrixString .= ">"; + return $MatrixString; +} + +1; + +__END__ + +=head1 NAME + +Matrix + +=head1 SYNOPSIS + +use Matrix; + +use Matrix qw(:all); + +=head1 DESCRIPTION + +B<Matrix> class provides the following methods: + +new, AddColumnValues, AddRowValues, Copy, GetColumnValues, +GetColumnValuesAsColumnMatrix, GetColumnValuesAsRowMatrix, +GetColumnValuesAsString, GetColumnValuesAsVector, GetDiagonalValues, +GetDiagonalValuesAsColumnMatrix, GetDiagonalValuesAsRowMatrix, +GetDiagonalValuesAsString, GetDiagonalValuesAsVector, GetDimension, +GetMatrixValuesReference, GetNumOfColumns, GetNumOfRows, GetRowValues, +GetRowValuesAsColumnMatrix, GetRowValuesAsRowMatrix, GetRowValuesAsString, +GetRowValuesAsVector, GetSize, GetValue, IdentityMatrix, IsAntiSymmetric, +IsBiDiagonal, IsDiagonal, IsIdentity, IsLeftTriangular, IsLowerBiDiagonal, +IsLowerTriangular, IsLowerUniTriangular, IsMatrix, IsNegative, IsPositive, +IsRightTriangular, IsSkewSymmetric, IsSquare, IsStrictlyLowerTriangular, +IsStrictlyUpperTriangular, IsSymmetric, IsTriDiagonal, IsUnit, +IsUnitLowerTriangular, IsUnitUpperTriangular, IsUpperBiDiagonal, +IsUpperTriangular, IsUpperUniTriangular, NewFromColumns, NewFromDiagonal, +NewFromRows, One, SetAllValues, SetColumnValues, SetDiagonalValues, +SetMatrixPrintStyle, SetRowValues, SetValue, SetValuePrintFormat, StringifyMatrix, +Transpose, UnitMatrix, Zero, ZeroMatrix + +The following functions are available: + +IsMatrix, IdentityMatrix, NewFromRows, NewFromColumns, NewFromDiagonal, +UnitMatrix, ZeroMatrix + +The following operators are overloaded: + + "" bool ! + @{} + + - * / ** % + == != < <= > >= + neg + abs exp log sqrt cos sin + +The matrix row and column indicies start from zero. + +=head2 FUNCTIONS + +=over 4 + +=item B<new> + + $NewMatrix = $Matrix->new($NumOfRows, $NumOfCols); + +Creates a new B<Matrix> of size I<NumOfRows x NumOfCol> and returns B<NewMatrix> +object. + +=item B<AddColumnValues> + + $Matrix->AddColumnValues(@Values); + $Matrix->AddColumnValues(\@Values); + $Matrix->AddColumnValues($VectorObject); + $Matrix->AddColumnValues("Value1 Value2 Value3 ..."); + +Adds column values to I<Matrix> using an array, reference to an array, another vector, or space +delimited value string and returns I<Matrix>. + +=item B<AddRowValues> + + $Matrix->AddRowValues(@Values); + $Matrix->AddRowValues(\@Values); + $Matrix->AddRowValues($VectorObject); + $Matrix->AddRowValues("Value1 Value2 Value3 ..."); + +Adds row values to I<Matrix> using an array, reference to an array, another vector, or space +delimited value string and returns B<Matrix>. + +=item B<Copy> + + $NewMatrix = $Matrix->Copy(); + +Creates a copy of I<Matrix> and returns B<NewMatrix>. + +=item B<GetColumnValues> + + @Values = $Matrix->GetColumnValues($ColIndex); + $ValueCount = $Matrix->GetColumnValues($ColIndex); + +Returns an array containing column value specified using I<ColIndex> with column index +starting at 0. In scalar context, number of column values is returned. + +=item B<GetColumnValuesAsColumnMatrix> + + $ColumnMatrix = $Matrix->GetColumnValuesAsColumnMatrix($ColIndex); + +Returns a new B<ColumnMatrix> containing column values specified using I<ColIndex> with +column index starting at 0. + +=item B<GetColumnValuesAsRowMatrix> + + $RowMatrix = $Matrix->GetColumnValuesAsRowMatrix($ColIndex); + +Returns a new B<RowMatrix> containing column values specified using I<ColIndex> with +column index starting at 0. + +=item B<GetColumnValuesAsString> + + $ColumnValuesString = $Matrix->GetColumnValuesAsString($ColIndex); + +Returns a space delimited B<ColumnValuesString> column values specified using I<ColIndex> with +column index starting at 0. + +=item B<GetColumnValuesAsVector> + + $ColumnVector = $Matrix->GetColumnValuesAsVector($ColIndex); + +Returns a new B<ColumnVector> column values specified using I<RowIndex> with +column index starting at 0. + +=item B<GetDiagonalValues> + + @Values = $Matrix->GetDiagonalValues(); + $ValueCount = $Matrix->GetDiagonalValues(); + +Returns an array containing diagonal values. In scalar context, number of diagonal +values is returned. + +=item B<GetDiagonalValuesAsColumnMatrix> + + $ColumnMatrix = $Matrix->GetDiagonalValuesAsColumnMatrix(); + +Returns a new B<ColumnMatrix> containing diagonal values corresponding to I<Matrix>. + +=item B<GetDiagonalValuesAsRowMatrix> + + $RowMatrix = $Matrix->GetDiagonalValuesAsRowMatrix(); + +Returns a new B<RowMatrix> containing diagonal values corresponding to I<Matrix>. + +=item B<GetDiagonalValuesAsString> + + $DiagonalValuesString = $Matrix->GetDiagonalValuesAsString(); + +Returns a space delimited B<DiagonalValuesString> containing diagonal values corresponding to +I<Matrix>. + +=item B<GetDiagonalValuesAsVector> + + $DiagonalVector = $Matrix->GetDiagonalValuesAsVector(); + +Returns a new B<DiagonalVector> containing diagonal values corresponding to I<Matrix>. + +=item B<GetDimension> + + ($NumOfRows, $NumOfCols) = $Matrix->GetDimension(); + +Returns size of I<Matrix>. + +=item B<GetMatrixValuesReference> + + $ValuesRef = $Matrix->GetMatrixValuesReference(); + +Returns a reference to array containing rows and column values corresponding to I<Matrix>. + +=item B<GetNumOfColumns> + + $NumOfCols = $Matrix->GetNumOfColumns(); + +Returns B<NumOfCols> in I<Matrix>. + +=item B<GetNumOfRows> + + $NumOfRows = $Matrix->GetNumOfRows(); + +Returns B<NumOfRows> in I<Matrix>. + +=item B<GetRowValues> + + @Values = $Matrix->GetRowValues($RowIndex); + $ValueCount = $Matrix->GetRowValues($RowIndex); + +Returns an array containing row value specified using I<RowIndex> with row index +starting at 0. In scalar context, number of row values is returned. + +=item B<GetRowValuesAsColumnMatrix> + + $ColumnMatrix = $Matrix->GetRowValuesAsColumnMatrix($RowIndex); + +Returns a new B<ColumnMatrix> containing row values specified using I<RowIndex> with +column index starting at 0. + +=item B<GetRowValuesAsRowMatrix> + + $RowMatrix = $Matrix->GetRowValuesAsRowMatrix($RowIndex); + +Returns a new B<RowMatrix> containing row values specified using I<RowIndex> with +row index starting at 0. + +=item B<GetRowValuesAsString> + + $RowValuesString = $Matrix->GetRowValuesAsString($RowIndex); + +Returns a space delimited B<RowValuesString> row values specified using I<RowIndex> with +row index starting at 0. + +=item B<GetRowValuesAsVector> + + $RowVector = $Matrix->GetColumnValuesAsVector($RowIndex); + +Returns a new B<RowVector> row values specified using I<RowIndex> with +row index starting at 0. + +=item B<GetSize> + + ($NumOfRows, $NumOfCols) = $Matrix->GetSize(); + +Returns size of I<Matrix>. + +=item B<GetValue> + + $Value = $Matrix->GetValue($RowIndex, $ColIndex, [$SkipIndexCheck]); + +Returns B<Value> of I<Matrix> element specified using I<RowIndex> and I<ColIndex> with indicies +starting at 0 with optional validation of specified index values. + +=item B<IdentityMatrix> + + $NewIdentityMatrix = $Matrix->IdentityMatrix($NumOfRows, $NumOfCols); + $NewIdentityMatrix = Matrix::IdentityMatrix($NumOfRows, $NumOfCols); + $NewIdentityMatrix = Matrix::IdentityMatrix(); + +Creates a new B<IdentityMatrix> of specified size I<NumOfRows x NumOfCol> or of size 3 x 3 and +returns B<NewIdentityMatrix> object. + +=item B<IsAntiSymmetric> + + $Status = $Matrix->IsAntiSymmetric(); + +Returns 1 or 0 based on whether I<Matrix> is an anti symmetric matrix. + +A matrix is an anti symmetric matrix: + + . It's a square matrix + . Its elements are asymmetric with respect to main diagonal. In other words, + elements below the main diagonal are equal to the negative of elements above + the main diagonal. + +Transpose of an anti symmetric matrix equals the negative of the matrix. + +=item B<IsBiDiagonal> + + $Status = $Matrix->IsBiDiagonal(); + +Returns 1 or 0 based on whether I<Matrix> is upper or lower bidiagonal matrix. + +=item B<IsDiagonal> + + $Status = $Matrix->IsDiagonal(); + +Returns 1 or 0 based on whether I<Matrix> is a diagonal matrix. + +A matrix is a diagonal matrix: + + . It's a square matrix + . All its off-diagonal elements are zeros and its diagonal elements may or may not + be zeros + +=item B<IsIdentity> + + $Status = $Matrix->IsIdentity(); + +Returns 1 or 0 based on whether I<Matrix> is an identity matrix. + +=item B<IsLeftTriangular> + + $Status = $Matrix->IsLeftTriangular(); + +Returns 1 or 0 based on whether I<Matrix> is a left or lower matrix. + +A matrix is a left triangular matrix: + + . It's a square matrix + . All its entries above the main diagonal are zero + +=item B<IsLowerBiDiagonal> + + $Status = $Matrix->IsLowerBiDiagonal(); + +Returns 1 or 0 based on whether I<Matrix> is a lower bidiagonal matrix. + +A matrix is a lower bidiagonal matrix: + + . It's a square matrix + . All its main diagonal and lower diagonal elements are non-zeros and all its + other elements are zeros + +=item B<IsLowerTriangular> + + $Status = $Matrix->IsLowerTriangular(); + +Returns 1 or 0 based on whether I<Matrix> is a left or lower triangular matrix. + +A matrix is a lower triangular matrix: + + . It's a square matrix + . All its entries above the main diagonal are zero + +=item B<IsLowerUniTriangular> + + $Status = $Matrix->IsLowerUniTriangular(); + +Returns 1 or 0 based on whether I<Matrix> is a lower triangular matrix. + +=item B<IsMatrix> + + $Status = Matrix::IsMatrix($Object); + +Returns 1 or 0 based on whether I<Object> is a B<Matrix> object. + +=item B<IsNegative> + + $Status = $Matrix->IsNegative(); + +Returns 1 or 0 based on whether I<Matrix> is a negative matrix containing only values +less than or equal to zero. + +=item B<IsPositive> + + $Status = $Matrix->IsPositive(); + +Returns 1 or 0 based on whether I<Matrix> is a negative matrix containing only values +greater than or equal to zero. + +=item B<IsRightTriangular> + + $Status = $Matrix->IsRightTriangular(); + +Returns 1 or 0 based on whether I<Matrix> is a right or upper triangular matrix. + +=item B<IsSkewSymmetric> + + $Status = $Matrix->IsSkewSymmetric(); + +Returns 1 or 0 based on whether I<Matrix> is a skew or anti symmetric matrix. + +=item B<IsSquare> + + $Status = $Matrix->IsSquare(); + +Returns 1 or 0 based on whether I<Matrix> is a square matrix containing equal +number of rows and columns. + +=item B<IsStrictlyLowerTriangular> + + $Status = $Matrix->IsStrictlyLowerTriangular(); + +Returns 1 or 0 based on whether I<Matrix> is a strictly lower triangular matrix. + +A matrix is a strictly lower triangular matrix: + + . It's a square matrix + . All its entries on and above the main diagonal are zero + +=item B<IsStrictlyUpperTriangular> + + $Status = $Matrix->IsStrictlyUpperTriangular(); + +Returns 1 or 0 based on whether I<Matrix> is a strictly upper triangular matrix. + +A matrix is a strictly upper triangular matrix: + + . It's a square matrix + . All its entries on and below the main diagonal are zero + +=item B<IsSymmetric> + + $Status = $Matrix->IsSymmetric(); + +Returns 1 or 0 based on whether I<Matrix> is a symmetric matrix. + +A matrix is a symmetric matrix: + + . It's a square matrix + . Its elements are symmetric with respect to main diagonal. In other words, + elements below the main diagonal are equal to the elements above the main + diagonal. + +Transpose of a symmetric matrix equals the matrix itself. + +=item B<IsTriDiagonal> + + $Status = $Matrix->IsTriDiagonal(); + +Returns 1 or 0 based on whether I<Matrix> is a tridiagonal matrix. + +A matrix is a tribidiagonal matrix: + + . It's a square matrix + . All its main diagonal, upper diagonal, and lower diagonal elements are non-zeros and all its + other elements are zeros + +=item B<IsUnit> + + $Status = $Matrix->IsUnit(); + +Returns 1 or 0 based on whether I<Matrix> is a unit matrix. + +A matrix is a unit matrix: + + . It's a square matrix + . All its diagonal elements are ones and its off-diagonal elements are zeros + +=item B<IsUnitLowerTriangular> + + $Status = $Matrix->IsUnitLowerTriangular(); + +Returns 1 or 0 based on whether I<Matrix> is an unit lower triangular matrix. + +A matrix is an unit lower triangular matrix: + + . It's a square matrix + . All its entries main diagonal are one + . All its entries above the main diagonal are zero + +=item B<IsUnitUpperTriangular> + + $Status = $Matrix->IsUnitUpperTriangular(); + +Returns 1 or 0 based on whether I<Matrix> is an unit upper triangular matrix. + +A matrix is an unit upper triangular matrix: + + . It's a square matrix + . All its entries main diagonal are one + . All its entries below the main diagonal are zero + +=item B<IsUpperBiDiagonal> + + $Status = $Matrix->IsUpperBiDiagonal(); + +Returns 1 or 0 based on whether I<Matrix> is an upper bidiagonal matrix. + +A matrix is an upper bidiagonal matrix: + + . It's a square matrix + . All its main diagonal and upper diagonal elements are non-zeros and all its + other elements are zeros + +=item B<IsUpperTriangular> + + $Status = $Matrix->IsUpperTriangular(); + +Returns 1 or 0 based on whether I<Matrix> is a right or upper triangular matrix. + +A matrix is an upper triangular matrix: + + . It's a square matrix + . All its entries below the main diagonal are zero + +=item B<IsUpperUniTriangular> + + $Status = $Matrix->IsUpperUniTriangular(); + +Returns 1 or 0 based on whether I<Matrix> is a right or upper triangular matrix. + +=item B<NewFromColumns> + + $NewMatrix = Matrix::NewFromColumns($Col1Vector, $Col2Vector, ...); + $NewMatrix = Matrix::NewFromColumns($Col1ValuesRef, $Col2ValuesRef, ...); + $NewMatrix = Matrix::NewFromColumns("Val1 Val2 ...", "Val1 Val2", ...); + + $NewMatrix = $Matrix->NewFromColumns($Col1Vector, $Col2Vector, ...); + $NewMatrix = $Matrix->NewFromColumns($Col1ValuesRef, $Col2ValuesRef, ...); + $NewMatrix = $Matrix->NewFromColumns("Val1 Val2 ...", "Val1 Val2", ...); + +Creates a new B<Matrix> using specified column values and returns B<NewMatrix> object. + +The column values can be specified in one of the following formats: + + . List of vector objects + . References to list of values + . List of strings containing columns values delimited by space + +Each column must contain the same number of values. + +=item B<NewFromDiagonal> + + $NewMatrix = Matrix::NewFromDiagonal($DiagonalVector); + $NewMatrix = Matrix::NewFromDiagonal($DiagonalValuesRef); + $NewMatrix = Matrix::NewFromDiagonal("Val1 Val2 ..."); + + $NewMatrix = Matrix->NewFromDiagonal($DiagonalVector); + $NewMatrix = Matrix->NewFromDiagonal($DiagonalValuesRef); + $NewMatrix = Matrix->NewFromDiagonal("Val1 Val2 ..."); + +Creates a new B<Matrix> using specified diagonal values and returns B<NewMatrix> object. + +The column values can be specified in one of the following formats: + + . A vector object + . Reference to list of values + . Strings containing diagonal values delimited by space + +=item B<NewFromRows> + + $NewMatrix = Matrix::NewFromRows($Row1Vector, $RowVector, ...); + $NewMatrix = Matrix::NewFromRows($Row1ValuesRef, $Row2ValuesRef, ...); + $NewMatrix = Matrix::NewFromRows("Val1 Val2 ...", "Val1 Val2", ...); + + $NewMatrix = $Matrix->NewFromRows($Row1Vector, $Row2Vector, ...); + $NewMatrix = $Matrix->NewFromRows($Row1ValuesRef, $Row2ValuesRef, ...); + $NewMatrix = $Matrix->NewFromRows("Val1 Val2 ...", "Val1 Val2", ...); + +Creates a new B<Matrix> using specified row values and returns B<NewMatrix> object. + +The row values can be specified in one of the following formats: + + . List of vector objects + . References to list of values + . List of strings containing columns values delimited by space + +Each row must contain the same number of values. + +=item B<One> + + $Matrix->One(); + +Sets values of all I<Matrix> elements to 1 and returns I<Matrix>. + +=item B<SetAllValues> + + $Matrix->SetAllValues($Value); + +Sets values of all I<Matrix> elements to specified I<Value> and returns I<Matrix>. + +=item B<SetColumnValues> + + $Matrix->SetColumnValues($ColIndex, @Values); + $Matrix->SetColumnValues($ColIndex, \@Values); + $Matrix->SetColumnValues($ColIndex, $VectorObject); + $Matrix->SetColumnValues($ColIndex, "Value1 Value2 Value3 ..."); + +Sets column values of a specified I<ColIndex> of I<Matrix> using an array, reference to an array, +another vector, or space delimited value string and returns I<Matrix>. + +=item B<SetDiagonalValues> + + $Matrix->SetDiagonalValues(@Values); + $Matrix->SetDiagonalValues(\@Values); + $Matrix->SetDiagonalValues($VectorObject); + $Matrix->SetDiagonalValues("Value1 Value2 Value3 ..."); + +Sets values of the diagonal in square I<Matrix> and returns I<Matrix>. + +=item B<SetMatrixPrintStyle> + + $Matrix->SetMatrixPrintStyle($MatrixStyle); + $Matrix::SetMatrixPrintStyle($MatrixStyle); + +Sets print style for matrix rows for an individual object or the whole class during StringifyMatrix +operation. Possible I<MatrixStyle> values: I<AllRowsInOneLine, OneRowPerLine>. Default: +I<AllRowsInOneLine>. + +=item B<SetRowValues> + + $Matrix->SetRowValues($ColIndex, @Values); + $Matrix->SetRowValues($ColIndex, \@Values); + $Matrix->SetRowValues($ColIndex, $VectorObjext); + $Matrix->SetRowValues($ColIndex, "Value1 Value2 Value3 ..."); + +Sets row values of a specified I<RowIndex> of I<Matrix> using an array, reference to an array, +another vector, or space delimited value string and returns I<Matrix>. + +=item B<SetValue> + + $Matrix->SetValue($RowIndex, $ColIndex, $Value, [$SkipIndexCheck]); + +Sets B<Value> of I<Matrix> element specified using I<RowIndex> and I<ColIndex> with indicies +starting at 0 with optional validation of specified index values and return I<Matrix>. + +=item B<SetValuePrintFormat> + + $Matrix->SetValuePrintFormat($ValueFormat); + $Matrix::SetValuePrintFormat($ValueFormat); + +Sets value print format for an individual object or the whole class during StringifyMatrix operation +and returns I<Matrix>. + +=item B<StringifyMatrix> + + $String = $Matrix->StringifyMatrix(); + +Returns a string containing information about I<Matrix> object. + +=item B<Transpose> + + $Matrix->Transpose(); + +Transposes I<Matrix> by swaping rows with columns and returns I<Matrix>. + +=item B<UnitMatrix> + + $NewUnitMatrix = $Matrix::UnitMatrix($NumOfRows, $NumOfCols); + $NewUnitMatrix = $Matrix::UnitMatrix(); + $NewUnitMatrix = $Matrix->UnitMatrix($NumOfRows, $NumOfCols); + +Creates a new B<UnitMatrix> of specified size I<NumOfRows x NumOfCol> or of size 3 x 3 and +returns B<NewUnitMatrix> object. + +=item B<Zero> + + $Matrix->Zero(); + +Sets values of all I<Matrix> elements to 0 and returns I<Matrix>. + +=item B<ZeroMatrix> + + $NewZeroMatrix = $Matrix::ZeroMatrix($NumOfRows, $NumOfCols); + $NewZeroMatrix = $Matrix::ZeroMatrix(); + $NewZeroMatrix = $Matrix->ZeroMatrix($NumOfRows, $NumOfCols); + +Creates a new B<ZeroMatrix> of specified size I<NumOfRows x NumOfCol> or of size 3 x 3 and +returns B<NewZeroMatrix> object. + +=back + +=head1 AUTHOR + +Manish Sud <msud@san.rr.com> + +=head1 SEE ALSO + +Vector.pm + +=head1 COPYRIGHT + +Copyright (C) 2015 Manish Sud. All rights reserved. + +This file is part of MayaChemTools. + +MayaChemTools is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License as published by the Free +Software Foundation; either version 3 of the License, or (at your option) +any later version. + +=cut