From: <Microsoft Internet Explorer 5 で保存する>
Subject: search.cpan.org: The CPAN Search Site
Date: Thu, 11 Aug 2005 10:31:13 +0900
MIME-Version: 1.0
Content-Type: multipart/related;
	type="text/html";
	boundary="----=_NextPart_000_0008_01C59E5F.CC267000"
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2670

This is a multi-part message in MIME format.

------=_NextPart_000_0008_01C59E5F.CC267000
Content-Type: text/html;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Location: http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD><TITLE>search.cpan.org: The CPAN Search Site</TITLE>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1"><LINK=20
href=3D"http://search.cpan.org/s/style.css" type=3Dtext/css =
rel=3Dstylesheet><LINK=20
title=3D"RSS 1.0" href=3D"http://search.cpan.org/uploads.rdf"=20
type=3Dapplication/rss+xml rel=3Dalternate>
<META content=3D"MSHTML 6.00.2900.2668" name=3DGENERATOR></HEAD>
<BODY id=3Dcpansearch>
<CENTER>
<DIV class=3Dlogo><A href=3D"http://search.cpan.org/"><IMG alt=3DCPAN=20
src=3D"http://search.cpan.org/s/img/cpan_banner.png"></A></DIV></CENTER>
<DIV class=3Dmenubar><A href=3D"http://search.cpan.org/">Home</A> =B7 <A =

href=3D"http://search.cpan.org/author/">Authors</A> =B7 <A=20
href=3D"http://search.cpan.org/recent">Recent</A> =B7 <A=20
href=3D"http://log.perl.org/cpansearch/">News</A> =B7 <A=20
href=3D"http://search.cpan.org/mirror">Mirrors</A> =B7 <A=20
href=3D"http://search.cpan.org/faq.html">FAQ</A> =B7 <A=20
href=3D"http://search.cpan.org/feedback">Feedback</A> </DIV>
<FORM class=3Dsearchbox name=3Df action=3D/search method=3Dget><INPUT =
size=3D35=20
name=3Dquery> <BR>in <SELECT name=3Dmode> <OPTION value=3Dall =
selected>All</OPTION>=20
  <OPTION value=3Dmodule>Modules</OPTION> <OPTION=20
  value=3Ddist>Distributions</OPTION> <OPTION=20
value=3Dauthor>Authors</OPTION></SELECT>&nbsp;<INPUT type=3Dsubmit =
value=3D"CPAN Search">=20
</FORM><A name=3D_top></A>
<DIV class=3Dpath><A href=3D"http://search.cpan.org/~leto/">Jonathan =
Leto</A> &gt;=20
<A=20
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/">Math-MatrixRea=
l-1.9</A>=20
&gt; Math::MatrixReal </DIV>Module Version: 1.9 &nbsp; <A=20
href=3D"http://search.cpan.org/src/LETO/Math-MatrixReal-1.9/MatrixReal.pm=
">Source</A>=20
&nbsp;=20
<DIV style=3D"FLOAT: right">Download: <A=20
href=3D"http://search.cpan.org/CPAN/authors/id/L/LE/LETO/Math-MatrixReal-=
1.9.tar.gz">Math-MatrixReal-1.9.tar.gz</A></DIV>
<P>
<DIV class=3Dpod><A name=3D_top></A>
<DIV class=3Dpod>
<DIV class=3Dtoc>
<UL>
  <LI><A=20
  =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#NA=
ME">NAME</A>=20

  <LI><A=20
  =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#DE=
SCRIPTION">DESCRIPTION</A>=20

  <LI><A=20
  =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#SY=
NOPSIS">SYNOPSIS</A>=20

  <UL>
    <LI><A=20
    =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#Co=
nstructor_Methods_And_Such">Constructor=20
    Methods And Such</A>=20
    <LI><A=20
    =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#Ma=
trix_Row,_Column_and_Element_operations">Matrix=20
    Row, Column and Element operations</A>=20
    <LI><A=20
    =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#Ma=
trix_Operations">Matrix=20
    Operations</A>=20
    <LI><A=20
    =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#Ar=
ithmetic_Operations">Arithmetic=20
    Operations</A>=20
    <LI><A=20
    =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#Bo=
olean_Matrix_Operations">Boolean=20
    Matrix Operations</A>=20
    <LI><A=20
    =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#Ei=
gensystems">Eigensystems</A>=20

    <LI><A=20
    =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#Mi=
scellaneous">Miscellaneous</A>=20
    </LI></UL>
  <LI><A=20
  =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#OV=
ERLOADED_OPERATORS">OVERLOADED=20
  OPERATORS</A>=20
  <UL>
    <LI><A=20
    =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#SY=
NOPSIS">SYNOPSIS</A>=20

    <LI><A=20
    =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#DE=
SCRIPTION">DESCRIPTION</A>=20
    </LI></UL>
  <LI><A=20
  =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#SE=
E_ALSO">SEE=20
  ALSO</A>=20
  <LI><A=20
  =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#VE=
RSION">VERSION</A>=20

  <LI><A=20
  =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#AU=
THORS">AUTHORS</A>=20

  <LI><A=20
  =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#CR=
EDITS">CREDITS</A>=20

  <LI><A=20
  =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#CO=
PYRIGHT">COPYRIGHT</A>=20

  <LI><A=20
  =
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#LI=
CENSE_AGREEMENT">LICENSE=20
  AGREEMENT</A> </LI></UL></DIV><!-- generated by TUCS::Pod2HTML v, =
using Pod::Simple::PullParser v2.020, under Perl v5.008003 at Thu Aug 11 =
01:30:16 2005 GMT --><!-- start doc --><PRE>        for(my $i =3D 0;$i =
&lt; $rows; $i++ ){
                $big =3D abs($matrix-&gt;[0][$i][0]);
                for(my $j=3D0;$j &lt; $cols; $j++ ){
                        $big =3D $big &lt; abs($matrix-&gt;[0][$i][$j])=20
                                ? abs($matrix-&gt;[0][$i][$j]) : $big;
                }
                next unless $big;
                # now $big is biggest element in row
                for(my $j =3D 0;$j &lt; $cols; $j++ ){
                        $matrix-&gt;[0][$i][$j]  /=3D $big;
                }
                # now all elements are between [-1,1] and=20
                # dependence can be easily checked
        }

        for(my $i =3D 0;$i &lt; $rows; $i++ ){
                for(my $k =3D 0; $k &lt; $rows; $k++ ){
                        next if ($i =3D=3D $k);
                        print "i,k =3D $i,$k\n";
                        $tmprow =3D $matrix-&gt;row($i+1) + =
$matrix-&gt;row($k+1);
                        print "tmprow=3D $tmprow\n";
                        print "tmprow has " . =
$tmprow-&gt;_count_zeroes_row . " zeroes.\n";
                        print "i+1 has " . =
$matrix-&gt;row($i+1)-&gt;_count_zeroes_row . " zeroes\n";
                        print "k+1 has " . =
$matrix-&gt;row($k+1)-&gt;_count_zeroes_row . " zeroes\n";

                        $tmprow =3D $tmprow-&gt;_normalize_row;     =20
                        if( $tmprow-&gt;norm_sum =3D=3D 0 ){
                                for(my $j=3D0;$j&lt;$cols;$j++){
                                        $matrix-&gt;[0][$k][$j] =3D 0;
                                }
                        } elsif ( $tmprow-&gt;_count_zeroes_row &gt; =
$matrix-&gt;row($i+1)-&gt;_count_zeroes_row ){
                                print "tmprow has more zeroes, replacing =
row " . ($i+1) . "\n";
                                ## assign row  =20
                                $matrix-&gt;assign_row($i+1,$tmprow);
                        } elsif ( $tmprow-&gt;_count_zeroes_row &gt; =
$matrix-&gt;row($k+1)-&gt;_count_zeroes_row ){
                                print "tmprow has more zeroes, replacing =
row " . ($k+1) . "\n";
                                $matrix-&gt;assign_row($k+1,$tmprow);
                        }      =20
                                       =20
                }
        }
        return $matrix;
}</PRE>
<H1><A name=3DNAME></A>NAME <A=20
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#_t=
op"><IMG=20
alt=3D^ src=3D"http://search.cpan.org/s/img/up.gif"></A></H1>
<P>Math::MatrixReal - Matrix of Reals</P>
<P>Implements the data type "matrix of reals" (and consequently also =
"vector of=20
reals").</P>
<H1><A name=3DDESCRIPTION></A>DESCRIPTION <A=20
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#_t=
op"><IMG=20
alt=3D^ src=3D"http://search.cpan.org/s/img/up.gif"></A></H1>
<P>Implements the data type "matrix of reals", which can be used almost =
like any=20
other basic Perl type thanks to <B>OPERATOR OVERLOADING</B>, =
i.e.,</P><PRE>  $product =3D $matrix1 * $matrix2;</PRE>
<P>does what you would like it to do (a matrix multiplication).</P>
<P>Also features many important operations and methods: matrix norm, =
matrix=20
transposition, matrix inverse, determinant of a matrix, order and =
numerical=20
condition of a matrix, scalar product of vectors, vector product of =
vectors,=20
vector length, projection of row and column vectors, a comfortable way =
for=20
reading in a matrix from a file, the keyboard or your code, and many =
more.</P>
<P>Allows to solve linear equation systems using an efficient algorithm =
known as=20
"L-R-decomposition" and several approximative (iterative) methods.</P>
<P>Features an implementation of Kleene's algorithm to compute the =
minimal costs=20
for all paths in a graph with weighted edges (the "weights" being the =
costs=20
associated with each edge).</P>
<H1><A name=3DSYNOPSIS></A>SYNOPSIS <A=20
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#_t=
op"><IMG=20
alt=3D^ src=3D"http://search.cpan.org/s/img/up.gif"></A></H1>
<H2><A name=3DConstructor_Methods_And_Such></A>Constructor Methods And =
Such</H2>
<UL>
  <LI><CODE>use Math::MatrixReal;</CODE>=20
  <P>Makes the methods and overloaded operators of this module available =
to your=20
  program.</P>
  <LI><CODE>$new_matrix =3D new Math::MatrixReal($rows,$columns);</CODE> =

  <P>The matrix object constructor method. A new matrix of size $rows by =

  $columns will be created, with the value <CODE>0.0</CODE> for all=20
elements.</P>
  <P>Note that this method is implicitly called by many of the other =
methods in=20
  this module.</P>
  <LI><CODE>$new_matrix =3D=20
  $some_matrix-&gt;</CODE><CODE>new($rows,$columns);</CODE>=20
  <P>Another way of calling the matrix object constructor method.</P>
  <P>Matrix "<CODE>$some_matrix</CODE>" is not changed by this in any =
way.</P>
  <LI><CODE>$new_matrix =3D $matrix-&gt;new_from_cols( [=20
  $column_vector|$array_ref|$string, ... ] )</CODE>=20
  <P>Creates a new matrix given a reference to an array of any of the=20
  following:</P>
  <UL>
    <LI>column vectors ( n by 1 Math::MatrixReal matrices )=20
    <LI>references to arrays=20
    <LI>strings properly formatted to create a column with =
Math::MatrixReal's=20
    <CODE>new_from_string</CODE> command </LI></UL>
  <P>You may mix and match these as you wish. However, all must be of =
the same=20
  dimension--no padding happens automatically. Example:</P><PRE>        =
my $matrix =3D Math::MatrixReal-&gt;new_from_cols( [ [1,2], [3,4] ] );
        print $matrix;</PRE>
  <P>will print</P><PRE>        [  1.000000000000E+00  =
3.000000000000E+00 ]
        [  2.000000000000E+00  4.000000000000E+00 ]</PRE>
  <LI><CODE>new_from_rows( [ $row_vector|$array_ref|$string, ... ] =
)</CODE>=20
  <P>Creates a new matrix given a reference to an array of any of the=20
  following:</P>
  <UL>
    <LI>row vectors ( 1 by n Math::MatrixReal matrices )=20
    <LI>references to arrays=20
    <LI>strings properly formatted to create a row with =
Math::MatrixReal's=20
    <CODE>new_from_string</CODE> command </LI></UL>
  <P>You may mix and match these as you wish. However, all must be of =
the same=20
  dimension--no padding happens automatically. Example:</P><PRE>        =
my $matrix =3D Math::MatrixReal-&gt;new_from_rows( [ [1,2], [3,4] ] );
        print $matrix;</PRE>
  <P>will print</P><PRE>        [  1.000000000000E+00  =
2.000000000000E+00 ]
        [  3.000000000000E+00  4.000000000000E+00 ]</PRE>
  <LI><CODE>$new_matrix =3D Math::MatrixReal-&gt;new_diag( $array_ref =
);</CODE>=20
  <P>This method allows you to create a diagonal matrix by only =
specifying the=20
  diagonal elements. Example:</P><PRE>        $matrix =3D =
Math::MatrixReal-&gt;new_diag( [ 1,2,3,4 ] );
        print $matrix;</PRE>
  <P>will print</P><PRE>        [  1.000000000000E+00  =
0.000000000000E+00  0.000000000000E+00  0.000000000000E+00 ]
        [  0.000000000000E+00  2.000000000000E+00  0.000000000000E+00  =
0.000000000000E+00 ]
        [  0.000000000000E+00  0.000000000000E+00  3.000000000000E+00  =
0.000000000000E+00 ]
        [  0.000000000000E+00  0.000000000000E+00  0.000000000000E+00  =
4.000000000000E+00 ]</PRE>
  <LI><CODE>$new_matrix =3D=20
  Math::MatrixReal-&gt;</CODE><CODE>new_from_string($string);</CODE>=20
  <P>This method allows you to read in a matrix from a string (for =
instance,=20
  from the keyboard, from a file or from your code).</P>
  <P>The syntax is simple: each row must start with "<CODE>[ </CODE>" =
and end=20
  with "<CODE> ]\n</CODE>" ("<CODE>\n</CODE>" being the newline =
character and=20
  "<CODE> </CODE>" a space or tab) and contain one or more numbers, all=20
  separated from each other by spaces or tabs.</P>
  <P>Additional spaces or tabs can be added at will, but no =
comments.</P>
  <P>Examples:</P><PRE>  $string =3D "[ 1 2 3 ]\n[ 2 2 -1 ]\n[ 1 1 1 =
]\n";
  $matrix =3D Math::MatrixReal-&gt;new_from_string($string);
  print "$matrix";</PRE>
  <P>By the way, this prints</P><PRE>  [  1.000000000000E+00  =
2.000000000000E+00  3.000000000000E+00 ]
  [  2.000000000000E+00  2.000000000000E+00 -1.000000000000E+00 ]
  [  1.000000000000E+00  1.000000000000E+00  1.000000000000E+00 ]</PRE>
  <P>But you can also do this in a much more comfortable way using the=20
  shell-like "here-document" syntax:</P><PRE>  $matrix =3D =
