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