Math::MatrixReal-&gt;new_from_string(&lt;&lt;'MATRIX');
  [  1  0  0  0  0  0  1  ]
  [  0  1  0  0  0  0  0  ]
  [  0  0  1  0  0  0  0  ]
  [  0  0  0  1  0  0  0  ]
  [  0  0  0  0  1  0  0  ]
  [  0  0  0  0  0  1  0  ]
  [  1  0  0  0  0  0 -1  ]
  MATRIX</PRE>
  <P>You can even use variables in the matrix:</P><PRE>  $c1 =3D   2  /  =
3;
  $c2 =3D  -2  /  5;
  $c3 =3D  26  /  9;

  $matrix =3D Math::MatrixReal-&gt;new_from_string(&lt;&lt;"MATRIX");

      [   3    2    0   ]
      [   0    3    2   ]
      [  $c1  $c2  $c3  ]

  MATRIX</PRE>
  <P>(Remember that you may use spaces and tabs to format the matrix to =
your=20
  taste)</P>
  <P>Note that this method uses exactly the same representation for a =
matrix as=20
  the "stringify" operator "": this means that you can convert any =
matrix into a=20
  string with <CODE>$string =3D "$matrix";</CODE> and read it back in =
later (for=20
  instance from a file!).</P>
  <P>Note however that you may suffer a precision loss in this process =
because=20
  only 13 digits are supported in the mantissa when printed!!</P>
  <P>If the string you supply (or someone else supplies) does not obey =
the=20
  syntax mentioned above, an exception is raised, which can be caught by =
"eval"=20
  as follows:</P><PRE>  print "Please enter your matrix (in one line): =
";
  $string =3D &lt;STDIN&gt;;
  $string =3D~ s/\\n/\n/g;
  eval { $matrix =3D Math::MatrixReal-&gt;new_from_string($string); };
  if ($@)
  {
      print "$@";
      # ...
      # (error handling)
  }
  else
  {
      # continue...
  }</PRE>
  <P>or as follows:</P><PRE>  eval { $matrix =3D =
Math::MatrixReal-&gt;new_from_string(&lt;&lt;"MATRIX"); };
  [   3    2    0   ]
  [   0    3    2   ]
  [  $c1  $c2  $c3  ]
  MATRIX
  if ($@)
  # ...</PRE>
  <P>Actually, the method shown above for reading a matrix from the =
keyboard is=20
  a little awkward, since you have to enter a lot of "\n"'s for the=20
newlines.</P>
  <P>A better way is shown in this piece of code:</P><PRE>  while (1)
  {
      print "\nPlease enter your matrix ";
      print "(multiple lines, &lt;ctrl-D&gt; =3D done):\n";
      eval { $new_matrix =3D
          Math::MatrixReal-&gt;new_from_string(join('',&lt;STDIN&gt;)); =
};
      if ($@)
      {
          $@ =3D~ s/\s+at\b.*?$//;
          print "${@}Please try again.\n";
      }
      else { last; }
  }</PRE>
  <P>Possible error messages of the "new_from_string()" method =
are:</P><PRE>  Math::MatrixReal::new_from_string(): syntax error in =
input string
  Math::MatrixReal::new_from_string(): empty input string</PRE>
  <P>If the input string has rows with varying numbers of columns, the =
following=20
  warning will be printed to STDERR:</P><PRE>  =
Math::MatrixReal::new_from_string(): missing elements will be set to =
zero!</PRE>
  <P>If everything is okay, the method returns an object reference to =
the (newly=20
  allocated) matrix containing the elements you specified.</P>
  <LI><CODE>$new_matrix =3D $some_matrix-&gt;shadow();</CODE>=20
  <P>Returns an object reference to a <B>NEW</B> but <B>EMPTY</B> matrix =
(filled=20
  with zero's) of the <B>SAME SIZE</B> as matrix=20
"<CODE>$some_matrix</CODE>".</P>
  <P>Matrix "<CODE>$some_matrix</CODE>" is not changed by this in any =
way.</P>
  <LI><CODE>$matrix1-&gt;copy($matrix2);</CODE>=20
  <P>Copies the contents of matrix "<CODE>$matrix2</CODE>" to an =
<B>ALREADY=20
  EXISTING</B> matrix "<CODE>$matrix1</CODE>" (which must have the same =
size as=20
  matrix "<CODE>$matrix2</CODE>"!).</P>
  <P>Matrix "<CODE>$matrix2</CODE>" is not changed by this in any =
way.</P>
  <LI><CODE>$twin_matrix =3D $some_matrix-&gt;clone();</CODE>=20
  <P>Returns an object reference to a <B>NEW</B> matrix of the <B>SAME =
SIZE</B>=20
  as matrix "<CODE>$some_matrix</CODE>". The contents of matrix=20
  "<CODE>$some_matrix</CODE>" have <B>ALREADY BEEN COPIED</B> to the new =
matrix=20
  "<CODE>$twin_matrix</CODE>". This is the method that the operator =
"=3D" is=20
  overloaded to when you type <CODE>$a =3D $b</CODE>, when =
<CODE>$a</CODE> and=20
  <CODE>$b</CODE> are matrices.</P>
  <P>Matrix "<CODE>$some_matrix</CODE>" is not changed by this in any=20
  way.</P></LI></UL>
<H2><A name=3DMatrix_Row,_Column_and_Element_operations></A>Matrix Row, =
Column and=20
Element operations</H2>
<UL>
  <LI><CODE>$row_vector =3D $matrix-&gt;row($row);</CODE>=20
  <P>This is a projection method which returns an object reference to a=20
  <B>NEW</B> matrix (which in fact is a (row) vector since it has only =
one row)=20
  to which row number "<CODE>$row</CODE>" of matrix =
"<CODE>$matrix</CODE>" has=20
  already been copied.</P>
  <P>Matrix "<CODE>$matrix</CODE>" is not changed by this in any =
way.</P>
  <LI><CODE>$column_vector =3D $matrix-&gt;column($column);</CODE>=20
  <P>This is a projection method which returns an object reference to a=20
  <B>NEW</B> matrix (which in fact is a (column) vector since it has =
only one=20
  column) to which column number "<CODE>$column</CODE>" of matrix=20
  "<CODE>$matrix</CODE>" has already been copied.</P>
  <P>Matrix "<CODE>$matrix</CODE>" is not changed by this in any =
way.</P>
  <LI><CODE>$matrix-&gt;assign($row,$column,$value);</CODE>=20
  <P>Explicitly assigns a value "<CODE>$value</CODE>" to a single =
element of the=20
  matrix "<CODE>$matrix</CODE>", located in row "<CODE>$row</CODE>" and =
column=20
  "<CODE>$column</CODE>", thereby replacing the value previously stored=20
  there.</P>
  <LI><CODE>$value =3D =
$matrix-&gt;</CODE><CODE>element($row,$column);</CODE>=20
  <P>Returns the value of a specific element of the matrix=20
  "<CODE>$matrix</CODE>", located in row "<CODE>$row</CODE>" and column=20
  "<CODE>$column</CODE>".</P>
  <LI><CODE>$new_matrix =3D $matrix-&gt;each( \&amp;function )</CODE>;=20
  <P>Creates a new matrix by evaluating a code reference on each element =
of the=20
  given matrix. The function is passed the element, the row index and =
the column=20
  index, in that order. The value the function returns ( or the value of =
the=20
  last executed statement ) is the value given to the corresponding =
element in=20
  $new_matrix.</P>
  <P>Example:</P><PRE>        # add 1 to every element in the matrix
        $matrix =3D $matrix-&gt;each ( sub { (shift) + 1 } );</PRE>
  <P>Example:</P><PRE>        my $cofactor =3D $matrix-&gt;each( sub { =
my(undef,$i,$j) =3D @_;
                ($i+$j) % 2 =3D=3D 0 ? =
$matrix-&gt;minor($i,$j)-&gt;det()
                : -1*$matrix-&gt;minor($i,$j)-&gt;det();
                } );</PRE>
  <P>This code needs some explanation. For each element of $matrix, it =
throws=20
  away the actual value and stores the row and column indexes in $i and =
$j. Then=20
  it sets element [$i,$j] in $cofactor to the determinant of=20
  <CODE>$matrix-&gt;minor($i,$j)</CODE> if it is an "even" element, or=20
  <CODE>-1*$matrix-&gt;minor($i,$j)</CODE> if it is an "odd" =
element.</P>
  <LI><CODE>$new_matrix =3D $matrix-&gt;each_diag( \&amp;function =
)</CODE>;=20
  <P>Creates a new matrix by evaluating a code reference on each =
diagonal=20
  element of the given matrix. The function is passed the element, the =
row index=20
  and the column index, in that order. The value the function returns ( =
or the=20
  value of the last executed statement ) is the value given to the =
corresponding=20
  element in $new_matrix.</P>
  <LI><CODE>$matrix-&gt;swap_col( $col1, $col2 );</CODE>=20
  <P>This method takes two one-based column numbers and swaps the values =
of each=20
  element in each column. <CODE>$matrix-&gt;swap_col(2,3)</CODE> would =
replace=20
  column 2 in $matrix with column 3, and replace column 3 with column =
2.</P>
  <LI><CODE>$matrix-&gt;swap_row( $row1, $row2 );</CODE>=20
  <P>This method takes two one-based row numbers and swaps the values of =
each=20
  element in each row. <CODE>$matrix-&gt;swap_row(2,3)</CODE> would =
replace row=20
  2 in $matrix with row 3, and replace row 3 with row 2.</P></LI></UL>
<H2><A name=3DMatrix_Operations></A>Matrix Operations</H2>
<UL>
  <LI><CODE>$det =3D $matrix-&gt;det();</CODE>=20
  <P>Returns the determinant of the matrix, without going through the =
rigamarole=20
  of computing a LR decomposition. This method should be much faster =
than LR=20
  decomposition if the matrix is diagonal or triangular. Otherwise, it =
is just a=20
  wrapper for <CODE>$matrix-&gt;decompose_LR-&gt;det_LR</CODE>. If the=20
  determinant is zero, there is no inverse and vice-versa. Only =
quadratic=20
  matrices have determinants.</P>
  <LI><CODE>$inverse =3D $matrix-&gt;inverse();</CODE>=20
  <P>Returns the inverse of a matrix, without going through the =
rigamarole of=20
  computing a LR decomposition. If no inverse exists, undef is returned =
and an=20
  error is printed via <CODE>carp()</CODE>. This is nothing but a =
wrapper for=20
  <CODE>$matrix-&gt;decompose_LR-&gt;invert_LR</CODE>.</P>
  <LI><CODE>($rows,$columns) =3D $matrix-&gt;dim();</CODE>=20
  <P>Returns a list of two items, representing the number of rows and =
columns=20
  the given matrix "<CODE>$matrix</CODE>" contains.</P>
  <LI><CODE>$norm_one =3D $matrix-&gt;norm_one();</CODE>=20
  <P>Returns the "one"-norm of the given matrix =
"<CODE>$matrix</CODE>".</P>
  <P>The "one"-norm is defined as follows:</P>
  <P>For each column, the sum of the absolute values of the elements in =
the=20
  different rows of that column is calculated. Finally, the maximum of =
these=20
  sums is returned.</P>
  <P>Note that the "one"-norm and the "maximum"-norm are mathematically=20
  equivalent, although for the same matrix they usually yield a =
different=20
  value.</P>
  <P>Therefore, you should only compare values that have been calculated =
using=20
  the same norm!</P>
  <P>Throughout this package, the "one"-norm is (arbitrarily) used for =
all=20
  comparisons, for the sake of uniformity and comparability, except for =
the=20
  iterative methods "solve_GSM()", "solve_SSM()" and "solve_RM()" which =
use=20
  either norm depending on the matrix itself.</P>
  <LI><CODE>$norm_max =3D $matrix-&gt;norm_max();</CODE>=20
  <P>Returns the "maximum"-norm of the given matrix $matrix.</P>
  <P>The "maximum"-norm is defined as follows:</P>
  <P>For each row, the sum of the absolute values of the elements in the =

  different columns of that row is calculated. Finally, the maximum of =
these=20
  sums is returned.</P>
  <P>Note that the "maximum"-norm and the "one"-norm are mathematically=20
  equivalent, although for the same matrix they usually yield a =
different=20
  value.</P>
  <P>Therefore, you should only compare values that have been calculated =
using=20
  the same norm!</P>
  <P>Throughout this package, the "one"-norm is (arbitrarily) used for =
all=20
  comparisons, for the sake of uniformity and comparability, except for =
the=20
  iterative methods "solve_GSM()", "solve_SSM()" and "solve_RM()" which =
use=20
  either norm depending on the matrix itself.</P>
  <LI><CODE>$norm_sum =3D $matrix-&gt;norm_sum();</CODE>=20
  <P>This is a very simple norm which is defined as the sum of the =
absolute=20
  values of every element.</P>
  <LI><CODE>$p_norm</CODE> =3D $matrix-&gt;norm_p($n);&gt;=20
  <P>This function returns the "p-norm" of a vector. The argument $n =
must be a=20
  number greater than or equal to 1 or the string "Inf". The p-norm is =
defined=20
  as (sum(x_i^p))^(1/p). In words, it raised each element to the p-th =
power,=20
  adds them up, and then takes the p-th root of that number. If the =
string "Inf"=20
  is passed, the "infinity-norm" is computed, which is really the limit =
of the=20
  p-norm as p goes to infinity. It is defined as the maximum element of =
the=20
  vector. Also, note that the familiar Euclidean distance between two =
vectors is=20
  just a special case of a p-norm, when p is equal to 2.</P>
  <P>Example: $a =3D Math::MatrixReal-&gt;new_from_cols([[1,2,3]]); $p1 =
=3D=20
  $a-&gt;norm_p(1); $p2 =3D $a-&gt;norm_p(2); $p3 =3D $a-&gt;norm_p(3); =
$pinf =3D=20
  $a-&gt;norm_p("Inf");</P><PRE>        print "(1,2,3,Inf) =
norm:\n$p1\n$p2\n$p3\n$pinf\n";

        $i1 =3D $a-&gt;new_from_rows([[1,0]]);
        $i2 =3D $a-&gt;new_from_rows([[0,1]]);

        # this should be sqrt(2) since it is the same as the=20
        # hypotenuse of a 1 by 1 right triangle

        $dist  =3D ($i1-$i2)-&gt;norm_p(2);
        print "Distance is $dist, which should be " . sqrt(2) . =
"\n";</PRE>
  <P>Output:</P><PRE>        (1,2,3,Inf) norm:
        6
        3.74165738677394139
        3.30192724889462668
        3

        Distance is 1.41421356237309505, which should be =
1.41421356237309505</PRE>
  <LI><CODE>$frob_norm</CODE> =3D =
<CODE>$matrix-&gt;norm_frobenius();</CODE>=20
  <P>This norm is similar to that of a p-norm where p is 2, except it =
acts on a=20
  <B>matrix</B>, not a vector. Each element of the matrix is squared, =
this is=20
  added up, and then a square root is taken.</P>
  <LI><CODE>$matrix-&gt;spectral_radius();</CODE>=20
  <P>Returns the maximum value of the absolute value of all eigenvalues. =

  Currently this computes <B>all</B> eigenvalues, then sifts through =
them to=20
  find the largest in absolute value. Needless to say, this is very =
inefficient,=20
  and in the future an algorithm that computes only the largest =
eigenvalue may=20
  be implemented.</P>
  <LI><CODE>$matrix1-&gt;transpose($matrix2);</CODE>=20
  <P>Calculates the transposed matrix of matrix $matrix2 and stores the =
result=20
  in matrix "<CODE>$matrix1</CODE>" (which must already exist and have =
the same=20
  size as matrix "<CODE>$matrix2</CODE>"!).</P>
  <P>This operation can also be carried out "in-place", i.e., input and =
output=20
  matrix may be identical.</P>
  <P>Transposition is a symmetry operation: imagine you rotate the =
matrix along=20
  the axis of its main diagonal (going through elements (1,1), (2,2), =
(3,3) and=20
  so on) by 180 degrees.</P>
  <P>Another way of looking at it is to say that rows and columns are =
swapped.=20
  In fact the contents of element <CODE>(i,j)</CODE> are swapped with =
those of=20
  element <CODE>(j,i)</CODE>.</P>
  <P>Note that (especially for vectors) it makes a big difference if you =
have a=20
  row vector, like this:</P><PRE>  [ -1 0 1 ]</PRE>
  <P>or a column vector, like this:</P><PRE>  [ -1 ]
  [  0 ]
  [  1 ]</PRE>
  <P>the one vector being the transposed of the other!</P>
  <P>This is especially true for the matrix product of two =
vectors:</P><PRE>               [ -1 ]
  [ -1 0 1 ] * [  0 ]  =3D  [ 2 ] ,  whereas
               [  1 ]

                             *     [ -1  0  1 ]
  [ -1 ]                                            [  1  0 -1 ]
  [  0 ] * [ -1 0 1 ]  =3D  [ -1 ]   [  1  0 -1 ]  =3D  [  0  0  0 ]
  [  1 ]                  [  0 ]   [  0  0  0 ]     [ -1  0  1 ]
                          [  1 ]   [ -1  0  1 ]</PRE>
  <P>So be careful about what you really mean!</P>
  <P>Hint: throughout this module, whenever a vector is explicitly =
required for=20
  input, a <B>COLUMN</B> vector is expected!</P>
  <LI><CODE>$trace =3D $matrix-&gt;trace();</CODE>=20
  <P>This returns the trace of the matrix, which is defined as the sum =
of the=20
  diagonal elements. The matrix must be quadratic.</P>
  <LI><CODE>$minor =3D $matrix-&gt;minor($row,$col);</CODE>=20
  <P>Returns the minor matrix corresponding to $row and $col. $matrix =
must be=20
  quadratic. If $matrix is n rows by n cols, the minor of $row and $col =
will be=20
  an (n-1) by (n-1) matrix. The minor is defined as crossing out the row =
and the=20
  col specified and returning the remaining rows and columns as a =
matrix. This=20
  method is used by <CODE>cofactor()</CODE>.</P>
  <LI><CODE>$cofactor =3D $matrix-&gt;cofactor();</CODE>=20
  <P>The cofactor matrix is constructed as follows:</P>
  <P>For each element, cross out the row and column that it sits in. =
Now, take=20
  the determinant of the matrix that is left in the other rows and =
columns.=20
  Multiply the determinant by (-1)^(i+j), where i is the row index, and =
j is the=20
  column index. Replace the given element with this value.</P>
  <P>The cofactor matrix can be used to find the inverse of the matrix. =
One=20
  formula for the inverse of a matrix is the cofactor matrix transposed =
divided=20
  by the original determinant of the matrix.</P>
  <P>The following two inverses should be exactly the same:</P><PRE>     =
   my $inverse1 =3D $matrix-&gt;inverse;
        my $inverse2 =3D ~($matrix-&gt;cofactor)-&gt;each( sub { =
(shift)/$matrix-&gt;det() } );</PRE>
  <P>Caveat: Although the cofactor matrix is simple algorithm to compute =
the=20
  inverse of a matrix, and can be used with pencil and paper for small =
matrices,=20
  it is comically slower than the native <CODE>inverse()</CODE> =
function. Here=20
  is a small benchmark:</P><PRE>        # $matrix1 is 15x15
        $det =3D $matrix1-&gt;det;
        timethese( 10,
        {'inverse' =3D&gt; sub { $matrix1-&gt;inverse(); },
          'cofactor' =3D&gt; sub { (~$matrix1-&gt;cofactor)-&gt;each ( =
sub { (shift)/$det; } ) }
        } );


        Benchmark: timing 10 iterations of LR, cofactor, inverse...
        inverse:  1 wallclock secs ( 0.56 usr +  0.00 sys =3D  0.56 CPU) =
@ 17.86/s (n=3D10)
        cofactor: 36 wallclock secs (36.62 usr +  0.01 sys =3D 36.63 =
CPU) @  0.27/s (n=3D10)</PRE>
  <LI><CODE>$adjoint =3D $matrix-&gt;adjoint();</CODE>=20
  <P>The adjoint is just the transpose of the cofactor matrix. This =
method is=20
  just an alias for <CODE>~($matrix-&gt;cofactor)</CODE>.</P></LI></UL>
<H2><A name=3DArithmetic_Operations></A>Arithmetic Operations</H2>
<UL>
  <LI><CODE>$matrix1-&gt;add($matrix2,$matrix3);</CODE>=20
  <P>Calculates the sum of matrix "<CODE>$matrix2</CODE>" and matrix=20
  "<CODE>$matrix3</CODE>" and stores the result in matrix=20
  "<CODE>$matrix1</CODE>" (which must already exist and have the same =
size as=20
  matrix "<CODE>$matrix2</CODE>" and matrix =
"<CODE>$matrix3</CODE>"!).</P>
  <P>This operation can also be carried out "in-place", i.e., the output =
and one=20
  (or both) of the input matrices may be identical.</P>
  <LI><CODE>$matrix1-&gt;subtract($matrix2,$matrix3);</CODE>=20
  <P>Calculates the difference of matrix "<CODE>$matrix2</CODE>" minus =
matrix=20
  "<CODE>$matrix3</CODE>" and stores the result in matrix=20
  "<CODE>$matrix1</CODE>" (which must already exist and have the same =
size as=20
  matrix "<CODE>$matrix2</CODE>" and matrix =
"<CODE>$matrix3</CODE>"!).</P>
  <P>This operation can also be carried out "in-place", i.e., the output =
and one=20
  (or both) of the input matrices may be identical.</P>
  <P>Note that this operation is the same as=20
  <CODE>$matrix1-&gt;add($matrix2,-$matrix3);</CODE>, although the =
latter is a=20
  little less efficient.</P>
  <LI><CODE>$matrix1-&gt;multiply_scalar($matrix2,$scalar);</CODE>=20
  <P>Calculates the product of matrix "<CODE>$matrix2</CODE>" and the =
number=20
  "<CODE>$scalar</CODE>" (i.e., multiplies each element of matrix=20
  "<CODE>$matrix2</CODE>" with the factor "<CODE>$scalar</CODE>") and =
stores the=20
  result in matrix "<CODE>$matrix1</CODE>" (which must already exist and =
have=20
  the same size as matrix "<CODE>$matrix2</CODE>"!).</P>
  <P>This operation can also be carried out "in-place", i.e., input and =
output=20
  matrix may be identical.</P>
  <LI><CODE>$product_matrix =3D $matrix1-&gt;multiply($matrix2);</CODE>=20
  <P>Calculates the product of matrix "<CODE>$matrix1</CODE>" and matrix =

  "<CODE>$matrix2</CODE>" and returns an object reference to a new =
matrix=20
  "<CODE>$product_matrix</CODE>" in which the result of this operation =
has been=20
  stored.</P>
  <P>Note that the dimensions of the two matrices =
"<CODE>$matrix1</CODE>" and=20
  "<CODE>$matrix2</CODE>" (i.e., their numbers of rows and columns) must =

  harmonize in the following way (example):</P><PRE>                     =
     [ 2 2 ]
                          [ 2 2 ]
                          [ 2 2 ]

              [ 1 1 1 ]   [ * * ]
              [ 1 1 1 ]   [ * * ]
              [ 1 1 1 ]   [ * * ]
              [ 1 1 1 ]   [ * * ]</PRE>
  <P>I.e., the number of columns of matrix "<CODE>$matrix1</CODE>" has =
to be the=20
  same as the number of rows of matrix "<CODE>$matrix2</CODE>".</P>
  <P>The number of rows and columns of the resulting matrix=20
  "<CODE>$product_matrix</CODE>" is determined by the number of rows of =
matrix=20
  "<CODE>$matrix1</CODE>" and the number of columns of matrix=20
  "<CODE>$matrix2</CODE>", respectively.</P>
  <LI><CODE>$matrix1-&gt;negate($matrix2);</CODE>=20
  <P>Calculates the negative of matrix "<CODE>$matrix2</CODE>" (i.e., =
multiplies=20
  all elements with "-1") and stores the result in matrix=20
  "<CODE>$matrix1</CODE>" (which must already exist and have the same =
size as=20
  matrix "<CODE>$matrix2</CODE>"!).</P>
  <P>This operation can also be carried out "in-place", i.e., input and =
output=20
  matrix may be identical.</P>
  <LI><CODE>$matrix_to_power =3D $matrix1-&gt;exponent($integer);</CODE> =

  <P>Raises the matrix to the <CODE>$integer</CODE> power. Obviously,=20
  <CODE>$integer</CODE> must be an integer. If it is zero, the identity =
matrix=20
  is returned. If a negative integer is given, the inverse will be =
computed (if=20
  it exists) and then raised the the absolute value of =
<CODE>$integer</CODE>.=20
  The matrix must be quadratic.</P></LI></UL>
<H2><A name=3DBoolean_Matrix_Operations></A>Boolean Matrix =
Operations</H2>
<UL>
  <LI><CODE>$matrix-&gt;is_quadratic();</CODE>=20
  <P>Returns a boolean value indicating if the given matrix is quadratic =
(also=20
  know as "square" or "n by n"). A matrix is quadratic if it has the =
same number=20
  of rows as it does columns.</P>
  <LI><CODE>$matrix-&gt;is_square();</CODE>=20
  <P>This is an alias for <CODE>is_quadratic()</CODE>.</P>
  <LI><CODE>$matrix-&gt;is_symmetric();</CODE>=20
  <P>Returns a boolean value indicating if the given matrix is =
symmetric. By=20
  definition, a matrix is symmetric if and only if=20
  (<B>M</B>[<I>i</I>,<I>j</I>]=3D<B>M</B>[<I>j</I>,<I>i</I>]). This is =
equivalent=20
  to <CODE>($matrix =3D=3D ~$matrix)</CODE> but without memory =
allocation. Only=20
  quadratic matrices can be symmetric.</P>
  <P>Notes: A symmetric matrix always has real eigenvalues/eigenvectors. =
A=20
  matrix plus its transpose is always symmetric.</P>
  <LI><CODE>$matrix-&gt;is_skew_symmetric();</CODE>=20
  <P>Returns a boolean value indicating if the given matrix is skew =
symmetric.=20
  By definition, a matrix is symmetric if and only if=20
  (<B>M</B>[<I>i</I>,<I>j</I>]=3D<B>-M</B>[<I>j</I>,<I>i</I>]). This is =
equivalent=20
  to <CODE>($matrix =3D=3D -(~$matrix))</CODE> but without memory =
allocation. Only=20
  quadratic matrices can be skew symmetric.</P>
  <LI><CODE>$matrix-&gt;is_diagonal();</CODE>=20
  <P>Returns a boolean value indicating if the given matrix is diagonal, =
i.e.=20
  all of the nonzero elements are on the main diagonal. Only quadratic =
matrices=20
  can be diagonal.</P>
  <LI><CODE>$matrix-&gt;is_tridiagonal();</CODE>=20
  <P>Returns a boolean value indicating if the given matrix is =
tridiagonal, i.e.=20
  all of the nonzero elements are on the main diagonal or the diagonals =
above=20
  and below the main diagonal. Only quadratic matrices can be =
tridiagonal.</P>
  <LI><CODE>$matrix-&gt;is_upper_triangular();</CODE>=20
  <P>Returns a boolean value indicating if the given matrix is upper =
triangular,=20
  i.e. all of the nonzero elements not on the main diagonal are above =
it. Only=20
  quadratic matrices can be upper triangular. Note: diagonal matrices =
are both=20
  upper and lower triangular.</P>
  <LI><CODE>$matrix-&gt;is_lower_triangular();</CODE>=20
  <P>Returns a boolean value indicating if the given matrix is lower =
triangular,=20
  i.e. all of the nonzero elements not on the main diagonal are below =
it. Only=20
  quadratic matrices can be lower triangular. Note: diagonal matrices =
are both=20
  upper and lower triangular.</P>
  <LI><CODE>$matrix-&gt;is_orthogonal();</CODE>=20
  <P>Returns a boolean value indicating if the given matrix is =
orthogonal. An=20
  orthogonal matrix is has the property that the transpose equals the =
inverse of=20
  the matrix. Instead of computing each and comparing them, this method=20
  multiplies the matrix by it's transpose, and returns true if this =
turns out to=20
  be the identity matrix, false otherwise. Only quadratic matrices can=20
  orthogonal.</P>
  <LI><CODE>$matrix-&gt;is_binary();</CODE>=20
  <P>Returns a boolean value indicating if the given matrix is binary. A =
matrix=20
  is binary if it contains only zeroes or ones.</P>
  <LI><CODE>$matrix-&gt;is_gramian();</CODE>=20
  <P>Returns a boolean value indicating if the give matrix is Gramian. A =
matrix=20
  <CODE>$A</CODE> is Gramian if and only if there exists a square matrix =

  <CODE>$B</CODE> such that <CODE>$A =3D ~$B*$B</CODE>. This is =
equivalent to=20
  checking if <CODE>$A</CODE> is symmetric and has all nonnegative =
eigenvalues,=20
  which is what Math::MatrixReal uses to check for this property.</P>
  <LI><CODE>$matrix-&gt;is_LR();</CODE>=20
  <P>Returns a boolean value indicating if the matrix is an LR =
decomposition=20
  matrix.</P>
  <LI><CODE>$matrix-&gt;is_positive();</CODE>=20
  <P>Returns a boolean value indicating if the matrix contains only =
positive=20
  entries. Note that a zero entry is not positive and will cause=20
  <CODE>is_positive()</CODE> to return false.</P>
  <LI><CODE>$matrix-&gt;is_negative();</CODE>=20
  <P>Returns a boolean value indicating if the matrix contains only =
negative=20
  entries. Note that a zero entry is not negative and will cause=20
  <CODE>is_negative()</CODE> to return false.</P>
  <LI><CODE>$matrix-&gt;is_periodic($k);</CODE>=20
  <P>Returns a boolean value indicating if the matrix is periodic with =
period=20
  $k. This is true if <CODE>$matrix ** ($k+1) =3D=3D $matrix</CODE>. =
When <CODE>$k=20
  =3D=3D 1</CODE>, this reduces down to the <CODE>is_idempotent()</CODE> =

  function.</P>
  <LI><CODE>$matrix-&gt;is_idempotent();</CODE>=20
  <P>Returns a boolean value indicating if the matrix is idempotent, =
which is=20
  defined as the square of the matrix being equal to the original =
matrix, i.e=20
  <CODE>$matrix ** 2 =3D=3D $matrix</CODE>.</P>
  <LI><CODE>$matrix-&gt;is_row_vector();</CODE>=20
  <P>Returns a boolean value indicating if the matrix is a row vector. A =
row=20
  vector is a matrix which is 1xn. Note that the 1x1 matrix is both a =
row and=20
  column vector.</P>
  <LI><CODE>$matrix-&gt;is_col_vector();</CODE>=20
  <P>Returns a boolean value indicating if the matrix is a col vector. A =
col=20
  vector is a matrix which is nx1. Note that the 1x1 matrix is both a =
row and=20
  column vector.</P></LI></UL>
<H2><A name=3DEigensystems></A>Eigensystems</H2>
<UL>
  <LI><CODE>($l, $V) =3D $matrix-&gt;sym_diagonalize();</CODE>=20
  <P>This method performs the diagonalization of the quadratic =
<I>symmetric</I>=20
  matrix <B>M</B> stored in $matrix. On output, <B>l</B> is a column =
vector=20
  containing all the eigenvalues of <B>M</B> and <B>V</B> is an =
orthogonal=20
  matrix which columns are the corresponding normalized eigenvectors. =
The=20
  primary property of an eigenvalue <I>l</I> and an eigenvector <B>x</B> =
is of=20
  course that: <B>M</B> * <B>x</B> =3D <I>l</I> * <B>x</B>.</P>
  <P>The method uses a Householder reduction to tridiagonal form =
followed by a=20
  QL algoritm with implicit shifts on this tridiagonal. (The tridiagonal =
matrix=20
  is kept internally in a compact form in this routine to save memory.) =
In fact,=20
  this routine wraps the householder() and tri_diagonalize() methods =
described=20
  below when their intermediate results are not desired. The overall =
algorithmic=20
  complexity of this technique is O(N^3). According to several books, =
the=20
  coefficient hidden by the 'O' is one of the best possible for general=20
  (symmetric) matrixes.</P>
  <LI><CODE>($T, $Q) =3D $matrix-&gt;householder();</CODE>=20
  <P>This method performs the Householder algorithm which reduces the =
<I>n</I>=20
  by <I>n</I> real <I>symmetric</I> matrix <B>M</B> contained in $matrix =
to=20
  tridiagonal form. On output, <B>T</B> is a symmetric tridiagonal =
matrix (only=20
  diagonal and off-diagonal elements are non-zero) and <B>Q</B> is an=20
  <I>orthogonal</I> matrix performing the tranformation between <B>M</B> =
and=20
  <B>T</B> (<CODE>$M =3D=3D $Q * $T * ~$Q</CODE>).</P>
  <LI><CODE>($l, $V) =3D $T-&gt;tri_diagonalize([$Q]);</CODE>=20
  <P>This method diagonalizes the symmetric tridiagonal matrix <B>T</B>. =
On=20
  output, $l and $V are similar to the output values described for=20
  sym_diagonalize().</P>
  <P>The optional argument $Q corresponds to an orthogonal =
transformation matrix=20
  <B>Q</B> that should be used additionally during <B>V</B> =
(eigenvectors)=20
  computation. It should be supplied if the desired eigenvectors =
correspond to a=20
  more general symmetric matrix <B>M</B> previously reduced by the =
householder()=20
  method, not a mere tridiagonal. If <B>T</B> is really a tridiagonal =
matrix,=20
  <B>Q</B> can be omitted (it will be internally created in fact as an =
identity=20
  matrix). The method uses a QL algorithm (with implicit shifts).</P>
  <LI><CODE>$l =3D $matrix-&gt;sym_eigenvalues();</CODE>=20
  <P>This method computes the eigenvalues of the quadratic =
<I>symmetric</I>=20
  matrix <B>M</B> stored in $matrix. On output, <B>l</B> is a column =
vector=20
  containing all the eigenvalues of <B>M</B>. Eigenvectors are not =
computed (on=20
  the contrary of <CODE>sym_diagonalize()</CODE>) and this method is =
more=20
  efficient (even though it uses a similar algorithm with two phases). =
However,=20
  understand that the algorithmic complexity of this technique is still =
also=20
  O(N^3). But the coefficient hidden by the 'O' is better by a factor =
of...,=20
  well, see your benchmark, it's wiser.</P>
  <P>This routine wraps the householder_tridiagonal() and =
tri_eigenvalues()=20
  methods described below when the intermediate tridiagonal matrix is =
not=20
  needed.</P>
  <LI><CODE>$T =3D $matrix-&gt;householder_tridiagonal();</CODE>=20
  <P>This method performs the Householder algorithm which reduces the =
<I>n</I>=20
  by <I>n</I> real <I>symmetric</I> matrix <B>M</B> contained in $matrix =
to=20
  tridiagonal form. On output, <B>T</B> is the obtained symmetric =
tridiagonal=20
  matrix (only diagonal and off-diagonal elements are non-zero). The =
operation=20
  is similar to the householder() method, but potentially a little more=20
  efficient as the transformation matrix is not computed.</P>
  <LI><CODE>$l =3D $T-&gt;tri_eigenvalues();</CODE>=20
  <P>This method computesthe eigenvalues of the symmetric tridiagonal =
matrix=20
  <B>T</B>. On output, $l is a vector containing the eigenvalues =
(similar to=20
  <CODE>sym_eigenvalues()</CODE>). This method is much more efficient =
than=20
  tri_diagonalize() when eigenvectors are not needed.</P></LI></UL>
<H2><A name=3DMiscellaneous></A>Miscellaneous</H2>
<UL>
  <LI><CODE>$matrix-&gt;zero();</CODE>=20
  <P>Assigns a zero to every element of the matrix =
"<CODE>$matrix</CODE>", i.e.,=20
  erases all values previously stored there, thereby effectively =
transforming=20
  the matrix into a "zero"-matrix or "null"-matrix, the neutral element =
of the=20
  addition operation in a Ring.</P>
  <P>(For instance the (quadratic) matrices with "n" rows and columns =
and matrix=20
  addition and multiplication form a Ring. Most prominent characteristic =
of a=20
  Ring is that multiplication is not commutative, i.e., in general,=20
  "<CODE>matrix1 * matrix2</CODE>" is not the same as "<CODE>matrix2 *=20
  matrix1</CODE>"!)</P>
  <LI><CODE>$matrix-&gt;one();</CODE>=20
  <P>Assigns one's to the elements on the main diagonal (elements (1,1), =
(2,2),=20
  (3,3) and so on) of matrix "<CODE>$matrix</CODE>" and zero's to all =
others,=20
  thereby erasing all values previously stored there and transforming =
the matrix=20
  into a "one"-matrix, the neutral element of the multiplication =
operation in a=20
  Ring.</P>
  <P>(If the matrix is quadratic (which this method doesn't require, =
though),=20
  then multiplying this matrix with itself yields this same matrix =
again, and=20
  multiplying it with some other matrix leaves that other matrix =
unchanged!)</P>
  <LI><CODE>$latex_string =3D $matrix-&gt;as_latex( align=3D&gt; "c", =
format =3D&gt;=20
  "%s", name =3D&gt; "" );</CODE>=20
  <P>This function returns the matrix as a LaTeX string. It takes a hash =
as an=20
  argument which is used to control the style of the output. The hash =
element=20
  <CODE>align</CODE> may be "c","l" or "r", corresponding to center, =
left and=20
  right, respectively. The <CODE>format</CODE> element is a format =
string that=20
  is given to <CODE>sprintf</CODE> to control the style of number =
format, such a=20
  floating point or scientific notation. The <CODE>name</CODE> element =
can be=20
  used so that a LaTeX string of "$name =3D " is prepended to the =
string.</P>
  <P>Example:</P><PRE>        my $a =3D =
Math::MatrixReal-&gt;new_from_cols([[ 1.234, 5.678, 9.1011],[1,2,3]] );
        print $a-&gt;as_latex( ( format =3D&gt; "%.2f", align =3D&gt; =
"l",name =3D&gt; "A" ) );</PRE>
  <P>Output: $A =3D $ $ \left( \begin{array}{ll} 1.23&amp;1.00 \\ =
5.68&amp;2.00 \\=20
  9.10&amp;3.00 \end{array} \right) $</P>
  <LI><CODE>$yacas_string =3D $matrix-&gt;as_yacas( format =3D&gt; "%s", =
name =3D&gt;=20
  "", semi =3D&gt; 0 );</CODE>=20
  <P>This function returns the matrix as a string that can be read by =
Yacas. It=20
  takes a hash as an an argument which controls the style of the output. =
The=20
  <CODE>format</CODE> element is a format string that is given to=20
  <CODE>sprintf</CODE> to control the style of number format, such a =
floating=20
  point or scientific notation. The <CODE>name</CODE> element can be =
used so=20
  that "$name =3D " is prepended to the string. The &lt;semi&gt; element =
can be=20
  set to 1 to that a semicolon is appended (so Matlab does not print out =
the=20
  matrix.)</P>
  <P>Example:</P><PRE>        $a =3D =
Math::MatrixReal-&gt;new_from_cols([[ 1.234, 5.678, 9.1011],[1,2,3]] );
        print $a-&gt;as_yacas( ( format =3D&gt; "%.2f", align =3D&gt; =
"l",name =3D&gt; "A" ) );</PRE>
  <P>Output:</P><PRE>        A :=3D =
{{1.23,1.00},{5.68,2.00},{9.10,3.00}}</PRE>
  <LI><CODE>$matlab_string =3D $matrix-&gt;as_matlab( format =3D&gt; =
"%s", name=20
  =3D&gt; "", semi =3D&gt; 0 );</CODE>=20
  <P>This function returns the matrix as a string that can be read by =
Matlab. It=20
  takes a hash as an an argument which controls the style of the output. =
The=20
  <CODE>format</CODE> element is a format string that is given to=20
  <CODE>sprintf</CODE> to control the style of number format, such a =
floating=20
  point or scientific notation. The <CODE>name</CODE> element can be =
used so=20
  that "$name =3D " is prepended to the string. The &lt;semi&gt; element =
can be=20
  set to 1 to that a semicolon is appended (so Matlab does not print out =
the=20
  matrix.)</P>
  <P>Example:</P><PRE>        my $a =3D =
Math::MatrixReal-&gt;new_from_rows([[ 1.234, 5.678, 9.1011],[1,2,3]] );
        print $a-&gt;as_matlab( ( format =3D&gt; "%.3f", name =3D&gt; =
"A",semi =3D&gt; 1 ) );</PRE>
  <P>Output: A =3D [ 1.234 5.678 9.101; 1.000 2.000 3.000];</P>
  <LI><CODE>$scilab_string =3D $matrix-&gt;as_scilab( format =3D&gt; =
"%s", name=20
  =3D&gt; "", semi =3D&gt; 0 );</CODE>=20
  <P>This function is just an alias for <CODE>as_matlab()</CODE>, since =
both=20
  Scilab and Matlab have the same matrix format.</P>
  <LI><CODE>$minimum =3D =
Math::MatrixReal::min($number1,$number2);</CODE>=20
  <P>Returns the minimum of the two numbers "<CODE>number1</CODE>" and=20
  "<CODE>number2</CODE>".</P>
  <LI><CODE>$maximum =3D =
Math::MatrixReal::max($number1,$number2);</CODE>=20
  <P>Returns the maximum of the two numbers "<CODE>number1</CODE>" and=20
  "<CODE>number2</CODE>".</P>
  <LI><CODE>$minimal_cost_matrix =3D $cost_matrix-&gt;kleene();</CODE>=20
  <P>Copies the matrix "<CODE>$cost_matrix</CODE>" (which has to be =
quadratic!)=20
  to a new matrix of the same size (i.e., "clones" the input matrix) and =
applies=20
  Kleene's algorithm to it.</P>
  <P>See <A=20
  =
href=3D"http://search.cpan.org/perldoc?Math%3A%3AKleene">Math::Kleene(3)<=
/A> for=20
  more details about this algorithm!</P>
  <P>The method returns an object reference to the new matrix.</P>
  <P>Matrix "<CODE>$cost_matrix</CODE>" is not changed by this method in =
any=20
  way.</P>
  <LI><CODE>($norm_matrix,$norm_vector) =3D =
$matrix-&gt;normalize($vector);</CODE>=20

  <P>This method is used to improve the numerical stability when solving =
linear=20
  equation systems.</P>
  <P>Suppose you have a matrix "A" and a vector "b" and you want to find =
out a=20
  vector "x" so that <CODE>A * x =3D b</CODE>, i.e., the vector "x" =
which solves=20
  the equation system represented by the matrix "A" and the vector =
"b".</P>
  <P>Applying this method to the pair (A,b) yields a pair (A',b') where =
each row=20
  has been divided by (the absolute value of) the greatest coefficient =
appearing=20
  in that row. So this coefficient becomes equal to "1" (or "-1") in the =
new=20
  pair (A',b') (all others become smaller than one and greater than =
minus=20
  one).</P>
  <P>Note that this operation does not change the equation system itself =
because=20
  the same division is carried out on either side of the equation =
sign!</P>
  <P>The method requires a quadratic (!) matrix "<CODE>$matrix</CODE>" =
and a=20
  vector "<CODE>$vector</CODE>" for input (the vector must be a column =
vector=20
  with the same number of rows as the input matrix) and returns a list =
of two=20
  items which are object references to a new matrix and a new vector, in =
this=20
  order.</P>
  <P>The output matrix and vector are clones of the input matrix and =
vector to=20
  which the operation explained above has been applied.</P>
  <P>The input matrix and vector are not changed by this in any way.</P>
  <P>Example of how this method can affect the result of the methods to =
solve=20
  equation systems (explained immediately below following this =
method):</P>
  <P>Consider the following little program:</P><PRE>  #!perl -w

  use Math::MatrixReal qw(new_from_string);

  $A =3D Math::MatrixReal-&gt;new_from_string(&lt;&lt;"MATRIX");
  [  1   2   3  ]
  [  5   7  11  ]
  [ 23  19  13  ]
  MATRIX

  $b =3D Math::MatrixReal-&gt;new_from_string(&lt;&lt;"MATRIX");
  [   0   ]
  [   1   ]
  [  29   ]
  MATRIX

  $LR =3D $A-&gt;decompose_LR();
  if (($dim,$x,$B) =3D $LR-&gt;solve_LR($b))
  {
      $test =3D $A * $x;
      print "x =3D \n$x";
      print "A * x =3D \n$test";
  }

  ($A_,$b_) =3D $A-&gt;normalize($b);

  $LR =3D $A_-&gt;decompose_LR();
  if (($dim,$x,$B) =3D $LR-&gt;solve_LR($b_))
  {
      $test =3D $A * $x;
      print "x =3D \n$x";
      print "A * x =3D \n$test";
  }</PRE>
  <P>This will print:</P><PRE>  x =3D
  [  1.000000000000E+00 ]
  [  1.000000000000E+00 ]
  [ -1.000000000000E+00 ]
  A * x =3D
  [  4.440892098501E-16 ]
  [  1.000000000000E+00 ]
  [  2.900000000000E+01 ]
  x =3D
  [  1.000000000000E+00 ]
  [  1.000000000000E+00 ]
  [ -1.000000000000E+00 ]
  A * x =3D
  [  0.000000000000E+00 ]
  [  1.000000000000E+00 ]
  [  2.900000000000E+01 ]</PRE>
  <P>You can see that in the second example (where "normalize()" has =
been used),=20
  the result is "better", i.e., more accurate!</P>
  <LI><CODE>$LR_matrix =3D $matrix-&gt;decompose_LR();</CODE>=20
  <P>This method is needed to solve linear equation systems.</P>
  <P>Suppose you have a matrix "A" and a vector "b" and you want to find =
out a=20
  vector "x" so that <CODE>A * x =3D b</CODE>, i.e., the vector "x" =
which solves=20
  the equation system represented by the matrix "A" and the vector =
"b".</P>
  <P>You might also have a matrix "A" and a whole bunch of different =
vectors=20
  "b1".."bk" for which you need to find vectors "x1".."xk" so that =
<CODE>A * xi=20
  =3D bi</CODE>, for <CODE>i=3D1..k</CODE>.</P>
  <P>Using Gaussian transformations (multiplying a row or column with a =
factor,=20
  swapping two rows or two columns and adding a multiple of one row or =
column to=20
  another), it is possible to decompose any matrix "A" into two =
triangular=20
  matrices, called "L" and "R" (for "Left" and "Right").</P>
  <P>"L" has one's on the main diagonal (the elements (1,1), (2,2), =
(3,3) and so=20
  so), non-zero values to the left and below of the main diagonal and =
all zero's=20
  in the upper right half of the matrix.</P>
  <P>"R" has non-zero values on the main diagonal as well as to the =
right and=20
  above of the main diagonal and all zero's in the lower left half of =
the=20
  matrix, as follows:</P><PRE>          [ 1 0 0 0 0 ]      [ x x x x x ]
          [ x 1 0 0 0 ]      [ 0 x x x x ]
      L =3D [ x x 1 0 0 ]  R =3D [ 0 0 x x x ]
          [ x x x 1 0 ]      [ 0 0 0 x x ]
          [ x x x x 1 ]      [ 0 0 0 0 x ]</PRE>
  <P>Note that "<CODE>L * R</CODE>" is equivalent to matrix "A" in the =
sense=20
  that <CODE>L * R * x =3D b &lt;=3D=3D&gt; A * x =3D b</CODE> for all =
vectors "x",=20
  leaving out of account permutations of the rows and columns (these are =
taken=20
  care of "magically" by this module!) and numerical errors.</P>
  <P>Trick:</P>
  <P>Because we know that "L" has one's on its main diagonal, we can =
store both=20
  matrices together in the same array without information loss! =
I.e.,</P><PRE>                 [ R R R R R ]
                 [ L R R R R ]
            LR =3D [ L L R R R ]
                 [ L L L R R ]
                 [ L L L L R ]</PRE>
  <P>Beware, though, that "LR" and "<CODE>L * R</CODE>" are not the =
same!!!</P>
  <P>Note also that for the same reason, you cannot apply the method=20
  "normalize()" to an "LR" decomposition matrix. Trying to do so will =
yield=20
  meaningless rubbish!</P>
  <P>(You need to apply "normalize()" to each pair (Ai,bi) <B>BEFORE</B> =

  decomposing the matrix "Ai'"!)</P>
  <P>Now what does all this help us in solving linear equation =
systems?</P>
  <P>It helps us because a triangular matrix is the next best thing that =
can=20
  happen to us besides a diagonal matrix (a matrix that has non-zero =
values only=20
  on its main diagonal - in which case the solution is trivial, simply =
divide=20
  "<CODE>b[i]</CODE>" by "<CODE>A[i,i]</CODE>" to get =
"<CODE>x[i]</CODE>"!).</P>
  <P>To find the solution to our problem "<CODE>A * x =3D b</CODE>", we =
divide=20
  this problem in parts: instead of solving <CODE>A * x =3D b</CODE> =
directly, we=20
  first decompose "A" into "L" and "R" and then solve "<CODE>L * y =3D =
b</CODE>"=20
  and finally "<CODE>R * x =3D y</CODE>" (motto: divide and rule!).</P>
  <P>From the illustration above it is clear that solving "<CODE>L * y =
=3D=20
  b</CODE>" and "<CODE>R * x =3D y</CODE>" is straightforward: we =
immediately know=20
  that <CODE>y[1] =3D b[1]</CODE>. We then deduce swiftly that</P><PRE>  =
y[2] =3D b[2] - L[2,1] * y[1]</PRE>
  <P>(and we know "<CODE>y[1]</CODE>" by now!), that</P><PRE>  y[3] =3D =
b[3] - L[3,1] * y[1] - L[3,2] * y[2]</PRE>
  <P>and so on.</P>
  <P>Having effortlessly calculated the vector "y", we now proceed to =
calculate=20
  the vector "x" in a similar fashion: we see immediately that =
<CODE>x[n] =3D y[n]=20
  / R[n,n]</CODE>. It follows that</P><PRE>  x[n-1] =3D ( y[n-1] - =
R[n-1,n] * x[n] ) / R[n-1,n-1]</PRE>
  <P>and</P><PRE>  x[n-2] =3D ( y[n-2] - R[n-2,n-1] * x[n-1] - R[n-2,n] =
* x[n] )
           / R[n-2,n-2]</PRE>
  <P>and so on.</P>
  <P>You can see that - especially when you have many vectors "b1".."bk" =
for=20
  which you are searching solutions to <CODE>A * xi =3D bi</CODE> - this =
scheme is=20
  much more efficient than a straightforward, "brute force" =
approach.</P>
  <P>This method requires a quadratic matrix as its input matrix.</P>
  <P>If you don't have that many equations, fill up with zero's (i.e., =
do=20
  nothing to fill the superfluous rows if it's a "fresh" matrix, i.e., a =
matrix=20
  that has been created with "new()" or "shadow()").</P>
  <P>The method returns an object reference to a new matrix containing =
the=20
  matrices "L" and "R".</P>
  <P>The input matrix is not changed by this method in any way.</P>
  <P>Note that you can "copy()" or "clone()" the result of this method =
without=20
  losing its "magical" properties (for instance concerning the hidden=20
  permutations of its rows and columns).</P>
  <P>However, as soon as you are applying any method that alters the =
contents of=20
  the matrix, its "magical" properties are stripped off, and the matrix=20
  immediately reverts to an "ordinary" matrix (with the values it just =
happens=20
  to contain at that moment, be they meaningful as an ordinary matrix or =

  not!).</P>
  <LI><CODE>($dimension,$x_vector,$base_matrix) =3D=20
  $LR_matrix</CODE><CODE>-&gt;</CODE><CODE>solve_LR($b_vector);</CODE>=20
  <P>Use this method to actually solve an equation system.</P>
  <P>Matrix "<CODE>$LR_matrix</CODE>" must be a (quadratic) matrix =
returned by=20
  the method "decompose_LR()", the LR decomposition matrix of the matrix =
"A" of=20
  your equation system <CODE>A * x =3D b</CODE>.</P>
  <P>The input vector "<CODE>$b_vector</CODE>" is the vector "b" in your =

  equation system <CODE>A * x =3D b</CODE>, which must be a column =
vector and have=20
  the same number of rows as the input matrix =
"<CODE>$LR_matrix</CODE>".</P>
  <P>The method returns a list of three items if a solution exists or an =
empty=20
  list otherwise (!).</P>
  <P>Therefore, you should always use this method like this:</P><PRE>  =
if ( ($dim,$x_vec,$base) =3D $LR-&gt;solve_LR($b_vec) )
  {
      # do something with the solution...
  }
  else
  {
      # do something with the fact that there is no solution...
  }</PRE>
  <P>The three items returned are: the dimension =
"<CODE>$dimension</CODE>" of=20
  the solution space (which is zero if only one solution exists, one if =
the=20
  solution is a straight line, two if the solution is a plane, and so =
on), the=20
  solution vector "<CODE>$x_vector</CODE>" (which is the vector "x" of =
your=20
  equation system <CODE>A * x =3D b</CODE>) and a matrix=20
  "<CODE>$base_matrix</CODE>" representing a base of the solution space =
(a set=20
  of vectors which put up the solution space like the spokes of an=20
umbrella).</P>
  <P>Only the first "<CODE>$dimension</CODE>" columns of this base =
matrix=20
  actually contain entries, the remaining columns are all zero.</P>
  <P>Now what is all this stuff with that "base" good for?</P>
  <P>The output vector "x" is <B>ALWAYS</B> a solution of your equation =
system=20
  <CODE>A * x =3D b</CODE>.</P>
  <P>But also any vector "<CODE>$vector</CODE>"</P><PRE>  $vector =3D =
$x_vector-&gt;clone();

  $machine_infinity =3D 1E+99; # or something like that

  for ( $i =3D 1; $i &lt;=3D $dimension; $i++ )
  {
      $vector +=3D rand($machine_infinity) * =
$base_matrix-&gt;column($i);
  }</PRE>
  <P>is a solution to your problem <CODE>A * x =3D b</CODE>, i.e., if=20
  "<CODE>$A_matrix</CODE>" contains your matrix "A", then</P><PRE>  =
print abs( $A_matrix * $vector - $b_vector ), "\n";</PRE>
  <P>should print a number around 1E-16 or so!</P>
  <P>By the way, note that you can actually calculate those vectors=20
  "<CODE>$vector</CODE>" a little more efficient as follows:</P><PRE>  =
$rand_vector =3D $x_vector-&gt;shadow();

  $machine_infinity =3D 1E+99; # or something like that

  for ( $i =3D 1; $i &lt;=3D $dimension; $i++ )
  {
      $rand_vector-&gt;assign($i,1, rand($machine_infinity) );
  }

  $vector =3D $x_vector + ( $base_matrix * $rand_vector );</PRE>
  <P>Note that the input matrix and vector are not changed by this =
method in any=20
  way.</P>
  <LI><CODE>$inverse_matrix =3D $LR_matrix-&gt;invert_LR();</CODE>=20
  <P>Use this method to calculate the inverse of a given matrix=20
  "<CODE>$LR_matrix</CODE>", which must be a (quadratic) matrix returned =
by the=20
  method "decompose_LR()".</P>
  <P>The method returns an object reference to a new matrix of the same =
size as=20
  the input matrix containing the inverse of the matrix that you =
initially fed=20
  into "decompose_LR()" <B>IF THE INVERSE EXISTS</B>, or an empty list=20
  otherwise.</P>
  <P>Therefore, you should always use this method in the following =
way:</P><PRE>  if ( $inverse_matrix =3D $LR-&gt;invert_LR() )
  {
      # do something with the inverse matrix...
  }
  else
  {
      # do something with the fact that there is no inverse matrix...
  }</PRE>
  <P>Note that by definition (disregarding numerical errors), the =
product of the=20
  initial matrix and its inverse (or vice-versa) is always a matrix =
containing=20
  one's on the main diagonal (elements (1,1), (2,2), (3,3) and so on) =
and zero's=20
  elsewhere.</P>
  <P>The input matrix is not changed by this method in any way.</P>
  <LI><CODE>$condition =3D =
$matrix-&gt;condition($inverse_matrix);</CODE>=20
  <P>In fact this method is just a shortcut for</P><PRE>  abs($matrix) * =
abs($inverse_matrix)</PRE>
  <P>Both input matrices must be quadratic and have the same size, and =
the=20
  result is meaningful only if one of them is the inverse of the other =
(for=20
  instance, as returned by the method "invert_LR()").</P>
  <P>The number returned is a measure of the "condition" of the given =
matrix=20
  "<CODE>$matrix</CODE>", i.e., a measure of the numerical stability of =
the=20
  matrix.</P>
  <P>This number is always positive, and the smaller its value, the =
better the=20
  condition of the matrix (the better the stability of all subsequent=20
  computations carried out using this matrix).</P>
  <P>Numerical stability means for example that if</P><PRE>  abs( =
$vec_correct - $vec_with_error ) &lt; $epsilon</PRE>
  <P>holds, there must be a "<CODE>$delta</CODE>" which doesn't depend =
on the=20
  vector "<CODE>$vec_correct</CODE>" (nor =
"<CODE>$vec_with_error</CODE>", by the=20
  way) so that</P><PRE>  abs( $matrix * $vec_correct - $matrix * =
$vec_with_error ) &lt; $delta</PRE>
  <P>also holds.</P>
  <LI><CODE>$determinant =3D $LR_matrix-&gt;det_LR();</CODE>=20
  <P>Calculates the determinant of a matrix, whose LR decomposition =
matrix=20
  "<CODE>$LR_matrix</CODE>" must be given (which must be a (quadratic) =
matrix=20
  returned by the method "decompose_LR()").</P>
  <P>In fact the determinant is a by-product of the LR decomposition: It =
is (in=20
  principle, that is, except for the sign) simply the product of the =
elements on=20
  the main diagonal (elements (1,1), (2,2), (3,3) and so on) of the LR=20
  decomposition matrix.</P>
  <P>(The sign is taken care of "magically" by this module)</P>
  <LI><CODE>$order =3D $LR_matrix-&gt;order_LR();</CODE>=20
  <P>Calculates the order (called "Rang" in German) of a matrix, whose =
LR=20
  decomposition matrix "<CODE>$LR_matrix</CODE>" must be given (which =
must be a=20
  (quadratic) matrix returned by the method "decompose_LR()").</P>
  <P>This number is a measure of the number of linear independent row =
and column=20
  vectors (=3D number of linear independent equations in the case of a =
matrix=20
  representing an equation system) of the matrix that was initially fed =
into=20
  "decompose_LR()".</P>
  <P>If "n" is the number of rows and columns of the (quadratic!) =
matrix, then=20
  "n - order" is the dimension of the solution space of the associated =
equation=20
  system.</P>
  <LI><CODE>$rank =3D $LR_matrix-&gt;rank_LR();</CODE>=20
  <P>This is an alias for the <CODE>order_LR()</CODE> function. The =
"order" is=20
  usually called the "rank" in the United States.</P>
  <LI><CODE>$scalar_product =3D =
$vector1-&gt;scalar_product($vector2);</CODE>=20
  <P>Returns the scalar product of vector "<CODE>$vector1</CODE>" and =
vector=20
  "<CODE>$vector2</CODE>".</P>
  <P>Both vectors must be column vectors (i.e., a matrix having several =
rows but=20
  only one column).</P>
  <P>This is a (more efficient!) shortcut for</P><PRE>  $temp           =
=3D ~$vector1 * $vector2;
  $scalar_product =3D  $temp-&gt;element(1,1);</PRE>
  <P>or the sum <CODE>i=3D1..n</CODE> of the products <CODE>vector1[i] * =

  vector2[i]</CODE>.</P>
  <P>Provided none of the two input vectors is the null vector, then the =
two=20
  vectors are orthogonal, i.e., have an angle of 90 degrees between =
them,=20
  exactly when their scalar product is zero, and vice-versa.</P>
  <LI><CODE>$vector_product =3D =
$vector1-&gt;vector_product($vector2);</CODE>=20
  <P>Returns the vector product of vector "<CODE>$vector1</CODE>" and =
vector=20
  "<CODE>$vector2</CODE>".</P>
  <P>Both vectors must be column vectors (i.e., a matrix having several =
rows but=20
  only one column).</P>
  <P>Currently, the vector product is only defined for 3 dimensions =
(i.e.,=20
  vectors with 3 rows); all other vectors trigger an error message.</P>
  <P>In 3 dimensions, the vector product of two vectors "x" and "y" is =
defined=20
  as</P><PRE>              |  x[1]  y[1]  e[1]  |
  determinant |  x[2]  y[2]  e[2]  |
              |  x[3]  y[3]  e[3]  |</PRE>
  <P>where the "<CODE>x[i]</CODE>" and "<CODE>y[i]</CODE>" are the =
components of=20
  the two vectors "x" and "y", respectively, and the "<CODE>e[i]</CODE>" =
are=20
  unity vectors (i.e., vectors with a length equal to one) with a one in =
row "i"=20
  and zero's elsewhere (this means that you have numbers and vectors as =
elements=20
  in this matrix!).</P>
  <P>This determinant evaluates to the rather simple formula</P><PRE>  =
z[1] =3D x[2] * y[3] - x[3] * y[2]
  z[2] =3D x[3] * y[1] - x[1] * y[3]
  z[3] =3D x[1] * y[2] - x[2] * y[1]</PRE>
  <P>A characteristic property of the vector product is that the =
resulting=20
  vector is orthogonal to both of the input vectors (if neither of both =
is the=20
  null vector, otherwise this is trivial), i.e., the scalar product of =
each of=20
  the input vectors with the resulting vector is always zero.</P>
  <LI><CODE>$length =3D $vector-&gt;length();</CODE>=20
  <P>This is actually a shortcut for</P><PRE>  $length =3D sqrt( =
$vector-&gt;scalar_product($vector) );</PRE>
  <P>and returns the length of a given (column!) vector=20
  "<CODE>$vector</CODE>".</P>
  <P>Note that the "length" calculated by this method is in fact the =
"two"-norm=20
  of a vector "<CODE>$vector</CODE>"!</P>
  <P>The general definition for norms of vectors is the =
following:</P><PRE>  sub vector_norm
  {
      croak "Usage: \$norm =3D \$vector-&gt;vector_norm(\$n);"
        if (@_ !=3D 2);

      my($vector,$n) =3D @_;
      my($rows,$cols) =3D ($vector-&gt;[1],$vector-&gt;[2]);
      my($k,$comp,$sum);

      croak "Math::MatrixReal::vector_norm(): vector is not a column =
vector"
        unless ($cols =3D=3D 1);

      croak "Math::MatrixReal::vector_norm(): norm index must be &gt; 0"
        unless ($n &gt; 0);

      croak "Math::MatrixReal::vector_norm(): norm index must be =
integer"
        unless ($n =3D=3D int($n));

      $sum =3D 0;
      for ( $k =3D 0; $k &lt; $rows; $k++ )
      {
          $comp =3D abs( $vector-&gt;[0][$k][0] );
          $sum +=3D $comp ** $n;
      }
      return( $sum ** (1 / $n) );
  }</PRE>
  <P>Note that the case "n =3D 1" is the "one"-norm for matrices applied =
to a=20
  vector, the case "n =3D 2" is the euclidian norm or length of a =
vector, and if=20
  "n" goes to infinity, you have the "infinity"- or "maximum"-norm for =
matrices=20
  applied to a vector!</P>
  <LI><CODE>$xn_vector =3D=20
  =
$matrix-&gt;</CODE><CODE>solve_GSM($x0_vector,$b_vector,$epsilon);</CODE>=
=20
  <LI><CODE>$xn_vector =3D=20
  =
$matrix-&gt;</CODE><CODE>solve_SSM($x0_vector,$b_vector,$epsilon);</CODE>=
=20
  <LI><CODE>$xn_vector =3D=20
  =
$matrix-&gt;</CODE><CODE>solve_RM($x0_vector,$b_vector,$weight,$epsilon);=
</CODE>=20

  <P>In some cases it might not be practical or desirable to solve an =
equation=20
  system "<CODE>A * x =3D b</CODE>" using an analytical algorithm like =
the=20
  "decompose_LR()" and "solve_LR()" method pair.</P>
  <P>In fact in some cases, due to the numerical properties (the =
"condition") of=20
  the matrix "A", the numerical error of the obtained result can be =
greater than=20
  by using an approximative (iterative) algorithm like one of the three=20
  implemented here.</P>
  <P>All three methods, GSM ("Global Step Method" or =
"Gesamtschrittverfahren"),=20
  SSM ("Single Step Method" or "Einzelschrittverfahren") and RM =
("Relaxation=20
  Method" or "Relaxationsverfahren"), are fix-point iterations, that is, =
can be=20
  described by an iteration function "<CODE>x(t+1) =3D Phi( x(t) =
)</CODE>" which=20
  has the property:</P><PRE>  Phi(x)  =3D  x    &lt;=3D=3D&gt;    A * x  =
=3D  b</PRE>
  <P>We can define "<CODE>Phi(x)</CODE>" as follows:</P><PRE>  Phi(x)  =
:=3D  ( En - A ) * x  +  b</PRE>
  <P>where "En" is a matrix of the same size as "A" ("n" rows and =
columns) with=20
  one's on its main diagonal and zero's elsewhere.</P>
  <P>This function has the required property.</P>
  <P>Proof:</P><PRE>           A * x        =3D   b

  &lt;=3D=3D&gt;  -( A * x )      =3D  -b

  &lt;=3D=3D&gt;  -( A * x ) + x  =3D  -b + x

  &lt;=3D=3D&gt;  -( A * x ) + x + b  =3D  x

  &lt;=3D=3D&gt;  x - ( A * x ) + b  =3D  x

  &lt;=3D=3D&gt;  ( En - A ) * x + b  =3D  x</PRE>
  <P>This last step is true because</P><PRE>  x[i] - ( a[i,1] x[1] + ... =
+ a[i,i] x[i] + ... + a[i,n] x[n] ) + b[i]</PRE>
  <P>is the same as</P><PRE>  ( -a[i,1] x[1] + ... + (1 - a[i,i]) x[i] + =
... + -a[i,n] x[n] ) + b[i]</PRE>
  <P>qed</P>
  <P>Note that actually solving the equation system "<CODE>A * x =3D =
b</CODE>"=20
  means to calculate</P><PRE>        a[i,1] x[1] + ... + a[i,i] x[i] + =
... + a[i,n] x[n]  =3D  b[i]

  &lt;=3D=3D&gt;  a[i,i] x[i]  =3D
        b[i]
        - ( a[i,1] x[1] + ... + a[i,i] x[i] + ... + a[i,n] x[n] )
        + a[i,i] x[i]

  &lt;=3D=3D&gt;  x[i]  =3D
        ( b[i]
            - ( a[i,1] x[1] + ... + a[i,i] x[i] + ... + a[i,n] x[n] )
            + a[i,i] x[i]
        ) / a[i,i]

  &lt;=3D=3D&gt;  x[i]  =3D
        ( b[i] -
            ( a[i,1] x[1] + ... + a[i,i-1] x[i-1] +
              a[i,i+1] x[i+1] + ... + a[i,n] x[n] )
        ) / a[i,i]</PRE>
  <P>There is one major restriction, though: a fix-point iteration is =
guaranteed=20
  to converge only if the first derivative of the iteration function has =
an=20
  absolute value less than one in an area around the point =
"<CODE>x(*)</CODE>"=20
  for which "<CODE>Phi( x(*) ) =3D x(*)</CODE>" is to be true, and if =
the start=20
  vector "<CODE>x(0)</CODE>" lies within that area!</P>
  <P>This is best verified grafically, which unfortunately is impossible =
to do=20
  in this textual documentation!</P>
  <P>See literature on Numerical Analysis for details!</P>
  <P>In our case, this restriction translates to the following three=20
  conditions:</P>
  <P>There must exist a norm so that the norm of the matrix of the =
iteration=20
  function, <CODE>( En - A )</CODE>, has a value less than one, the =
matrix "A"=20
  may not have any zero value on its main diagonal and the initial =
vector=20
  "<CODE>x(0)</CODE>" must be "good enough", i.e., "close enough" to the =

  solution "<CODE>x(*)</CODE>".</P>
  <P>(Remember school math: the first derivative of a straight line =
given by=20
  "<CODE>y =3D a * x + b</CODE>" is "a"!)</P>
  <P>The three methods expect a (quadratic!) matrix =
"<CODE>$matrix</CODE>" as=20
  their first argument, a start vector "<CODE>$x0_vector</CODE>", a =
vector=20
  "<CODE>$b_vector</CODE>" (which is the vector "b" in your equation =
system=20
  "<CODE>A * x =3D b</CODE>"), in the case of the "Relaxation Method" =
("RM"), a=20
  real number "<CODE>$weight</CODE>" best between zero and two, and =
finally an=20
  error limit (real number) "<CODE>$epsilon</CODE>".</P>
  <P>(Note that the weight "<CODE>$weight</CODE>" used by the =
"Relaxation=20
  Method" ("RM") is <B>NOT</B> checked to lie within any reasonable =
range!)</P>
  <P>The three methods first test the first two conditions of the three=20
  conditions listed above and return an empty list if these conditions =
are not=20
  fulfilled.</P>
  <P>Therefore, you should always test their return value using some =
code=20
  like:</P><PRE>  if ( $xn_vector =3D =
$A_matrix-&gt;solve_GSM($x0_vector,$b_vector,1E-12) )
  {
      # do something with the solution...
  }
  else
  {
      # do something with the fact that there is no solution...
  }</PRE>
  <P>Otherwise, they iterate until <CODE>abs( Phi(x) - x ) &lt;=20
  epsilon</CODE>.</P>
  <P>(Beware that theoretically, infinite loops might result if the =
starting=20
  vector is too far "off" the solution! In practice, this shouldn't be a =

  problem. Anyway, you can always press &lt;ctrl-C&gt; if you think that =
the=20
  iteration takes too long!)</P>
  <P>The difference between the three methods is the following:</P>
  <P>In the "Global Step Method" ("GSM"), the new vector =
"<CODE>x(t+1)</CODE>"=20
  (called "y" here) is calculated from the vector "<CODE>x(t)</CODE>" =
(called=20
  "x" here) according to the formula:</P><PRE>  y[i] =3D
  ( b[i]
      - ( a[i,1] x[1] + ... + a[i,i-1] x[i-1] +
          a[i,i+1] x[i+1] + ... + a[i,n] x[n] )
  ) / a[i,i]</PRE>
  <P>In the "Single Step Method" ("SSM"), the components of the vector=20
  "<CODE>x(t+1)</CODE>" which have already been calculated are used to =
calculate=20
  the remaining components, i.e.</P><PRE>  y[i] =3D
  ( b[i]
      - ( a[i,1] y[1] + ... + a[i,i-1] y[i-1] +  # note the "y[]"!
          a[i,i+1] x[i+1] + ... + a[i,n] x[n] )  # note the "x[]"!
  ) / a[i,i]</PRE>
  <P>In the "Relaxation method" ("RM"), the components of the vector=20
  "<CODE>x(t+1)</CODE>" are calculated by "mixing" old and new value =
(like cold=20
  and hot water), and the weight "<CODE>$weight</CODE>" determines the=20
  "aperture" of both the "hot water tap" as well as of the "cold water =
tap",=20
  according to the formula:</P><PRE>  y[i] =3D
  ( b[i]
      - ( a[i,1] y[1] + ... + a[i,i-1] y[i-1] +  # note the "y[]"!
          a[i,i+1] x[i+1] + ... + a[i,n] x[n] )  # note the "x[]"!
  ) / a[i,i]
  y[i] =3D weight * y[i] + (1 - weight) * x[i]</PRE>
  <P>Note that the weight "<CODE>$weight</CODE>" should be greater than =
zero and=20
  less than two (!).</P>
  <P>The three methods are supposed to be of different efficiency.=20
  Experiment!</P>
  <P>Remember that in most cases, it is probably advantageous to first=20
  "normalize()" your equation system prior to solving it!</P></LI></UL>
<H1><A name=3DOVERLOADED_OPERATORS></A>OVERLOADED OPERATORS <A=20
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#_t=
op"><IMG=20
alt=3D^ src=3D"http://search.cpan.org/s/img/up.gif"></A></H1>
<H2><A name=3DSYNOPSIS></A>SYNOPSIS</H2>
<UL>
  <LI>Unary operators:=20
  <P>"<CODE>-</CODE>", "<CODE>~</CODE>", "<CODE>abs</CODE>", =
<CODE>test</CODE>,=20
  "<CODE>!</CODE>", '<CODE>""</CODE>'</P>
  <LI>Binary (arithmetic) operators:=20
  <P>"<CODE>+</CODE>", "<CODE>-</CODE>", "<CODE>*</CODE>", =
"<CODE>**</CODE>",=20
  "<CODE>+=3D</CODE>", "<CODE>-=3D</CODE>", "<CODE>*=3D</CODE>",=20
"<CODE>**=3D</CODE>"</P>
  <LI>Binary (relational) operators:=20
  <P>"<CODE>=3D=3D</CODE>", "<CODE>!=3D</CODE>", "<CODE>&lt;</CODE>",=20
  "<CODE>&lt;=3D</CODE>", "<CODE>&gt;</CODE>", =
"<CODE>&gt;=3D</CODE>"</P>
  <P>"<CODE>eq</CODE>", "<CODE>ne</CODE>", "<CODE>lt</CODE>", =
"<CODE>le</CODE>",=20
  "<CODE>gt</CODE>", "<CODE>ge</CODE>"</P>
  <P>Note that the latter ("<CODE>eq</CODE>", "<CODE>ne</CODE>", ... ) =
are just=20
  synonyms of the former ("<CODE>=3D=3D</CODE>", "<CODE>!=3D</CODE>", =
... ), defined=20
  for convenience only.</P></LI></UL>
<H2><A name=3DDESCRIPTION></A>DESCRIPTION</H2>
<DL>
  <DT><A name=3D"'-'"></A>'-'=20
  <DD>
  <P>Unary minus</P>
  <P>Returns the negative of the given matrix, i.e., the matrix with all =

  elements multiplied with the factor "-1".</P>
  <P>Example:</P><PRE>    $matrix =3D -$matrix;</PRE>
  <DT><A name=3D"'~'"></A>'~'=20
  <DD>
  <P>Transposition</P>
  <P>Returns the transposed of the given matrix.</P>
  <P>Examples:</P><PRE>    $temp =3D ~$vector * $vector;
    $length =3D sqrt( $temp-&gt;element(1,1) );

    if (~$matrix =3D=3D $matrix) { # matrix is symmetric ... }</PRE>
  <DT><A name=3Dabs></A>abs=20
  <DD>
  <P>Norm</P>
  <P>Returns the "one"-Norm of the given matrix.</P>
  <P>Example:</P><PRE>    $error =3D abs( $A * $x - $b );</PRE>
  <DT><A name=3Dtest></A>test=20
  <DD>
  <P>Boolean test</P>
  <P>Tests wether there is at least one non-zero element in the =
matrix.</P>
  <P>Example:</P><PRE>    if ($xn_vector) { # result of iteration is not =
zero ... }</PRE>
  <DT><A name=3D"'!'"></A>'!'=20
  <DD>
  <P>Negated boolean test</P>
  <P>Tests wether the matrix contains only zero's.</P>
  <P>Examples:</P><PRE>    if (! $b_vector) { # heterogenous equation =
system ... }
    else             { # homogenous equation system ... }

    unless ($x_vector) { # not the null-vector! }</PRE>
  <DT><A name=3D"'&quot;&quot;&quot;&quot;'"></A>'""""'=20
  <DD>
  <P>"Stringify" operator</P>
  <P>Converts the given matrix into a string.</P>
  <P>Uses scientific representation to keep precision loss to a minimum =
in case=20
  you want to read this string back in again later with =
"new_from_string()".</P>
  <P>Uses a 13-digit mantissa and a 20-character field for each element =
so that=20
  lines will wrap nicely on an 80-column screen.</P>
  <P>Examples:</P><PRE>    $matrix =3D =
Math::MatrixReal-&gt;new_from_string(&lt;&lt;"MATRIX");
    [ 1  0 ]
    [ 0 -1 ]
    MATRIX
    print "$matrix";

    [  1.000000000000E+00  0.000000000000E+00 ]
    [  0.000000000000E+00 -1.000000000000E+00 ]

    $string =3D "$matrix";
    $test =3D Math::MatrixReal-&gt;new_from_string($string);
    if ($test =3D=3D $matrix) { print ":-)\n"; } else { print ":-(\n"; =
}</PRE>
  <DT><A name=3D"'+'"></A>'+'=20
  <DD>
  <P>Addition</P>
  <P>Returns the sum of the two given matrices.</P>
  <P>Examples:</P><PRE>    $matrix_S =3D $matrix_A + $matrix_B;

    $matrix_A +=3D $matrix_B;</PRE>
  <DT><A name=3D"'-'"></A>'-'=20
  <DD>
  <P>Subtraction</P>
  <P>Returns the difference of the two given matrices.</P>
  <P>Examples:</P><PRE>    $matrix_D =3D $matrix_A - $matrix_B;

    $matrix_A -=3D $matrix_B;</PRE>
  <P>Note that this is the same as:</P><PRE>    $matrix_S =3D $matrix_A =
+ -$matrix_B;

    $matrix_A +=3D -$matrix_B;</PRE>
  <P>(The latter are less efficient, though)</P>
  <DT><A name=3D"'*'"></A>'*'=20
  <DD>
  <P>Multiplication</P>
  <P>Returns the matrix product of the two given matrices or the product =
of the=20
  given matrix and scalar factor.</P>
  <P>Examples:</P><PRE>    $matrix_P =3D $matrix_A * $matrix_B;

    $matrix_A *=3D $matrix_B;

    $vector_b =3D $matrix_A * $vector_x;

    $matrix_B =3D -1 * $matrix_A;

    $matrix_B =3D $matrix_A * -1;

    $matrix_A *=3D -1;</PRE>
  <DT><A name=3D"'**'"></A>'**'=20
  <DD>
  <P>Exponentiation</P>
  <P>Returns the matrix raised to an integer power. If 0 is passed, the =
identity=20
  matrix is returned. If a negative integer is passed, it computes the =
inverse=20
  (if it exists) and then raised the inverse to the absolute value of =
the=20
  integer. The matrix must be quadratic.</P>
  <P>Examples:</P><PRE>    $matrix2 =3D $matrix ** 2;

    $matrix **=3D 2;

    $inv2 =3D $matrix ** -2;

    $ident =3D $matrix ** 0;</PRE>
  <DT><A name=3D"'=3D=3D'"></A>'=3D=3D'=20
  <DD>
  <P>Equality</P>
  <P>Tests two matrices for equality.</P>
  <P>Example:</P><PRE>    if ( $A * $x =3D=3D $b ) { print "EUREKA!\n"; =
}</PRE>
  <P>Note that in most cases, due to numerical errors (due to the finite =

  precision of computer arithmetics), it is a bad idea to compare two =
matrices=20
  or vectors this way.</P>
  <P>Better use the norm of the difference of the two matrices you want =
to=20
  compare and compare that norm with a small number, like this:</P><PRE> =
   if ( abs( $A * $x - $b ) &lt; 1E-12 ) { print "BINGO!\n"; }</PRE>
  <DT><A name=3D"'!=3D'"></A>'!=3D'=20
  <DD>
  <P>Inequality</P>
  <P>Tests two matrices for inequality.</P>
  <P>Example:</P><PRE>    while ($x0_vector !=3D $xn_vector) { # proceed =
with iteration ... }</PRE>
  <P>(Stops when the iteration becomes stationary)</P>
  <P>Note that (just like with the '=3D=3D' operator), it is usually a =
bad idea to=20
  compare matrices or vectors this way. Compare the norm of the =
difference of=20
  the two matrices with a small number instead.</P>
  <DT><A name=3D"'<'"></A>'&lt;'=20
  <DD>
  <P>Less than</P>
  <P>Examples:</P><PRE>    if ( $matrix1 &lt; $matrix2 ) { # ... }

    if ( $vector &lt; $epsilon ) { # ... }

    if ( 1E-12 &lt; $vector ) { # ... }

    if ( $A * $x - $b &lt; 1E-12 ) { # ... }</PRE>
  <P>These are just shortcuts for saying:</P><PRE>    if ( abs($matrix1) =
&lt; abs($matrix2) ) { # ... }

    if ( abs($vector) &lt; abs($epsilon) ) { # ... }

    if ( abs(1E-12) &lt; abs($vector) ) { # ... }

    if ( abs( $A * $x - $b ) &lt; abs(1E-12) ) { # ... }</PRE>
  <P>Uses the "one"-norm for matrices and Perl's built-in "abs()" for=20
  scalars.</P>
  <DT><A name=3D"'<=3D'"></A>'&lt;=3D'=20
  <DD>
  <P>Less than or equal</P>
  <P>As with the '&lt;' operator, this is just a shortcut for the same=20
  expression with "abs()" around all arguments.</P>
  <P>Example:</P><PRE>    if ( $A * $x - $b &lt;=3D 1E-12 ) { # ... =
}</PRE>
  <P>which in fact is the same as:</P><PRE>    if ( abs( $A * $x - $b ) =
&lt;=3D abs(1E-12) ) { # ... }</PRE>
  <P>Uses the "one"-norm for matrices and Perl's built-in "abs()" for=20
  scalars.</P>
  <DT><A name=3D"'>'"></A>'&gt;'=20
  <DD>
  <P>Greater than</P>
  <P>As with the '&lt;' and '&lt;=3D' operator, this</P><PRE>    if ( =
$xn - $x0 &gt; 1E-12 ) { # ... }</PRE>
  <P>is just a shortcut for:</P><PRE>    if ( abs( $xn - $x0 ) &gt; =
abs(1E-12) ) { # ... }</PRE>
  <P>Uses the "one"-norm for matrices and Perl's built-in "abs()" for=20
  scalars.</P>
  <DT><A name=3D"'>=3D'"></A>'&gt;=3D'=20
  <DD>
  <P>Greater than or equal</P>
  <P>As with the '&lt;', '&lt;=3D' and '&gt;' operator, the =
following</P><PRE>    if ( $LR &gt;=3D $A ) { # ... }</PRE>
  <P>is simply a shortcut for:</P><PRE>    if ( abs($LR) &gt;=3D abs($A) =
) { # ... }</PRE>
  <P>Uses the "one"-norm for matrices and Perl's built-in "abs()" for=20
  scalars.</P></DD></DL>
<H1><A name=3DSEE_ALSO></A>SEE ALSO <A=20
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#_t=
op"><IMG=20
alt=3D^ src=3D"http://search.cpan.org/s/img/up.gif"></A></H1>
<P><A=20
href=3D"http://search.cpan.org/perldoc?Math%3A%3AVectorReal">Math::Vector=
Real</A>,=20
<A =
href=3D"http://search.cpan.org/perldoc?Math%3A%3APARI">Math::PARI</A>, =
<A=20
href=3D"http://search.cpan.org/perldoc?Math%3A%3AMatrixBool">Math::Matrix=
Bool</A>,=20
<A =
href=3D"http://search.cpan.org/perldoc?DFA%3A%3AKleene">DFA::Kleene</A>, =
<A=20
href=3D"http://search.cpan.org/perldoc?Math%3A%3AKleene">Math::Kleene</A>=
, <A=20
href=3D"http://search.cpan.org/perldoc?Set%3A%3AIntegerRange">Set::Intege=
rRange</A>,=20
<A=20
href=3D"http://search.cpan.org/perldoc?Set%3A%3AIntegerFast">Set::Integer=
Fast</A>=20
.</P>
<H1><A name=3DVERSION></A>VERSION <A=20
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#_t=
op"><IMG=20
alt=3D^ src=3D"http://search.cpan.org/s/img/up.gif"></A></H1>
<P>This man page documents Math::MatrixReal version 1.9.</P>
<P>The latest version can always be found at <A=20
href=3D"http://leto.net/code/Math-MatrixReal/">http://leto.net/code/Math-=
MatrixReal/</A></P>
<H1><A name=3DAUTHORS></A>AUTHORS <A=20
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#_t=
op"><IMG=20
alt=3D^ src=3D"http://search.cpan.org/s/img/up.gif"></A></H1>
<P>Steffen Beyer &lt;sb@engelschall.com&gt;, Rodolphe Ortalo=20
&lt;ortalo@laas.fr&gt;, Jonathan Leto &lt;jonathan@leto.net&gt;.</P>
<P>Currently maintained by Jonathan Leto, send all bugs/patches to =
me.</P>
<H1><A name=3DCREDITS></A>CREDITS <A=20
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#_t=
op"><IMG=20
alt=3D^ src=3D"http://search.cpan.org/s/img/up.gif"></A></H1>
<P>Many thanks to Prof. Pahlings for stoking the fire of my enthusiasm =
for=20
Algebra and Linear Algebra at the university (RWTH Aachen, Germany), and =
to=20
Prof. Esser and his assistant, Mr. Jarausch, for their fascinating =
lectures in=20
Numerical Analysis!</P>
<H1><A name=3DCOPYRIGHT></A>COPYRIGHT <A=20
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#_t=
op"><IMG=20
alt=3D^ src=3D"http://search.cpan.org/s/img/up.gif"></A></H1>
<P>Copyright (c) 1996-2002 by Steffen Beyer, Rodolphe Ortalo, Jonathan =
Leto. All=20
rights reserved.</P>
<H1><A name=3DLICENSE_AGREEMENT></A>LICENSE AGREEMENT <A=20
href=3D"http://search.cpan.org/~leto/Math-MatrixReal-1.9/MatrixReal.pm#_t=
op"><IMG=20
alt=3D^ src=3D"http://search.cpan.org/s/img/up.gif"></A></H1>
<P>This package is free software; you can redistribute it and/or modify =
it under=20
the same terms as Perl itself.</P><!-- end doc --></DIV></DIV>
<DIV class=3Dfooter>hosted by <A=20
href=3D"http://www.perl.org/siteinfo.html">perl.org</A>, hardware =
provided=20
by<BR><A href=3D"http://www.bizrate.com/"><IMG=20
src=3D"http://search.cpan.org/s/img/bizrate_logo.png"></A> </DIV><!-- =
Thu Aug 11 01:30:17 2005 GMT (0.588869094848633) @x15 --></BODY></HTML>

------=_NextPart_000_0008_01C59E5F.CC267000
Content-Type: image/png
Content-Transfer-Encoding: base64
Content-Location: http://search.cpan.org/s/img/cpan_banner.png

iVBORw0KGgoAAAANSUhEUgAAAQgAAABNCAMAAABtygqmAAADAFBMVEW//88CAgIGBgYKCgoODg4S
EhIWFhYaGhoeHh4iIiImJiYqKiouLi4yMjI2NjY6Ojo+Pj5CQkJGRkZKSkpOTk5SUlJWVlZaWlpe
Xl5iYmJmZmZqampubm5ycnJ2dnZ6enp+fn6CgoKGhoaKioqOjo6SkpKWlpaampqenp6ioqKmpqaq
qqqurq6ysrK2tra6urq+vr7CwsLGxsbKysrOzs7S0tLW1tba2tre3t7i4uLm5ubq6uru7u7y8vL2
9vb6+vr+/v4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAACqShimAAAAAXRSTlMAQObYZgAAAAlwSFlzAAALEwAACxMBAJqcGAAAEMFJREFU
eNrtXId2IruyRVLn3NBkkw2YDB3Iwf//Va9KMDO26QDvjO+7b+ZoLQ8Yq7ulXWlXlZhc7r92vJ+L
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

------=_NextPart_000_0008_01C59E5F.CC267000
Content-Type: image/gif
Content-Transfer-Encoding: base64
Content-Location: http://search.cpan.org/s/img/up.gif

R0lGODlhDwAPAIAAAABmmf///yH5BAEAAAEALAAAAAAPAA8AAAIjhI8Jwe1tXlgvulMpS1crT33W
uGBkpm3pZEEr1qGZHEuSKBYAOw==

------=_NextPart_000_0008_01C59E5F.CC267000
Content-Type: image/png
Content-Transfer-Encoding: base64
Content-Location: http://search.cpan.org/s/img/bizrate_logo.png

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
mWP+AAAAAElFTkSuQmCC

------=_NextPart_000_0008_01C59E5F.CC267000
Content-Type: text/css;
	charset="iso-2022-jp"
Content-Transfer-Encoding: quoted-printable
Content-Location: http://search.cpan.org/s/style.css

BODY {
	BACKGROUND: white
}
.logo {
	BACKGROUND: white
}
BODY {
	PADDING-RIGHT: 1ex; PADDING-LEFT: 1ex; PADDING-BOTTOM: 1ex; MARGIN: =
0px; COLOR: black; PADDING-TOP: 1ex; FONT-FAMILY: arial,sans-serif
}
TABLE {
	BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: =
0px; BORDER-COLLAPSE: collapse; BORDER-RIGHT-WIDTH: 0px; border-spacing: =
0
}
IMG {
	BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: =
0px
}
FORM {
	MARGIN: 0px
}
INPUT {
	MARGIN: 2px
}
.logo {
	FLOAT: left; WIDTH: 264px; HEIGHT: 77px
}
.front .logo {
	DISPLAY: block; FLOAT: none
}
.front .searchbox {
	MARGIN: 2ex auto; TEXT-ALIGN: center
}
.front .menubar {
	TEXT-ALIGN: center
}
.menubar {
	PADDING-RIGHT: 1px; PADDING-LEFT: 1px; BACKGROUND: #006699; =
PADDING-BOTTOM: 1px; MARGIN: 1ex 0px; PADDING-TOP: 1px
}
.menubar A {
	PADDING-RIGHT: 0.8ex; PADDING-LEFT: 0.8ex; PADDING-BOTTOM: 0.8ex; FONT: =
bold 10pt Arial,Helvetica,sans-serif; PADDING-TOP: 0.8ex
}
.menubar A:link {
	COLOR: white; TEXT-DECORATION: none
}
.menubar A:visited {
	COLOR: white; TEXT-DECORATION: none
}
.menubar A:hover {
	COLOR: #ff6600; TEXT-DECORATION: underline
}
A:link {
	BACKGROUND: none transparent scroll repeat 0% 0%; COLOR: #006699
}
A:visited {
	BACKGROUND: none transparent scroll repeat 0% 0%; COLOR: #006699
}
UNKNOWN {
	BACKGROUND: none transparent scroll repeat 0% 0%; COLOR: #ff0000
}
TD {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; PADDING-TOP: 0px
}
DIV {
	BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: =
0px; BORDER-RIGHT-WIDTH: 0px
}
DT {
	MARGIN-TOP: 1em
}
.credits TD {
	PADDING-RIGHT: 2ex; PADDING-LEFT: 2ex; PADDING-BOTTOM: 0.5ex; =
PADDING-TOP: 0.5ex
}
.huge {
	FONT-SIZE: 32pt
}
.s {
	BACKGROUND: #dddddd
}
.s TD {
	PADDING-RIGHT: 1ex; PADDING-LEFT: 1ex; PADDING-BOTTOM: 0.2ex; =
VERTICAL-ALIGN: baseline; PADDING-TOP: 0.2ex
}
.r TD {
	PADDING-RIGHT: 1ex; PADDING-LEFT: 1ex; PADDING-BOTTOM: 0.2ex; =
VERTICAL-ALIGN: baseline; PADDING-TOP: 0.2ex
}
TH {
	PADDING-RIGHT: 1ex; PADDING-LEFT: 1ex; BACKGROUND: #bbbbbb; =
PADDING-BOTTOM: 0.4ex; PADDING-TOP: 0.4ex; TEXT-ALIGN: left
}
TH A:link {
	BACKGROUND: none transparent scroll repeat 0% 0%; COLOR: black
}
TH A:visited {
	BACKGROUND: none transparent scroll repeat 0% 0%; COLOR: black
}
.box {
	BORDER-RIGHT: #006699 1px solid; PADDING-RIGHT: 0px; BORDER-TOP: =
#006699 1px solid; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1ex =
0px; BORDER-LEFT: #006699 1px solid; PADDING-TOP: 0px; BORDER-BOTTOM: =
#006699 1px solid
}
.distfiles TD {
	PADDING-RIGHT: 2ex; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; =
VERTICAL-ALIGN: baseline; PADDING-TOP: 0px
}
.manifest TD {
	PADDING-RIGHT: 1ex; PADDING-LEFT: 1ex; PADDING-BOTTOM: 0px; =
VERTICAL-ALIGN: top; PADDING-TOP: 0px
}
.l1 {
	FONT-WEIGHT: bold
}
.l2 {
	FONT-WEIGHT: normal
}
.t1 {
	BACKGROUND: #006699; COLOR: white
}
.t2 {
	BACKGROUND: #006699; COLOR: white
}
.t3 {
	BACKGROUND: #006699; COLOR: white
}
.t4 {
	BACKGROUND: #006699; COLOR: white
}
.t4 {
	PADDING-RIGHT: 0.4ex; PADDING-LEFT: 0.4ex; PADDING-BOTTOM: 0.2ex; =
PADDING-TOP: 0.2ex
}
.t1 {
	PADDING-RIGHT: 1ex; PADDING-LEFT: 1ex; PADDING-BOTTOM: 0.5ex; =
PADDING-TOP: 0.5ex
}
.t2 {
	PADDING-RIGHT: 1ex; PADDING-LEFT: 1ex; PADDING-BOTTOM: 0.5ex; =
PADDING-TOP: 0.5ex
}
.t3 {
	PADDING-RIGHT: 1ex; PADDING-LEFT: 1ex; PADDING-BOTTOM: 0.5ex; =
PADDING-TOP: 0.5ex
}
.box .t1 {
	MARGIN: 0px
}
.box .t2 {
	MARGIN: 0px
}
.box .t3 {
	MARGIN: 0px
}
.t1 {
	FONT-WEIGHT: bold; FONT-SIZE: 1.4em; TEXT-ALIGN: center
}
.t2 {
	FONT-WEIGHT: bold; FONT-SIZE: 1em; TEXT-ALIGN: left
}
.t3 {
	FONT-WEIGHT: normal; FONT-SIZE: 1em; TEXT-ALIGN: left
}
.datecell {
	WIDTH: 17em; TEXT-ALIGN: center
}
.cell {
	PADDING-RIGHT: 1ex; PADDING-LEFT: 1ex; PADDING-BOTTOM: 0.2ex; =
PADDING-TOP: 0.2ex; TEXT-ALIGN: left
}
.label {
	PADDING-RIGHT: 1ex; PADDING-LEFT: 1ex; FONT-WEIGHT: bold; BACKGROUND: =
#aaaaaa; PADDING-BOTTOM: 0.2ex; VERTICAL-ALIGN: baseline; COLOR: black; =
PADDING-TOP: 0.2ex; WHITE-SPACE: nowrap; TEXT-ALIGN: right
}
.categories {
	MARGIN-BOTTOM: 1ex; PADDING-BOTTOM: 1ex; BORDER-BOTTOM: #006699 3px =
double
}
.categories TABLE {
	MARGIN: auto
}
.categories TD {
	PADDING-RIGHT: 1ex; PADDING-LEFT: 1ex; PADDING-BOTTOM: 0.5ex; =
VERTICAL-ALIGN: baseline; PADDING-TOP: 0.5ex
}
.path A {
	FONT-WEIGHT: bold; BACKGROUND: none transparent scroll repeat 0% 0%; =
COLOR: #006699
}
.pages {
	PADDING-RIGHT: 0.4ex; PADDING-LEFT: 0.4ex; BACKGROUND: #dddddd; =
PADDING-BOTTOM: 0.2ex; COLOR: #006699; PADDING-TOP: 0.2ex
}
.path {
	PADDING-RIGHT: 1ex; PADDING-LEFT: 1ex; BACKGROUND: #dddddd; =
PADDING-BOTTOM: 0.5ex; MARGIN: 1ex 0px; COLOR: #006699; PADDING-TOP: =
0.5ex; BORDER-BOTTOM: #006699 1px solid
}
.menubar TD {
	BACKGROUND: #006699; COLOR: white
}
.menubar {
	PADDING-RIGHT: 1px; PADDING-LEFT: 1px; BACKGROUND: #006699; =
PADDING-BOTTOM: 1px; MARGIN: 1ex 0px; COLOR: white; PADDING-TOP: 1px
}
.menubar .links {
	PADDING-RIGHT: 0.2ex; PADDING-LEFT: 0.2ex; BACKGROUND: none transparent =
scroll repeat 0% 0%; PADDING-BOTTOM: 0.2ex; COLOR: white; PADDING-TOP: =
0.2ex; TEXT-ALIGN: left
}
.menubar .searchbar {
	PADDING-RIGHT: 2px; PADDING-LEFT: 2px; BACKGROUND: black; =
PADDING-BOTTOM: 2px; MARGIN: 0px; COLOR: black; PADDING-TOP: 2px; =
TEXT-ALIGN: right
}
A.m:link {
	BACKGROUND: #006699; FONT: bold 10pt Arial,Helvetica,sans-serif; COLOR: =
white; TEXT-DECORATION: none
}
A.m:visited {
	BACKGROUND: #006699; FONT: bold 10pt Arial,Helvetica,sans-serif; COLOR: =
white; TEXT-DECORATION: none
}
A.o:link {
	BACKGROUND: #006699; FONT: bold 10pt Arial,Helvetica,sans-serif; COLOR: =
#ccffcc; TEXT-DECORATION: none
}
A.o:visited {
	BACKGROUND: #006699; FONT: bold 10pt Arial,Helvetica,sans-serif; COLOR: =
#ccffcc; TEXT-DECORATION: none
}
A.o:hover {
	BACKGROUND: none transparent scroll repeat 0% 0%; COLOR: #ff6600; =
TEXT-DECORATION: underline
}
A.m:hover {
	BACKGROUND: none transparent scroll repeat 0% 0%; COLOR: #ff6600; =
TEXT-DECORATION: underline
}
TABLE.dlsip {
	BORDER-RIGHT: #dddddd 0.4ex solid; BORDER-TOP: #dddddd 0.4ex solid; =
BACKGROUND: #dddddd; BORDER-LEFT: #dddddd 0.4ex solid; BORDER-BOTTOM: =
#dddddd 0.4ex solid
}
.pod PRE {
	BORDER-RIGHT: #888888 1px solid; PADDING-RIGHT: 1em; BORDER-TOP: =
#888888 1px solid; PADDING-LEFT: 1em; BACKGROUND: #eeeeee; =
PADDING-BOTTOM: 1em; BORDER-LEFT: #888888 1px solid; COLOR: black; =
PADDING-TOP: 1em; BORDER-BOTTOM: #888888 1px solid; WHITE-SPACE: pre
}
.pod H1 {
	FONT-SIZE: large; BACKGROUND: none transparent scroll repeat 0% 0%; =
COLOR: #006699
}
.pod H2 {
	FONT-SIZE: medium; BACKGROUND: none transparent scroll repeat 0% 0%; =
COLOR: #006699
}
.pod IMG {
	VERTICAL-ALIGN: top
}
.pod .toc A {
	TEXT-DECORATION: none
}
.pod .toc LI {
	LINE-HEIGHT: 1.2em; LIST-STYLE-TYPE: none
}
.faq DT {
	FONT-WEIGHT: bold; FONT-SIZE: 1.4em
}
.chmenu {
	PADDING-RIGHT: 0.5ex; PADDING-LEFT: 0.5ex; BACKGROUND: black; =
PADDING-BOTTOM: 0.5ex; MARGIN: 1ex auto; FONT: bold 1.1em =
Arial,Helvetica,sans-serif; COLOR: red; PADDING-TOP: 0.5ex
}
.chmenu TD {
	PADDING-RIGHT: 1ex; PADDING-LEFT: 1ex; PADDING-BOTTOM: 0.2ex; =
PADDING-TOP: 0.2ex
}
.chmenu A:link {
	BACKGROUND: none transparent scroll repeat 0% 0%; COLOR: white; =
TEXT-DECORATION: none
}
.chmenu A:visited {
	BACKGROUND: none transparent scroll repeat 0% 0%; COLOR: white; =
TEXT-DECORATION: none
}
.chmenu A:hover {
	BACKGROUND: none transparent scroll repeat 0% 0%; COLOR: #ff6600; =
TEXT-DECORATION: underline
}
.column {
	PADDING-RIGHT: 1ex; PADDING-LEFT: 1ex; PADDING-BOTTOM: 0.5ex; =
VERTICAL-ALIGN: top; PADDING-TOP: 0.5ex
}
.datebar {
	MARGIN: auto; WIDTH: 14em
}
.date {
	BACKGROUND: none transparent scroll repeat 0% 0%; COLOR: #008000
}
.footer {
	BORDER-TOP: #006699 1px solid; MARGIN-TOP: 1ex; FONT-SIZE: x-small; =
COLOR: #006699; LINE-HEIGHT: 120%; TEXT-ALIGN: right
}
.front .footer {
	BORDER-TOP: medium none
}

------=_NextPart_000_0008_01C59E5F.CC267000--
