File Coverage

blib/lib/Math/Matrix.pm
Criterion Covered Total %
statement 2052 2191 93.6
branch 915 1468 62.3
condition 120 255 47.0
subroutine 228 233 97.8
pod 187 187 100.0
total 3502 4334 80.8


line stmt bran cond sub pod time code
1             # -*- mode: perl; coding: utf-8-unix -*-
2              
3             package Math::Matrix;
4              
5 124     124   1321444 use strict;
  124         1036  
  124         3596  
6 124     124   637 use warnings;
  124         232  
  124         2952  
7              
8 124     124   580 use Carp;
  124         255  
  124         12778  
9 124     124   893 use Scalar::Util 'blessed';
  124         272  
  124         63967  
10              
11             our $VERSION = '0.92';
12             our $eps = 0.00001;
13              
14             use overload
15              
16             '+' => sub {
17 3     3   20 my ($x, $y, $swap) = @_;
18 3         8 $x -> add($y);
19             },
20              
21             '-' => sub {
22 6     6   47 my ($x, $y, $swap) = @_;
23 6 100       21 if ($swap) {
24 3 100 66     40 return $x -> neg() if !ref($y) && $y == 0;
25              
26 1         3 my $class = ref $x;
27 1         4 return $class -> new($y) -> sub($x);
28             }
29 3         9 $x -> sub($y);
30             },
31              
32             '*' => sub {
33 18     18   147 my ($x, $y, $swap) = @_;
34 18         45 $x -> mul($y);
35             },
36              
37             '**' => sub {
38 3     3   20 my ($x, $y, $swap) = @_;
39 3 100       8 if ($swap) {
40 1         3 my $class = ref $x;
41 1         4 return $class -> new($y) -> pow($x);
42             }
43 2         8 $x -> pow($y);
44             },
45              
46             '==' => sub {
47 2     2   17 my ($x, $y, $swap) = @_;
48 2         8 $x -> meq($y);
49             },
50              
51             '!=' => sub {
52 2     2   5695 my ($x, $y, $swap) = @_;
53 2         6 $x -> mne($y);
54             },
55              
56             'int' => sub {
57 2     2   13 my ($x, $y, $swap) = @_;
58 2         7 $x -> int();
59             },
60              
61             'abs' => sub {
62 1     1   9 my ($x, $y, $swap) = @_;
63 1         3 $x -> abs();
64             },
65              
66 124         2845 '~' => 'transpose',
67             '""' => 'as_string',
68 124     124   154198 '=' => 'clone';
  124         132732  
69              
70             =pod
71              
72             =encoding utf8
73              
74             =head1 NAME
75              
76             Math::Matrix - multiply and invert matrices
77              
78             =head1 SYNOPSIS
79              
80             use Math::Matrix;
81              
82             # Generate a random 3-by-3 matrix.
83             srand(time);
84             my $A = Math::Matrix -> new([rand, rand, rand],
85             [rand, rand, rand],
86             [rand, rand, rand]);
87             $A -> print("A\n");
88              
89             # Append a fourth column to $A.
90             my $x = Math::Matrix -> new([rand, rand, rand]);
91             my $E = $A -> concat($x -> transpose);
92             $E -> print("Equation system\n");
93              
94             # Compute the solution.
95             my $s = $E -> solve;
96             $s -> print("Solutions s\n");
97              
98             # Verify that the solution equals $x.
99             $A -> multiply($s) -> print("A*s\n");
100              
101             =head1 DESCRIPTION
102              
103             This module implements various constructors and methods for creating and
104             manipulating matrices.
105              
106             All methods return new objects, so, for example, C<$X-Eadd($Y)> does not
107             modify C<$X>.
108              
109             $X -> add($Y); # $X not modified; output is lost
110             $X = $X -> add($Y); # this works
111              
112             Some operators are overloaded (see L) and allow the operand to be
113             modified directly.
114              
115             $X = $X + $Y; # this works
116             $X += $Y; # so does this
117              
118             =head1 METHODS
119              
120             =head2 Constructors
121              
122             =over 4
123              
124             =item new()
125              
126             Creates a new object from the input arguments and returns it.
127              
128             If a single input argument is given, and that argument is a reference to array
129             whose first element is itself a reference to an array, it is assumed that the
130             argument contains the whole matrix, like this:
131              
132             $x = Math::Matrix->new([[1, 2, 3], [4, 5, 6]]); # 2-by-3 matrix
133             $x = Math::Matrix->new([[1, 2, 3]]); # 1-by-3 matrix
134             $x = Math::Matrix->new([[1], [2], [3]]); # 3-by-1 matrix
135              
136             If a single input argument is given, and that argument is not a reference to an
137             array, a 1-by-1 matrix is returned.
138              
139             $x = Math::Matrix->new(1); # 1-by-1 matrix
140              
141             Note that all the folling cases result in an empty matrix:
142              
143             $x = Math::Matrix->new([[], [], []]);
144             $x = Math::Matrix->new([[]]);
145             $x = Math::Matrix->new([]);
146              
147             If C> is called as an instance method with no input arguments, a zero
148             filled matrix with identical dimensions is returned:
149              
150             $b = $a->new(); # $b is a zero matrix with the size of $a
151              
152             Each row must contain the same number of elements.
153              
154             =cut
155              
156             sub new {
157 939     939 1 947630 my $that = shift;
158 939   66     4065 my $class = ref($that) || $that;
159 939         1619 my $self = [];
160              
161             # If called as an instance method and no arguments are given, return a
162             # zero matrix of the same size as the invocand.
163              
164 939 100 100     2904 if (ref($that) && (@_ == 0)) {
165 11         79 @$self = map [ (0) x @$_ ], @$that;
166             }
167              
168             # Otherwise return a new matrix based on the input arguments. The object
169             # data is a blessed reference to an array containing the matrix data. This
170             # array contains a list of arrays, one for each row, which in turn contains
171             # a list of elements. An empty matrix has no rows.
172             #
173             # [[ 1, 2, 3 ], [ 4, 5, 6 ]] 2-by-3 matrix
174             # [[ 1, 2, 3 ]] 1-by-3 matrix
175             # [[ 1 ], [ 2 ], [ 3 ]] 3-by-1 matrix
176             # [[ 1 ]] 1-by-1 matrix
177             # [] empty matrix
178              
179             else {
180              
181 928         1372 my $data;
182              
183             # If there is a single argument, and that is not a reference,
184             # assume new() has been called as, e.g., $class -> new(3).
185              
186 928 100 100     5915 if (@_ == 1 && !ref($_[0])) {
    100 66        
      100        
      100        
187 16         32 $data = [[ $_[0] ]];
188             }
189              
190             # If there is a single argument, and that is a reference to an array,
191             # and that array contains at least one element, and that element is
192             # itself a reference to an array, then assume new() has been called
193             # with the matrix as one argument, i.e., a reference to an array of
194             # arrays, e.g., $class -> new([ [1, 2], [3, 4] ]) ...
195              
196             elsif (@_ == 1 && ref($_[0]) eq 'ARRAY'
197 900         3853 && @{$_[0]} > 0 && ref($_[0][0]) eq 'ARRAY')
198             {
199 639         1073 $data = $_[0];
200             }
201              
202             # ... otherwise assume that each argument to new() is a row. Note that
203             # new() called with no arguments results in an empty matrix.
204              
205             else {
206 273         636 $data = [ @_ ];
207             }
208              
209             # Sanity checking.
210              
211 928 100       2209 if (@$data) {
212 927         1406 my $nrow = @$data;
213 927         1329 my $ncol;
214              
215 927         2731 for my $i (0 .. $nrow - 1) {
216 1818         2618 my $row = $data -> [$i];
217              
218             # Verify that the row is a reference to an array.
219              
220 1818 50       3562 croak "row with index $i is not a reference to an array"
221             unless ref($row) eq 'ARRAY';
222              
223             # In the first round, get the number of elements, i.e., the
224             # number of columns in the matrix. In the successive
225             # rounds, verify that each row has the same number of
226             # elements.
227              
228 1818 100       3115 if ($i == 0) {
229 927         1795 $ncol = @$row;
230             } else {
231 891 50       2001 croak "each row must have the same number of elements"
232             unless @$row == $ncol;
233             }
234             }
235              
236             # Copy the data into $self only if the matrix is non-emtpy.
237              
238 927 100       4135 @$self = map [ @$_ ], @$data if $ncol;
239             }
240             }
241              
242 939         2842 bless $self, $class;
243             }
244              
245             =pod
246              
247             =item new_from_sub()
248              
249             Creates a new matrix object by doing a subroutine call to create each element.
250              
251             $sub = sub { ... };
252             $x = Math::Matrix -> new_from_sub($sub); # 1-by-1
253             $x = Math::Matrix -> new_from_sub($sub, $m); # $m-by-$m
254             $x = Math::Matrix -> new_from_sub($sub, $m, $n); # $m-by-$n
255              
256             The subroutine is called in scalar context with two input arguments, the row and
257             column indices of the element to be created. Note that no checks are performed
258             on the output of the subroutine.
259              
260             Example 1, a 4-by-4 identity matrix can be created with
261              
262             $sub = sub { $_[0] == $_[1] ? 1 : 0 };
263             $x = Math::Matrix -> new_from_sub($sub, 4);
264              
265             Example 2, the code
266              
267             $x = Math::Matrix -> new_from_sub(sub { 2**$_[1] }, 1, 11);
268              
269             creates the following 1-by-11 vector with powers of two
270              
271             [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 ]
272              
273             Example 3, the code, using C<$i> and C<$j> for increased readability
274              
275             $sub = sub {
276             ($i, $j) = @_;
277             $d = $j - $i;
278             return $d == -1 ? 5
279             : $d == 0 ? 6
280             : $d == 1 ? 7
281             : 0;
282             };
283             $x = Math::Matrix -> new_from_sub($sub, 5);
284              
285             creates the tridiagonal matrix
286              
287             [ 6 7 0 0 0 ]
288             [ 5 6 7 0 0 ]
289             [ 0 5 6 7 0 ]
290             [ 0 0 5 6 7 ]
291             [ 0 0 0 5 6 ]
292              
293             =cut
294              
295             sub new_from_sub {
296 3 50   3 1 3484 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
297 3 50       8 croak "Too many arguments for ", (caller(0))[3] if @_ > 4;
298 3         7 my $class = shift;
299              
300 3 50       8 croak +(caller(0))[3], " is a class method, not an instance method"
301             if ref $class;
302              
303 3         6 my $sub = shift;
304 3 50       8 croak "The first input argument must be a code reference"
305             unless ref($sub) eq 'CODE';
306              
307 3 100       14 my ($nrow, $ncol) = @_ == 0 ? (1, 1)
    50          
308             : @_ == 1 ? (@_, @_)
309             : (@_);
310              
311 3         22 my $x = bless [], $class;
312 3         12 for my $i (0 .. $nrow - 1) {
313 10         40 for my $j (0 .. $ncol - 1) {
314 52         230 $x -> [$i][$j] = $sub -> ($i, $j);
315             }
316             }
317              
318 3         21 return $x;
319             }
320              
321             =pod
322              
323             =item new_from_rows()
324              
325             Creates a new matrix by assuming each argument is a row vector.
326              
327             $x = Math::Matrix -> new_from_rows($y, $z, ...);
328              
329             For example
330              
331             $x = Math::Matrix -> new_from_rows([1, 2, 3],[4, 5, 6]);
332              
333             returns the matrix
334              
335             [ 1 2 3 ]
336             [ 4 5 6 ]
337              
338             =cut
339              
340             sub new_from_rows {
341 2 50   2 1 86 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
342 2         4 my $class = shift;
343              
344 2 50       6 croak +(caller(0))[3], " is a class method, not an instance method"
345             if ref $class;
346              
347 2         4 my @args = ();
348 2         9 for (my $i = 0 ; $i <= $#_ ; ++$i) {
349 8         13 my $x = $_[$i];
350 8 50 33     34 $x = $class -> new($x)
351             unless defined(blessed($x)) && $x -> isa($class);
352 8 100       20 if ($x -> is_vector()) {
353 4         12 push @args, $x -> to_row();
354             } else {
355 4         9 push @args, $x;
356             }
357             }
358              
359 2         5 $class -> new([]) -> catrow(@args);
360             }
361              
362             =pod
363              
364             =item new_from_cols()
365              
366             Creates a matrix by assuming each argument is a column vector.
367              
368             $x = Math::Matrix -> new_from_cols($y, $z, ...);
369              
370             For example,
371              
372             $x = Math::Matrix -> new_from_cols([1, 2, 3],[4, 5, 6]);
373              
374             returns the matrix
375              
376             [ 1 4 ]
377             [ 2 5 ]
378             [ 3 6 ]
379              
380             =cut
381              
382             sub new_from_cols {
383 1 50   1 1 85 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
384 1         2 my $class = shift;
385              
386 1 50       3 croak +(caller(0))[3], " is a class method, not an instance method"
387             if ref $class;
388              
389 1         4 $class -> new_from_rows(@_) -> swaprc();
390             }
391              
392             =pod
393              
394             =item id()
395              
396             Returns a new identity matrix.
397              
398             $I = Math::Matrix -> id($n); # $n-by-$n identity matrix
399             $I = $x -> id($n); # $n-by-$n identity matrix
400             $I = $x -> id(); # identity matrix with size of $x
401              
402             =cut
403              
404             sub id {
405 87     87 1 8473 my $self = shift;
406 87         155 my $ref = ref $self;
407 87   66     285 my $class = $ref || $self;
408              
409 87         114 my $n;
410 87 100       168 if (@_) {
411 84         128 $n = shift;
412             } else {
413 3 50       6 if ($ref) {
414 3         8 my ($mx, $nx) = $self -> size();
415 3 50       9 croak "When id() is called as an instance method, the invocand",
416             " must be a square matrix" unless $mx == $nx;
417 3         6 $n = $mx;
418             } else {
419 0         0 croak "When id() is called as a class method, the size must be",
420             " given as an input argument";
421             }
422             }
423              
424 87         537 bless [ map [ (0) x ($_ - 1), 1, (0) x ($n - $_) ], 1 .. $n ], $class;
425             }
426              
427             =pod
428              
429             =item new_identity()
430              
431             This is an alias for C>.
432              
433             =cut
434              
435             sub new_identity {
436 14     14 1 8879 id(@_);
437             }
438              
439             =pod
440              
441             =item eye()
442              
443             This is an alias for C>.
444              
445             =cut
446              
447             sub eye {
448 6     6 1 8804 new_identity(@_);
449             }
450              
451             =pod
452              
453             =item exchg()
454              
455             Exchange matrix.
456              
457             $x = Math::Matrix -> exchg($n); # $n-by-$n exchange matrix
458              
459             =cut
460              
461             sub exchg {
462 5 50   5 1 5736 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
463 5 50       13 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
464 5         11 my $class = shift;
465              
466 5         6 my $n = shift;
467 5         41 bless [ map [ (0) x ($n - $_), 1, (0) x ($_ - 1) ], 1 .. $n ], $class;
468             }
469              
470             =pod
471              
472             =item scalar()
473              
474             Returns a scalar matrix, i.e., a diagonal matrix with all the diagonal elements
475             set to the same value.
476              
477             # Create an $m-by-$m scalar matrix where each element is $c.
478             $x = Math::Matrix -> scalar($c, $m);
479              
480             # Create an $m-by-$n scalar matrix where each element is $c.
481             $x = Math::Matrix -> scalar($c, $m, $n);
482              
483             Multiplying a matrix A by a scalar matrix B is effectively the same as multiply
484             each element in A by the constant on the diagonal of B.
485              
486             =cut
487              
488             sub scalar {
489 6 50   6 1 6702 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
490 6 50       17 croak "Too many arguments for ", (caller(0))[3] if @_ > 4;
491 6         13 my $class = shift;
492              
493 6 50       13 croak +(caller(0))[3], " is a class method, not an instance method"
494             if ref $class;
495              
496 6         7 my $c = shift;
497 6 100       24 my ($m, $n) = @_ == 0 ? (1, 1)
    100          
498             : @_ == 1 ? (@_, @_)
499             : (@_);
500 6 50       12 croak "The number of rows must be equal to the number of columns"
501             unless $m == $n;
502              
503 6         48 bless [ map [ (0) x ($_ - 1), $c, (0) x ($n - $_) ], 1 .. $m ], $class;
504             }
505              
506             =pod
507              
508             =item zeros()
509              
510             Create a zero matrix.
511              
512             # Create an $m-by-$m matrix where each element is 0.
513             $x = Math::Matrix -> zeros($m);
514              
515             # Create an $m-by-$n matrix where each element is 0.
516             $x = Math::Matrix -> zeros($m, $n);
517              
518             =cut
519              
520             sub zeros {
521 13 50   13 1 4696 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
522 13 50       29 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
523 13         20 my $self = shift;
524 13         48 $self -> constant(0, @_);
525             };
526              
527             =pod
528              
529             =item ones()
530              
531             Create a matrix of ones.
532              
533             # Create an $m-by-$m matrix where each element is 1.
534             $x = Math::Matrix -> ones($m);
535              
536             # Create an $m-by-$n matrix where each element is 1.
537             $x = Math::Matrix -> ones($m, $n);
538              
539             =cut
540              
541             sub ones {
542 5 50   5 1 4737 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
543 5 50       17 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
544 5         8 my $self = shift;
545 5         14 $self -> constant(1, @_);
546             };
547              
548             =pod
549              
550             =item inf()
551              
552             Create a matrix of positive infinities.
553              
554             # Create an $m-by-$m matrix where each element is Inf.
555             $x = Math::Matrix -> inf($m);
556              
557             # Create an $m-by-$n matrix where each element is Inf.
558             $x = Math::Matrix -> inf($m, $n);
559              
560             =cut
561              
562             sub inf {
563 5 50   5 1 19063 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
564 5 50       13 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
565 5         9 my $self = shift;
566              
567 5         32 require Math::Trig;
568 5         31 my $inf = Math::Trig::Inf();
569 5         24 $self -> constant($inf, @_);
570             };
571              
572             =pod
573              
574             =item nan()
575              
576             Create a matrix of NaNs (Not-a-Number).
577              
578             # Create an $m-by-$m matrix where each element is NaN.
579             $x = Math::Matrix -> nan($m);
580              
581             # Create an $m-by-$n matrix where each element is NaN.
582             $x = Math::Matrix -> nan($m, $n);
583              
584             =cut
585              
586             sub nan {
587 5 50   5 1 4705 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
588 5 50       16 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
589 5         9 my $self = shift;
590              
591 5         29 require Math::Trig;
592 5         15 my $inf = Math::Trig::Inf();
593 5         19 my $nan = $inf - $inf;
594 5         15 $self -> constant($nan, @_);
595             };
596              
597             =pod
598              
599             =item constant()
600              
601             Returns a constant matrix, i.e., a matrix whose elements all have the same
602             value.
603              
604             # Create an $m-by-$m matrix where each element is $c.
605             $x = Math::Matrix -> constant($c, $m);
606              
607             # Create an $m-by-$n matrix where each element is $c.
608             $x = Math::Matrix -> constant($c, $m, $n);
609              
610             =cut
611              
612             sub constant {
613 33 50   33 1 4662 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
614 33 50       64 croak "Too many arguments for ", (caller(0))[3] if @_ > 4;
615 33         54 my $class = shift;
616              
617 33 50       65 croak +(caller(0))[3], " is a class method, not an instance method"
618             if ref $class;
619              
620 33         44 my $c = shift;
621 33 100       107 my ($m, $n) = @_ == 0 ? (1, 1)
    100          
622             : @_ == 1 ? (@_, @_)
623             : (@_);
624              
625 33         256 bless [ map [ ($c) x $n ], 1 .. $m ], $class;
626             }
627              
628             =pod
629              
630             =item rand()
631              
632             Returns a matrix of uniformly distributed random numbers in the range [0,1).
633              
634             $x = Math::Matrix -> rand($m); # $m-by-$m matrix
635             $x = Math::Matrix -> rand($m, $n); # $m-by-$n matrix
636              
637             To generate an C<$m>-by-C<$n> matrix of uniformly distributed random numbers in
638             the range [0,C<$a>), use
639              
640             $x = $a * Math::Matrix -> rand($m, $n);
641              
642             To generate an C<$m>-by-C<$n> matrix of uniformly distributed random numbers in
643             the range [C<$a>,C<$b>), use
644              
645             $x = $a + ($b - $a) * Math::Matrix -> rand($m, $n);
646              
647             See also C> and C>.
648              
649             =cut
650              
651             sub rand {
652 6 50   6 1 12395 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
653 6 50       15 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
654 6         12 my $class = shift;
655              
656 6 50       12 croak +(caller(0))[3], " is a class method, not an instance method"
657             if ref $class;
658              
659 6 100       23 my ($nrow, $ncol) = @_ == 0 ? (1, 1)
    100          
660             : @_ == 1 ? (@_, @_)
661             : (@_);
662              
663 6         16 my $x = bless [], $class;
664 6         18 for my $i (0 .. $nrow - 1) {
665 10         17 for my $j (0 .. $ncol - 1) {
666 22         115 $x -> [$i][$j] = CORE::rand;
667             }
668             }
669              
670 6         15 return $x;
671             }
672              
673             =pod
674              
675             =item randi()
676              
677             Returns a matrix of uniformly distributed random integers.
678              
679             $x = Math::Matrix -> randi($max); # 1-by-1 matrix
680             $x = Math::Matrix -> randi($max, $n); # $n-by-$n matrix
681             $x = Math::Matrix -> randi($max, $m, $n); # $m-by-$n matrix
682              
683             $x = Math::Matrix -> randi([$min, $max]); # 1-by-1 matrix
684             $x = Math::Matrix -> randi([$min, $max], $n); # $n-by-$n matrix
685             $x = Math::Matrix -> randi([$min, $max], $m, $n); # $m-by-$n matrix
686              
687             See also C> and C>.
688              
689             =cut
690              
691             sub randi {
692 6 50   6 1 16544 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
693 6 50       15 croak "Too many arguments for ", (caller(0))[3] if @_ > 4;
694 6         12 my $class = shift;
695              
696 6 50       12 croak +(caller(0))[3], " is a class method, not an instance method"
697             if ref $class;
698              
699 6         11 my ($min, $max);
700 6         10 my $lim = shift;
701 6 100       16 if (ref($lim) eq 'ARRAY') {
702 3         6 ($min, $max) = @$lim;
703             } else {
704 3         4 $min = 0;
705 3         6 $max = $lim;
706             }
707              
708 6 100       21 my ($nrow, $ncol) = @_ == 0 ? (1, 1)
    100          
709             : @_ == 1 ? (@_, @_)
710             : (@_);
711              
712 6         11 my $c = $max - $min + 1;
713 6         13 my $x = bless [], $class;
714 6         17 for my $i (0 .. $nrow - 1) {
715 14         28 for my $j (0 .. $ncol - 1) {
716 50         167 $x -> [$i][$j] = $min + CORE::int(CORE::rand($c));
717             }
718             }
719              
720 6         19 return $x;
721             }
722              
723             =pod
724              
725             =item randn()
726              
727             Returns a matrix of random numbers from the standard normal distribution.
728              
729             $x = Math::Matrix -> randn($m); # $m-by-$m matrix
730             $x = Math::Matrix -> randn($m, $n); # $m-by-$n matrix
731              
732             To generate an C<$m>-by-C<$n> matrix with mean C<$mu> and standard deviation
733             C<$sigma>, use
734              
735             $x = $mu + $sigma * Math::Matrix -> randn($m, $n);
736              
737             See also C> and C>.
738              
739             =cut
740              
741             sub randn {
742 6 50   6 1 6536 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
743 6 50       17 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
744 6         8 my $class = shift;
745              
746 6 50       13 croak +(caller(0))[3], " is a class method, not an instance method"
747             if ref $class;
748              
749 6 100       22 my ($nrow, $ncol) = @_ == 0 ? (1, 1)
    100          
750             : @_ == 1 ? (@_, @_)
751             : (@_);
752              
753 6         13 my $nelm = $nrow * $ncol;
754 6         8 my $twopi = 2 * atan2 0, -1;
755              
756             # The following might generate one value more than we need.
757              
758 6         12 my $x = [];
759 6         15 for (my $k = 0 ; $k < $nelm ; $k += 2) {
760 13         84 my $c1 = sqrt(-2 * log(CORE::rand));
761 13         24 my $c2 = $twopi * CORE::rand;
762 13         76 push @$x, $c1 * cos($c2), $c1 * sin($c2);
763             }
764 6 100       15 pop @$x if @$x > $nelm;
765              
766 6         14 $x = bless [ $x ], $class;
767 6         18 $x -> reshape($nrow, $ncol);
768             }
769              
770             =pod
771              
772             =item clone()
773              
774             Clones a matrix and returns the clone.
775              
776             $b = $a->clone;
777              
778             =cut
779              
780             sub clone {
781 123 50   123 1 2482 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
782 123         198 my $x = shift;
783 123         224 my $class = ref $x;
784              
785 123 50       254 croak +(caller(0))[3], " is an instance method, not a class method"
786             unless $class;
787              
788 123         663 my $y = [ map [ @$_ ], @$x ];
789 123         299 bless $y, $class;
790             }
791              
792             =pod
793              
794             =item diagonal()
795              
796             A constructor method that creates a diagonal matrix from a single list or array
797             of numbers.
798              
799             $p = Math::Matrix->diagonal(1, 4, 4, 8);
800             $q = Math::Matrix->diagonal([1, 4, 4, 8]);
801              
802             The matrix is zero filled except for the diagonal members, which take the
803             values of the vector.
804              
805             The method returns B in case of error.
806              
807             =cut
808              
809             #
810             # Either class or object call, create a square matrix with the same
811             # dimensions as the passed-in list or array.
812             #
813             sub diagonal {
814 2     2 1 2600 my $that = shift;
815 2   33     12 my $class = ref($that) || $that;
816 2         5 my @diag = @_;
817 2         4 my $self = [];
818              
819             # diagonal([2,3]) -> diagonal(2,3)
820 2 100       7 @diag = @{$diag[0]} if (ref $diag[0] eq "ARRAY");
  1         3  
821              
822 2         4 my $len = scalar @diag;
823 2 50       5 return undef if ($len == 0);
824              
825 2         7 for my $idx (0..$len-1) {
826 8         13 my @r = (0) x $len;
827 8         13 $r[$idx] = $diag[$idx];
828 8         11 push(@{$self}, [@r]);
  8         17  
829             }
830 2         7 bless $self, $class;
831             }
832              
833             =pod
834              
835             =item tridiagonal()
836              
837             A constructor method that creates a matrix from vectors of numbers.
838              
839             $p = Math::Matrix->tridiagonal([1, 4, 4, 8]);
840             $q = Math::Matrix->tridiagonal([1, 4, 4, 8], [9, 12, 15]);
841             $r = Math::Matrix->tridiagonal([1, 4, 4, 8], [9, 12, 15], [4, 3, 2]);
842              
843             In the first case, the main diagonal takes the values of the vector, while both
844             of the upper and lower diagonals's values are all set to one.
845              
846             In the second case, the main diagonal takes the values of the first vector,
847             while the upper and lower diagonals are each set to the values of the second
848             vector.
849              
850             In the third case, the main diagonal takes the values of the first vector,
851             while the upper diagonal is set to the values of the second vector, and the
852             lower diagonal is set to the values of the third vector.
853              
854             The method returns B in case of error.
855              
856             =cut
857              
858             #
859             # Either class or object call, create a square matrix with the same
860             # dimensions as the passed-in list or array.
861             #
862             sub tridiagonal {
863 4     4 1 7747 my $that = shift;
864 4   33     19 my $class = ref($that) || $that;
865 4         7 my(@up_d, @main_d, @low_d);
866 4         7 my $self = [];
867              
868             #
869             # Handle the different ways the tridiagonal vectors could
870             # be passed in.
871             #
872 4 50       22 if (ref $_[0] eq "ARRAY") {
873 4         9 @main_d = @{$_[0]};
  4         9  
874              
875 4 100       11 if (ref $_[1] eq "ARRAY") {
876 3         5 @up_d = @{$_[1]};
  3         5  
877              
878 3 100       8 if (ref $_[2] eq "ARRAY") {
879 2         3 @low_d = @{$_[2]};
  2         3  
880             }
881             }
882             } else {
883 0         0 @main_d = @_;
884             }
885              
886 4         9 my $len = scalar @main_d;
887 4 50       9 return undef if ($len == 0);
888              
889             #
890             # Default the upper and lower diagonals if no vector
891             # was passed in for them.
892             #
893 4 100       12 @up_d = (1) x ($len -1) if (scalar @up_d == 0);
894 4 100       8 @low_d = @up_d if (scalar @low_d == 0);
895              
896             #
897             # First row...
898             #
899 4         10 my @arow = (0) x $len;
900 4         9 @arow[0..1] = ($main_d[0], $up_d[0]);
901 4         7 push (@{$self}, [@arow]);
  4         10  
902              
903             #
904             # Bulk of the matrix...
905             #
906 4         11 for my $idx (1 .. $#main_d - 1) {
907 8         16 my @r = (0) x $len;
908 8         20 @r[$idx-1 .. $idx+1] = ($low_d[$idx-1], $main_d[$idx], $up_d[$idx]);
909 8         11 push (@{$self}, [@r]);
  8         19  
910             }
911              
912             #
913             # Last row.
914             #
915 4         9 my @zrow = (0) x $len;
916 4         9 @zrow[$len-2..$len-1] = ($low_d[$#main_d -1], $main_d[$#main_d]);
917 4         7 push (@{$self}, [@zrow]);
  4         7  
918              
919 4         16 bless $self, $class;
920             }
921              
922             =pod
923              
924             =item blkdiag()
925              
926             Create block diagonal matrix. Returns a block diagonal matrix given a list of
927             matrices.
928              
929             $z = Math::Matrix -> blkdiag($x, $y, ...);
930              
931             =cut
932              
933             sub blkdiag {
934 4 50   4 1 4401 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
935             #croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
936 4         8 my $class = shift;
937              
938 4         7 my $y = [];
939 4         7 my $nrowy = 0;
940 4         6 my $ncoly = 0;
941              
942 4         13 for my $i (0 .. $#_) {
943 9         14 my $x = $_[$i];
944              
945 9 100 66     50 $x = $class -> new($x)
946             unless defined(blessed($x)) && $x -> isa($class);
947              
948 9         21 my ($nrowx, $ncolx) = $x -> size();
949              
950             # Upper right submatrix.
951              
952 9         18 for my $i (0 .. $nrowy - 1) {
953 9         17 for my $j (0 .. $ncolx - 1) {
954 11         20 $y -> [$i][$ncoly + $j] = 0;
955             }
956             }
957              
958             # Lower left submatrix.
959              
960 9         16 for my $i (0 .. $nrowx - 1) {
961 11         20 for my $j (0 .. $ncoly - 1) {
962 17         29 $y -> [$nrowy + $i][$j] = 0;
963             }
964             }
965              
966             # Lower right submatrix.
967              
968 9         16 for my $i (0 .. $nrowx - 1) {
969 11         18 for my $j (0 .. $ncolx - 1) {
970 13         28 $y -> [$nrowy + $i][$ncoly + $j] = $x -> [$i][$j];
971             }
972             }
973              
974 9         13 $nrowy += $nrowx;
975 9         20 $ncoly += $ncolx;
976             }
977              
978 4         12 bless $y, $class;
979             }
980              
981             =pod
982              
983             =back
984              
985             =head2 Identify matrices
986              
987             =over 4
988              
989             =item is_empty()
990              
991             Returns 1 is the invocand is empty, i.e., it has no elements.
992              
993             $bool = $x -> is_empty();
994              
995             =cut
996              
997             sub is_empty {
998 52 50   52 1 245 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
999 52 50       118 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1000 52         85 my $x = shift;
1001 52         121 return $x -> nelm() == 0;
1002             }
1003              
1004             =pod
1005              
1006             =item is_scalar()
1007              
1008             Returns 1 is the invocand is a scalar, i.e., it has one element.
1009              
1010             $bool = $x -> is_scalar();
1011              
1012             =cut
1013              
1014             sub is_scalar {
1015 99 50   99 1 243 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1016 99 50       200 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1017 99         147 my $x = shift;
1018 99 100       205 return $x -> nelm() == 1 ? 1 : 0;
1019             }
1020              
1021             =pod
1022              
1023             =item is_vector()
1024              
1025             Returns 1 is the invocand is a vector, i.e., a row vector or a column vector.
1026              
1027             $bool = $x -> is_vector();
1028              
1029             =cut
1030              
1031             sub is_vector {
1032 52 50   52 1 148 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1033 52 50       114 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1034 52         82 my $x = shift;
1035 52 100 100     117 return $x -> is_col() || $x -> is_row() ? 1 : 0;
1036             }
1037              
1038             =pod
1039              
1040             =item is_row()
1041              
1042             Returns 1 if the invocand has exactly one row, and 0 otherwise.
1043              
1044             $bool = $x -> is_row();
1045              
1046             =cut
1047              
1048             sub is_row {
1049 73 50   73 1 186 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1050 73 50       137 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1051 73         128 my $x = shift;
1052 73 100       154 return $x -> nrow() == 1 ? 1 : 0;
1053             }
1054              
1055             =pod
1056              
1057             =item is_col()
1058              
1059             Returns 1 if the invocand has exactly one column, and 0 otherwise.
1060              
1061             $bool = $x -> is_col();
1062              
1063             =cut
1064              
1065             sub is_col {
1066 81 50   81 1 191 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1067 81 50       163 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1068 81         119 my $x = shift;
1069 81 100       186 return $x -> ncol() == 1 ? 1 : 0;
1070             }
1071              
1072             =pod
1073              
1074             =item is_square()
1075              
1076             Returns 1 is the invocand is square, and 0 otherwise.
1077              
1078             $bool = $x -> is_square();
1079              
1080             =cut
1081              
1082             sub is_square {
1083 76 50   76 1 181 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1084 76 50       152 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1085 76         120 my $x = shift;
1086 76         166 my ($nrow, $ncol) = $x -> size();
1087 76 100       325 return $nrow == $ncol ? 1 : 0;
1088             }
1089              
1090             =pod
1091              
1092             =item is_symmetric()
1093              
1094             Returns 1 is the invocand is symmetric, and 0 otherwise.
1095              
1096             $bool = $x -> is_symmetric();
1097              
1098             An symmetric matrix satisfies x(i,j) = x(j,i) for all i and j, for example
1099              
1100             [ 1 2 -3 ]
1101             [ 2 -4 5 ]
1102             [ -3 5 6 ]
1103              
1104             =cut
1105              
1106             sub is_symmetric {
1107 50 50   50 1 130 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1108 50 50       110 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1109 50         82 my $x = shift;
1110              
1111 50         121 my ($nrow, $ncol) = $x -> size();
1112 50 100       133 return 0 unless $nrow == $ncol;
1113              
1114 44         127 for my $i (1 .. $nrow - 1) {
1115 100         155 for my $j (0 .. $i - 1) {
1116 232 100       553 return 0 unless $x -> [$i][$j] == $x -> [$j][$i];
1117             }
1118             }
1119              
1120 25         133 return 1;
1121             }
1122              
1123             =pod
1124              
1125             =item is_antisymmetric()
1126              
1127             Returns 1 is the invocand is antisymmetric a.k.a. skew-symmetric, and 0
1128             otherwise.
1129              
1130             $bool = $x -> is_antisymmetric();
1131              
1132             An antisymmetric matrix satisfies x(i,j) = -x(j,i) for all i and j, for
1133             example
1134              
1135             [ 0 2 -3 ]
1136             [ -2 0 4 ]
1137             [ 3 -4 0 ]
1138              
1139             =cut
1140              
1141             sub is_antisymmetric {
1142 25 50   25 1 91 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1143 25 50       61 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1144 25         55 my $x = shift;
1145              
1146 25         62 my ($nrow, $ncol) = $x -> size();
1147 25 100       78 return 0 unless $nrow == $ncol;
1148              
1149             # Check the diagonal.
1150              
1151 22         63 for my $i (0 .. $nrow - 1) {
1152 38 100       161 return 0 unless $x -> [$i][$i] == 0;
1153             }
1154              
1155             # Check the off-diagonal.
1156              
1157 5         27 for my $i (1 .. $nrow - 1) {
1158 5         13 for my $j (0 .. $i - 1) {
1159 6 100       25 return 0 unless $x -> [$i][$j] == -$x -> [$j][$i];
1160             }
1161             }
1162              
1163 2         8 return 1;
1164             }
1165              
1166             =pod
1167              
1168             =item is_persymmetric()
1169              
1170             Returns 1 is the invocand is persymmetric, and 0 otherwise.
1171              
1172             $bool = $x -> is_persymmetric();
1173              
1174             A persymmetric matrix is a square matrix which is symmetric with respect to the
1175             anti-diagonal, e.g.:
1176              
1177             [ f h j k ]
1178             [ c g i j ]
1179             [ b d g h ]
1180             [ a b c f ]
1181              
1182             =cut
1183              
1184             sub is_persymmetric {
1185 23 50   23 1 76 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1186 23 50       49 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1187 23         45 my $x = shift;
1188              
1189 23         62 $x -> fliplr() -> is_symmetric();
1190             }
1191              
1192             =pod
1193              
1194             =item is_hankel()
1195              
1196             Returns 1 is the invocand is a Hankel matric a.k.a. a catalecticant matrix, and
1197             0 otherwise.
1198              
1199             $bool = $x -> is_hankel();
1200              
1201             A Hankel matrix is a square matrix in which each ascending skew-diagonal from
1202             left to right is constant, e.g.:
1203              
1204             [ e f g h i ]
1205             [ d e f g h ]
1206             [ c d e f g ]
1207             [ b c d e f ]
1208             [ a b c d e ]
1209              
1210             =cut
1211              
1212             sub is_hankel {
1213 23 50   23 1 82 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1214 23 50       64 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1215 23         60 my $x = shift;
1216              
1217 23         66 my ($nrow, $ncol) = $x -> size();
1218 23 100       66 return 0 unless $nrow == $ncol;
1219              
1220             # Check the lower triangular part.
1221              
1222 20         59 for my $i (0 .. $nrow - 2) {
1223 34         48 my $first = $x -> [$i][0];
1224 34         60 for my $k (1 .. $nrow - $i - 1) {
1225 71 100       233 return 0 unless $x -> [$i + $k][$k] == $first;
1226             }
1227             }
1228              
1229             # Check the strictly upper triangular part.
1230              
1231 8         65 for my $j (1 .. $ncol - 2) {
1232 15         26 my $first = $x -> [0][$j];
1233 15         32 for my $k (1 .. $nrow - $j - 1) {
1234 33 100       72 return 0 unless $x -> [$k][$j + $k] == $first;
1235             }
1236             }
1237              
1238 7         33 return 1;
1239             }
1240              
1241             =pod
1242              
1243             =item is_zero()
1244              
1245             Returns 1 is the invocand is a zero matrix, and 0 otherwise. A zero matrix
1246             contains no element whose value is different from zero.
1247              
1248             $bool = $x -> is_zero();
1249              
1250             =cut
1251              
1252             sub is_zero {
1253 25 50   25 1 80 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1254 25 50       64 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1255 25         38 my $x = shift;
1256 25         63 return $x -> is_constant(0);
1257             }
1258              
1259             =pod
1260              
1261             =item is_one()
1262              
1263             Returns 1 is the invocand is a matrix of ones, and 0 otherwise. A matrix of
1264             ones contains no element whose value is different from one.
1265              
1266             $bool = $x -> is_one();
1267              
1268             =cut
1269              
1270             sub is_one {
1271 25 50   25 1 82 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1272 25 50       54 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1273 25         43 my $x = shift;
1274 25         64 return $x -> is_constant(1);
1275             }
1276              
1277             =pod
1278              
1279             =item is_constant()
1280              
1281             Returns 1 is the invocand is a constant matrix, and 0 otherwise. A constant
1282             matrix is a matrix where no two elements have different values.
1283              
1284             $bool = $x -> is_constant();
1285              
1286             =cut
1287              
1288             sub is_constant {
1289 75 50   75 1 211 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1290 75 50       150 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
1291 75         116 my $x = shift;
1292              
1293 75         171 my ($nrow, $ncol) = $x -> size();
1294              
1295             # An empty matrix contains no elements that are different from $c.
1296              
1297 75 100       179 return 1 if $nrow * $ncol == 0;
1298              
1299 72 100       151 my $c = @_ ? shift() : $x -> [0][0];
1300 72         177 for my $i (0 .. $nrow - 1) {
1301 78         129 for my $j (0 .. $ncol - 1) {
1302 147 100       826 return 0 if $x -> [$i][$j] != $c;
1303             }
1304             }
1305              
1306 3         19 return 1;
1307             }
1308              
1309             =pod
1310              
1311             =item is_identity()
1312              
1313             Returns 1 is the invocand is an identity matrix, and 0 otherwise. An
1314             identity matrix contains ones on the main diagonal and zeros elsewhere.
1315              
1316             $bool = $x -> is_identity();
1317              
1318             =cut
1319              
1320             sub is_identity {
1321 25 50   25 1 102 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1322 25 50       58 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1323 25         39 my $x = shift;
1324              
1325 25         60 my ($nrow, $ncol) = $x -> size();
1326 25 100       73 return 0 unless $nrow == $ncol;
1327              
1328 22         67 for my $i (0 .. $nrow - 1) {
1329 24         58 for my $j (0 .. $ncol - 1) {
1330 36 100       200 return 0 if $x -> [$i][$j] != ($i == $j ? 1 : 0);
    100          
1331             }
1332             }
1333              
1334 3         16 return 1;
1335             }
1336              
1337             =pod
1338              
1339             =item is_exchg()
1340              
1341             Returns 1 is the invocand is an exchange matrix, and 0 otherwise.
1342              
1343             $bool = $x -> is_exchg();
1344              
1345             An exchange matrix contains ones on the main anti-diagonal and zeros elsewhere,
1346             for example
1347              
1348             [ 0 0 1 ]
1349             [ 0 1 0 ]
1350             [ 1 0 0 ]
1351              
1352             =cut
1353              
1354             sub is_exchg {
1355 25 50   25 1 101 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1356 25 50       58 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1357 25         36 my $x = shift;
1358              
1359 25         61 my ($nrow, $ncol) = $x -> size();
1360 25 100       78 return 0 unless $nrow == $ncol;
1361              
1362 22         40 my $imax = $nrow - 1;
1363 22         64 for my $i (0 .. $nrow - 1) {
1364 23         42 for my $j (0 .. $ncol - 1) {
1365 47 100       230 return 0 if $x -> [$i][$j] != ($i + $j == $imax ? 1 : 0);
    100          
1366             }
1367             }
1368              
1369 3         24 return 1;
1370             }
1371              
1372             =pod
1373              
1374             =item is_bool()
1375              
1376             Returns 1 is the invocand is a boolean matrix, and 0 otherwise.
1377              
1378             $bool = $x -> is_bool();
1379              
1380             A boolean matrix is a matrix is a matrix whose entries are either 0 or 1, for
1381             example
1382              
1383             [ 0 1 1 ]
1384             [ 1 0 0 ]
1385             [ 0 1 0 ]
1386              
1387             =cut
1388              
1389             sub is_bool {
1390 25 50   25 1 83 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1391 25 50       50 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1392 25         44 my $x = shift;
1393              
1394 25         89 my ($nrow, $ncol) = $x -> size();
1395              
1396 25         76 for my $i (0 .. $nrow - 1) {
1397 34         65 for my $j (0 .. $ncol - 1) {
1398 80         116 my $val = $x -> [$i][$j];
1399 80 100 100     312 return 0 if $val != 0 && $val != 1;
1400             }
1401             }
1402              
1403 5         24 return 1;
1404             }
1405              
1406             =pod
1407              
1408             =item is_perm()
1409              
1410             Returns 1 is the invocand is an permutation matrix, and 0 otherwise.
1411              
1412             $bool = $x -> is_perm();
1413              
1414             A permutation matrix is a square matrix with exactly one 1 in each row and
1415             column, and all other elements 0, for example
1416              
1417             [ 0 1 0 ]
1418             [ 1 0 0 ]
1419             [ 0 0 1 ]
1420              
1421             =cut
1422              
1423             sub is_perm {
1424 25 50   25 1 81 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1425 25 50       65 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1426 25         42 my $x = shift;
1427              
1428 25         73 my ($nrow, $ncol) = $x -> size();
1429 25 100       84 return 0 unless $nrow == $ncol;
1430              
1431 22         74 my $rowsum = [ (0) x $nrow ];
1432 22         45 my $colsum = [ (0) x $ncol ];
1433              
1434 22         60 for my $i (0 .. $nrow - 1) {
1435 30         53 for my $j (0 .. $ncol - 1) {
1436 74         113 my $val = $x -> [$i][$j];
1437 74 100 100     271 return 0 if $val != 0 && $val != 1;
1438 57 100       117 if ($val == 1) {
1439 16 50       34 return 0 if ++$rowsum -> [$i] > 1;
1440 16 50       40 return 0 if ++$colsum -> [$j] > 1;
1441             }
1442             }
1443             }
1444              
1445 5         14 for my $i (0 .. $nrow - 1) {
1446 10 50       18 return 0 if $rowsum -> [$i] != 1;
1447 10 50       23 return 0 if $colsum -> [$i] != 1;
1448             }
1449              
1450 5         25 return 1;
1451             }
1452              
1453             =pod
1454              
1455             =item is_int()
1456              
1457             Returns 1 is the invocand is an integer matrix, i.e., a matrix of integers, and
1458             0 otherwise.
1459              
1460             $bool = $x -> is_int();
1461              
1462             =cut
1463              
1464             sub is_int {
1465 25 50   25 1 98 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1466 25 50       69 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1467 25         41 my $x = shift;
1468              
1469 25         62 my ($nrow, $ncol) = $x -> size();
1470              
1471 25         74 for my $i (0 .. $nrow - 1) {
1472 83         119 for my $j (0 .. $ncol - 1) {
1473 347 50       637 return 0 unless $x -> [$i][$j] == int $x -> [$i][$j];
1474             }
1475             }
1476              
1477 25         158 return 1;
1478             }
1479              
1480             =pod
1481              
1482             =item is_diag()
1483              
1484             Returns 1 is the invocand is diagonal, and 0 otherwise.
1485              
1486             $bool = $x -> is_diag();
1487              
1488             A diagonal matrix is a square matrix where all non-zero elements, if any, are on
1489             the main diagonal. It has the following pattern, where only the elements marked
1490             as C can be non-zero,
1491              
1492             [ x 0 0 0 0 ]
1493             [ 0 x 0 0 0 ]
1494             [ 0 0 x 0 0 ]
1495             [ 0 0 0 x 0 ]
1496             [ 0 0 0 0 x ]
1497              
1498             =cut
1499              
1500             sub is_diag {
1501 25 50   25 1 90 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1502 25 50       56 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1503 25         43 my $x = shift;
1504 25         58 $x -> is_band(0);
1505             }
1506              
1507             =pod
1508              
1509             =item is_adiag()
1510              
1511             Returns 1 is the invocand is anti-diagonal, and 0 otherwise.
1512              
1513             $bool = $x -> is_adiag();
1514              
1515             A diagonal matrix is a square matrix where all non-zero elements, if any, are on
1516             the main antidiagonal. It has the following pattern, where only the elements
1517             marked as C can be non-zero,
1518              
1519             [ 0 0 0 0 x ]
1520             [ 0 0 0 x 0 ]
1521             [ 0 0 x 0 0 ]
1522             [ 0 x 0 0 0 ]
1523             [ x 0 0 0 0 ]
1524              
1525             =cut
1526              
1527             sub is_adiag {
1528 25 50   25 1 85 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1529 25 50       59 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1530 25         45 my $x = shift;
1531 25         61 $x -> is_aband(0);
1532             }
1533              
1534             =pod
1535              
1536             =item is_tridiag()
1537              
1538             Returns 1 is the invocand is tridiagonal, and 0 otherwise.
1539              
1540             $bool = $x -> is_tridiag();
1541              
1542             A tridiagonal matrix is a square matrix with nonzero elements only on the
1543             diagonal and slots horizontally or vertically adjacent the diagonal (i.e., along
1544             the subdiagonal and superdiagonal). It has the following pattern, where only the
1545             elements marked as C can be non-zero,
1546              
1547             [ x x 0 0 0 ]
1548             [ x x x 0 0 ]
1549             [ 0 x x x 0 ]
1550             [ 0 0 x x x ]
1551             [ 0 0 0 x x ]
1552              
1553             =cut
1554              
1555             sub is_tridiag {
1556 25 50   25 1 83 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1557 25 50       61 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1558 25         42 my $x = shift;
1559 25         54 $x -> is_band(1);
1560             }
1561              
1562             =pod
1563              
1564             =item is_atridiag()
1565              
1566             Returns 1 is the invocand is anti-tridiagonal, and 0 otherwise.
1567              
1568             $bool = $x -> is_tridiag();
1569              
1570             A anti-tridiagonal matrix is a square matrix with nonzero elements only on the
1571             anti-diagonal and slots horizontally or vertically adjacent the diagonal (i.e.,
1572             along the anti-subdiagonal and anti-superdiagonal). It has the following
1573             pattern, where only the elements marked as C can be non-zero,
1574              
1575             [ 0 0 0 x x ]
1576             [ 0 0 x x x ]
1577             [ 0 x x x 0 ]
1578             [ x x x 0 0 ]
1579             [ x x 0 0 0 ]
1580              
1581             =cut
1582              
1583             sub is_atridiag {
1584 25 50   25 1 84 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1585 25 50       51 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1586 25         39 my $x = shift;
1587 25         61 $x -> is_aband(1);
1588             }
1589              
1590             =pod
1591              
1592             =item is_pentadiag()
1593              
1594             Returns 1 is the invocand is pentadiagonal, and 0 otherwise.
1595              
1596             $bool = $x -> is_pentadiag();
1597              
1598             A pentadiagonal matrix is a square matrix with nonzero elements only on the
1599             diagonal and the two diagonals above and below the main diagonal. It has the
1600             following pattern, where only the elements marked as C can be non-zero,
1601              
1602             [ x x x 0 0 0 ]
1603             [ x x x x 0 0 ]
1604             [ x x x x x 0 ]
1605             [ 0 x x x x x ]
1606             [ 0 0 x x x x ]
1607             [ 0 0 0 x x x ]
1608              
1609             =cut
1610              
1611             sub is_pentadiag {
1612 25 50   25 1 76 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1613 25 50       65 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1614 25         39 my $x = shift;
1615 25         58 $x -> is_band(2);
1616             }
1617              
1618             =pod
1619              
1620             =item is_apentadiag()
1621              
1622             Returns 1 is the invocand is anti-pentadiagonal, and 0 otherwise.
1623              
1624             $bool = $x -> is_pentadiag();
1625              
1626             A anti-pentadiagonal matrix is a square matrix with nonzero elements only on the
1627             anti-diagonal and two anti-diagonals above and below the main anti-diagonal. It
1628             has the following pattern, where only the elements marked as C can be
1629             non-zero,
1630              
1631             [ 0 0 0 x x x ]
1632             [ 0 0 x x x x ]
1633             [ 0 x x x x x ]
1634             [ x x x x x 0 ]
1635             [ x x x x 0 0 ]
1636             [ x x x 0 0 0 ]
1637              
1638             =cut
1639              
1640             sub is_apentadiag {
1641 25 50   25 1 86 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1642 25 50       56 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1643 25         42 my $x = shift;
1644 25         60 $x -> is_aband(2);
1645             }
1646              
1647             =pod
1648              
1649             =item is_heptadiag()
1650              
1651             Returns 1 is the invocand is heptadiagonal, and 0 otherwise.
1652              
1653             $bool = $x -> is_heptadiag();
1654              
1655             A heptadiagonal matrix is a square matrix with nonzero elements only on the
1656             diagonal and the two diagonals above and below the main diagonal. It has the
1657             following pattern, where only the elements marked as C can be non-zero,
1658              
1659             [ x x x x 0 0 ]
1660             [ x x x x x 0 ]
1661             [ x x x x x x ]
1662             [ x x x x x x ]
1663             [ 0 x x x x x ]
1664             [ 0 0 x x x x ]
1665              
1666             =cut
1667              
1668             sub is_heptadiag {
1669 25 50   25 1 90 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1670 25 50       52 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1671 25         42 my $x = shift;
1672 25         56 $x -> is_band(3);
1673             }
1674              
1675             =pod
1676              
1677             =item is_aheptadiag()
1678              
1679             Returns 1 is the invocand is anti-heptadiagonal, and 0 otherwise.
1680              
1681             $bool = $x -> is_heptadiag();
1682              
1683             A anti-heptadiagonal matrix is a square matrix with nonzero elements only on the
1684             anti-diagonal and two anti-diagonals above and below the main anti-diagonal. It
1685             has the following pattern, where only the elements marked as C can be
1686             non-zero,
1687              
1688             [ 0 0 x x x x ]
1689             [ 0 x x x x x ]
1690             [ x x x x x x ]
1691             [ x x x x x x ]
1692             [ x x x x x 0 ]
1693             [ x x x x 0 0 ]
1694              
1695             =cut
1696              
1697             sub is_aheptadiag {
1698 25 50   25 1 80 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1699 25 50       58 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1700 25         40 my $x = shift;
1701 25         64 $x -> is_aband(3);
1702             }
1703              
1704             =pod
1705              
1706             =item is_band()
1707              
1708             Returns 1 is the invocand is a band matrix with a specified bandwidth, and 0
1709             otherwise.
1710              
1711             $bool = $x -> is_band($k);
1712              
1713             A band matrix is a square matrix with nonzero elements only on the diagonal and
1714             on the C<$k> diagonals above and below the main diagonal. The bandwidth C<$k>
1715             must be non-negative.
1716              
1717             $bool = $x -> is_band(0); # is $x diagonal?
1718             $bool = $x -> is_band(1); # is $x tridiagonal?
1719             $bool = $x -> is_band(2); # is $x pentadiagonal?
1720             $bool = $x -> is_band(3); # is $x heptadiagonal?
1721              
1722             See also C> and C>.
1723              
1724             =cut
1725              
1726             sub is_band {
1727 225 50   225 1 552 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
1728 225 50       402 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
1729 225         331 my $x = shift;
1730 225         374 my $class = ref $x;
1731              
1732 225         475 my ($nrow, $ncol) = $x -> size();
1733 225 100       612 return 0 unless $nrow == $ncol; # must be square
1734              
1735 198         332 my $k = shift; # bandwidth
1736 198 50       425 croak "Bandwidth can not be undefined" unless defined $k;
1737 198 50       363 if (ref $k) {
1738 0 0 0     0 $k = $class -> new($k)
1739             unless defined(blessed($k)) && $k -> isa($class);
1740 0 0       0 croak "Bandwidth must be a scalar" unless $k -> is_scalar();
1741 0         0 $k = $k -> [0][0];
1742             }
1743              
1744 198 100       639 return 0 if $nrow <= $k; # if the band doesn't fit inside
1745 136 100       416 return 1 if $nrow == $k + 1; # if the whole band fits exactly
1746              
1747 106         271 for my $i (0 .. $nrow - $k - 2) {
1748 130         247 for my $j ($k + 1 + $i .. $ncol - 1) {
1749 188 100 100     1048 return 0 if ($x -> [$i][$j] != 0 ||
1750             $x -> [$j][$i] != 0);
1751             }
1752             }
1753              
1754 23         159 return 1;
1755             }
1756              
1757             =pod
1758              
1759             =item is_aband()
1760              
1761             Returns 1 is the invocand is "anti-banded" with a specified bandwidth, and 0
1762             otherwise.
1763              
1764             $bool = $x -> is_aband($k);
1765              
1766             Some examples
1767              
1768             $bool = $x -> is_aband(0); # is $x anti-diagonal?
1769             $bool = $x -> is_aband(1); # is $x anti-tridiagonal?
1770             $bool = $x -> is_aband(2); # is $x anti-pentadiagonal?
1771             $bool = $x -> is_aband(3); # is $x anti-heptadiagonal?
1772              
1773             A band matrix is a square matrix with nonzero elements only on the diagonal and
1774             on the C<$k> diagonals above and below the main diagonal. The bandwidth C<$k>
1775             must be non-negative.
1776              
1777             A "anti-banded" matrix is a square matrix with nonzero elements only on the
1778             anti-diagonal and C<$k> anti-diagonals above and below the main anti-diagonal.
1779              
1780             See also C> and C>.
1781              
1782             =cut
1783              
1784             sub is_aband {
1785 225 50   225 1 592 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
1786 225 50       435 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
1787 225         374 my $x = shift;
1788 225         382 my $class = ref $x;
1789              
1790 225         504 my ($nrow, $ncol) = $x -> size();
1791 225 100       563 return 0 unless $nrow == $ncol; # must be square
1792              
1793 198         314 my $k = shift; # bandwidth
1794 198 50       367 croak "Bandwidth can not be undefined" unless defined $k;
1795 198 50       354 if (ref $k) {
1796 0 0 0     0 $k = $class -> new($k)
1797             unless defined(blessed($k)) && $k -> isa($class);
1798 0 0       0 croak "Bandwidth must be a scalar" unless $k -> is_scalar();
1799 0         0 $k = $k -> [0][0];
1800             }
1801              
1802 198 100       809 return 0 if $nrow <= $k; # if the band doesn't fit inside
1803 136 100       402 return 1 if $nrow == $k + 1; # if the whole band fits exactly
1804              
1805             # Check upper part.
1806              
1807 106         273 for my $i (0 .. $nrow - $k - 2) {
1808 134         227 for my $j (0 .. $nrow - $k - 2 - $i) {
1809 210 100       821 return 0 if $x -> [$i][$j] != 0;
1810             }
1811             }
1812              
1813             # Check lower part.
1814              
1815 35         81 for my $i ($k + 1 .. $nrow - 1) {
1816 57         99 for my $j ($nrow - $i + $k .. $nrow - 1) {
1817 89 100       209 return 0 if $x -> [$i][$j] != 0;
1818             }
1819             }
1820              
1821 27         128 return 1;
1822             }
1823              
1824             =pod
1825              
1826             =item is_triu()
1827              
1828             Returns 1 is the invocand is upper triangular, and 0 otherwise.
1829              
1830             $bool = $x -> is_triu();
1831              
1832             An upper triangular matrix is a square matrix where all non-zero elements are on
1833             or above the main diagonal. It has the following pattern, where only the
1834             elements marked as C can be non-zero. It has the following pattern, where
1835             only the elements marked as C can be non-zero,
1836              
1837             [ x x x x ]
1838             [ 0 x x x ]
1839             [ 0 0 x x ]
1840             [ 0 0 0 x ]
1841              
1842             =cut
1843              
1844             sub is_triu {
1845 25 50   25 1 76 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1846 25 50       63 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1847 25         39 my $x = shift;
1848              
1849 25         69 my $nrow = $x -> nrow();
1850 25         58 my $ncol = $x -> ncol();
1851              
1852 25 100       74 return 0 unless $nrow == $ncol;
1853              
1854 22         64 for my $i (1 .. $nrow - 1) {
1855 30         53 for my $j (0 .. $i - 1) {
1856 37 100       153 return 0 unless $x -> [$i][$j] == 0;
1857             }
1858             }
1859              
1860 6         31 return 1;
1861             }
1862              
1863             =pod
1864              
1865             =item is_striu()
1866              
1867             Returns 1 is the invocand is strictly upper triangular, and 0 otherwise.
1868              
1869             $bool = $x -> is_striu();
1870              
1871             A strictly upper triangular matrix is a square matrix where all non-zero
1872             elements are strictly above the main diagonal. It has the following pattern,
1873             where only the elements marked as C can be non-zero,
1874              
1875             [ 0 x x x ]
1876             [ 0 0 x x ]
1877             [ 0 0 0 x ]
1878             [ 0 0 0 0 ]
1879              
1880             =cut
1881              
1882             sub is_striu {
1883 25 50   25 1 86 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1884 25 50       57 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1885 25         42 my $x = shift;
1886              
1887 25         60 my $nrow = $x -> nrow();
1888 25         66 my $ncol = $x -> ncol();
1889              
1890 25 100       73 return 0 unless $nrow == $ncol;
1891              
1892 22         61 for my $i (0 .. $nrow - 1) {
1893 36         92 for my $j (0 .. $i) {
1894 50 100       204 return 0 unless $x -> [$i][$j] == 0;
1895             }
1896             }
1897              
1898 2         18 return 1;
1899             }
1900              
1901             =pod
1902              
1903             =item is_tril()
1904              
1905             Returns 1 is the invocand is lower triangular, and 0 otherwise.
1906              
1907             $bool = $x -> is_tril();
1908              
1909             A lower triangular matrix is a square matrix where all non-zero elements are on
1910             or below the main diagonal. It has the following pattern, where only the
1911             elements marked as C can be non-zero,
1912              
1913             [ x 0 0 0 ]
1914             [ x x 0 0 ]
1915             [ x x x 0 ]
1916             [ x x x x ]
1917              
1918             =cut
1919              
1920             sub is_tril {
1921 25 50   25 1 83 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1922 25 50       52 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1923 25         52 my $x = shift;
1924              
1925 25         60 my $nrow = $x -> nrow();
1926 25         58 my $ncol = $x -> ncol();
1927              
1928 25 100       76 return 0 unless $nrow == $ncol;
1929              
1930 22         72 for my $i (0 .. $nrow - 1) {
1931 28         61 for my $j ($i + 1 .. $ncol - 1) {
1932 35 100       153 return 0 unless $x -> [$i][$j] == 0;
1933             }
1934             }
1935              
1936 6         28 return 1;
1937             }
1938              
1939             =pod
1940              
1941             =item is_stril()
1942              
1943             Returns 1 is the invocand is strictly lower triangular, and 0 otherwise.
1944              
1945             $bool = $x -> is_stril();
1946              
1947             A strictly lower triangular matrix is a square matrix where all non-zero
1948             elements are strictly below the main diagonal. It has the following pattern,
1949             where only the elements marked as C can be non-zero,
1950              
1951             [ 0 0 0 0 ]
1952             [ x 0 0 0 ]
1953             [ x x 0 0 ]
1954             [ x x x 0 ]
1955              
1956             =cut
1957              
1958             sub is_stril {
1959 25 50   25 1 75 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1960 25 50       53 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1961 25         42 my $x = shift;
1962              
1963 25         63 my $nrow = $x -> nrow();
1964 25         55 my $ncol = $x -> ncol();
1965              
1966 25 100       70 return 0 unless $nrow == $ncol;
1967              
1968 22         83 for my $i (0 .. $nrow - 1) {
1969 24         48 for my $j ($i .. $ncol - 1) {
1970 46 100       175 return 0 unless $x -> [$i][$j] == 0;
1971             }
1972             }
1973              
1974 2         13 return 1;
1975             }
1976              
1977             =pod
1978              
1979             =item is_atriu()
1980              
1981             Returns 1 is the invocand is upper anti-triangular, and 0 otherwise.
1982              
1983             $bool = $x -> is_atriu();
1984              
1985             An upper anti-triangular matrix is a square matrix where all non-zero elements
1986             are on or above the main anti-diagonal. It has the following pattern, where only
1987             the elements marked as C can be non-zero,
1988              
1989             [ x x x x ]
1990             [ x x x 0 ]
1991             [ x x 0 0 ]
1992             [ x 0 0 0 ]
1993              
1994             =cut
1995              
1996             sub is_atriu {
1997 25 50   25 1 77 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1998 25 50       66 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1999 25         41 my $x = shift;
2000              
2001 25         59 my $nrow = $x -> nrow();
2002 25         54 my $ncol = $x -> ncol();
2003              
2004 25 100       66 return 0 unless $nrow == $ncol;
2005              
2006 22         64 for my $i (1 .. $nrow - 1) {
2007 29         68 for my $j ($ncol - $i .. $ncol - 1) {
2008 34 100       148 return 0 unless $x -> [$i][$j] == 0;
2009             }
2010             }
2011              
2012 6         50 return 1;
2013             }
2014              
2015             =pod
2016              
2017             =item is_satriu()
2018              
2019             Returns 1 is the invocand is strictly upper anti-triangular, and 0 otherwise.
2020              
2021             $bool = $x -> is_satriu();
2022              
2023             A strictly anti-triangular matrix is a square matrix where all non-zero elements
2024             are strictly above the main diagonal. It has the following pattern, where only
2025             the elements marked as C can be non-zero,
2026              
2027             [ x x x 0 ]
2028             [ x x 0 0 ]
2029             [ x 0 0 0 ]
2030             [ 0 0 0 0 ]
2031              
2032             =cut
2033              
2034             sub is_satriu {
2035 25 50   25 1 81 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2036 25 50       60 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2037 25         40 my $x = shift;
2038              
2039 25         68 my $nrow = $x -> nrow();
2040 25         52 my $ncol = $x -> ncol();
2041              
2042 25 100       76 return 0 unless $nrow == $ncol;
2043              
2044 22         65 for my $i (0 .. $nrow - 1) {
2045 34         77 for my $j ($ncol - $i - 1 .. $ncol - 1) {
2046 42 100       185 return 0 unless $x -> [$i][$j] == 0;
2047             }
2048             }
2049              
2050 2         12 return 1;
2051             }
2052              
2053             =pod
2054              
2055             =item is_atril()
2056              
2057             Returns 1 is the invocand is lower anti-triangular, and 0 otherwise.
2058              
2059             $bool = $x -> is_atril();
2060              
2061             A lower anti-triangular matrix is a square matrix where all non-zero elements
2062             are on or below the main anti-diagonal. It has the following pattern, where only
2063             the elements marked as C can be non-zero,
2064              
2065             [ 0 0 0 x ]
2066             [ 0 0 x x ]
2067             [ 0 x x x ]
2068             [ x x x x ]
2069              
2070             =cut
2071              
2072             sub is_atril {
2073 25 50   25 1 83 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2074 25 50       64 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2075 25         47 my $x = shift;
2076              
2077 25         58 my $nrow = $x -> nrow();
2078 25         49 my $ncol = $x -> ncol();
2079              
2080 25 100       60 return 0 unless $nrow == $ncol;
2081              
2082 22         96 for my $i (0 .. $nrow - 1) {
2083 28         51 for my $j (0 .. $ncol - $i - 2) {
2084 39 100       159 return 0 unless $x -> [$i][$j] == 0;
2085             }
2086             }
2087              
2088 6         35 return 1;
2089             }
2090              
2091             =pod
2092              
2093             =item is_satril()
2094              
2095             Returns 1 is the invocand is strictly lower anti-triangular, and 0 otherwise.
2096              
2097             $bool = $x -> is_satril();
2098              
2099             A strictly lower anti-triangular matrix is a square matrix where all non-zero
2100             elements are strictly below the main anti-diagonal. It has the following
2101             pattern, where only the elements marked as C can be non-zero,
2102              
2103             [ 0 0 0 0 ]
2104             [ 0 0 0 x ]
2105             [ 0 0 x x ]
2106             [ 0 x x x ]
2107              
2108             =cut
2109              
2110             sub is_satril {
2111 25 50   25 1 81 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2112 25 50       58 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2113 25         41 my $x = shift;
2114              
2115 25         61 my $nrow = $x -> nrow();
2116 25         55 my $ncol = $x -> ncol();
2117              
2118 25 100       78 return 0 unless $nrow == $ncol;
2119              
2120 22         63 for my $i (0 .. $nrow - 1) {
2121 24         43 for my $j (0 .. $ncol - $i - 1) {
2122 45 100       188 return 0 unless $x -> [$i][$j] == 0;
2123             }
2124             }
2125              
2126 2         10 return 1;
2127             }
2128              
2129             =pod
2130              
2131             =back
2132              
2133             =head2 Identify elements
2134              
2135             This section contains methods for identifying and locating elements within an
2136             array. See also C>.
2137              
2138             =over 4
2139              
2140             =item find()
2141              
2142             Returns the location of each non-zero element.
2143              
2144             $K = $x -> find(); # linear index
2145             ($I, $J) = $x -> find(); # subscripts
2146              
2147             For example, to find the linear index of each element that is greater than or
2148             equal to 1, use
2149              
2150             $K = $x -> sge(1) -> find();
2151              
2152             =cut
2153              
2154             sub find {
2155 4 50   4 1 35 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2156 4 50       10 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2157 4         6 my $x = shift;
2158              
2159 4         10 my ($m, $n) = $x -> size();
2160              
2161 4         7 my $I = [];
2162 4         5 my $J = [];
2163 4         9 for my $j (0 .. $n - 1) {
2164 6         13 for my $i (0 .. $m - 1) {
2165 12 100       21 next unless $x->[$i][$j];
2166 10         17 push @$I, $i;
2167 10         14 push @$J, $j;
2168             }
2169             }
2170              
2171 4 100       27 return $I, $J if wantarray;
2172              
2173 2         7 my $K = [ map { $m * $J -> [$_] + $I -> [$_] } 0 .. $#$I ];
  5         11  
2174 2         5 return $K;
2175             }
2176              
2177             =pod
2178              
2179             =item is_finite()
2180              
2181             Returns a matrix of ones and zeros. The element is one if the corresponding
2182             element in the invocand matrix is finite, and zero otherwise.
2183              
2184             $y = $x -> is_finite();
2185              
2186             =cut
2187              
2188             sub is_finite {
2189 2 50   2 1 14 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2190 2 50       6 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2191 2         3 my $x = shift;
2192              
2193 2         13 require Math::Trig;
2194 2         6 my $pinf = Math::Trig::Inf(); # positiv infinity
2195 2         8 my $ninf = -$pinf; # negative infinity
2196              
2197 2         6 bless [ map { [
2198             map {
2199 2 100 100     13 $ninf < $_ && $_ < $pinf ? 1 : 0
  6         30  
2200             } @$_
2201             ] } @$x ], ref $x;
2202             }
2203              
2204             =pod
2205              
2206             =item is_inf()
2207              
2208             Returns a matrix of ones and zeros. The element is one if the corresponding
2209             element in the invocand matrix is positive or negative infinity, and zero
2210             otherwise.
2211              
2212             $y = $x -> is_inf();
2213              
2214             =cut
2215              
2216             sub is_inf {
2217 2 50   2 1 12 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2218 2 50       7 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2219 2         4 my $x = shift;
2220              
2221 2         10 require Math::Trig;
2222 2         20 my $pinf = Math::Trig::Inf(); # positiv infinity
2223 2         10 my $ninf = -$pinf; # negative infinity
2224              
2225 2         7 bless [ map { [
2226             map {
2227 2 100 100     3 $_ == $pinf || $_ == $ninf ? 1 : 0;
  6         26  
2228             } @$_
2229             ] } @$x ], ref $x;
2230             }
2231              
2232             =pod
2233              
2234             =item is_nan()
2235              
2236             Returns a matrix of ones and zeros. The element is one if the corresponding
2237             element in the invocand matrix is a NaN (Not-a-Number), and zero otherwise.
2238              
2239             $y = $x -> is_nan();
2240              
2241             =cut
2242              
2243             sub is_nan {
2244 2 50   2 1 13 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2245 2 50       6 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2246 2         3 my $x = shift;
2247              
2248 2 100       6 bless [ map [ map { $_ != $_ ? 1 : 0 } @$_ ], @$x ], ref $x;
  6         20  
2249             }
2250              
2251             =pod
2252              
2253             =item all()
2254              
2255             Tests whether all of the elements along various dimensions of a matrix are
2256             non-zero. If the dimension argument is not given, the first non-singleton
2257             dimension is used.
2258              
2259             $y = $x -> all($dim);
2260             $y = $x -> all();
2261              
2262             =cut
2263              
2264             sub all {
2265 12 50   12 1 87 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2266 12 50       27 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
2267 12         16 my $x = shift;
2268 12         41 $x -> apply(\&_all, @_);
2269             }
2270              
2271             =pod
2272              
2273             =item any()
2274              
2275             Tests whether any of the elements along various dimensions of a matrix are
2276             non-zero. If the dimension argument is not given, the first non-singleton
2277             dimension is used.
2278              
2279             $y = $x -> any($dim);
2280             $y = $x -> any();
2281              
2282             =cut
2283              
2284             sub any {
2285 12 50   12 1 91 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2286 12 50       24 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
2287 12         21 my $x = shift;
2288 12         40 $x -> apply(\&_any, @_);
2289             }
2290              
2291             =pod
2292              
2293             =item cumall()
2294              
2295             A cumulative variant of C>. If the dimension argument is not given,
2296             the first non-singleton dimension is used.
2297              
2298             $y = $x -> cumall($dim);
2299             $y = $x -> cumall();
2300              
2301             =cut
2302              
2303             sub cumall {
2304 12 50   12 1 79 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2305 12 50       25 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
2306 12         19 my $x = shift;
2307 12         39 $x -> apply(\&_cumall, @_);
2308             }
2309              
2310             =pod
2311              
2312             =item cumany()
2313              
2314             A cumulative variant of C>. If the dimension argument is not given,
2315             the first non-singleton dimension is used.
2316              
2317             $y = $x -> cumany($dim);
2318             $y = $x -> cumany();
2319              
2320             =cut
2321              
2322             sub cumany {
2323 12 50   12 1 78 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2324 12 50       25 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
2325 12         18 my $x = shift;
2326 12         38 $x -> apply(\&_cumany, @_);
2327             }
2328              
2329             =pod
2330              
2331             =back
2332              
2333             =head2 Basic properties
2334              
2335             =over 4
2336              
2337             =item size()
2338              
2339             You can determine the dimensions of a matrix by calling:
2340              
2341             ($m, $n) = $a -> size;
2342              
2343             =cut
2344              
2345             sub size {
2346 2071     2071 1 718813 my $self = shift;
2347 2071         2779 my $m = @{$self};
  2071         6214  
2348 2071 100       4344 my $n = $m ? @{$self->[0]} : 0;
  1902         3225  
2349 2071         5211 ($m, $n);
2350             }
2351              
2352             =pod
2353              
2354             =item nelm()
2355              
2356             Returns the number of elements in the matrix.
2357              
2358             $n = $x -> nelm();
2359              
2360             =cut
2361              
2362             sub nelm {
2363 177 50   177 1 1285 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2364 177 50       344 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2365 177         268 my $x = shift;
2366 177 100       713 return @$x ? @$x * @{$x->[0]} : 0;
  150         771  
2367             }
2368              
2369             =pod
2370              
2371             =item nrow()
2372              
2373             Returns the number of rows.
2374              
2375             $m = $x -> nrow();
2376              
2377             =cut
2378              
2379             sub nrow {
2380 635 50   635 1 7052 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2381 635 50       1209 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2382 635         855 my $x = shift;
2383 635         1576 return scalar @$x;
2384             }
2385              
2386             =pod
2387              
2388             =item ncol()
2389              
2390             Returns the number of columns.
2391              
2392             $n = $x -> ncol();
2393              
2394             =cut
2395              
2396             sub ncol {
2397 576 50   576 1 2128 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2398 576 50       1059 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2399 576         778 my $x = shift;
2400 576 100       1683 return @$x ? scalar(@{$x->[0]}) : 0;
  529         1324  
2401             }
2402              
2403             =pod
2404              
2405             =item npag()
2406              
2407             Returns the number of pages. A non-matrix has one page.
2408              
2409             $n = $x -> pag();
2410              
2411             =cut
2412              
2413             sub npag {
2414 6 50   6 1 900 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2415 6 50       14 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2416 6         10 my $x = shift;
2417 6 100       30 return @$x ? 1 : 0;
2418             }
2419              
2420             =pod
2421              
2422             =item ndim()
2423              
2424             Returns the number of dimensions. This is the number of dimensions along which
2425             the length is different from one.
2426              
2427             $n = $x -> ndim();
2428              
2429             =cut
2430              
2431             sub ndim {
2432 6 50   6 1 1010 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2433 6 50       15 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2434 6         10 my $x = shift;
2435 6         14 my ($nrow, $ncol) = $x -> size();
2436 6         10 my $ndim = 0;
2437 6 100       12 ++$ndim if $nrow != 1;
2438 6 100       11 ++$ndim if $ncol != 1;
2439 6         24 return $ndim;
2440             }
2441              
2442             =pod
2443              
2444             =item bandwidth()
2445              
2446             Returns the bandwidth of a matrix. In scalar context, returns the number of the
2447             non-zero diagonal furthest away from the main diagonal. In list context,
2448             separate values are returned for the lower and upper bandwidth.
2449              
2450             $n = $x -> bandwidth();
2451             ($l, $u) = $x -> bandwidth();
2452              
2453             The bandwidth is a non-negative integer. If the bandwidth is 0, the matrix is
2454             diagonal or zero. If the bandwidth is 1, the matrix is tridiagonal. If the
2455             bandwidth is 2, the matrix is pentadiagonal etc.
2456              
2457             A matrix with the following pattern, where C denotes a non-zero value, would
2458             return 2 in scalar context, and (1,2) in list context.
2459              
2460             [ x x x 0 0 0 ]
2461             [ x x x x 0 0 ]
2462             [ 0 x x x x 0 ]
2463             [ 0 0 x x x x ]
2464             [ 0 0 0 x x x ]
2465             [ 0 0 0 0 x x ]
2466              
2467             See also C> and C>.
2468              
2469             =cut
2470              
2471             sub bandwidth {
2472 18 50   18 1 4246 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2473 18 50       50 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2474 18         29 my $x = shift;
2475              
2476 18         40 my ($nrow, $ncol) = $x -> size();
2477              
2478 18         34 my $upper = 0;
2479 18         20 my $lower = 0;
2480              
2481 18         45 for my $i (0 .. $nrow - 1) {
2482 52         70 for my $j (0 .. $ncol - 1) {
2483 192 100       325 next if $x -> [$i][$j] == 0;
2484 146         180 my $dist = $j - $i;
2485 146 100       214 if ($dist > 0) {
2486 52 100       99 $upper = $dist if $dist > $upper;
2487             } else {
2488 94 100       169 $lower = $dist if $dist < $lower;
2489             }
2490             }
2491             }
2492              
2493 18         26 $lower = -$lower;
2494 18 100       49 return $lower, $upper if wantarray;
2495 9 50       28 return $lower > $upper ? $lower : $upper;
2496             }
2497              
2498             =pod
2499              
2500             =back
2501              
2502             =head2 Manipulate matrices
2503              
2504             These methods are for combining matrices, splitting matrices, extracing parts of
2505             a matrix, inserting new parts into a matrix, deleting parts of a matrix etc.
2506             There are also methods for shuffling elements around (relocating elements)
2507             inside a matrix.
2508              
2509             These methods are not concerned with the values of the elements.
2510              
2511             =over 4
2512              
2513             =item catrow()
2514              
2515             Concatenate rows, i.e., concatenate matrices vertically. Any number of arguments
2516             is allowed. All non-empty matrices must have the same number or columns. The
2517             result is a new matrix.
2518              
2519             $x = Math::Matrix -> new([1, 2], [4, 5]); # 2-by-2 matrix
2520             $y = Math::Matrix -> new([3, 6]); # 1-by-2 matrix
2521             $z = $x -> catrow($y); # 3-by-2 matrix
2522              
2523             =cut
2524              
2525             sub catrow {
2526 25     25 1 141 my $x = shift;
2527 25         48 my $class = ref $x;
2528              
2529 25         34 my $ncol;
2530 25         50 my $z = bless [], $class; # initialize output
2531              
2532 25         50 for my $y ($x, @_) {
2533 63         145 my $ncoly = $y -> ncol();
2534 63 100       176 next if $ncoly == 0; # ignore empty $y
2535              
2536 44 100       91 if (defined $ncol) {
2537 22 50       49 croak "All operands must have the same number of columns in ",
2538             (caller(0))[3] unless $ncoly == $ncol;
2539             } else {
2540 22         33 $ncol = $ncoly;
2541             }
2542              
2543 44         154 push @$z, map [ @$_ ], @$y;
2544             }
2545              
2546 25         68 return $z;
2547             }
2548              
2549             =pod
2550              
2551             =item catcol()
2552              
2553             Concatenate columns, i.e., matrices horizontally. Any number of arguments is
2554             allowed. All non-empty matrices must have the same number or rows. The result is
2555             a new matrix.
2556              
2557             $x = Math::Matrix -> new([1, 2], [4, 5]); # 2-by-2 matrix
2558             $y = Math::Matrix -> new([3], [6]); # 2-by-1 matrix
2559             $z = $x -> catcol($y); # 2-by-3 matrix
2560              
2561             =cut
2562              
2563             sub catcol {
2564 90     90 1 227 my $x = shift;
2565 90         157 my $class = ref $x;
2566              
2567 90         119 my $nrow;
2568 90         162 my $z = bless [], $class; # initialize output
2569              
2570 90         187 for my $y ($x, @_) {
2571 187         362 my $nrowy = $y -> nrow();
2572 187 100       371 next if $nrowy == 0; # ignore empty $y
2573              
2574 172 100       331 if (defined $nrow) {
2575 85 50       170 croak "All operands must have the same number of rows in ",
2576             (caller(0))[3] unless $nrowy == $nrow;
2577             } else {
2578 87         125 $nrow = $nrowy;
2579             }
2580              
2581 172         316 for my $i (0 .. $nrow - 1) {
2582 411         482 push @{ $z -> [$i] }, @{ $y -> [$i] };
  411         622  
  411         894  
2583             }
2584             }
2585              
2586 90         182 return $z;
2587             }
2588              
2589             =pod
2590              
2591             =item getrow()
2592              
2593             Get the specified row(s). Returns a new matrix with the specified rows. The
2594             number of rows in the output is identical to the number of elements in the
2595             input.
2596              
2597             $y = $x -> getrow($i); # get one
2598             $y = $x -> getrow([$i0, $i1, $i2]); # get multiple
2599              
2600             =cut
2601              
2602             sub getrow {
2603 4 50   4 1 58 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
2604 4 50       13 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
2605 4         8 my $x = shift;
2606 4         6 my $class = ref $x;
2607              
2608 4         7 my $idx = shift;
2609 4 50       8 croak "Row index can not be undefined" unless defined $idx;
2610 4 100       10 if (ref $idx) {
2611 3 50 33     19 $idx = __PACKAGE__ -> new($idx)
2612             unless defined(blessed($idx)) && $idx -> isa($class);
2613 3         11 $idx = $idx -> to_row();
2614 3         7 $idx = $idx -> [0];
2615             } else {
2616 1         3 $idx = [ $idx ];
2617             }
2618              
2619 4         11 my ($nrowx, $ncolx) = $x -> size();
2620              
2621 4         7 my $y = [];
2622 4         9 for my $iy (0 .. $#$idx) {
2623 5         7 my $ix = $idx -> [$iy];
2624 5 50       11 croak "Row index value $ix too large for $nrowx-by-$ncolx matrix in ",
2625             (caller(0))[3] if $ix >= $nrowx;
2626 5         6 $y -> [$iy] = [ @{ $x -> [$ix] } ];
  5         13  
2627             }
2628              
2629 4         14 bless $y, $class;
2630             }
2631              
2632             =pod
2633              
2634             =item getcol()
2635              
2636             Get the specified column(s). Returns a new matrix with the specified columns.
2637             The number of columns in the output is identical to the number of elements in
2638             the input.
2639              
2640             $y = $x -> getcol($j); # get one
2641             $y = $x -> getcol([$j0, $j1, $j2]); # get multiple
2642              
2643             =cut
2644              
2645             sub getcol {
2646 4 50   4 1 39 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
2647 4 50       11 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
2648 4         5 my $x = shift;
2649 4         5 my $class = ref $x;
2650              
2651 4         4 my $idx = shift;
2652 4 50       9 croak "Column index can not be undefined" unless defined $idx;
2653 4 100       8 if (ref $idx) {
2654 3 50 33     15 $idx = __PACKAGE__ -> new($idx)
2655             unless defined(blessed($idx)) && $idx -> isa($class);
2656 3         6 $idx = $idx -> to_row();
2657 3         5 $idx = $idx -> [0];
2658             } else {
2659 1         2 $idx = [ $idx ];
2660             }
2661              
2662 4         8 my ($nrowx, $ncolx) = $x -> size();
2663              
2664 4         5 my $y = [];
2665 4         10 for my $jy (0 .. $#$idx) {
2666 5         6 my $jx = $idx -> [$jy];
2667 5 50       8 croak "Column index value $jx too large for $nrowx-by-$ncolx matrix in ",
2668             (caller(0))[3] if $jx >= $ncolx;
2669 5         7 for my $i (0 .. $nrowx - 1) {
2670 20         29 $y -> [$i][$jy] = $x -> [$i][$jx];
2671             }
2672             }
2673              
2674 4         9 bless $y, $class;
2675             }
2676              
2677             =pod
2678              
2679             =item delrow()
2680              
2681             Delete row(s). Returns a new matrix identical to the invocand but with the
2682             specified row(s) deleted.
2683              
2684             $y = $x -> delrow($i); # delete one
2685             $y = $x -> delrow([$i0, $i1, $i2]); # delete multiple
2686              
2687             =cut
2688              
2689             sub delrow {
2690 5 50   5 1 46 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
2691 5 50       11 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
2692 5         7 my $x = shift;
2693 5         10 my $class = ref $x;
2694              
2695 5         7 my $idxdel = shift;
2696 5 50       10 croak "Row index can not be undefined" unless defined $idxdel;
2697 5 100       12 if (ref $idxdel) {
2698 4 50 33     20 $idxdel = __PACKAGE__ -> new($idxdel)
2699             unless defined(blessed($idxdel)) && $idxdel -> isa($class);
2700 4         12 $idxdel = $idxdel -> to_row();
2701 4         8 $idxdel = $idxdel -> [0];
2702             } else {
2703 1         2 $idxdel = [ $idxdel ];
2704             }
2705              
2706 5         13 my $nrowx = $x -> nrow();
2707              
2708             # This should be made faster.
2709              
2710 5         10 my $idxget = [];
2711 5         11 for my $i (0 .. $nrowx - 1) {
2712 20         23 my $seen = 0;
2713 20         34 for my $idx (@$idxdel) {
2714 28 100       52 if ($i == int $idx) {
2715 9         9 $seen = 1;
2716 9         13 last;
2717             }
2718             }
2719 20 100       39 push @$idxget, $i unless $seen;
2720             }
2721              
2722 5         9 my $y = [];
2723 5         18 @$y = map [ @$_ ], @$x[ @$idxget ];
2724 5         17 bless $y, $class;
2725             }
2726              
2727             =pod
2728              
2729             =item delcol()
2730              
2731             Delete column(s). Returns a new matrix identical to the invocand but with the
2732             specified column(s) deleted.
2733              
2734             $y = $x -> delcol($j); # delete one
2735             $y = $x -> delcol([$j0, $j1, $j2]); # delete multiple
2736              
2737             =cut
2738              
2739             sub delcol {
2740 5 50   5 1 47 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
2741 5 50       11 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
2742 5         11 my $x = shift;
2743 5         7 my $class = ref $x;
2744              
2745 5         10 my $idxdel = shift;
2746 5 50       11 croak "Column index can not be undefined" unless defined $idxdel;
2747 5 100       9 if (ref $idxdel) {
2748 4 50 33     22 $idxdel = __PACKAGE__ -> new($idxdel)
2749             unless defined(blessed($idxdel)) && $idxdel -> isa($class);
2750 4         13 $idxdel = $idxdel -> to_row();
2751 4         7 $idxdel = $idxdel -> [0];
2752             } else {
2753 1         2 $idxdel = [ $idxdel ];
2754             }
2755              
2756 5         12 my ($nrowx, $ncolx) = $x -> size();
2757              
2758             # This should be made faster.
2759              
2760 5         9 my $idxget = [];
2761 5         11 for my $j (0 .. $ncolx - 1) {
2762 20         24 my $seen = 0;
2763 20         28 for my $idx (@$idxdel) {
2764 28 100       51 if ($j == int $idx) {
2765 9         14 $seen = 1;
2766 9         12 last;
2767             }
2768             }
2769 20 100       39 push @$idxget, $j unless $seen;
2770             }
2771              
2772 5         9 my $y = [];
2773 5 100       11 if (@$idxget) {
2774 4         7 for my $row (@$x) {
2775 16         20 push @$y, [ @{$row}[ @$idxget ] ];
  16         32  
2776             }
2777             }
2778 5         16 bless $y, $class;
2779             }
2780              
2781             =pod
2782              
2783             =item concat()
2784              
2785             Concatenate two matrices horizontally. The matrices must have the same number of
2786             rows. The result is a new matrix or B in case of error.
2787              
2788             $x = Math::Matrix -> new([1, 2], [4, 5]); # 2-by-2 matrix
2789             $y = Math::Matrix -> new([3], [6]); # 2-by-1 matrix
2790             $z = $x -> concat($y); # 2-by-3 matrix
2791              
2792             =cut
2793              
2794             sub concat {
2795 11     11 1 81 my $self = shift;
2796 11         19 my $other = shift;
2797 11         39 my $result = $self->clone();
2798              
2799 11 50       51 return undef if scalar(@{$self}) != scalar(@{$other});
  11         23  
  11         30  
2800 11         19 for my $i (0 .. $#{$self}) {
  11         30  
2801 27         37 push @{$result->[$i]}, @{$other->[$i]};
  27         47  
  27         61  
2802             }
2803 11         29 $result;
2804             }
2805              
2806             =pod
2807              
2808             =item splicerow()
2809              
2810             Row splicing. This is like Perl's built-in splice() function, except that it
2811             works on the rows of a matrix.
2812              
2813             $y = $x -> splicerow($offset);
2814             $y = $x -> splicerow($offset, $length);
2815             $y = $x -> splicerow($offset, $length, $a, $b, ...);
2816              
2817             The built-in splice() function modifies the first argument and returns the
2818             removed elements, if any. However, since splicerow() does not modify the
2819             invocand, it returns the modified version as the first output argument and the
2820             removed part as a (possibly empty) second output argument.
2821              
2822             $x = Math::Matrix -> new([[ 1, 2],
2823             [ 3, 4],
2824             [ 5, 6],
2825             [ 7, 8]]);
2826             $a = Math::Matrix -> new([[11, 12],
2827             [13, 14]]);
2828             ($y, $z) = $x -> splicerow(1, 2, $a);
2829              
2830             Gives C<$y>
2831              
2832             [ 1 2 ]
2833             [ 11 12 ]
2834             [ 13 14 ]
2835             [ 7 8 ]
2836              
2837             and C<$z>
2838              
2839             [ 3 4 ]
2840             [ 5 6 ]
2841              
2842             =cut
2843              
2844             sub splicerow {
2845 12 50   12 1 75 croak "Not enough input arguments" if @_ < 1;
2846 12         16 my $x = shift;
2847 12         21 my $class = ref $x;
2848              
2849 12         16 my $offs = 0;
2850 12         28 my $len = $x -> nrow();
2851 12         26 my $repl = $class -> new([]);
2852              
2853 12 100       27 if (@_) {
2854 10         14 $offs = shift;
2855 10 50       21 croak "Offset can not be undefined" unless defined $offs;
2856 10 50       21 if (ref $offs) {
2857 0 0 0     0 $offs = $class -> new($offs)
2858             unless defined(blessed($offs)) && $offs -> isa($class);
2859 0 0       0 croak "Offset must be a scalar" unless $offs -> is_scalar();
2860 0         0 $offs = $offs -> [0][0];
2861             }
2862              
2863 10 100       19 if (@_) {
2864 4         6 $len = shift;
2865 4 50       9 croak "Length can not be undefined" unless defined $len;
2866 4 50       7 if (ref $len) {
2867 0 0 0     0 $len = $class -> new($len)
2868             unless defined(blessed($len)) && $len -> isa($class);
2869 0 0       0 croak "length must be a scalar" unless $len -> is_scalar();
2870 0         0 $len = $len -> [0][0];
2871             }
2872              
2873 4 100       8 if (@_) {
2874 2         8 $repl = $repl -> catrow(@_);
2875             }
2876             }
2877             }
2878              
2879 12         27 my $y = $x -> clone();
2880 12         22 my $z = $class -> new([]);
2881              
2882 12         35 @$z = splice @$y, $offs, $len, @$repl;
2883 12 100       51 return wantarray ? ($y, $z) : $y;
2884             }
2885              
2886             =pod
2887              
2888             =item splicecol()
2889              
2890             Column splicing. This is like Perl's built-in splice() function, except that it
2891             works on the columns of a matrix.
2892              
2893             $y = $x -> splicecol($offset);
2894             $y = $x -> splicecol($offset, $length);
2895             $y = $x -> splicecol($offset, $length, $a, $b, ...);
2896              
2897             The built-in splice() function modifies the first argument and returns the
2898             removed elements, if any. However, since splicecol() does not modify the
2899             invocand, it returns the modified version as the first output argument and the
2900             removed part as a (possibly empty) second output argument.
2901              
2902             $x = Math::Matrix -> new([[ 1, 3, 5, 7 ],
2903             [ 2, 4, 6, 8 ]]);
2904             $a = Math::Matrix -> new([[11, 13],
2905             [12, 14]]);
2906             ($y, $z) = $x -> splicerow(1, 2, $a);
2907              
2908             Gives C<$y>
2909              
2910             [ 1 11 13 7 ]
2911             [ 2 12 14 8 ]
2912              
2913             and C<$z>
2914              
2915             [ 3 5 ]
2916             [ 4 6 ]
2917              
2918             =cut
2919              
2920             sub splicecol {
2921 20 50   20 1 135 croak "Not enough input arguments" if @_ < 1;
2922 20         43 my $x = shift;
2923 20         40 my $class = ref $x;
2924              
2925 20         53 my ($nrowx, $ncolx) = $x -> size();
2926              
2927 20         30 my $offs = 0;
2928 20         36 my $len = $ncolx;
2929 20         48 my $repl = $class -> new([]);
2930              
2931 20 100       57 if (@_) {
2932 18         29 $offs = shift;
2933 18 50       40 croak "Offset can not be undefined" unless defined $offs;
2934 18 50       52 if (ref $offs) {
2935 0 0 0     0 $offs = $class -> new($offs)
2936             unless defined(blessed($offs)) && $offs -> isa($class);
2937 0 0       0 croak "Offset must be a scalar" unless $offs -> is_scalar();
2938 0         0 $offs = $offs -> [0][0];
2939             }
2940              
2941 18 100       39 if (@_) {
2942 12         20 $len = shift;
2943 12 50       27 croak "Length can not be undefined" unless defined $len;
2944 12 50       32 if (ref $len) {
2945 0 0 0     0 $len = $class -> new($len)
2946             unless defined(blessed($len)) && $len -> isa($class);
2947 0 0       0 croak "length must be a scalar" unless $len -> is_scalar();
2948 0         0 $len = $len -> [0][0];
2949             }
2950              
2951 12 100       38 if (@_) {
2952 2         8 $repl = $repl -> catcol(@_);
2953             }
2954             }
2955             }
2956              
2957 20         49 my $y = $x -> clone();
2958 20         44 my $z = $class -> new([]);
2959              
2960 20 50       57 if ($offs > $len) {
2961 0         0 carp "splicecol() offset past end of array";
2962 0         0 $offs = $len;
2963             }
2964              
2965             # The case when we are not removing anything from the invocand matrix: If
2966             # the offset is identical to the number of columns in the invocand matrix,
2967             # just appending the replacement matrix to the invocand matrix.
2968              
2969 20 100 100     84 if ($offs == $len) {
    100          
2970 2 50       6 unless ($repl -> is_empty()) {
2971 0         0 for my $i (0 .. $nrowx - 1) {
2972 0         0 push @{ $y -> [$i] }, @{ $repl -> [$i] };
  0         0  
  0         0  
2973             }
2974             }
2975             }
2976              
2977             # The case when we are removing everything from the invocand matrix: If the
2978             # offset is zero, and the length is identical to the number of columns in
2979             # the invocand matrix, replace the whole invocand matrix with the
2980             # replacement matrix.
2981              
2982             elsif ($offs == 0 && $len == $ncolx) {
2983 4         10 @$z = @$y;
2984 4         8 @$y = @$repl;
2985             }
2986              
2987             # The case when we are removing parts of the invocand matrix.
2988              
2989             else {
2990 14 100       46 if ($repl -> is_empty()) {
2991 12         31 for my $i (0 .. $nrowx - 1) {
2992 43         55 @{ $z -> [$i] } = splice @{ $y -> [$i] }, $offs, $len;
  43         97  
  43         75  
2993             }
2994             } else {
2995 2         5 for my $i (0 .. $nrowx - 1) {
2996 4         8 @{ $z -> [$i] } = splice @{ $y -> [$i] }, $offs, $len, @{ $repl -> [$i] };
  4         9  
  4         8  
  4         11  
2997             }
2998             }
2999             }
3000              
3001 20 100       122 return wantarray ? ($y, $z) : $y;
3002             }
3003              
3004             =pod
3005              
3006             =item swaprc()
3007              
3008             Swap rows and columns. This method does nothing but shuffle elements around. For
3009             real numbers, swaprc() is identical to the transpose() method.
3010              
3011             A subclass implementing a matrix of complex numbers should provide a transpose()
3012             method that also takes the complex conjugate of each elements. The swaprc()
3013             method, on the other hand, should only shuffle elements around.
3014              
3015             =cut
3016              
3017             sub swaprc {
3018 5     5 1 34 my $x = shift;
3019 5         10 my $class = ref $x;
3020              
3021 5         11 my $y = bless [], $class;
3022 5         14 my $ncolx = $x -> ncol();
3023 5 100       13 return $y if $ncolx == 0;
3024              
3025 4         13 for my $j (0 .. $ncolx - 1) {
3026 9         30 push @$y, [ map $_->[$j], @$x ];
3027             }
3028 4         13 return $y;
3029             }
3030              
3031             =pod
3032              
3033             =item flipud()
3034              
3035             Flip upside-down, i.e., flip along dimension 1.
3036              
3037             $y = $x -> flipud();
3038              
3039             =cut
3040              
3041             sub flipud {
3042 2 50   2 1 26 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3043 2 50       6 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
3044 2         3 my $x = shift;
3045 2         5 my $class = ref $x;
3046              
3047 2         122 my $y = [ reverse map [ @$_ ], @$x ];
3048 2         7 bless $y, $class;;
3049             }
3050              
3051             =pod
3052              
3053             =item fliplr()
3054              
3055             Flip left-to-right, i.e., flip along dimension 2.
3056              
3057             $y = $x -> fliplr();
3058              
3059             =cut
3060              
3061             sub fliplr {
3062 25 50   25 1 71 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3063 25 50       55 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
3064 25         39 my $x = shift;
3065 25         45 my $class = ref $x;
3066              
3067 25         163 my $y = [ map [ reverse @$_ ], @$x ];
3068 25         85 bless $y, $class;
3069             }
3070              
3071             =pod
3072              
3073             =item flip()
3074              
3075             Flip along various dimensions of a matrix. If the dimension argument is not
3076             given, the first non-singleton dimension is used.
3077              
3078             $y = $x -> flip($dim);
3079             $y = $x -> flip();
3080              
3081             See also C> and C>.
3082              
3083             =cut
3084              
3085             sub flip {
3086 12 50   12 1 73 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3087 12 50       22 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3088 12         21 my $x = shift;
3089 12     20   60 $x -> apply(sub { reverse @_ }, @_);
  20         39  
3090             }
3091              
3092             =pod
3093              
3094             =item rot90()
3095              
3096             Rotate 90 degrees counterclockwise.
3097              
3098             $y = $x -> rot90(); # rotate 90 degrees counterclockwise
3099             $y = $x -> rot90($n); # rotate 90*$n degrees counterclockwise
3100              
3101             =cut
3102              
3103             sub rot90 {
3104 12 50   12 1 67 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3105 12 50       25 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3106 12         19 my $x = shift;
3107 12         22 my $class = ref $x;
3108              
3109 12         17 my $n = 1;
3110 12 100       29 if (@_) {
3111 10         16 $n = shift;
3112 10 100       22 if (ref $n) {
3113 2 100 66     25 $n = $class -> new($n)
3114             unless defined(blessed($n)) && $n -> isa($class);
3115 2 50       8 croak "Argument must be a scalar" unless $n -> is_scalar();
3116 2         4 $n = $n -> [0][0];
3117             }
3118 10 50       28 croak "Argument must be an integer" unless $n == int $n;
3119             }
3120              
3121 12         19 my $y = [];
3122              
3123             # Rotate 0 degrees, i.e., clone.
3124              
3125 12         23 $n %= 4;
3126 12 100       46 if ($n == 0) {
    100          
    100          
    50          
3127 1         4 $y = [ map [ @$_ ], @$x ];
3128             }
3129              
3130             # Rotate 90 degrees.
3131              
3132             elsif ($n == 1) {
3133 5         15 my ($nrowx, $ncolx) = $x -> size();
3134 5         11 my $jmax = $ncolx - 1;
3135 5         9 for my $i (0 .. $nrowx - 1) {
3136 8         14 for my $j (0 .. $ncolx - 1) {
3137 24         46 $y -> [$jmax - $j][$i] = $x -> [$i][$j];
3138             }
3139             }
3140             }
3141              
3142             # Rotate 180 degrees.
3143              
3144             elsif ($n == 2) {
3145 3         61 $y = [ map [ reverse @$_ ], reverse @$x ];
3146             }
3147              
3148             # Rotate 270 degrees.
3149              
3150             elsif ($n == 3) {
3151 3         11 my ($nrowx, $ncolx) = $x -> size();
3152 3         7 my $imax = $nrowx - 1;
3153 3         10 for my $i (0 .. $nrowx - 1) {
3154 4         9 for my $j (0 .. $ncolx - 1) {
3155 12         26 $y -> [$j][$imax - $i] = $x -> [$i][$j];
3156             }
3157             }
3158             }
3159              
3160 12         39 bless $y, $class;
3161             }
3162              
3163             =pod
3164              
3165             =item rot180()
3166              
3167             Rotate 180 degrees.
3168              
3169             $y = $x -> rot180();
3170              
3171             =cut
3172              
3173             sub rot180 {
3174 2 50   2 1 24 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3175 2 50       5 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
3176 2         3 my $x = shift;
3177 2         6 $x -> rot90(2);
3178             }
3179              
3180             =pod
3181              
3182             =item rot270()
3183              
3184             Rotate 270 degrees counterclockwise, i.e., 90 degrees clockwise.
3185              
3186             $y = $x -> rot270();
3187              
3188             =cut
3189              
3190             sub rot270 {
3191 2 50   2 1 26 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3192 2 50       5 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
3193 2         4 my $x = shift;
3194 2         7 $x -> rot90(3);
3195             }
3196              
3197             =pod
3198              
3199             =item repelm()
3200              
3201             Repeat elements.
3202              
3203             $x -> repelm($y);
3204              
3205             Repeats each element in $x the number of times specified in $y.
3206              
3207             If $x is the matrix
3208              
3209             [ 4 5 6 ]
3210             [ 7 8 9 ]
3211              
3212             and $y is
3213              
3214             [ 3 2 ]
3215              
3216             the returned matrix is
3217              
3218             [ 4 4 5 5 6 6 ]
3219             [ 4 4 5 5 6 6 ]
3220             [ 4 4 5 5 6 6 ]
3221             [ 7 7 8 8 9 9 ]
3222             [ 7 7 8 8 9 9 ]
3223             [ 7 7 8 8 9 9 ]
3224              
3225             =cut
3226              
3227             sub repelm {
3228 5 50   5 1 41 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
3229 5 50       11 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3230 5         7 my $x = shift;
3231 5         10 my $class = ref $x;
3232              
3233 5         6 my $y = shift;
3234 5 50 33     38 $y = __PACKAGE__ -> new($y)
3235             unless defined(blessed($y)) && $y -> isa(__PACKAGE__);
3236 5 50       17 croak "Input argument must contain two elements"
3237             unless $y -> nelm() == 2;
3238              
3239 5         14 my ($nrowx, $ncolx) = $x -> size();
3240              
3241 5         13 $y = $y -> to_col();
3242 5         8 my $nrowrep = $y -> [0][0];
3243 5         7 my $ncolrep = $y -> [1][0];
3244              
3245 5         8 my $z = [];
3246 5         9 for my $ix (0 .. $nrowx - 1) {
3247 8         11 for my $jx (0 .. $ncolx - 1) {
3248 24         37 for my $iy (0 .. $nrowrep - 1) {
3249 30         42 for my $jy (0 .. $ncolrep - 1) {
3250 36         48 my $iz = $ix * $nrowrep + $iy;
3251 36         43 my $jz = $jx * $ncolrep + $jy;
3252 36         61 $z -> [$iz][$jz] = $x -> [$ix][$jx];
3253             }
3254             }
3255             }
3256             }
3257              
3258 5         20 bless $z, $class;
3259             }
3260              
3261             =pod
3262              
3263             =item repmat()
3264              
3265             Repeat elements.
3266              
3267             $x -> repmat($y);
3268              
3269             Repeats the matrix $x the number of times specified in $y.
3270              
3271             If $x is the matrix
3272              
3273             [ 4 5 6 ]
3274             [ 7 8 9 ]
3275              
3276             and $y is
3277              
3278             [ 3 2 ]
3279              
3280             the returned matrix is
3281              
3282             [ 4 5 6 4 5 6 ]
3283             [ 7 8 9 7 8 9 ]
3284             [ 4 5 6 4 5 6 ]
3285             [ 7 8 9 7 8 9 ]
3286             [ 4 5 6 4 5 6 ]
3287             [ 7 8 9 7 8 9 ]
3288              
3289             =cut
3290              
3291             sub repmat {
3292 5 50   5 1 41 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
3293 5 50       12 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3294 5         8 my $x = shift;
3295 5         9 my $class = ref $x;
3296              
3297 5         8 my $y = shift;
3298 5 50 33     36 $y = __PACKAGE__ -> new($y)
3299             unless defined(blessed($y)) && $y -> isa(__PACKAGE__);
3300 5 50       19 croak "Input argument must contain two elements"
3301             unless $y -> nelm() == 2;
3302              
3303 5         13 my ($nrowx, $ncolx) = $x -> size();
3304              
3305 5         14 $y = $y -> to_col();
3306 5         10 my $nrowrep = $y -> [0][0];
3307 5         6 my $ncolrep = $y -> [1][0];
3308              
3309 5         11 my $z = [];
3310 5         8 for my $ix (0 .. $nrowx - 1) {
3311 8         11 for my $jx (0 .. $ncolx - 1) {
3312 24         37 for my $iy (0 .. $nrowrep - 1) {
3313 30         44 for my $jy (0 .. $ncolrep - 1) {
3314 36         49 my $iz = $iy * $nrowx + $ix;
3315 36         41 my $jz = $jy * $ncolx + $jx;
3316 36         64 $z -> [$iz][$jz] = $x -> [$ix][$jx];
3317             }
3318             }
3319             }
3320             }
3321              
3322 5         22 bless $z, $class;
3323             }
3324              
3325             =pod
3326              
3327             =item reshape()
3328              
3329             Returns a reshaped copy of a matrix. The reshaping is done by creating a new
3330             matrix and looping over the elements in column major order. The new matrix must
3331             have the same number of elements as the invocand matrix. The following returns
3332             an C<$m>-by-C<$n> matrix,
3333              
3334             $y = $x -> reshape($m, $n);
3335              
3336             The code
3337              
3338             $x = Math::Matrix -> new([[1, 3, 5, 7], [2, 4, 6, 8]]);
3339             $y = $x -> reshape(4, 2);
3340              
3341             creates the matrix $x
3342              
3343             [ 1 3 5 7 ]
3344             [ 2 4 6 8 ]
3345              
3346             and returns a reshaped copy $y
3347              
3348             [ 1 5 ]
3349             [ 2 6 ]
3350             [ 3 7 ]
3351             [ 4 8 ]
3352              
3353             =cut
3354              
3355             sub reshape {
3356 30 50   30 1 182 croak "Not enough arguments for ", (caller(0))[3] if @_ < 3;
3357 30 50       63 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
3358 30         50 my $x = shift;
3359 30         51 my $class = ref $x;
3360              
3361 30         86 my ($nrowx, $ncolx) = $x -> size();
3362 30         55 my $nelmx = $nrowx * $ncolx;
3363              
3364 30         51 my ($nrowy, $ncoly) = @_;
3365 30         45 my $nelmy = $nrowy * $ncoly;
3366              
3367 30 50       64 croak "when reshaping, the number of elements can not change in ",
3368             (caller(0))[3] unless $nelmx == $nelmy;
3369              
3370 30         51 my $y = [];
3371              
3372             # No reshaping; just clone.
3373              
3374 30 100 66     123 if ($nrowx == $nrowy && $ncolx == $ncoly) {
    100          
    100          
3375 5         23 $y = [ map [ @$_ ], @$x ];
3376             }
3377              
3378             elsif ($nrowx == 1) {
3379              
3380             # Reshape from a row vector to a column vector.
3381              
3382 10 100       29 if ($ncoly == 1) {
3383 4         9 $y = [ map [ $_ ], @{ $x -> [0] } ];
  4         27  
3384             }
3385              
3386             # Reshape from a row vector to a matrix.
3387              
3388             else {
3389 6         13 my $k = 0;
3390 6         22 for my $j (0 .. $ncoly - 1) {
3391 15         30 for my $i (0 .. $nrowy - 1) {
3392 33         66 $y -> [$i][$j] = $x -> [0][$k++];
3393             }
3394             }
3395             }
3396             }
3397              
3398             elsif ($ncolx == 1) {
3399              
3400             # Reshape from a column vector to a row vector.
3401              
3402 6 100       20 if ($nrowy == 1) {
3403 3         11 $y = [[ map { @$_ } @$x ]];
  18         31  
3404             }
3405              
3406             # Reshape from a column vector to a matrix.
3407              
3408             else {
3409 3         7 my $k = 0;
3410 3         42 for my $j (0 .. $ncoly - 1) {
3411 9         20 for my $i (0 .. $nrowy - 1) {
3412 18         40 $y -> [$i][$j] = $x -> [$k++][0];
3413             }
3414             }
3415             }
3416             }
3417              
3418             # The invocand is a matrix. This code works in all cases, but is somewhat
3419             # slower than the specialized code above.
3420              
3421             else {
3422 9         25 for my $k (0 .. $nelmx - 1) {
3423 54         73 my $ix = $k % $nrowx;
3424 54         73 my $jx = ($k - $ix) / $nrowx;
3425 54         67 my $iy = $k % $nrowy;
3426 54         84 my $jy = ($k - $iy) / $nrowy;
3427 54         108 $y -> [$iy][$jy] = $x -> [$ix][$jx];
3428             }
3429             }
3430              
3431 30         100 bless $y, $class;
3432             }
3433              
3434             =pod
3435              
3436             =item to_row()
3437              
3438             Reshape to a row.
3439              
3440             $x -> to_row();
3441              
3442             This method reshapes the matrix into a single row. It is essentially the same
3443             as, but faster than,
3444              
3445             $x -> reshape(1, $x -> nelm());
3446              
3447             =cut
3448              
3449             sub to_row {
3450 30 50   30 1 115 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3451 30 50       67 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
3452 30         46 my $x = shift;
3453 30         55 my $class = ref $x;
3454              
3455 30         57 my $y = bless [], $class;
3456              
3457 30         72 my $ncolx = $x -> ncol();
3458 30 100       76 return $y if $ncolx == 0;
3459              
3460 25         65 for my $j (0 .. $ncolx - 1) {
3461 61         79 push @{ $y -> [0] }, map $_->[$j], @$x;
  61         182  
3462             }
3463 25         94 return $y;
3464             }
3465              
3466             =pod
3467              
3468             =item to_col()
3469              
3470             Reshape to a column.
3471              
3472             $y = $x -> to_col();
3473              
3474             This method reshapes the matrix into a single column. It is essentially the same
3475             as, but faster than,
3476              
3477             $x -> reshape($x -> nelm(), 1);
3478              
3479             =cut
3480              
3481             sub to_col {
3482 19 50   19 1 70 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3483 19 50       79 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
3484 19         36 my $x = shift;
3485              
3486 19         34 my $class = ref $x;
3487              
3488 19         41 my $y = bless [], $class;
3489              
3490 19         48 my $ncolx = $x -> ncol();
3491 19 100       47 return $y if $ncolx == 0;
3492              
3493 18         44 for my $j (0 .. $ncolx - 1) {
3494 43         131 push @$y, map [ $_->[$j] ], @$x;
3495             }
3496 18         39 return $y;
3497             }
3498              
3499             =pod
3500              
3501             =item to_permmat()
3502              
3503             Permutation vector to permutation matrix. Converts a vector of zero-based
3504             permutation indices to a permutation matrix.
3505              
3506             $P = $v -> to_permmat();
3507              
3508             For example
3509              
3510             $v = Math::Matrix -> new([[0, 3, 1, 4, 2]]);
3511             $m = $v -> to_permmat();
3512              
3513             gives the permutation matrix C<$m>
3514              
3515             [ 1 0 0 0 0 ]
3516             [ 0 0 0 1 0 ]
3517             [ 0 1 0 0 0 ]
3518             [ 0 0 0 0 1 ]
3519             [ 0 0 1 0 0 ]
3520              
3521             =cut
3522              
3523             sub to_permmat {
3524 4 50   4 1 25 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3525 4 50       23 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
3526 4         7 my $v = shift;
3527 4         7 my $class = ref $v;
3528              
3529 4         11 my $n = $v -> nelm();
3530 4         11 my $P = $class -> zeros($n, $n); # initialize output
3531 4 100       12 return $P if $n == 0; # if emtpy $v
3532              
3533 3 50       8 croak "Invocand must be a vector" unless $v -> is_vector();
3534 3         10 $v = $v -> to_col();
3535              
3536 3         7 for my $i (0 .. $n - 1) {
3537 9         13 my $j = $v -> [$i][0];
3538 9 50 33     30 croak "index out of range" unless 0 <= $j && $j < $n;
3539 9         15 $P -> [$i][$j] = 1;
3540             }
3541              
3542 3         23 return $P;
3543             }
3544              
3545             =pod
3546              
3547             =item to_permvec()
3548              
3549             Permutation matrix to permutation vector. Converts a permutation matrix to a
3550             vector of zero-based permutation indices.
3551              
3552             $v = $P -> to_permvec();
3553              
3554             $v = Math::Matrix -> new([[0, 3, 1, 4, 2]]);
3555             $m = $v -> to_permmat();
3556              
3557             Gives the permutation matrix C<$m>
3558              
3559             [ 1 0 0 0 0 ]
3560             [ 0 0 0 1 0 ]
3561             [ 0 1 0 0 0 ]
3562             [ 0 0 0 0 1 ]
3563             [ 0 0 1 0 0 ]
3564              
3565             See also C>.
3566              
3567             =cut
3568              
3569             sub to_permvec {
3570 4 50   4 1 40 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3571 4 50       8 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
3572 4         6 my $P = shift;
3573 4         7 my $class = ref $P;
3574              
3575 4 50       11 croak "Invocand matrix must be square" unless $P -> is_square();
3576 4         13 my $n = $P -> nrow();
3577              
3578 4         12 my $v = $class -> zeros($n, 1); # initialize output
3579              
3580 4         11 my $seen = [ (0) x $n ]; # keep track of the ones
3581              
3582 4         9 for my $i (0 .. $n - 1) {
3583 9         11 my $k;
3584 9         15 for my $j (0 .. $n - 1) {
3585 27 100       51 next if $P -> [$i][$j] == 0;
3586 9 50       19 if ($P -> [$i][$j] == 1) {
3587 9 50       15 croak "invalid permutation matrix; more than one row has",
3588             " an element with value 1 in column $j" if $seen->[$j]++;
3589 9         12 $k = $j;
3590 9         15 next;
3591             }
3592 0         0 croak "invalid permutation matrix; element ($i,$j)",
3593             " is neither 0 nor 1";
3594             }
3595 9 50       15 croak "invalid permutation matrix; row $i has no element with value 1"
3596             unless defined $k;
3597 9         16 $v->[$i][0] = $k;
3598             }
3599              
3600 4         13 return $v;
3601             }
3602              
3603             =pod
3604              
3605             =item triu()
3606              
3607             Upper triangular part. Extract the upper triangular part of a matrix and set all
3608             other elements to zero.
3609              
3610             $y = $x -> triu();
3611             $y = $x -> triu($n);
3612              
3613             The optional second argument specifies how many diagonals above or below the
3614             main diagonal should also be set to zero. The default value of C<$n> is zero
3615             which includes the main diagonal.
3616              
3617             =cut
3618              
3619             sub triu {
3620 12 50   12 1 83 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3621 12 50       28 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3622 12         13 my $x = shift;
3623 12         25 my $class = ref $x;
3624              
3625 12         15 my $n = 0;
3626 12 100       26 if (@_) {
3627 10         13 $n = shift;
3628 10 50       21 if (ref $n) {
3629 0 0 0     0 $n = $class -> new($n)
3630             unless defined(blessed($n)) && $n -> isa($class);
3631 0 0       0 croak "Argument must be a scalar" unless $n -> is_scalar();
3632 0         0 $n = $n -> [0][0];
3633             }
3634 10 50       25 croak "Argument must be an integer" unless $n == int $n;
3635             }
3636              
3637 12         29 my ($nrowx, $ncolx) = $x -> size();
3638              
3639 12         21 my $y = [];
3640 12         27 for my $i (0 .. $nrowx - 1) {
3641 30         44 for my $j (0 .. $ncolx - 1) {
3642 72 100       155 $y -> [$i][$j] = $j - $i >= $n ? $x -> [$i][$j] : 0;
3643             }
3644             }
3645              
3646 12         31 bless $y, $class;
3647             }
3648              
3649             =pod
3650              
3651             =item tril()
3652              
3653             Lower triangular part. Extract the lower triangular part of a matrix and set all
3654             other elements to zero.
3655              
3656             $y = $x -> tril();
3657             $y = $x -> tril($n);
3658              
3659             The optional second argument specifies how many diagonals above or below the
3660             main diagonal should also be set to zero. The default value of C<$n> is zero
3661             which includes the main diagonal.
3662              
3663             =cut
3664              
3665             sub tril {
3666 12 50   12 1 90 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3667 12 50       26 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3668 12         19 my $x = shift;
3669 12         18 my $class = ref $x;
3670              
3671 12         17 my $n = 0;
3672 12 100       21 if (@_) {
3673 10         14 $n = shift;
3674 10 50       19 if (ref $n) {
3675 0 0 0     0 $n = $class -> new($n)
3676             unless defined(blessed($n)) && $n -> isa($class);
3677 0 0       0 croak "Argument must be a scalar" unless $n -> is_scalar();
3678 0         0 $n = $n -> [0][0];
3679             }
3680 10 50       23 croak "Argument must be an integer" unless $n == int $n;
3681             }
3682              
3683 12         28 my ($nrowx, $ncolx) = $x -> size();
3684              
3685 12         18 my $y = [];
3686 12         25 for my $i (0 .. $nrowx - 1) {
3687 30         46 for my $j (0 .. $ncolx - 1) {
3688 72 100       143 $y -> [$i][$j] = $j - $i <= $n ? $x -> [$i][$j] : 0;
3689             }
3690             }
3691              
3692 12         37 bless $y, $class;
3693             }
3694              
3695             =pod
3696              
3697             =item slice()
3698              
3699             Extract columns:
3700              
3701             a->slice(1,3,5);
3702              
3703             =cut
3704              
3705             sub slice {
3706 16     16 1 60 my $self = shift;
3707 16         31 my $class = ref($self);
3708 16         35 my $result = [];
3709              
3710 16         80 for my $i (0 .. $#$self) {
3711 39         65 push @$result, [ @{$self->[$i]}[@_] ];
  39         96  
3712             }
3713              
3714 16         47 bless $result, $class;
3715             }
3716              
3717             =pod
3718              
3719             =item diagonal_vector()
3720              
3721             Extract the diagonal as an array:
3722              
3723             $diag = $a->diagonal_vector;
3724              
3725             =cut
3726              
3727             sub diagonal_vector {
3728 1     1 1 2025 my $self = shift;
3729 1         2 my @diag;
3730 1         3 my $idx = 0;
3731 1         4 my($m, $n) = $self->size();
3732              
3733 1 50       5 croak "Not a square matrix" if $m != $n;
3734              
3735 1         2 foreach my $r (@{$self}) {
  1         4  
3736 4         9 push @diag, $r->[$idx++];
3737             }
3738 1         5 return \@diag;
3739             }
3740              
3741             =pod
3742              
3743             =item tridiagonal_vector()
3744              
3745             Extract the diagonals that make up a tridiagonal matrix:
3746              
3747             ($main_d, $upper_d, $lower_d) = $a->tridiagonal_vector;
3748              
3749             =cut
3750              
3751             sub tridiagonal_vector {
3752 1     1 1 1430 my $self = shift;
3753 1         6 my(@main_d, @up_d, @low_d);
3754 1         4 my($m, $n) = $self->size();
3755 1         2 my $idx = 0;
3756              
3757 1 50       4 croak "Not a square matrix" if $m != $n;
3758              
3759 1         2 foreach my $r (@{$self}) {
  1         2  
3760 4 100       11 push @low_d, $r->[$idx - 1] if ($idx > 0);
3761 4         6 push @main_d, $r->[$idx++];
3762 4 100       11 push @up_d, $r->[$idx] if ($idx < $m);
3763             }
3764 1         11 return ([@main_d],[@up_d],[@low_d]);
3765             }
3766              
3767             =pod
3768              
3769             =back
3770              
3771             =head2 Mathematical functions
3772              
3773             =head3 Addition
3774              
3775             =over 4
3776              
3777             =item add()
3778              
3779             Addition. If one operands is a scalar, it is treated like a constant matrix with
3780             the same size as the other operand. Otherwise ordinary matrix addition is
3781             performed.
3782              
3783             $z = $x -> add($y);
3784              
3785             See also C> and C>.
3786              
3787             =cut
3788              
3789             sub add {
3790 8 50   8 1 68 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
3791 8 50       22 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3792 8         11 my $x = shift;
3793 8         16 my $class = ref $x;
3794              
3795 8         10 my $y = shift;
3796 8 100 66     79 $y = $class -> new($y) unless defined(blessed($y)) && $y -> isa($class);
3797              
3798 8 100 100     25 $x -> is_scalar() || $y -> is_scalar() ? $x -> sadd($y) : $x -> madd($y);
3799             }
3800              
3801             =pod
3802              
3803             =item madd()
3804              
3805             Matrix addition. Add two matrices of the same dimensions. An error is thrown if
3806             the matrices don't have the same size.
3807              
3808             $z = $x -> madd($y);
3809              
3810             See also C> and C>.
3811              
3812             =cut
3813              
3814             sub madd {
3815 5 50   5 1 37 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
3816 5 50       59 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3817 5         9 my $x = shift;
3818 5         12 my $class = ref $x;
3819              
3820 5         10 my $y = shift;
3821 5 50 33     51 $y = $class -> new($y) unless defined(blessed($y)) && $y -> isa($class);
3822              
3823 5         23 my ($nrowx, $ncolx) = $x -> size();
3824 5         12 my ($nrowy, $ncoly) = $y -> size();
3825              
3826 5 50 33     26 croak "Can't add $nrowx-by-$ncolx matrix to $nrowy-by-$ncoly matrix"
3827             unless $nrowx == $nrowy && $ncolx == $ncoly;
3828              
3829 5         11 my $z = [];
3830 5         17 for my $i (0 .. $nrowx - 1) {
3831 7         13 for my $j (0 .. $ncolx - 1) {
3832 21         44 $z->[$i][$j] = $x->[$i][$j] + $y->[$i][$j];
3833             }
3834             }
3835              
3836 5         28 bless $z, $class;
3837             }
3838              
3839             =pod
3840              
3841             =item sadd()
3842              
3843             Scalar (element by element) addition with scalar expansion. This method places
3844             no requirements on the size of the input matrices.
3845              
3846             $z = $x -> sadd($y);
3847              
3848             See also C> and C>.
3849              
3850             =cut
3851              
3852             sub sadd {
3853 9 50   9 1 47 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
3854 9 50       21 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3855 9         13 my $x = shift;
3856              
3857 9     33   38 my $sub = sub { $_[0] + $_[1] };
  33         67  
3858 9         33 $x -> sapply($sub, @_);
3859             }
3860              
3861             =pod
3862              
3863             =back
3864              
3865             =head3 Subtraction
3866              
3867             =over 4
3868              
3869             =item sub()
3870              
3871             Subtraction. If one operands is a scalar, it is treated as a constant matrix
3872             with the same size as the other operand. Otherwise, ordinarly matrix subtraction
3873             is performed.
3874              
3875             $z = $x -> sub($y);
3876              
3877             See also C> and C>.
3878              
3879             =cut
3880              
3881             sub sub {
3882 9 50   9 1 57 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
3883 9 50       20 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3884 9         19 my $x = shift;
3885 9         25 my $class = ref $x;
3886              
3887 9         22 my $y = shift;
3888 9 100 66     67 $y = $class -> new($y) unless defined(blessed($y)) && $y -> isa($class);
3889              
3890 9 100 100     30 $x -> is_scalar() || $y -> is_scalar() ? $x -> ssub($y) : $x -> msub($y);
3891             }
3892              
3893             =pod
3894              
3895             =item msub()
3896              
3897             Matrix subtraction. Subtract two matrices of the same size. An error is thrown
3898             if the matrices don't have the same size.
3899              
3900             $z = $x -> msub($y);
3901              
3902             See also C> and C>.
3903              
3904             =cut
3905              
3906             sub msub {
3907 6 50   6 1 45 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
3908 6 50       30 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3909 6         11 my $x = shift;
3910 6         42 my $class = ref $x;
3911              
3912 6         13 my $y = shift;
3913 6 50 33     53 $y = $class -> new($y) unless defined(blessed($y)) && $y -> isa($class);
3914              
3915 6         35 my ($nrowx, $ncolx) = $x -> size();
3916 6         15 my ($nrowy, $ncoly) = $y -> size();
3917              
3918 6 50 33     29 croak "Can't subtract $nrowy-by-$ncoly matrix from $nrowx-by-$ncolx matrix"
3919             unless $nrowx == $nrowy && $ncolx == $ncoly;
3920              
3921 6         13 my $z = [];
3922 6         21 for my $i (0 .. $nrowx - 1) {
3923 8         16 for my $j (0 .. $ncolx - 1) {
3924 24         57 $z->[$i][$j] = $x->[$i][$j] - $y->[$i][$j];
3925             }
3926             }
3927              
3928 6         40 bless $z, $class;
3929             }
3930              
3931             =pod
3932              
3933             =item ssub()
3934              
3935             Scalar (element by element) subtraction with scalar expansion. This method
3936             places no requirements on the size of the input matrices.
3937              
3938             $z = $x -> ssub($y);
3939              
3940             See also C> and C>.
3941              
3942             =cut
3943              
3944             sub ssub {
3945 9 50   9 1 53 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
3946 9 50       18 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3947 9         15 my $x = shift;
3948              
3949 9     33   36 my $sub = sub { $_[0] - $_[1] };
  33         72  
3950 9         32 $x -> sapply($sub, @_);
3951             }
3952              
3953             =pod
3954              
3955             =item subtract()
3956              
3957             This is an alias for C>.
3958              
3959             =cut
3960              
3961             sub subtract {
3962 1     1 1 6 my $x = shift;
3963 1         4 $x -> sub(@_);
3964             }
3965              
3966             =pod
3967              
3968             =back
3969              
3970             =head3 Negation
3971              
3972             =over 4
3973              
3974             =item neg()
3975              
3976             Negation. Negate a matrix.
3977              
3978             $y = $x -> neg();
3979              
3980             It is effectively equivalent to
3981              
3982             $y = $x -> map(sub { -$_ });
3983              
3984             =cut
3985              
3986             sub neg {
3987 4 50   4 1 39 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3988 4 50       13 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
3989 4         7 my $x = shift;
3990 4         81 bless [ map [ map -$_, @$_ ], @$x ], ref $x;
3991             }
3992              
3993             =pod
3994              
3995             =item negative()
3996              
3997             This is an alias for C>.
3998              
3999             =cut
4000              
4001             sub negative {
4002 0     0 1 0 my $x = shift;
4003 0         0 $x -> neg(@_);
4004             }
4005              
4006             =pod
4007              
4008             =back
4009              
4010             =head3 Multiplication
4011              
4012             =over 4
4013              
4014             =item mul()
4015              
4016             Multiplication. If one operands is a scalar, it is treated as a constant matrix
4017             with the same size as the other operand. Otherwise, ordinary matrix
4018             multiplication is performed.
4019              
4020             $z = $x -> mul($y);
4021              
4022             =cut
4023              
4024             sub mul {
4025 22 50   22 1 76 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4026 22 50       45 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4027 22         31 my $x = shift;
4028 22         42 my $class = ref $x;
4029              
4030 22         30 my $y = shift;
4031 22 100 66     127 $y = $class -> new($y) unless defined(blessed($y)) && $y -> isa($class);
4032              
4033 22 100 100     59 $x -> is_scalar() || $y -> is_scalar() ? $x -> smul($y) : $x -> mmul($y);
4034             }
4035              
4036             =pod
4037              
4038             =item mmul()
4039              
4040             Matrix multiplication. An error is thrown if the sizes don't match; the number
4041             of columns in the first operand must be equal to the number of rows in the
4042             second operand.
4043              
4044             $z = $x -> mmul($y);
4045              
4046             =cut
4047              
4048             sub mmul {
4049 29 50   29 1 97 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4050 29 50       65 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4051 29         44 my $x = shift;
4052 29         55 my $class = ref $x;
4053              
4054 29         44 my $y = shift;
4055 29 50 33     215 $y = $class -> new($y) unless defined(blessed($y)) && $y -> isa($class);
4056              
4057 29         90 my $mx = $x -> nrow();
4058 29         65 my $nx = $x -> ncol();
4059              
4060 29         74 my $my = $y -> nrow();
4061 29         59 my $ny = $y -> ncol();
4062              
4063 29 50       69 croak "Can't multiply $mx-by-$nx matrix with $my-by-$ny matrix"
4064             unless $nx == $my;
4065              
4066 29         52 my $z = [];
4067 29         70 my $l = $nx - 1; # "inner length"
4068 29         80 for my $i (0 .. $mx - 1) {
4069 64         121 for my $j (0 .. $ny - 1) {
4070 172         561 $z -> [$i][$j] = _sum(map $x -> [$i][$_] * $y -> [$_][$j], 0 .. $l);
4071             }
4072             }
4073              
4074 29         161 bless $z, $class;
4075             }
4076              
4077             =pod
4078              
4079             =item smul()
4080              
4081             Scalar (element by element) multiplication with scalar expansion. This method
4082             places no requirements on the size of the input matrices.
4083              
4084             $z = $x -> smul($y);
4085              
4086             =cut
4087              
4088             sub smul {
4089 12 50   12 1 57 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4090 12 50       29 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4091 12         18 my $x = shift;
4092              
4093 12     36   50 my $sub = sub { $_[0] * $_[1] };
  36         81  
4094 12         40 $x -> sapply($sub, @_);
4095             }
4096              
4097             =pod
4098              
4099             =item mmuladd()
4100              
4101             Matrix fused multiply and add. If C<$x> is a C<$p>-by-C<$q> matrix, then C<$y>
4102             must be a C<$q>-by-C<$r> matrix and C<$z> must be a C<$p>-by-C<$r> matrix. An
4103             error is thrown if the sizes don't match.
4104              
4105             $w = $x -> mmuladd($y, $z);
4106              
4107             The fused multiply and add is equivalent to, but computed with higher accuracy
4108             than
4109              
4110             $w = $x -> mmul($y) -> madd($z);
4111              
4112             This method can be used to improve the solution of linear systems.
4113              
4114             =cut
4115              
4116             sub mmuladd {
4117 2 50   2 1 25 croak "Not enough arguments for ", (caller(0))[3] if @_ < 3;
4118 2 50       5 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
4119 2         3 my $x = shift;
4120 2         5 my $class = ref $x;
4121              
4122 2         7 my ($mx, $nx) = $x -> size();
4123              
4124 2         3 my $y = shift;
4125 2 50 33     22 $y = $class -> new($y) unless defined(blessed($y)) && $y -> isa($class);
4126 2         5 my ($my, $ny) = $y -> size();
4127              
4128 2 50       5 croak "Can't multiply $mx-by-$nx matrix with $my-by-$ny matrix"
4129             unless $nx == $my;
4130              
4131 2         3 my $z = shift;
4132 2 50 33     12 $z = $class -> new($z) unless defined(blessed($z)) && $z -> isa($class);
4133 2         5 my ($mz, $nz) = $z -> size();
4134              
4135 2 50 33     8 croak "Can't add $mz-by-$nz matrix to $mx-by-$ny matrix"
4136             unless $mz == $mx && $nz == $ny;
4137              
4138 2         4 my $w = [];
4139 2         14 my $l = $nx - 1; # "inner length"
4140 2         7 for my $i (0 .. $mx - 1) {
4141 6         10 for my $j (0 .. $ny - 1) {
4142 12         41 $w -> [$i][$j]
4143             = _sum(map($x -> [$i][$_] * $y -> [$_][$j], 0 .. $l),
4144             $z -> [$i][$j]);
4145             }
4146             }
4147              
4148 2         8 bless $w, $class;
4149             }
4150              
4151             =pod
4152              
4153             =item kron()
4154              
4155             Kronecker tensor product.
4156              
4157             $A -> kronprod($B);
4158              
4159             If C<$A> is an C<$m>-by-C<$n> matrix and C<$B> is a C<$p>-by-C<$q> matrix, then
4160             C<< $A -> kron($B) >> is an C<$m>*C<$p>-by-C<$n>*C<$q> matrix formed by taking
4161             all possible products between the elements of C<$A> and the elements of C<$B>.
4162              
4163             =cut
4164              
4165             sub kron {
4166 4 50   4 1 48 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4167 4 50       18 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4168 4         8 my $x = shift;
4169 4         7 my $class = ref $x;
4170              
4171 4         9 my $y = shift;
4172 4 50 33     31 $y = $class -> new($y) unless defined(blessed($y)) && $y -> isa($class);
4173              
4174 4         15 my ($nrowx, $ncolx) = $x -> size();
4175 4         8 my ($nrowy, $ncoly) = $y -> size();
4176              
4177 4         8 my $z = bless [], $class;
4178              
4179 4         10 for my $ix (0 .. $nrowx - 1) {
4180 4         7 for my $jx (0 .. $ncolx - 1) {
4181 8         15 for my $iy (0 .. $nrowy - 1) {
4182 8         12 for my $jy (0 .. $ncoly - 1) {
4183 16         24 my $iz = $ix * $nrowx + $iy;
4184 16         21 my $jz = $jx * $ncolx + $jy;
4185 16         29 $z -> [$iz][$jz] = $x -> [$ix][$jx] * $y -> [$iy][$jy];
4186             }
4187             }
4188             }
4189             }
4190              
4191 4         10 return $z;
4192             }
4193              
4194             =pod
4195              
4196             =item multiply()
4197              
4198             This is an alias for C>.
4199              
4200             =cut
4201              
4202             sub multiply {
4203 8     8 1 40 my $x = shift;
4204 8         26 $x -> mmul(@_);
4205             }
4206              
4207             =pod
4208              
4209             =item multiply_scalar()
4210              
4211             Multiplies a matrix and a scalar resulting in a matrix of the same dimensions
4212             with each element scaled with the scalar.
4213              
4214             $a->multiply_scalar(2); scale matrix by factor 2
4215              
4216             =cut
4217              
4218             sub multiply_scalar {
4219 7     7 1 32 my $self = shift;
4220 7         12 my $factor = shift;
4221 7         15 my $result = $self->new();
4222              
4223 7         21 my $last = $#{$self->[0]};
  7         17  
4224 7         46 for my $i (0 .. $#{$self}) {
  7         21  
4225 13         25 for my $j (0 .. $last) {
4226 33         62 $result->[$i][$j] = $factor * $self->[$i][$j];
4227             }
4228             }
4229 7         25 $result;
4230             }
4231              
4232             =pod
4233              
4234             =back
4235              
4236             =head3 Powers
4237              
4238             =over 4
4239              
4240             =item pow()
4241              
4242             Power function.
4243              
4244             This is an alias for C>.
4245              
4246             See also C>.
4247              
4248             =cut
4249              
4250             sub pow {
4251 7     7 1 26 my $x = shift;
4252 7         18 $x -> mpow(@_);
4253             }
4254              
4255             =pod
4256              
4257             =item mpow()
4258              
4259             Matrix power. The second operand must be a non-negative integer.
4260              
4261             $y = $x -> mpow($n);
4262              
4263             The following example
4264              
4265             $x = Math::Matrix -> new([[0, -2],[1, 4]]);
4266             $y = 4;
4267             $z = $x -> pow($y);
4268              
4269             returns the matrix
4270              
4271             [ -28 -96 ]
4272             [ 48 164 ]
4273              
4274             See also C>.
4275              
4276             =cut
4277              
4278             sub mpow {
4279 11 50   11 1 50 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4280 11 50       18 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4281 11         18 my $x = shift;
4282 11         17 my $class = ref $x;
4283              
4284 11 50       28 croak "Invocand matrix must be square in ", (caller(0))[3]
4285             unless $x -> is_square();
4286              
4287 11         16 my $n = shift;
4288 11 50       23 croak "Exponent can not be undefined" unless defined $n;
4289 11 100       25 if (ref $n) {
4290 9 50 33     62 $n = $class -> new($n) unless defined(blessed($n)) && $n -> isa($class);
4291 9 50       22 croak "Exponent must be a scalar in ", (caller(0))[3]
4292             unless $n -> is_scalar();
4293 9         18 $n = $n -> [0][0];
4294             }
4295 11 50       24 croak "Exponent must be a non-negative integer" unless $n == int $n;
4296              
4297 11 100       23 return $class -> new([]) if $x -> is_empty();
4298              
4299 8         18 my ($nrowx, $ncolx) = $x -> size();
4300 8 100       21 return $class -> id($nrowx, $ncolx) if $n == 0;
4301 6 100       16 return $x -> clone() if $n == 1;
4302              
4303 4         11 my $y = $class -> id($nrowx, $ncolx);
4304 4         9 my $tmp = $x;
4305 4         6 while (1) {
4306 11         18 my $rem = $n % 2;
4307 11 100       34 $y *= $tmp if $rem;
4308 11         18 $n = ($n - $rem) / 2;
4309 11 100       28 last if $n == 0;
4310 7         17 $tmp = $tmp * $tmp;
4311             }
4312              
4313 4         15 return $y;
4314             }
4315              
4316             =pod
4317              
4318             =item spow()
4319              
4320             Scalar (element by element) power function. This method doesn't require the
4321             matrices to have the same size.
4322              
4323             $z = $x -> spow($y);
4324              
4325             See also C>.
4326              
4327             =cut
4328              
4329             sub spow {
4330 4 50   4 1 30 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4331 4 50       9 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4332 4         7 my $x = shift;
4333              
4334 4     14   15 my $sub = sub { $_[0] ** $_[1] };
  14         36  
4335 4         13 $x -> sapply($sub, @_);
4336             }
4337              
4338             =pod
4339              
4340             =back
4341              
4342             =head3 Inversion
4343              
4344             =over 4
4345              
4346             =item inv()
4347              
4348             This is an alias for C>.
4349              
4350             =cut
4351              
4352             sub inv {
4353 1     1 1 9 my $x = shift;
4354 1         4 $x -> minv();
4355             }
4356              
4357             =pod
4358              
4359             =item invert()
4360              
4361             Invert a Matrix using C.
4362              
4363             =cut
4364              
4365             sub invert {
4366 1     1 1 3 my $M = shift;
4367 1         14 my ($m, $n) = $M->size;
4368 1 50       4 croak "Can't invert $m-by-$n matrix; matrix must be square"
4369             if $m != $n;
4370 1         4 my $I = $M->new_identity($n);
4371 1         4 ($M->concat($I))->solve;
4372             }
4373              
4374             =pod
4375              
4376             =item minv()
4377              
4378             Matrix inverse. Invert a matrix.
4379              
4380             $y = $x -> inv();
4381              
4382             See the section L for a list of
4383             additional parameters that can be used for trying to obtain a better solution
4384             through iteration.
4385              
4386             =cut
4387              
4388             sub minv {
4389 2 50   2 1 22 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
4390             #croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
4391 2         3 my $x = shift;
4392 2         4 my $class = ref $x;
4393              
4394 2         6 my $n = $x -> nrow();
4395 2         7 return $class -> id($n) -> mldiv($x, @_);
4396             }
4397              
4398             =pod
4399              
4400             =item sinv()
4401              
4402             Scalar (element by element) inverse. Invert each element in a matrix.
4403              
4404             $y = $x -> sinv();
4405              
4406             =cut
4407              
4408             sub sinv {
4409 2 50   2 1 26 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
4410 2 50       5 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
4411 2         5 my $x = shift;
4412              
4413 2         51 bless [ map [ map 1/$_, @$_ ], @$x ], ref $x;
4414             }
4415              
4416             =pod
4417              
4418             =item mldiv()
4419              
4420             Matrix left division. Returns the solution x of the linear system of equations
4421             A*x = y, by computing A^(-1)*y.
4422              
4423             $x = $y -> mldiv($A);
4424              
4425             This method also handles overdetermined and underdetermined systems. There are
4426             three cases
4427              
4428             =over 4
4429              
4430             =item *
4431              
4432             If A is a square matrix, then
4433              
4434             x = A\y = inv(A)*y
4435              
4436             so that A*x = y to within round-off accuracy.
4437              
4438             =item *
4439              
4440             If A is an M-by-N matrix where M > N, then A\y is computed as
4441              
4442             A\y = (A'*A)\(A'*y) = inv(A'*A)*(A'*y)
4443              
4444             where A' denotes the transpose of A. The returned matrix is the least squares
4445             solution to the linear system of equations A*x = y, if it exists. The matrix
4446             A'*A must be non-singular.
4447              
4448             =item *
4449              
4450             If A is an where M < N, then A\y is computed as
4451              
4452             A\y = A'*((A*A')\y)
4453              
4454             This solution is not unique. The matrix A*A' must be non-singular.
4455              
4456             =back
4457              
4458             See the section L for a list of
4459             additional parameters that can be used for trying to obtain a better solution
4460             through iteration.
4461              
4462             =cut
4463              
4464             sub mldiv {
4465 10 50   10 1 49 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4466             #croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4467 10         19 my $y = shift;
4468 10         18 my $class = ref $y;
4469              
4470 10         16 my $A = shift;
4471 10 50 33     84 $A = $class -> new($A) unless defined(blessed($A)) && $A -> isa($class);
4472              
4473 10         70 my ($m, $n) = $A -> size();
4474              
4475 10 100       39 if ($m > $n) {
    100          
4476              
4477             # If A is an M-by-N matrix where M > N, i.e., an overdetermined system,
4478             # compute (A'*A)\(A'*y) by doing a one level deep recursion.
4479              
4480 1         4 my $At = $A -> transpose();
4481 1         5 return $At -> mmul($y) -> mldiv($At -> mmul($A), @_);
4482              
4483             } elsif ($m < $n) {
4484              
4485             # If A is an M-by-N matrix where M < N, i.e., and underdetermined
4486             # system, compute A'*((A*A')\y) by doing a one level deep recursion.
4487             # This solution is not unique.
4488              
4489 1         2 my $At = $A -> transpose();
4490 1         4 return $At -> mldiv($At -> mmul($A), @_);
4491             }
4492              
4493             # If extra arguments are given ...
4494              
4495 8 50       24 if (@_) {
4496              
4497 0         0 require Config;
4498 0         0 my $max_iter = 20;
4499             my $rel_tol = ($Config::Config{uselongdouble} ||
4500 0 0 0     0 $Config::Config{usequadmath}) ? 1e-19 : 1e-9;
4501 0         0 my $abs_tol = 0;
4502 0         0 my $debug;
4503              
4504 0         0 while (@_) {
4505 0         0 my $param = shift;
4506 0 0       0 croak "parameter name can not be undefined" unless defined $param;
4507              
4508 0 0       0 croak "missing value for parameter '$param'" unless @_;
4509 0         0 my $value = shift;
4510              
4511 0 0       0 if ($param eq 'MaxIter') {
4512 0 0       0 croak "value for parameter 'MaxIter' can not be undefined"
4513             unless defined $value;
4514 0 0 0     0 croak "value for parameter 'MaxIter' must be a positive integer"
4515             unless $value > 0 && $value == int $value;
4516 0         0 $max_iter = $value;
4517 0         0 next;
4518             }
4519              
4520 0 0       0 if ($param eq 'RelTol') {
4521 0 0       0 croak "value for parameter 'RelTol' can not be undefined"
4522             unless defined $value;
4523 0 0       0 croak "value for parameter 'RelTol' must be non-negative"
4524             unless $value >= 0;
4525 0         0 $rel_tol = $value;
4526 0         0 next;
4527             }
4528              
4529 0 0       0 if ($param eq 'AbsTol') {
4530 0 0       0 croak "value for parameter 'AbsTol' can not be undefined"
4531             unless defined $value;
4532 0 0       0 croak "value for parameter 'AbsTol' must be non-negative"
4533             unless $value >= 0;
4534 0         0 $abs_tol = $value;
4535 0         0 next;
4536             }
4537              
4538 0 0       0 if ($param eq 'Debug') {
4539 0         0 $debug = $value;
4540 0         0 next;
4541             }
4542              
4543 0         0 croak "unknown parameter '$param'";
4544             }
4545              
4546 0 0       0 if ($debug) {
4547 0         0 printf "\n";
4548 0         0 printf "max_iter = %24d\n", $max_iter;
4549 0         0 printf "rel_tol = %24.15e\n", $rel_tol;
4550 0         0 printf "abs_tol = %24.15e\n", $abs_tol;
4551             }
4552              
4553 0         0 my $y_norm = _hypot(map { @$_ } @$y);
  0         0  
4554              
4555 0         0 my $x = $y -> mldiv($A);
4556              
4557 0         0 my $x_best;
4558             my $iter_best;
4559 0         0 my $abs_err_best;
4560 0         0 my $rel_err_best;
4561              
4562 0         0 for (my $iter = 1 ; ; $iter++) {
4563              
4564             # Compute the residuals.
4565              
4566 0         0 my $r = $A -> mmuladd($x, -$y);
4567              
4568             # Compute the errors.
4569              
4570 0         0 my $r_norm = _hypot(map @$_, @$r);
4571 0         0 my $abs_err = $r_norm;
4572 0 0       0 my $rel_err = $y_norm == 0 ? $r_norm : $r_norm / $y_norm;
4573              
4574 0 0       0 if ($debug) {
4575 0         0 printf "\n";
4576 0         0 printf "iter = %24d\n", $iter;
4577 0         0 printf "r_norm = %24.15e\n", $r_norm;
4578 0         0 printf "y_norm = %24.15e\n", $y_norm;
4579 0         0 printf "abs_err = %24.15e\n", $abs_err;
4580 0         0 printf "rel_err = %24.15e\n", $rel_err;
4581             }
4582              
4583             # See if this is the first round or we have an new all-time best.
4584              
4585 0 0 0     0 if ($iter == 1 ||
      0        
4586             $abs_err < $abs_err_best ||
4587             $rel_err < $rel_err_best)
4588             {
4589 0         0 $x_best = $x;
4590 0         0 $iter_best = $iter;
4591 0         0 $abs_err_best = $abs_err;
4592 0         0 $rel_err_best = $rel_err;
4593             }
4594              
4595 0 0 0     0 if ($abs_err_best <= $abs_tol || $rel_err_best <= $rel_tol) {
4596 0         0 last;
4597             } else {
4598              
4599             # If we still haven't got the desired result, but have reached
4600             # the maximum number of iterations, display a warning.
4601              
4602 0 0       0 if ($iter == $max_iter) {
4603 0         0 carp "mldiv() stopped because the maximum number of",
4604             " iterations (max. iter = $max_iter) was reached without",
4605             " converging to any of the desired tolerances (",
4606             "rel_tol = ", $rel_tol, ", ",
4607             "abs_tol = ", $abs_tol, ").",
4608             " The best iterate (iter. = ", $iter_best, ") has",
4609             " a relative residual of ", $rel_err_best, " and",
4610             " an absolute residual of ", $abs_err_best, ".";
4611 0         0 last;
4612             }
4613             }
4614              
4615             # Compute delta $x.
4616              
4617 0         0 my $d = $r -> mldiv($A);
4618              
4619             # Compute the improved solution $x.
4620              
4621 0         0 $x -= $d;
4622             }
4623              
4624 0 0       0 return $x_best, $rel_err_best, $abs_err_best, $iter_best if wantarray;
4625 0         0 return $x_best;
4626             }
4627              
4628             # If A is an M-by-M, compute A\y directly.
4629              
4630 8 50       29 croak "mldiv(): sizes don't match" unless $y -> nrow() == $n;
4631              
4632             # Create the augmented matrix.
4633              
4634 8         28 my $x = $A -> catcol($y);
4635              
4636             # Perform forward elimination.
4637              
4638 8         18 my ($rowperm, $colperm);
4639 8         19 eval { ($x, $rowperm, $colperm) = $x -> felim_fp() };
  8         28  
4640 8 50       63 croak "mldiv(): matrix is singular or close to singular" if $@;
4641              
4642             # Perform backward substitution.
4643              
4644 8         15 eval { $x = $x -> bsubs() };
  8         35  
4645 8 50       22 croak "mldiv(): matrix is singular or close to singular" if $@;
4646              
4647             # Remove left half to keep only the augmented matrix.
4648              
4649 8         31 $x = $x -> splicecol(0, $n);
4650              
4651             # Reordering the rows is only necessary when full (complete) pivoting is
4652             # used above. If partial pivoting is used, this reordeing could be skipped,
4653             # but it executes so fast that it causes no harm to do it anyway.
4654              
4655 8         31 @$x[ @$colperm ] = @$x;
4656              
4657 8         40 return $x;
4658             }
4659              
4660             =pod
4661              
4662             =item sldiv()
4663              
4664             Scalar (left) division.
4665              
4666             $x -> sldiv($y);
4667              
4668             For scalars, there is no difference between left and right division, so this is
4669             just an alias for C>.
4670              
4671             =cut
4672              
4673             sub sldiv {
4674 2     2 1 10 my $x = shift;
4675 2         6 $x -> sdiv(@_)
4676             }
4677              
4678             =pod
4679              
4680             =item mrdiv()
4681              
4682             Matrix right division. Returns the solution x of the linear system of equations
4683             x*A = y, by computing x = y/A = y*inv(A) = (A'\y')', where A' and y' denote the
4684             transpose of A and y, respectively, and \ is matrix left division (see
4685             C>).
4686              
4687             $x = $y -> mrdiv($A);
4688              
4689             See the section L for a list of
4690             additional parameters that can be used for trying to obtain a better solution
4691             through iteration.
4692              
4693             =cut
4694              
4695             sub mrdiv {
4696 1 50   1 1 20 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4697             #croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4698 1         3 my $y = shift;
4699 1         2 my $class = ref $y;
4700              
4701 1         2 my $A = shift;
4702 1 50 33     15 $A = $class -> new($A) unless defined(blessed($A)) && $A -> isa($class);
4703              
4704 1         7 $y -> transpose() -> mldiv($A -> transpose(), @_) -> transpose();
4705             }
4706              
4707             =pod
4708              
4709             =item srdiv()
4710              
4711             Scalar (right) division.
4712              
4713             $x -> srdiv($y);
4714              
4715             For scalars, there is no difference between left and right division, so this is
4716             just an alias for C>.
4717              
4718             =cut
4719              
4720             sub srdiv {
4721 2     2 1 10 my $x = shift;
4722 2         5 $x -> sdiv(@_)
4723             }
4724              
4725             =pod
4726              
4727             =item sdiv()
4728              
4729             Scalar division. Performs scalar (element by element) division.
4730              
4731             $x -> sdiv($y);
4732              
4733             =cut
4734              
4735             sub sdiv {
4736 6 50   6 1 30 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4737 6 50       12 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4738 6         9 my $x = shift;
4739              
4740 6     126   24 my $sub = sub { $_[0] / $_[1] };
  126         241  
4741 6         19 $x -> sapply($sub, @_);
4742             }
4743              
4744             =pod
4745              
4746             =item mpinv()
4747              
4748             Matrix pseudo-inverse, C<(A'*A)^(-1)*A'>, where "C<'>" is the transpose
4749             operator.
4750              
4751             See the section L for a list of
4752             additional parameters that can be used for trying to obtain a better solution
4753             through iteration.
4754              
4755             =cut
4756              
4757             sub mpinv {
4758 2     2 1 21 my $A = shift;
4759              
4760 2         7 my $At = $A -> transpose();
4761 2         8 return $At -> mldiv($At -> mmul($A), @_);
4762             }
4763              
4764             =pod
4765              
4766             =item pinv()
4767              
4768             This is an alias for C>.
4769              
4770             =cut
4771              
4772             sub pinv {
4773 1     1 1 6 my $x = shift;
4774 1         3 $x -> mpinv();
4775             }
4776              
4777             =pod
4778              
4779             =item pinvert()
4780              
4781             This is an alias for C>.
4782              
4783             =cut
4784              
4785             sub pinvert {
4786 0     0 1 0 my $x = shift;
4787 0         0 $x -> mpinv();
4788             }
4789              
4790             =pod
4791              
4792             =item solve()
4793              
4794             Solves a equation system given by the matrix. The number of colums must be
4795             greater than the number of rows. If variables are dependent from each other,
4796             the second and all further of the dependent coefficients are 0. This means the
4797             method can handle such systems. The method returns a matrix containing the
4798             solutions in its columns or B in case of error.
4799              
4800             =cut
4801              
4802             sub solve {
4803 3     3 1 21 my $self = shift;
4804 3         8 my $class = ref($self);
4805              
4806 3         7 my $m = $self->clone();
4807 3         5 my $mr = $#{$m};
  3         7  
4808 3         5 my $mc = $#{$m->[0]};
  3         7  
4809 3         15 my $f;
4810             my $try;
4811              
4812 3 50       10 return undef if $mc <= $mr;
4813 3         10 ROW: for(my $i = 0; $i <= $mr; $i++) {
4814 9         13 $try=$i;
4815             # make diagonal element nonzero if possible
4816 9         24 while (abs($m->[$i]->[$i]) < $eps) {
4817 0 0       0 last ROW if $try++ > $mr;
4818 0         0 my $row = splice(@{$m},$i,1);
  0         0  
4819 0         0 push(@{$m}, $row);
  0         0  
4820             }
4821              
4822             # normalize row
4823 9         13 $f = $m->[$i]->[$i];
4824 9         21 for (my $k = 0; $k <= $mc; $k++) {
4825 42         74 $m->[$i]->[$k] /= $f;
4826             }
4827             # subtract multiple of designated row from other rows
4828 9         17 for (my $j = 0; $j <= $mr; $j++) {
4829 27 100       61 next if $i == $j;
4830 18         24 $f = $m->[$j]->[$i];
4831 18         40 for (my $k = 0; $k <= $mc; $k++) {
4832 84         162 $m->[$j]->[$k] -= $m->[$i]->[$k] * $f;
4833             }
4834             }
4835             }
4836              
4837             # Answer is in augmented column
4838 3         7 $class -> new([ @{ $m -> transpose }[$mr+1 .. $mc] ]) -> transpose;
  3         9  
4839             }
4840              
4841             =pod
4842              
4843             =back
4844              
4845             =head3 Factorisation
4846              
4847             =over 4
4848              
4849             =item chol()
4850              
4851             Cholesky decomposition.
4852              
4853             $L = $A -> chol();
4854              
4855             Every symmetric, positive definite matrix A can be decomposed into a product of
4856             a unique lower triangular matrix L and its transpose, so that A = L*L', where L'
4857             denotes the transpose of L. L is called the Cholesky factor of A.
4858              
4859             =cut
4860              
4861             sub chol {
4862 2     2 1 23 my $x = shift;
4863 2         3 my $class = ref $x;
4864              
4865 2 50       6 croak "Input matrix must be a symmetric" unless $x -> is_symmetric();
4866              
4867 2         11 my $y = [ map [ (0) x @$x ], @$x ]; # matrix of zeros
4868 2         6 for my $i (0 .. $#$x) {
4869 7         12 for my $j (0 .. $i) {
4870 16         19 my $z = $x->[$i][$j];
4871 16         36 $z -= $y->[$i][$_] * $y->[$j][$_] for 0 .. $j;
4872 16 100       37 if ($i == $j) {
4873 7 50       14 croak "Matrix is not positive definite" if $z < 0;
4874 7         16 $y->[$i][$j] = sqrt($z);
4875             } else {
4876 9 50       16 croak "Matrix is not positive definite" if $y->[$j][$j] == 0;
4877 9         20 $y->[$i][$j] = $z / $y->[$j][$j];
4878             }
4879             }
4880             }
4881 2         8 bless $y, $class;
4882             }
4883              
4884             =pod
4885              
4886             =back
4887              
4888             =head3 Miscellaneous matrix functions
4889              
4890             =over 4
4891              
4892             =item transpose()
4893              
4894             Returns the transposed matrix. This is the matrix where colums and rows of the
4895             argument matrix are swapped.
4896              
4897             A subclass implementing matrices of complex numbers should provide a
4898             C> method that takes the complex conjugate of each element.
4899              
4900             =cut
4901              
4902             sub transpose {
4903 34     34 1 228 my $x = shift;
4904 34         60 my $class = ref $x;
4905              
4906 34         70 my $y = bless [], $class;
4907 34         88 my $ncolx = $x -> ncol();
4908 34 100       125 return $y if $ncolx == 0;
4909              
4910 30         84 for my $j (0 .. $ncolx - 1) {
4911 88         287 push @$y, [ map $_->[$j], @$x ];
4912             }
4913 30         107 return $y;
4914             }
4915              
4916             =pod
4917              
4918             =item minormatrix()
4919              
4920             Minor matrix. The (i,j) minor matrix of a matrix is identical to the original
4921             matrix except that row i and column j has been removed.
4922              
4923             $y = $x -> minormatrix($i, $j);
4924              
4925             See also C>.
4926              
4927             =cut
4928              
4929             sub minormatrix {
4930 37 50   37 1 101 croak "Not enough arguments for ", (caller(0))[3] if @_ < 3;
4931 37 50       70 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
4932 37         50 my $x = shift;
4933 37         76 my $class = ref $x;
4934              
4935 37         66 my ($m, $n) = $x -> size();
4936              
4937 37         56 my $i = shift;
4938 37 50 33     145 croak "Row index value $i outside of $m-by-$n matrix"
4939             unless 0 <= $i && $i < $m;
4940              
4941 37         55 my $j = shift;
4942 37 50 33     123 croak "Column index value $j outside of $m-by-$n matrix"
4943             unless 0 <= $j && $j < $n;
4944              
4945             # We could just use the following, which is simpler, but also slower:
4946             #
4947             # $x -> delrow($i) -> delcol($j);
4948              
4949 37         92 my @rowidx = 0 .. $m - 1;
4950 37         61 splice @rowidx, $i, 1;
4951              
4952 37         77 my @colidx = 0 .. $n - 1;
4953 37         62 splice @colidx, $j, 1;
4954              
4955 37         51 bless [ map [ @{$_}[@colidx] ], @{$x}[@rowidx] ], $class;
  74         259  
  37         77  
4956             }
4957              
4958             =pod
4959              
4960             =item minor()
4961              
4962             Minor. The (i,j) minor of a matrix is the determinant of the (i,j) minor matrix.
4963              
4964             $y = $x -> minor($i, $j);
4965              
4966             See also C>.
4967              
4968             =cut
4969              
4970             sub minor {
4971 36 50   36 1 4181 croak "Not enough arguments for ", (caller(0))[3] if @_ < 3;
4972 36 50       69 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
4973 36         53 my $x = shift;
4974              
4975 36 50       83 croak "Matrix must be square" unless $x -> is_square();
4976              
4977 36         86 $x -> minormatrix(@_) -> determinant();
4978             }
4979              
4980             =pod
4981              
4982             =item cofactormatrix()
4983              
4984             Cofactor matrix. Element (i,j) in the cofactor matrix is the (i,j) cofactor,
4985             which is (-1)^(i+j) multiplied by the determinant of the (i,j) minor matrix.
4986              
4987             $y = $x -> cofactormatrix();
4988              
4989             =cut
4990              
4991             sub cofactormatrix {
4992 4 50   4 1 32 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
4993 4 50       12 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
4994 4         7 my $x = shift;
4995              
4996 4         12 my ($m, $n) = $x -> size();
4997 4 50       12 croak "matrix must be square" unless $m == $n;
4998              
4999 4         7 my $y = [];
5000 4         16 for my $i (0 .. $m - 1) {
5001 6         13 for my $j (0 .. $n - 1) {
5002 18         52 $y -> [$i][$j] = (-1) ** ($i + $j) * $x -> minor($i, $j);
5003             }
5004             }
5005              
5006 4         13 bless $y;
5007             }
5008              
5009             =pod
5010              
5011             =item cofactor()
5012              
5013             Cofactor. The (i,j) cofactor of a matrix is (-1)**(i+j) times the (i,j) minor of
5014             the matrix.
5015              
5016             $y = $x -> cofactor($i, $j);
5017              
5018             =cut
5019              
5020             sub cofactor {
5021 9 50   9 1 4028 croak "Not enough arguments for ", (caller(0))[3] if @_ < 3;
5022 9 50       24 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
5023 9         16 my $x = shift;
5024              
5025 9         20 my ($m, $n) = $x -> size();
5026 9 50       21 croak "matrix must be square" unless $m == $n;
5027              
5028 9         16 my ($i, $j) = @_;
5029 9         27 (-1) ** ($i + $j) * $x -> minor($i, $j);
5030             }
5031              
5032             =pod
5033              
5034             =item adjugate()
5035              
5036             Adjugate of a matrix. The adjugate, also called classical adjoint or adjunct, of
5037             a square matrix is the transpose of the cofactor matrix.
5038              
5039             $y = $x -> adjugate();
5040              
5041             =cut
5042              
5043             sub adjugate {
5044 2 50   2 1 38 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5045 2 50       9 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
5046 2         3 my $x = shift;
5047              
5048 2         8 $x -> cofactormatrix() -> transpose();
5049             }
5050              
5051             =pod
5052              
5053             =item det()
5054              
5055             Determinant. Returns the determinant of a matrix. The matrix must be square.
5056              
5057             $y = $x -> det();
5058              
5059             The matrix is computed by forward elimination, which might cause round-off
5060             errors. So for example, the determinant might be a non-integer even for an
5061             integer matrix.
5062              
5063             =cut
5064              
5065             sub det {
5066 59 50   59 1 158 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5067 59 50       117 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
5068 59         78 my $x = shift;
5069 59         99 my $class = ref $x;
5070              
5071 59         120 my ($nrowx, $ncolx) = $x -> size();
5072 59 50       161 croak "matrix must be square" unless $nrowx == $ncolx;
5073              
5074             # Create the augmented matrix.
5075              
5076 59         146 $x = $x -> catcol($class -> id($nrowx));
5077              
5078             # Perform forward elimination.
5079              
5080 59         186 my ($iperm, $jperm, $iswap, $jswap);
5081 59         103 eval { ($x, $iperm, $jperm, $iswap, $jswap) = $x -> felim_fp() };
  59         131  
5082              
5083             # Compute the product of the elements on the diagonal.
5084              
5085 59         153 my $det = 1;
5086 59         150 for (my $i = 0 ; $i < $nrowx ; ++$i) {
5087 140 100       337 last if ($det *= $x -> [$i][$i]) == 0;
5088             }
5089              
5090             # Adjust the sign according to the number of inversions.
5091              
5092 59 100       144 $det = ($iswap + $jswap) % 2 ? -$det : $det;
5093              
5094 59         254 return $det;
5095             }
5096              
5097             =pod
5098              
5099             =item determinant()
5100              
5101             This is an alias for C>.
5102              
5103             =cut
5104              
5105             sub determinant {
5106 56     56 1 112 my $x = shift;
5107 56         152 $x -> det(@_);
5108             }
5109              
5110             =pod
5111              
5112             =item detr()
5113              
5114             Determinant. Returns the determinant of a matrix. The matrix must be square.
5115              
5116             $y = $x -> determinant();
5117              
5118             The determinant is computed by recursion, so it is generally much slower than
5119             C>.
5120              
5121             =cut
5122              
5123             sub detr {
5124 3     3 1 21 my $x = shift;
5125 3         8 my $class = ref($x);
5126 3         5 my $imax = $#$x;
5127 3         6 my $jmax = $#{$x->[0]};
  3         4  
5128              
5129 3 50       10 return undef unless $imax == $jmax; # input must be a square matrix
5130              
5131             # Matrix is 3 × 3
5132              
5133             return
5134 3 100       16 $x -> [0][0] * ($x -> [1][1] * $x -> [2][2] - $x -> [1][2] * $x -> [2][1])
5135             - $x -> [0][1] * ($x -> [1][0] * $x -> [2][2] - $x -> [1][2] * $x -> [2][0])
5136             + $x -> [0][2] * ($x -> [1][0] * $x -> [2][1] - $x -> [1][1] * $x -> [2][0])
5137             if $imax == 2;
5138              
5139             # Matrix is 2 × 2
5140              
5141 2 50       5 return $x -> [0][0] * $x -> [1][1] - $x -> [1][0] * $x -> [0][1]
5142             if $imax == 1;
5143              
5144             # Matrix is 1 × 1
5145              
5146 2 100       6 return $x -> [0][0] if $imax == 0;
5147              
5148             # Matrix is N × N for N > 3.
5149              
5150 1         2 my $det = 0;
5151              
5152             # Create a matrix with column 0 removed. We only need to do this once.
5153 1         3 my $x0 = bless [ map [ @{$_}[1 .. $jmax] ], @$x ], $class;
  5         12  
5154              
5155 1         4 for my $i (0 .. $imax) {
5156              
5157             # Create a matrix with row $i and column 0 removed.
5158 5         12 my $x1 = bless [ map [ @$_ ], @{$x0}[ 0 .. $i-1, $i+1 .. $imax ] ], $class;
  5         21  
5159              
5160 5         13 my $term = $x1 -> determinant();
5161 5 100       15 $term *= $i % 2 ? -$x->[$i][0] : $x->[$i][0];
5162              
5163 5         14 $det += $term;
5164             }
5165              
5166 1         4 return $det;
5167             }
5168              
5169             =pod
5170              
5171             =back
5172              
5173             =head3 Elementwise mathematical functions
5174              
5175             These method work on each element of a matrix.
5176              
5177             =over 4
5178              
5179             =item int()
5180              
5181             Truncate to integer. Truncates each element to an integer.
5182              
5183             $y = $x -> int();
5184              
5185             This function is effectivly the same as
5186              
5187             $y = $x -> map(sub { int });
5188              
5189             =cut
5190              
5191             sub int {
5192 4 50   4 1 26 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5193 4 50       9 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
5194 4         6 my $x = shift;
5195              
5196 4         61 bless [ map [ map int($_), @$_ ], @$x ], ref $x;
5197             }
5198              
5199             =pod
5200              
5201             =item floor()
5202              
5203             Round to negative infinity. Rounds each element to negative infinity.
5204              
5205             $y = $x -> floor();
5206              
5207             =cut
5208              
5209             sub floor {
5210 2 50   2 1 25 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5211 2 50       6 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
5212 2         4 my $x = shift;
5213              
5214 2         44 bless [ map { [
5215             map {
5216 6         9 my $ix = CORE::int($_);
  24         38  
5217 24 100       48 ($ix <= $_) ? $ix : $ix - 1;
5218             } @$_
5219             ] } @$x ], ref $x;
5220             }
5221              
5222             =pod
5223              
5224             =item ceil()
5225              
5226             Round to positive infinity. Rounds each element to positive infinity.
5227              
5228             $y = $x -> int();
5229              
5230             =cut
5231              
5232             sub ceil {
5233 2 50   2 1 25 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5234 2 50       5 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
5235 2         4 my $x = shift;
5236              
5237 2         41 bless [ map { [
5238             map {
5239 6         10 my $ix = CORE::int($_);
  24         32  
5240 24 100       53 ($ix >= $_) ? $ix : $ix + 1;
5241             } @$_
5242             ] } @$x ], ref $x;
5243             }
5244              
5245             =pod
5246              
5247             =item abs()
5248              
5249             Absolute value. The absolute value of each element.
5250              
5251             $y = $x -> abs();
5252              
5253             This is effectivly the same as
5254              
5255             $y = $x -> map(sub { abs });
5256              
5257             =cut
5258              
5259             sub abs {
5260 3 50   3 1 27 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5261 3 50       7 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
5262 3         5 my $x = shift;
5263              
5264 3         71 bless [ map [ map abs($_), @$_ ], @$x ], ref $x;
5265             }
5266              
5267             =pod
5268              
5269             =item sign()
5270              
5271             Sign function. Apply the sign function to each element.
5272              
5273             $y = $x -> sign();
5274              
5275             This is effectivly the same as
5276              
5277             $y = $x -> map(sub { $_ <=> 0 });
5278              
5279             =cut
5280              
5281             sub sign {
5282 2 50   2 1 14 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5283 2 50       5 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
5284 2         4 my $x = shift;
5285              
5286 2         6 bless [ map [ map { $_ <=> 0 } @$_ ], @$x ], ref $x;
  24         41  
5287             }
5288              
5289             =pod
5290              
5291             =back
5292              
5293             =head3 Columnwise or rowwise mathematical functions
5294              
5295             These method work along each column or row of a matrix. Some of these methods
5296             return a matrix with the same size as the invocand matrix. Other methods
5297             collapse the dimension, so that, e.g., if the method is applied to the first
5298             dimension a I

-by-I matrix becomes a 1-by-I matrix, and if applied to

5299             the second dimension, it becomes a I

-by-1 matrix. Others, like C>,

5300             reduces the length along the dimension by one, so a I

-by-I matrix becomes

5301             a (I

-1)-by-I or a I

-by-(I-1) matrix.

5302              
5303             =over 4
5304              
5305             =item sum()
5306              
5307             Sum of elements along various dimensions of a matrix. If the dimension argument
5308             is not given, the first non-singleton dimension is used.
5309              
5310             $y = $x -> sum($dim);
5311             $y = $x -> sum();
5312              
5313             =cut
5314              
5315             sub sum {
5316 12 50   12 1 78 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5317 12 50       24 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5318 12         19 my $x = shift;
5319 12         53 $x -> apply(\&_sum, @_);
5320             }
5321              
5322             =pod
5323              
5324             =item prod()
5325              
5326             Product of elements along various dimensions of a matrix. If the dimension
5327             argument is not given, the first non-singleton dimension is used.
5328              
5329             $y = $x -> prod($dim);
5330             $y = $x -> prod();
5331              
5332             =cut
5333              
5334             sub prod {
5335 12 50   12 1 84 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5336 12 50       27 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5337 12         17 my $x = shift;
5338 12         58 $x -> apply(\&_prod, @_);
5339             }
5340              
5341             =pod
5342              
5343             =item mean()
5344              
5345             Mean of elements along various dimensions of a matrix. If the dimension argument
5346             is not given, the first non-singleton dimension is used.
5347              
5348             $y = $x -> mean($dim);
5349             $y = $x -> mean();
5350              
5351             =cut
5352              
5353             sub mean {
5354 12 50   12 1 75 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5355 12 50       24 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5356 12         17 my $x = shift;
5357 12         39 $x -> apply(\&_mean, @_);
5358             }
5359              
5360             =pod
5361              
5362             =item hypot()
5363              
5364             Hypotenuse. Computes the square root of the sum of the square of each element
5365             along various dimensions of a matrix. If the dimension argument is not given,
5366             the first non-singleton dimension is used.
5367              
5368             $y = $x -> hypot($dim);
5369             $y = $x -> hypot();
5370              
5371             For example,
5372              
5373             $x = Math::Matrix -> new([[3, 4],
5374             [5, 12]]);
5375             $y = $x -> hypot(2);
5376              
5377             returns the 2-by-1 matrix
5378              
5379             [ 5 ]
5380             [ 13 ]
5381              
5382             =cut
5383              
5384             sub hypot {
5385 12 50   12 1 72 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5386 12 50       24 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5387 12         15 my $x = shift;
5388 12         38 $x -> apply(\&_hypot, @_);
5389             }
5390              
5391             =pod
5392              
5393             =item min()
5394              
5395             Minimum of elements along various dimensions of a matrix. If the dimension
5396             argument is not given, the first non-singleton dimension is used.
5397              
5398             $y = $x -> min($dim);
5399             $y = $x -> min();
5400              
5401             =cut
5402              
5403             sub min {
5404 12 50   12 1 88 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5405 12 50       23 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5406 12         20 my $x = shift;
5407 12         40 $x -> apply(\&_min, @_);
5408             }
5409              
5410             =pod
5411              
5412             =item max()
5413              
5414             Maximum of elements along various dimensions of a matrix. If the dimension
5415             argument is not given, the first non-singleton dimension is used.
5416              
5417             $y = $x -> max($dim);
5418             $y = $x -> max();
5419              
5420             =cut
5421              
5422             sub max {
5423 12 50   12 1 91 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5424 12 50       25 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5425 12         19 my $x = shift;
5426 12         38 $x -> apply(\&_max, @_);
5427             }
5428              
5429             =pod
5430              
5431             =item median()
5432              
5433             Median of elements along various dimensions of a matrix. If the dimension
5434             argument is not given, the first non-singleton dimension is used.
5435              
5436             $y = $x -> median($dim);
5437             $y = $x -> median();
5438              
5439             =cut
5440              
5441             sub median {
5442 12 50   12 1 76 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5443 12 50       24 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5444 12         19 my $x = shift;
5445 12         40 $x -> apply(\&_median, @_);
5446             }
5447              
5448             =pod
5449              
5450             =item cumsum()
5451              
5452             Returns the cumulative sum along various dimensions of a matrix. If the
5453             dimension argument is not given, the first non-singleton dimension is used.
5454              
5455             $y = $x -> cumsum($dim);
5456             $y = $x -> cumsum();
5457              
5458             =cut
5459              
5460             sub cumsum {
5461 12 50   12 1 91 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5462 12 50       25 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5463 12         18 my $x = shift;
5464 12         39 $x -> apply(\&_cumsum, @_);
5465             }
5466              
5467             =pod
5468              
5469             =item cumprod()
5470              
5471             Returns the cumulative product along various dimensions of a matrix. If the
5472             dimension argument is not given, the first non-singleton dimension is used.
5473              
5474             $y = $x -> cumprod($dim);
5475             $y = $x -> cumprod();
5476              
5477             =cut
5478              
5479             sub cumprod {
5480 12 50   12 1 78 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5481 12 50       19 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5482 12         20 my $x = shift;
5483 12         37 $x -> apply(\&_cumprod, @_);
5484             }
5485              
5486             =pod
5487              
5488             =item cummean()
5489              
5490             Returns the cumulative mean along various dimensions of a matrix. If the
5491             dimension argument is not given, the first non-singleton dimension is used.
5492              
5493             $y = $x -> cummean($dim);
5494             $y = $x -> cummean();
5495              
5496             =cut
5497              
5498             sub cummean {
5499 12 50   12 1 81 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5500 12 50       24 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5501 12         17 my $x = shift;
5502 12         37 $x -> apply(\&_cummean, @_);
5503             }
5504              
5505             =pod
5506              
5507             =item diff()
5508              
5509             Returns the differences between adjacent elements. If the dimension argument is
5510             not given, the first non-singleton dimension is used.
5511              
5512             $y = $x -> diff($dim);
5513             $y = $x -> diff();
5514              
5515             =cut
5516              
5517             sub diff {
5518 12 50   12 1 79 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5519 12 50       25 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5520 12         14 my $x = shift;
5521 12         37 $x -> apply(\&_diff, @_);
5522             }
5523              
5524             =pod
5525              
5526             =item vecnorm()
5527              
5528             Return the C<$p>-norm of the elements of C<$x>. If the dimension argument is not
5529             given, the first non-singleton dimension is used.
5530              
5531             $y = $x -> vecnorm($p, $dim);
5532             $y = $x -> vecnorm($p);
5533             $y = $x -> vecnorm();
5534              
5535             The C<$p>-norm of a vector is defined as the C<$p>th root of the sum of the
5536             absolute values fo the elements raised to the C<$p>th power.
5537              
5538             =cut
5539              
5540             sub vecnorm {
5541 34 50   34 1 212 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5542 34 50       68 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
5543 34         44 my $x = shift;
5544 34         87 my $class = ref $x;
5545              
5546 34         46 my $p = 2;
5547 34 100       62 if (@_) {
5548 28         42 $p = shift;
5549 28 50       55 croak 'When the \$p argument is given, it can not be undefined'
5550             unless defined $p;
5551 28 50       50 if (ref $p) {
5552 0 0 0     0 $p = $class -> new($p)
5553             unless defined(blessed($p)) && $p -> isa($class);
5554 0 0       0 croak 'The $p argument must be a scalar' unless $p -> is_scalar();
5555 0         0 $p = $p -> [0][0];
5556             }
5557             }
5558              
5559 34     46   125 my $sub = sub { _vecnorm($p, @_) };
  46         94  
5560 34         82 $x -> apply($sub, @_);
5561             }
5562              
5563             =pod
5564              
5565             =item apply()
5566              
5567             Applies a subroutine to each row or column of a matrix. If the dimension
5568             argument is not given, the first non-singleton dimension is used.
5569              
5570             $y = $x -> apply($sub, $dim);
5571             $y = $x -> apply($sub);
5572              
5573             The subroutine is passed a list with all elements in a single column or row.
5574              
5575             =cut
5576              
5577             sub apply {
5578 226     226 1 328 my $x = shift;
5579 226         411 my $class = ref $x;
5580              
5581 226         296 my $sub = shift;
5582              
5583             # Get the size of the input $x.
5584              
5585 226         511 my ($nrowx, $ncolx) = $x -> size();
5586              
5587             # Get the dimension along which to apply the subroutine.
5588              
5589 226         322 my $dim;
5590 226 100       429 if (@_) {
5591 144         213 $dim = shift;
5592 144 50       314 croak "Dimension can not be undefined" unless defined $dim;
5593 144 50       292 if (ref $dim) {
5594 0 0 0     0 $dim = $class -> new($dim)
5595             unless defined(blessed($dim)) && $dim -> isa($class);
5596 0 0       0 croak "Dimension must be a scalar" unless $dim -> is_scalar();
5597 0         0 $dim = $dim -> [0][0];
5598 0 0 0     0 croak "Dimension must be a positive integer"
5599             unless $dim > 0 && $dim == CORE::int($dim);
5600             }
5601 144 50 66     461 croak "Dimension must be 1 or 2" unless $dim == 1 || $dim == 2;
5602             } else {
5603 82 100       193 $dim = $nrowx > 1 ? 1 : 2;
5604             }
5605              
5606             # Initialise output.
5607              
5608 226         339 my $y = [];
5609              
5610             # Work along the first dimension, i.e., each column.
5611              
5612 226         370 my ($nrowy, $ncoly);
5613 226 100       531 if ($dim == 1) {
    50          
5614 114         176 $nrowy = 0;
5615 114         249 for my $j (0 .. $ncolx - 1) {
5616 289         905 my @col = $sub -> (map $_ -> [$j], @$x);
5617 289 100       543 if ($j == 0) {
5618 98         157 $nrowy = @col;
5619             } else {
5620 191 50       366 croak "The number of elements in each column must be the same"
5621             unless $nrowy == @col;
5622             }
5623 289         968 $y -> [$_][$j] = $col[$_] for 0 .. $#col;
5624             }
5625 114 100       269 $y = [] if $nrowy == 0;
5626             }
5627              
5628             # Work along the second dimension, i.e., each row.
5629              
5630             elsif ($dim == 2) {
5631 112         166 $ncoly = 0;
5632 112         246 for my $i (0 .. $nrowx - 1) {
5633 169         239 my @row = $sub -> (@{ $x -> [$i] });
  169         372  
5634 169 100       339 if ($i == 0) {
5635 76         119 $ncoly = @row;
5636             } else {
5637 93 50       200 croak "The number of elements in each row must be the same"
5638             unless $ncoly == @row;
5639             }
5640 169         414 $y -> [$i] = [ @row ];
5641             }
5642 112 100       256 $y = [] if $ncoly == 0;
5643             }
5644              
5645 226         780 bless $y, $class;
5646             }
5647              
5648             =pod
5649              
5650             =back
5651              
5652             =head2 Comparison
5653              
5654             =head3 Matrix comparison
5655              
5656             Methods matrix comparison. These methods return a scalar value.
5657              
5658             =over 4
5659              
5660             =item meq()
5661              
5662             Matrix equal to. Returns 1 if two matrices are identical and 0 otherwise.
5663              
5664             $bool = $x -> meq($y);
5665              
5666             =cut
5667              
5668             sub meq {
5669 7 50   7 1 43 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
5670 7 50       28 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5671 7         12 my $x = shift;
5672 7         12 my $class = ref $x;
5673              
5674 7         11 my $y = shift;
5675 7 100 66     50 $y = $class -> new($y)
5676             unless defined(blessed($y)) && $y -> isa($class);
5677              
5678 7         22 my ($nrowx, $ncolx) = $x -> size();
5679 7         12 my ($nrowy, $ncoly) = $y -> size();
5680              
5681             # Quick exit if the sizes don't match.
5682              
5683 7 100 66     28 return 0 unless $nrowx == $nrowy && $ncolx == $ncoly;
5684              
5685             # Compare the elements.
5686              
5687 6         14 for my $i (0 .. $nrowx - 1) {
5688 5         13 for my $j (0 .. $ncolx - 1) {
5689 20 100       51 return 0 if $x->[$i][$j] != $y->[$i][$j];
5690             }
5691             }
5692 4         12 return 1;
5693             }
5694              
5695             =pod
5696              
5697             =item mne()
5698              
5699             Matrix not equal to. Returns 1 if two matrices are different and 0 otherwise.
5700              
5701             $bool = $x -> mne($y);
5702              
5703             =cut
5704              
5705             sub mne {
5706 7 50   7 1 14239 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
5707 7 50       16 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5708 7         12 my $x = shift;
5709 7         14 my $class = ref $x;
5710              
5711 7         9 my $y = shift;
5712 7 100 66     50 $y = $class -> new($y)
5713             unless defined(blessed($y)) && $y -> isa($class);
5714              
5715 7         19 my ($nrowx, $ncolx) = $x -> size();
5716 7         14 my ($nrowy, $ncoly) = $y -> size();
5717              
5718             # Quick exit if the sizes don't match.
5719              
5720 7 100 66     24 return 1 unless $nrowx == $nrowy && $ncolx == $ncoly;
5721              
5722             # Compare the elements.
5723              
5724 6         18 for my $i (0 .. $nrowx - 1) {
5725 5         10 for my $j (0 .. $ncolx - 1) {
5726 20 100       49 return 1 if $x->[$i][$j] != $y->[$i][$j];
5727             }
5728             }
5729 4         15 return 0;
5730             }
5731              
5732             =pod
5733              
5734             =item equal()
5735              
5736             Decide if two matrices are equal. The criterion is, that each pair of elements
5737             differs less than $Math::Matrix::eps.
5738              
5739             $bool = $x -> equal($y);
5740              
5741             =cut
5742              
5743             sub equal {
5744 5     5 1 30 my $A = shift;
5745 5         8 my $B = shift;
5746              
5747 5         7 my $jmax = $#{$A->[0]};
  5         9  
5748 5         9 for my $i (0 .. $#{$A}) {
  5         10  
5749 15         20 for my $j (0 .. $jmax) {
5750 45 50       99 return 0 if CORE::abs($A->[$i][$j] - $B->[$i][$j]) >= $eps;
5751             }
5752             }
5753 5         19 return 1;
5754             }
5755              
5756             =pod
5757              
5758             =back
5759              
5760             =head3 Scalar comparison
5761              
5762             Each of these methods performs scalar (element by element) comparison and
5763             returns a matrix of ones and zeros. Scalar expansion is performed if necessary.
5764              
5765             =over 4
5766              
5767             =item seq()
5768              
5769             Scalar equality. Performs scalar (element by element) comparison of two
5770             matrices.
5771              
5772             $bool = $x -> seq($y);
5773              
5774             =cut
5775              
5776             sub seq {
5777 1 50   1 1 22 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
5778 1 50       6 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5779 1         2 my $x = shift;
5780 1         3 my $class = ref $x;
5781              
5782 1         1 my $y = shift;
5783 1 50 33     16 $y = $class -> new($y)
5784             unless defined(blessed($y)) && $y -> isa($class);
5785              
5786 1 100   9   11 $x -> sapply(sub { $_[0] == $_[1] ? 1 : 0 }, $y);
  9         21  
5787             }
5788              
5789             =pod
5790              
5791             =item sne()
5792              
5793             Scalar (element by element) not equal to. Performs scalar (element by element)
5794             comparison of two matrices.
5795              
5796             $bool = $x -> sne($y);
5797              
5798             =cut
5799              
5800             sub sne {
5801 1 50   1 1 8 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
5802 1 50       4 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5803 1         3 my $x = shift;
5804 1         2 my $class = ref $x;
5805              
5806 1         2 my $y = shift;
5807 1 50 33     9 $y = $class -> new($y)
5808             unless defined(blessed($y)) && $y -> isa($class);
5809              
5810 1 100   9   7 $x -> sapply(sub { $_[0] != $_[1] ? 1 : 0 }, $y);
  9         21  
5811             }
5812              
5813             =pod
5814              
5815             =item slt()
5816              
5817             Scalar (element by element) less than. Performs scalar (element by element)
5818             comparison of two matrices.
5819              
5820             $bool = $x -> slt($y);
5821              
5822             =cut
5823              
5824             sub slt {
5825 1 50   1 1 8 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
5826 1 50       6 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5827 1         2 my $x = shift;
5828 1         3 my $class = ref $x;
5829              
5830 1         2 my $y = shift;
5831 1 50 33     10 $y = $class -> new($y)
5832             unless defined(blessed($y)) && $y -> isa($class);
5833              
5834 1 100   9   5 $x -> sapply(sub { $_[0] < $_[1] ? 1 : 0 }, $y);
  9         23  
5835             }
5836              
5837             =pod
5838              
5839             =item sle()
5840              
5841             Scalar (element by element) less than or equal to. Performs scalar
5842             (element by element) comparison of two matrices.
5843              
5844             $bool = $x -> sle($y);
5845              
5846             =cut
5847              
5848             sub sle {
5849 1 50   1 1 8 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
5850 1 50       4 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5851 1         4 my $x = shift;
5852 1         2 my $class = ref $x;
5853              
5854 1         2 my $y = shift;
5855 1 50 33     11 $y = $class -> new($y)
5856             unless defined(blessed($y)) && $y -> isa($class);
5857              
5858 1 100   9   8 $x -> sapply(sub { $_[0] <= $_[1] ? 1 : 0 }, $y);
  9         22  
5859             }
5860              
5861             =pod
5862              
5863             =item sgt()
5864              
5865             Scalar (element by element) greater than. Performs scalar (element by element)
5866             comparison of two matrices.
5867              
5868             $bool = $x -> sgt($y);
5869              
5870             =cut
5871              
5872             sub sgt {
5873 1 50   1 1 9 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
5874 1 50       4 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5875 1         2 my $x = shift;
5876 1         3 my $class = ref $x;
5877              
5878 1         3 my $y = shift;
5879 1 50 33     9 $y = $class -> new($y)
5880             unless defined(blessed($y)) && $y -> isa($class);
5881              
5882 1 100   9   7 $x -> sapply(sub { $_[0] > $_[1] ? 1 : 0 }, $y);
  9         21  
5883             }
5884              
5885             =pod
5886              
5887             =item sge()
5888              
5889             Scalar (element by element) greater than or equal to. Performs scalar
5890             (element by element) comparison of two matrices.
5891              
5892             $bool = $x -> sge($y);
5893              
5894             =cut
5895              
5896             sub sge {
5897 1 50   1 1 9 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
5898 1 50       5 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5899 1         2 my $x = shift;
5900 1         3 my $class = ref $x;
5901              
5902 1         2 my $y = shift;
5903 1 50 33     11 $y = $class -> new($y)
5904             unless defined(blessed($y)) && $y -> isa($class);
5905              
5906 1 100   9   6 $x -> sapply(sub { $_[0] >= $_[1] ? 1 : 0 }, $y);
  9         23  
5907             }
5908              
5909             =pod
5910              
5911             =item scmp()
5912              
5913             Scalar (element by element) comparison. Performs scalar (element by element)
5914             comparison of two matrices. Each element in the output matrix is either -1, 0,
5915             or 1 depending on whether the elements are less than, equal to, or greater than
5916             each other.
5917              
5918             $bool = $x -> scmp($y);
5919              
5920             =cut
5921              
5922             sub scmp {
5923 1 50   1 1 9 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
5924 1 50       5 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
5925 1         2 my $x = shift;
5926 1         3 my $class = ref $x;
5927              
5928 1         3 my $y = shift;
5929 1 50 33     11 $y = $class -> new($y)
5930             unless defined(blessed($y)) && $y -> isa($class);
5931              
5932 1     9   7 $x -> sapply(sub { $_[0] <=> $_[1] }, $y);
  9         18  
5933             }
5934              
5935             =pod
5936              
5937             =back
5938              
5939             =head2 Vector functions
5940              
5941             =over 4
5942              
5943             =item dot_product()
5944              
5945             Compute the dot product of two vectors. The second operand does not have to be
5946             an object.
5947              
5948             # $x and $y are both objects
5949             $x = Math::Matrix -> new([1, 2, 3]);
5950             $y = Math::Matrix -> new([4, 5, 6]);
5951             $p = $x -> dot_product($y); # $p = 32
5952              
5953             # Only $x is an object.
5954             $p = $x -> dot_product([4, 5, 6]); # $p = 32
5955              
5956             =cut
5957              
5958             sub dot_product {
5959 3     3 1 1249 my $x = shift;
5960 3         20 my $class = ref $x;
5961              
5962 3         6 my $y = shift;
5963 3 100 66     32 $y = $class -> new($y)
5964             unless defined(blessed($y)) && $y -> isa($class);
5965              
5966 3 50       13 croak "First argument must be a vector" unless $x -> is_vector();
5967 3 100       15 $x = $x -> to_row() unless $x -> is_row();
5968              
5969 3 50       8 croak "Second argument must be a vector" unless $x -> is_vector();
5970 3 50       8 $y = $y -> to_col() unless $x -> is_col();
5971              
5972 3 50       8 croak "The two vectors must have the same length"
5973             unless $x -> nelm() == $y -> nelm();
5974              
5975 3         10 $x -> multiply($y) -> [0][0];
5976             }
5977              
5978             =pod
5979              
5980             =item outer_product()
5981              
5982             Compute the outer product of two vectors. The second operand does not have to be
5983             an object.
5984              
5985             # $x and $y are both objects
5986             $x = Math::Matrix -> new([1, 2, 3]);
5987             $y = Math::Matrix -> new([4, 5, 6, 7]);
5988             $p = $x -> outer_product($y);
5989              
5990             # Only $x is an object.
5991             $p = $x -> outer_product([4, 5, 6, y]);
5992              
5993             =cut
5994              
5995             sub outer_product {
5996 1     1 1 6 my $x = shift;
5997 1         13 my $class = ref $x;
5998              
5999 1         2 my $y = shift;
6000 1 50 33     15 $y = $class -> new($y)
6001             unless defined(blessed($y)) && $y -> isa($class);
6002              
6003 1 50       6 croak "First argument must be a vector" unless $x -> is_vector();
6004 1 50       3 $x = $x -> to_col() unless $x -> is_col();
6005              
6006 1 50       3 croak "Second argument must be a vector" unless $x -> is_vector();
6007 1 50       3 $y = $y -> to_row() unless $x -> is_row();
6008              
6009 1         4 $x -> multiply($y);
6010             }
6011              
6012             =pod
6013              
6014             =item absolute()
6015              
6016             Compute the absolute value (i.e., length) of a vector.
6017              
6018             $v = Math::Matrix -> new([3, 4]);
6019             $a = $v -> absolute(); # $v = 5
6020              
6021             =cut
6022              
6023             sub absolute {
6024 8     8 1 17 my $x = shift;
6025 8 50       34 croak "Argument must be a vector" unless $x -> is_vector();
6026              
6027 8         11 _hypot(@{ $x -> to_row() -> [0] });
  8         21  
6028             }
6029              
6030             =pod
6031              
6032             =item normalize()
6033              
6034             Normalize a vector, i.e., scale a vector so its length becomes 1.
6035              
6036             $v = Math::Matrix -> new([3, 4]);
6037             $u = $v -> normalize(); # $u = [ 0.6, 0.8 ]
6038              
6039             =cut
6040              
6041             sub normalize {
6042 2     2 1 5 my $vector = shift;
6043 2         16 my $length = $vector->absolute();
6044             return undef
6045 2 50       5 unless $length;
6046 2         8 $vector->multiply_scalar(1 / $length);
6047             }
6048              
6049             =pod
6050              
6051             =item cross_product()
6052              
6053             Compute the cross-product of vectors.
6054              
6055             $x = Math::Matrix -> new([1,3,2],
6056             [5,4,2]);
6057             $p = $x -> cross_product(); # $p = [ -2, 8, -11 ]
6058              
6059             =cut
6060              
6061             sub cross_product {
6062 3     3 1 26 my $vectors = shift;
6063 3         15 my $class = ref($vectors);
6064              
6065 3         5 my $dimensions = @{$vectors->[0]};
  3         47  
6066             return undef
6067 3 50       11 unless $dimensions == @$vectors + 1;
6068              
6069 3         5 my @axis;
6070 3         10 foreach my $column (0..$dimensions-1) {
6071 10         39 my $tmp = $vectors->slice(0..$column-1,
6072             $column+1..$dimensions-1);
6073 10         25 my $scalar = $tmp->determinant;
6074 10 100       23 $scalar *= ($column % 2) ? -1 : 1;
6075 10         28 push @axis, $scalar;
6076             }
6077 3         11 my $axis = $class->new(\@axis);
6078 3 100       13 $axis = $axis->multiply_scalar(($dimensions % 2) ? 1 : -1);
6079             }
6080              
6081             =pod
6082              
6083             =back
6084              
6085             =head2 Conversion
6086              
6087             =over 4
6088              
6089             =item as_string()
6090              
6091             Creates a string representation of the matrix and returns it.
6092              
6093             $x = Math::Matrix -> new([1, 2], [3, 4]);
6094             $s = $x -> as_string();
6095              
6096             =cut
6097              
6098             sub as_string {
6099 12     12 1 221 my $self = shift;
6100 12         20 my $out = "";
6101 12         19 for my $row (@{$self}) {
  12         111  
6102 23         34 for my $col (@{$row}) {
  23         33  
6103 64         279 $out = $out . sprintf "%10.5f ", $col;
6104             }
6105 23         37 $out = $out . sprintf "\n";
6106             }
6107 12         78 $out;
6108             }
6109              
6110             =pod
6111              
6112             =item as_array()
6113              
6114             Returns the matrix as an unblessed Perl array, i.e., and ordinary, unblessed
6115             reference.
6116              
6117             $y = $x -> as_array(); # ref($y) returns 'ARRAY'
6118              
6119             =cut
6120              
6121             sub as_array {
6122 3     3 1 25 my $x = shift;
6123 3         45 [ map [ @$_ ], @$x ];
6124             }
6125              
6126             =pod
6127              
6128             =back
6129              
6130             =head2 Matrix utilities
6131              
6132             =head3 Apply a subroutine to each element
6133              
6134             =over 4
6135              
6136             =item map()
6137              
6138             Call a subroutine for every element of a matrix, locally setting C<$_> to each
6139             element and passing the matrix row and column indices as input arguments.
6140              
6141             # square each element
6142             $y = $x -> map(sub { $_ ** 2 });
6143              
6144             # set strictly lower triangular part to zero
6145             $y = $x -> map(sub { $_[0] > $_[1] ? 0 : $_ })'
6146              
6147             =cut
6148              
6149             sub map {
6150 3     3 1 44 my $x = shift;
6151 3         9 my $class = ref $x;
6152              
6153 3         5 my $sub = shift;
6154 3 50       7 croak "The first input argument must be a code reference"
6155             unless ref($sub) eq 'CODE';
6156              
6157 3         5 my $y = [];
6158 3         9 my ($nrow, $ncol) = $x -> size();
6159 3         9 for my $i (0 .. $nrow - 1) {
6160 5         13 for my $j (0 .. $ncol - 1) {
6161 15         40 local $_ = $x -> [$i][$j];
6162 15         25 $y -> [$i][$j] = $sub -> ($i, $j);
6163             }
6164             }
6165              
6166 3         10 bless $y, $class;
6167             }
6168              
6169             =pod
6170              
6171             =item sapply()
6172              
6173             Applies a subroutine to each element of a matrix, or each set of corresponding
6174             elements if multiple matrices are given, and returns the result. The first
6175             argument is the subroutine to apply. The following arguments, if any, are
6176             additional matrices on which to apply the subroutine.
6177              
6178             $w = $x -> sapply($sub); # single operand
6179             $w = $x -> sapply($sub, $y); # two operands
6180             $w = $x -> sapply($sub, $y, $z); # three operands
6181              
6182             Each matrix element, or corresponding set of elements, are passed to the
6183             subroutine as input arguments.
6184              
6185             When used with a single operand, this method is similar to the C>
6186             method, the syntax is different, since C> supports multiple
6187             operands.
6188              
6189             See also C>.
6190              
6191             =over 4
6192              
6193             =item *
6194              
6195             The subroutine is run in scalar context.
6196              
6197             =item *
6198              
6199             No checks are done on the return value of the subroutine.
6200              
6201             =item *
6202              
6203             The number of rows in the output matrix equals the number of rows in the operand
6204             with the largest number of rows. Ditto for columns. So if C<$x> is 5-by-2
6205             matrix, and C<$y> is a 3-by-4 matrix, the result is a 5-by-4 matrix.
6206              
6207             =item *
6208              
6209             For each operand that has a number of rows smaller than the maximum value, the
6210             rows are recyled. Ditto for columns.
6211              
6212             =item *
6213              
6214             Don't modify the variables $_[0], $_[1] etc. inside the subroutine. Otherwise,
6215             there is a risk of modifying the operand matrices.
6216              
6217             =item *
6218              
6219             If the matrix elements are objects that are not cloned when the "=" (assignment)
6220             operator is used, you might have to explicitly clone the objects used inside the
6221             subroutine. Otherwise, the elements in the output matrix might be references to
6222             objects in the operand matrices, rather than references to new objects.
6223              
6224             =back
6225              
6226             Some examples
6227              
6228             =over 4
6229              
6230             =item One operand
6231              
6232             With one operand, i.e., the invocand matrix, the subroutine is applied to each
6233             element of the invocand matrix. The returned matrix has the same size as the
6234             invocand. For example, multiplying the matrix C<$x> with the scalar C<$c>
6235              
6236             $sub = sub { $c * $_[0] }; # subroutine to multiply by $c
6237             $z = $x -> sapply($sub); # multiply each element by $c
6238              
6239             =item Two operands
6240              
6241             When two operands are specfied, the subroutine is applied to each pair of
6242             corresponding elements in the two operands. For example, adding two matrices can
6243             be implemented as
6244              
6245             $sub = sub { $_[0] * $_[1] };
6246             $z = $x -> sapply($sub, $y);
6247              
6248             Note that if the matrices have different sizes, the rows and/or columns of the
6249             smaller are recycled to match the size of the larger. If C<$x> is a
6250             C<$p>-by-C<$q> matrix and C<$y> is a C<$r>-by-C<$s> matrix, then C<$z> is a
6251             max(C<$p>,C<$r>)-by-max(C<$q>,C<$s>) matrix, and
6252              
6253             $z -> [$i][$j] = $sub -> ($x -> [$i % $p][$j % $q],
6254             $y -> [$i % $r][$j % $s]);
6255              
6256             Because of this recycling, multiplying the matrix C<$x> with the scalar C<$c>
6257             (see above) can also be implemented as
6258              
6259             $sub = sub { $_[0] * $_[1] };
6260             $z = $x -> sapply($sub, $c);
6261              
6262             Generating a matrix with all combinations of C<$x**$y> for C<$x> being 4, 5, and
6263             6 and C<$y> being 1, 2, 3, and 4 can be done with
6264              
6265             $c = Math::Matrix -> new([[4], [5], [6]]); # 3-by-1 column
6266             $r = Math::Matrix -> new([[1, 2, 3, 4]]); # 1-by-4 row
6267             $x = $c -> sapply(sub { $_[0] ** $_[1] }, $r); # 3-by-4 matrix
6268              
6269             =item Multiple operands
6270              
6271             In general, the sapply() method can have any number of arguments. For example,
6272             to compute the sum of the four matrices C<$x>, C<$y>, C<$z>, and C<$w>,
6273              
6274             $sub = sub {
6275             $sum = 0;
6276             for $val (@_) {
6277             $sum += $val;
6278             };
6279             return $sum;
6280             };
6281             $sum = $x -> sapply($sub, $y, $z, $w);
6282              
6283             =back
6284              
6285             =cut
6286              
6287             sub sapply {
6288 176 50   176 1 1608 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
6289 176         371 my $x = shift;
6290 176         328 my $class = ref $x;
6291              
6292             # Get the subroutine to apply on all the elements.
6293              
6294 176         241 my $sub = shift;
6295 176 50       427 croak "input argument must be a reference to a subroutine"
6296             unless ref($sub) eq 'CODE';
6297              
6298 176         336 my $y = bless [], $class;
6299              
6300             # For speed, treat a single matrix operand as a special case.
6301              
6302 176 100       402 if (@_ == 0) {
6303 119         364 my ($nrowx, $ncolx) = $x -> size();
6304 119 100       422 return $y if $nrowx * $ncolx == 0; # quick exit if $x is empty
6305              
6306 86         197 for my $i (0 .. $nrowx - 1) {
6307 168         3615 for my $j (0 .. $ncolx - 1) {
6308 390         12309 $y -> [$i][$j] = $sub -> ($x -> [$i][$j]);
6309             }
6310             }
6311              
6312 86         4032 return $y;
6313             }
6314              
6315             # Create some auxiliary arrays.
6316              
6317 57         161 my @args = ($x, @_); # all matrices
6318 57         104 my @size = (); # size of each matrix
6319 57         94 my @nelm = (); # number of elements in each matrix
6320              
6321             # Loop over the input arguments to perform some checks and get their
6322             # properties. Also get the size (number of rows and columns) of the output
6323             # matrix.
6324              
6325 57         87 my $nrowy = 0;
6326 57         78 my $ncoly = 0;
6327              
6328 57         132 for my $k (0 .. $#args) {
6329              
6330             # Make sure the k'th argument is a matrix object.
6331              
6332 117 100 66     709 $args[$k] = $class -> new($args[$k])
6333             unless defined(blessed($args[$k])) && $args[$k] -> isa($class);
6334              
6335             # Get the number of rows, columns, and elements in the k'th argument,
6336             # and save this information for later.
6337              
6338 117         291 my ($nrowk, $ncolk) = $args[$k] -> size();
6339 117         239 $size[$k] = [ $nrowk, $ncolk ];
6340 117         199 $nelm[$k] = $nrowk * $ncolk;
6341              
6342             # Update the size of the output matrix.
6343              
6344 117 100       229 $nrowy = $nrowk if $nrowk > $nrowy;
6345 117 100       258 $ncoly = $ncolk if $ncolk > $ncoly;
6346             }
6347              
6348             # We only accept empty matrices if all matrices are empty.
6349              
6350 57         114 my $n_empty = grep { $_ == 0 } @nelm;
  117         272  
6351 57 100       206 return $y if $n_empty == @args; # quick exit if all are empty
6352              
6353             # At ths point, we know that not all matrices are empty, but some might be
6354             # empty. We only continue if none are empty.
6355              
6356 50 50       124 croak "Either all or none of the matrices must be empty in ", (caller(0))[3]
6357             unless $n_empty == 0;
6358              
6359             # Loop over the subscripts into the output matrix.
6360              
6361 50         119 for my $i (0 .. $nrowy - 1) {
6362 108         348 for my $j (0 .. $ncoly - 1) {
6363              
6364             # Initialize the argument list for the subroutine call that will
6365             # give the value for element ($i,$j) in the output matrix.
6366              
6367 359         1497 my @elms = ();
6368              
6369             # Loop over the matrices.
6370              
6371 359         537 for my $k (0 .. $#args) {
6372              
6373             # Get the number of rows and columns in the k'th matrix.
6374              
6375 727         1007 my $nrowk = $size[$k][0];
6376 727         874 my $ncolk = $size[$k][1];
6377              
6378             # Compute the subscripts of the element to use in the k'th
6379             # matrix.
6380              
6381 727         928 my $ik = $i % $nrowk;
6382 727         909 my $jk = $j % $ncolk;
6383              
6384             # Get the element from the k'th matrix to use in this call.
6385              
6386 727         1121 $elms[$k] = $args[$k][$ik][$jk];
6387             }
6388              
6389             # Now we have the argument list for the subroutine call.
6390              
6391 359         601 $y -> [$i][$j] = $sub -> (@elms);
6392             }
6393             }
6394              
6395 50         577 return $y;
6396             }
6397              
6398             =pod
6399              
6400             =back
6401              
6402             =head3 Forward elimination
6403              
6404             These methods take a matrix as input, performs forward elimination, and returns
6405             a matrix where all elements below the main diagonal are zero. In list context,
6406             four additional arguments are returned: an array with the row permutations, an
6407             array with the column permutations, an integer with the number of row swaps and
6408             an integer with the number of column swaps performed during elimination.
6409              
6410             The permutation vectors can be converted to permutation matrices with
6411             C>.
6412              
6413             =over
6414              
6415             =item felim_np()
6416              
6417             Perform forward elimination with no pivoting.
6418              
6419             $y = $x -> felim_np();
6420              
6421             Forward elimination without pivoting may fail even when the matrix is
6422             non-singular.
6423              
6424             This method is provided mostly for illustration purposes.
6425              
6426             =cut
6427              
6428             sub felim_np {
6429 1 50   1 1 21 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
6430 1 50       4 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
6431 1         2 my $x = shift;
6432              
6433 1         4 $x = $x -> clone();
6434 1         5 my $nrow = $x -> nrow();
6435 1         6 my $ncol = $x -> ncol();
6436              
6437 1         12 my $imax = $nrow - 1;
6438 1         3 my $jmax = $ncol - 1;
6439              
6440 1         4 my $iperm = [ 0 .. $imax ]; # row permutation vector
6441 1         2 my $jperm = [ 0 .. $imax ]; # column permutation vector
6442 1         2 my $iswap = 0; # number of row swaps
6443 1         3 my $jswap = 0; # number of column swaps
6444              
6445 1         2 my $debug = 0;
6446              
6447 1 50       4 printf "\nfelim_np(): before 0:\n\n%s\n", $x if $debug;
6448              
6449 1   66     7 for (my $i = 0 ; $i <= $imax && $i <= $jmax ; ++$i) {
6450              
6451             # The so far remaining unreduced submatrix starts at element ($i,$i).
6452              
6453             # Skip this round, if all elements below (i,i) are zero.
6454              
6455 5         7 my $saw_non_zero = 0;
6456 5         10 for (my $u = $i + 1 ; $u <= $imax ; ++$u) {
6457 6 100       17 if ($x->[$u][$i] != 0) {
6458 4         6 $saw_non_zero = 1;
6459 4         6 last;
6460             }
6461             }
6462 5 100       10 next unless $saw_non_zero;
6463              
6464             # Since we don't use pivoting, element ($i,$i) must be non-zero.
6465              
6466 4 50       10 if ($x->[$i][$i] == 0) {
6467 0         0 croak "No pivot element found for row $i";
6468             }
6469              
6470             # Subtract row $i from each row $u below $i.
6471              
6472 4         9 for (my $u = $i + 1 ; $u <= $imax ; ++$u) {
6473 10         19 for (my $j = $jmax ; $j >= $i ; --$j) {
6474 40         84 $x->[$u][$j] -= ($x->[$i][$j] * $x->[$u][$i]) / $x->[$i][$i];
6475             }
6476              
6477             # In case of round-off errors.
6478              
6479 10         26 $x->[$u][$i] *= 0;
6480             }
6481              
6482 4 50       16 printf "\nfelim_np(): after %u:\n\n%s\n\n", $i, $x if $debug;
6483             }
6484              
6485 1 50       3 return $x, $iperm, $jperm, $iswap, $jswap if wantarray;
6486 1         5 return $x;
6487             }
6488              
6489             =pod
6490              
6491             =item felim_tp()
6492              
6493             Perform forward elimination with trivial pivoting, a variant of partial
6494             pivoting.
6495              
6496             $y = $x -> felim_tp();
6497              
6498             If A is a p-by-q matrix, and the so far remaining unreduced submatrix starts at
6499             element (i,i), the pivot element is the first element in column i that is
6500             non-zero.
6501              
6502             This method is provided mostly for illustration purposes.
6503              
6504             =cut
6505              
6506             sub felim_tp {
6507 1 50   1 1 8 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
6508 1 50       4 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
6509 1         2 my $x = shift;
6510              
6511 1 50       2 croak "felim_tp(): too many input arguments" if @_ > 0;
6512              
6513 1         3 $x = $x -> clone();
6514 1         5 my $nrow = $x -> nrow();
6515 1         3 my $ncol = $x -> ncol();
6516              
6517 1         2 my $imax = $nrow - 1;
6518 1         2 my $jmax = $ncol - 1;
6519              
6520 1         3 my $iperm = [ 0 .. $imax ]; # row permutation vector
6521 1         3 my $jperm = [ 0 .. $imax ]; # column permutation vector
6522 1         2 my $iswap = 0; # number of row swaps
6523 1         2 my $jswap = 0; # number of column swaps
6524              
6525 1         2 my $debug = 0;
6526              
6527 1 50       4 printf "\nfelim_tp(): before 0:\n\n%s\n", $x if $debug;
6528              
6529 1   66     9 for (my $i = 0 ; $i <= $imax && $i <= $jmax ; ++$i) {
6530              
6531             # The so far remaining unreduced submatrix starts at element ($i,$i).
6532              
6533             # Skip this round, if all elements below (i,i) are zero.
6534              
6535 5         7 my $saw_non_zero = 0;
6536 5         12 for (my $u = $i + 1 ; $u <= $imax ; ++$u) {
6537 6 100       15 if ($x->[$u][$i] != 0) {
6538 4         5 $saw_non_zero = 1;
6539 4         7 last;
6540             }
6541             }
6542 5 100       13 next unless $saw_non_zero;
6543              
6544             # The pivot element is the first element in column $i (in the unreduced
6545             # submatrix) that is non-zero.
6546              
6547 4         5 my $p; # index of pivot row
6548              
6549 4         8 for (my $u = $i ; $u <= $imax ; ++$u) {
6550 4 50       8 if ($x->[$u][$i] != 0) {
6551 4         6 $p = $u;
6552 4         6 last;
6553             }
6554             }
6555              
6556 4 50       6 printf "\nfelim_tp(): pivot element is (%u,%u)\n", $p, $i if $debug;
6557              
6558             # Swap rows $i and $p.
6559              
6560 4 50       9 if ($p != $i) {
6561 0         0 ($x->[$i], $x->[$p]) = ($x->[$p], $x->[$i]);
6562 0         0 ($iperm->[$i], $iperm->[$p]) = ($iperm->[$p], $iperm->[$i]);
6563 0         0 $iswap++;
6564             }
6565              
6566             # Subtract row $i from all following rows.
6567              
6568 4         18 for (my $u = $i + 1 ; $u <= $imax ; ++$u) {
6569              
6570 10         22 for (my $j = $jmax ; $j >= $i ; --$j) {
6571 40         83 $x->[$u][$j] -= ($x->[$i][$j] * $x->[$u][$i]) / $x->[$i][$i];
6572             }
6573              
6574             # In case of round-off errors.
6575              
6576 10         19 $x->[$u][$i] *= 0;
6577             }
6578              
6579 4 50       15 printf "\nfelim_tp(): after %u:\n\n%s\n\n", $i, $x if $debug;
6580             }
6581              
6582 1 50       3 return $x, $iperm, $jperm, $iswap, $jswap if wantarray;
6583 1         5 return $x;
6584             }
6585              
6586             =pod
6587              
6588             =item felim_pp()
6589              
6590             Perform forward elimination with (unscaled) partial pivoting.
6591              
6592             $y = $x -> felim_pp();
6593              
6594             If A is a p-by-q matrix, and the so far remaining unreduced submatrix starts at
6595             element (i,i), the pivot element is the element in column i that has the largest
6596             absolute value.
6597              
6598             This method is provided mostly for illustration purposes.
6599              
6600             =cut
6601              
6602             sub felim_pp {
6603 1 50   1 1 9 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
6604 1 50       6 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
6605 1         1 my $x = shift;
6606              
6607 1 50       4 croak "felim_pp(): too many input arguments" if @_ > 0;
6608              
6609 1         4 $x = $x -> clone();
6610 1         3 my $nrow = $x -> nrow();
6611 1         4 my $ncol = $x -> ncol();
6612              
6613 1         3 my $imax = $nrow - 1;
6614 1         2 my $jmax = $ncol - 1;
6615              
6616 1         3 my $iperm = [ 0 .. $imax ]; # row permutation vector
6617 1         3 my $jperm = [ 0 .. $imax ]; # column permutation vector
6618 1         3 my $iswap = 0; # number of row swaps
6619 1         2 my $jswap = 0; # number of column swaps
6620              
6621 1         2 my $debug = 0;
6622              
6623 1 50       3 printf "\nfelim_pp(): before 0:\n\n%s\n", $x if $debug;
6624              
6625 1   66     8 for (my $i = 0 ; $i <= $imax && $i <= $jmax ; ++$i) {
6626              
6627             # The so far remaining unreduced submatrix starts at element ($i,$i).
6628              
6629             # Skip this round, if all elements below (i,i) are zero.
6630              
6631 5         7 my $saw_non_zero = 0;
6632 5         11 for (my $u = $i + 1 ; $u <= $imax ; ++$u) {
6633 6 100       13 if ($x->[$u][$i] != 0) {
6634 4         6 $saw_non_zero = 1;
6635 4         6 last;
6636             }
6637             }
6638 5 100       15 next unless $saw_non_zero;
6639              
6640             # The pivot element is the element in column $i (in the unreduced
6641             # submatrix) that has the largest absolute value.
6642              
6643 4         5 my $p; # index of pivot row
6644 4         7 my $max_abs_val = 0;
6645              
6646 4         8 for (my $u = $i ; $u <= $imax ; ++$u) {
6647 14         20 my $abs_val = CORE::abs($x->[$u][$i]);
6648 14 100       27 if ($abs_val > $max_abs_val) {
6649 5         9 $max_abs_val = $abs_val;
6650 5         8 $p = $u;
6651             }
6652             }
6653              
6654 4 50       9 printf "\nfelim_pp(): pivot element is (%u,%u)\n", $p, $i if $debug;
6655              
6656             # Swap rows $i and $p.
6657              
6658 4 100       7 if ($p != $i) {
6659 1         4 ($x->[$p], $x->[$i]) = ($x->[$i], $x->[$p]);
6660 1         3 ($iperm->[$p], $iperm->[$i]) = ($iperm->[$i], $iperm->[$p]);
6661 1         1 $iswap++;
6662             }
6663              
6664             # Subtract row $i from all following rows.
6665              
6666 4         10 for (my $u = $i + 1 ; $u <= $imax ; ++$u) {
6667              
6668 10         16 for (my $j = $jmax ; $j >= $i ; --$j) {
6669 40         84 $x->[$u][$j] -= ($x->[$i][$j] * $x->[$u][$i]) / $x->[$i][$i];
6670             }
6671              
6672             # In case of round-off errors.
6673              
6674 10         19 $x->[$u][$i] *= 0;
6675             }
6676              
6677 4 50       15 printf "\nfelim_pp(): after %u:\n\n%s\n\n", $i, $x if $debug;
6678             }
6679              
6680 1 50       3 return $x, $iperm, $jperm, $iswap, $jswap if wantarray;
6681 1         4 return $x;
6682             }
6683              
6684             =pod
6685              
6686             =item felim_sp()
6687              
6688             Perform forward elimination with scaled pivoting, a variant of partial pivoting.
6689              
6690             $y = $x -> felim_sp();
6691              
6692             If A is a p-by-q matrix, and the so far remaining unreduced submatrix starts at
6693             element (i,i), the pivot element is the element in column i that has the largest
6694             absolute value relative to the other elements on the same row.
6695              
6696             =cut
6697              
6698             sub felim_sp {
6699 1 50   1 1 21 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
6700 1 50       19 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
6701 1         5 my $x = shift;
6702              
6703 1 50       4 croak "felim_sp(): too many input arguments" if @_ > 0;
6704              
6705 1         4 $x = $x -> clone();
6706 1         3 my $nrow = $x -> nrow();
6707 1         3 my $ncol = $x -> ncol();
6708              
6709 1         3 my $imax = $nrow - 1;
6710 1         2 my $jmax = $ncol - 1;
6711              
6712 1         2 my $iperm = [ 0 .. $imax ]; # row permutation vector
6713 1         4 my $jperm = [ 0 .. $imax ]; # column permutation vector
6714 1         1 my $iswap = 0; # number of row swaps
6715 1         2 my $jswap = 0; # number of column swaps
6716              
6717 1         2 my $debug = 0;
6718              
6719 1 50       4 printf "\nfelim_sp(): before 0:\n\n%s\n", $x if $debug;
6720              
6721 1   66     7 for (my $i = 0 ; $i <= $imax && $i <= $jmax ; ++$i) {
6722              
6723             # The so far remaining unreduced submatrix starts at element ($i,$i).
6724              
6725             # Skip this round, if all elements below (i,i) are zero.
6726              
6727 5         9 my $saw_non_zero = 0;
6728 5         11 for (my $u = $i + 1 ; $u <= $imax ; ++$u) {
6729 6 100       13 if ($x->[$u][$i] != 0) {
6730 4         6 $saw_non_zero = 1;
6731 4         5 last;
6732             }
6733             }
6734 5 100       12 next unless $saw_non_zero;
6735              
6736             # The pivot element is the element in column $i (in the unreduced
6737             # submatrix) that has the largest absolute value relative to the other
6738             # elements on the same row.
6739              
6740 4         4 my $p;
6741 4         7 my $max_abs_ratio = 0;
6742              
6743 4         8 for (my $u = $i ; $u <= $imax ; ++$u) {
6744              
6745             # Find the element with the largest absolute value in row $u.
6746              
6747 14         18 my $max_abs_val = 0;
6748 14         25 for (my $v = $i ; $v <= $jmax ; ++$v) {
6749 54         70 my $abs_val = CORE::abs($x->[$u][$v]);
6750 54 100       144 $max_abs_val = $abs_val if $abs_val > $max_abs_val;
6751             }
6752              
6753 14 50       20 next if $max_abs_val == 0;
6754              
6755             # Find the ratio for this row and see if it the best so far.
6756              
6757 14         21 my $abs_ratio = CORE::abs($x->[$u][$i]) / $max_abs_val;
6758             #croak "column ", $i + 1, " has only zeros"
6759             # if $ratio == 0;
6760              
6761 14 100       32 if ($abs_ratio > $max_abs_ratio) {
6762 6         7 $max_abs_ratio = $abs_ratio;
6763 6         11 $p = $u;
6764             }
6765              
6766             }
6767              
6768 4 50       10 printf "\nfelim_sp(): pivot element is (%u,%u)\n", $p, $i if $debug;
6769              
6770             # Swap rows $i and $p.
6771              
6772 4 100       8 if ($p != $i) {
6773 2         7 ($x->[$p], $x->[$i]) = ($x->[$i], $x->[$p]);
6774 2         5 ($iperm->[$p], $iperm->[$i]) = ($iperm->[$i], $iperm->[$p]);
6775 2         3 $iswap++;
6776             }
6777              
6778             # Subtract row $i from all following rows.
6779              
6780 4         8 for (my $u = $i + 1 ; $u <= $imax ; ++$u) {
6781              
6782 10         18 for (my $j = $jmax ; $j >= $i ; --$j) {
6783 40         81 $x->[$u][$j] -= ($x->[$i][$j] * $x->[$u][$i]) / $x->[$i][$i];
6784             }
6785              
6786             # In case of round-off errors.
6787              
6788 10         19 $x->[$u][$i] *= 0;
6789             }
6790              
6791 4 50       16 printf "\nfelim_sp(): after %u:\n\n%s\n\n", $i, $x if $debug;
6792             }
6793              
6794 1 50       4 return $x, $iperm, $jperm, $iswap, $jswap if wantarray;
6795 1         4 return $x;
6796             }
6797              
6798             =pod
6799              
6800             =item felim_fp()
6801              
6802             Performs forward elimination with full pivoting.
6803              
6804             $y = $x -> felim_fp();
6805              
6806             The elimination is done with full pivoting, also called complete pivoting or
6807             total pivoting. If A is a p-by-q matrix, and the so far remaining unreduced
6808             submatrix starts at element (i,i), the pivot element is the element in the whole
6809             submatrix that has the largest absolute value. With full pivoting, both rows and
6810             columns might be swapped.
6811              
6812             =cut
6813              
6814             sub felim_fp {
6815 68 50   68 1 179 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
6816 68 50       145 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
6817 68         100 my $x = shift;
6818              
6819 68 50       140 croak "felim_fp(): too many input arguments" if @_ > 0;
6820              
6821 68         142 $x = $x -> clone();
6822 68         131 my $nrow = $x -> nrow();
6823 68         189 my $ncol = $x -> ncol();
6824              
6825 68         116 my $imax = $nrow - 1;
6826 68         98 my $jmax = $ncol - 1;
6827              
6828 68         134 my $iperm = [ 0 .. $imax ]; # row permutation vector
6829 68         126 my $jperm = [ 0 .. $imax ]; # column permutation vector
6830 68         134 my $iswap = 0; # number of row swaps
6831 68         94 my $jswap = 0; # number of column swaps
6832              
6833 68         89 my $debug = 0;
6834              
6835 68 50       165 printf "\nfelim_fp(): before 0:\n\n%s\n", $x if $debug;
6836              
6837 68   66     291 for (my $i = 0 ; $i <= $imax && $i <= $jmax ; ++$i) {
6838              
6839             # The so far remaining unreduced submatrix starts at element ($i,$i).
6840             # The pivot element is the element in the whole submatrix that has the
6841             # largest absolute value.
6842              
6843 180         270 my $p; # index of pivot row
6844             my $q; # index of pivot column
6845              
6846             # Loop over each row and column in the submatrix to find the element
6847             # with the largest absolute value.
6848              
6849 180         241 my $max_abs_val = 0;
6850 180         333 for (my $u = $i ; $u <= $imax ; ++$u) {
6851 368   66     1001 for (my $v = $i ; $v <= $imax && $v <= $jmax ; ++$v) {
6852 972         1337 my $abs_val = CORE::abs($x->[$u][$v]);
6853 972 100       2404 if ($abs_val > $max_abs_val) {
6854 336         424 $max_abs_val = $abs_val;
6855 336         400 $p = $u;
6856 336         840 $q = $v;
6857             }
6858             }
6859             }
6860              
6861             # If we didn't find a pivot element, it means that the so far unreduced
6862             # submatrix contains zeros only, in which case we're done.
6863              
6864 180 100       328 last unless defined $p;
6865              
6866 177 50       300 printf "\nfelim_fp(): pivot element is (%u,%u)\n", $p, $q if $debug;
6867              
6868             # Swap rows $i and $p.
6869              
6870 177 100       312 if ($p != $i) {
6871 74 50       137 printf "\nfelim_fp(): swapping rows %u and %u\n", $p, $i if $debug;
6872 74 50       123 printf "\nfrom this:\n\n%s\n", $x if $debug;
6873 74         201 ($x->[$p], $x->[$i]) = ($x->[$i], $x->[$p]);
6874 74 50       203 printf "\nto this:\n\n%s\n", $x if $debug;
6875 74         132 ($iperm->[$p], $iperm->[$i]) = ($iperm->[$i], $iperm->[$p]);
6876 74         110 $iswap++;
6877             }
6878              
6879             # Swap columns $i and $q.
6880              
6881 177 100       359 if ($q != $i) {
6882 71 50       158 printf "\nfelim_fp(): swapping columns %u and %u\n", $q, $i if $debug;
6883 71 50       142 printf "\nfrom this:\n\n%s\n", $x if $debug;
6884 71         150 for (my $u = 0 ; $u <= $imax ; ++$u) {
6885 242         673 ($x->[$u][$q], $x->[$u][$i]) = ($x->[$u][$i], $x->[$u][$q]);
6886             }
6887 71 50       125 printf "\nto this:\n\n%s\n", $x if $debug;
6888 71         126 ($jperm->[$q], $jperm->[$i]) = ($jperm->[$i], $jperm->[$q]);
6889 71         104 $jswap++;
6890             }
6891              
6892             # Subtract row $i from all following rows.
6893              
6894 177         395 for (my $u = $i + 1 ; $u <= $imax ; ++$u) {
6895              
6896 188         354 for (my $j = $jmax ; $j >= $i ; --$j) {
6897 1228         2630 $x->[$u][$j] -= ($x->[$i][$j] * $x->[$u][$i]) / $x->[$i][$i];
6898             }
6899              
6900             # In case of round-off errors.
6901              
6902 188         449 $x->[$u][$i] *= 0;
6903             }
6904              
6905 177 50       564 printf "\nfelim_fp(): after %u:\n\n%s\n\n", $i, $x if $debug;
6906             }
6907              
6908 68 100       289 return $x, $iperm, $jperm, $iswap, $jswap if wantarray;
6909 1         4 return $x;
6910             }
6911              
6912             =pod
6913              
6914             =back
6915              
6916             =head3 Back-substitution
6917              
6918             =over 4
6919              
6920             =item bsubs()
6921              
6922             Performs back-substitution.
6923              
6924             $y = $x -> bsubs();
6925              
6926             The leftmost square portion of the matrix must be upper triangular.
6927              
6928             =cut
6929              
6930             sub bsubs {
6931 8 50   8 1 38 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
6932 8 50       21 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
6933 8         16 my $x = shift;
6934              
6935 8 50       26 croak "bsubs(): too many input arguments" if @_ > 0;
6936              
6937 8         21 my $nrow = $x -> nrow();
6938 8         21 my $ncol = $x -> ncol();
6939              
6940 8         17 my $imax = $nrow - 1;
6941 8         14 my $jmax = $ncol - 1;
6942              
6943 8         14 my $debug = 0;
6944              
6945 8 50       18 printf "\nbsubs(): before 0:\n\n%s\n", $x if $debug;
6946              
6947 8         39 for (my $i = 0 ; $i <= $imax ; ++$i) {
6948              
6949             # Check the elements below ($i,$i). They should all be zero.
6950              
6951 35         72 for (my $k = $i + 1 ; $k <= $imax ; ++$k) {
6952 62 50       138 croak "matrix is not upper triangular; element ($i,$i) is non-zero"
6953             unless $x->[$k][$i] == 0;
6954             }
6955              
6956             # There is no rows above the first row to perform back-substitution on.
6957              
6958 35 100       79 next if $i == 0;
6959              
6960             # If the element on the diagonal is zero, we can't use it to perform
6961             # back-substitution. However, this is not a problem if all the elements
6962             # above ($i,$i) are zero.
6963              
6964 27 50       95 if ($x->[$i][$i] == 0) {
6965 0         0 my $non_zero = 0;
6966 0         0 my $k;
6967 0         0 for ($k = 0 ; $k < $i ; ++$k) {
6968 0 0       0 if ($x->[$k][$i] != 0) {
6969 0         0 $non_zero++;
6970 0         0 last;
6971             }
6972             }
6973 0 0       0 if ($non_zero) {
6974 0         0 croak "bsubs(): back substitution failed; diagonal element",
6975             " ($i,$i) is zero, but ($k,$i) isn't";
6976 0         0 next;
6977             }
6978             }
6979              
6980             # Subtract row $i from each row $u above row $i.
6981              
6982 27         63 for (my $u = $i - 1 ; $u >= 0 ; --$u) {
6983              
6984             # From row $u subtract $c times of row $i.
6985              
6986 62         135 my $c = $x->[$u][$i] / $x->[$i][$i];
6987              
6988 62         112 for (my $j = $jmax ; $j >= $i ; --$j) {
6989 366         641 $x->[$u][$j] -= $c * $x->[$i][$j];
6990             }
6991              
6992             # In case of round-off errors. (Will they ever happen?)
6993              
6994 62         113 $x->[$u][$i] *= 0;
6995             }
6996              
6997 27 50       65 printf "\nbsubs(): after %u:\n\n%s\n\n", $i, $x if $debug;
6998             }
6999              
7000             # Normalise.
7001              
7002 8         33 for (my $i = 0 ; $i <= $imax ; ++$i) {
7003 35 50       68 next if $x->[$i][$i] == 1; # row is already normalized
7004 35 50       70 next if $x->[$i][$i] == 0; # row can't be normalized
7005 35         66 for (my $j = $imax + 1 ; $j <= $jmax ; ++$j) {
7006 142         249 $x->[$i][$j] /= $x->[$i][$i];
7007             }
7008 35         66 $x->[$i][$i] = 1;
7009             }
7010              
7011 8 50       19 printf "\nbsubs(): after normalisation:\n\n%s\n\n", $x if $debug;
7012              
7013 8         45 return $x;
7014             }
7015              
7016             =pod
7017              
7018             =back
7019              
7020             =head2 Miscellaneous methods
7021              
7022             =over 4
7023              
7024             =item print()
7025              
7026             Prints the matrix on STDOUT. If the method has additional parameters, these are
7027             printed before the matrix is printed.
7028              
7029             =cut
7030              
7031             sub print {
7032 7     7 1 54 my $self = shift;
7033              
7034 7 50       112 print @_ if scalar(@_);
7035 7         29 print $self->as_string;
7036             }
7037              
7038             =pod
7039              
7040             =item version()
7041              
7042             Returns a string contining the package name and version number.
7043              
7044             =cut
7045              
7046             sub version {
7047 1     1 1 104 return "Math::Matrix $VERSION";
7048             }
7049              
7050             # Internal utility methods.
7051              
7052             # Compute the sum of all elements using Neumaier's algorithm, an improvement
7053             # over Kahan's algorithm.
7054             #
7055             # See
7056             # https://en.wikipedia.org/wiki/Kahan_summation_algorithm#Further_enhancements
7057              
7058             sub _sum {
7059 292     292   413 my $sum = 0;
7060 292         360 my $c = 0;
7061              
7062 292         447 for (@_) {
7063 889         1186 my $t = $sum + $_;
7064 889 100       1401 if (CORE::abs($sum) >= CORE::abs($_)) {
7065 431         583 $c += ($sum - $t) + $_;
7066             } else {
7067 458         633 $c += ($_ - $t) + $sum;
7068             }
7069 889         1265 $sum = $t;
7070             }
7071              
7072 292         711 return $sum + $c;
7073             }
7074              
7075             # _prod LIST
7076             #
7077              
7078             sub _prod {
7079 27     27   37 my $prod = 1;
7080 27         59 $prod *= $_ for @_;
7081 27         45 return $prod;
7082             }
7083              
7084             # _mean LIST
7085             #
7086             # Method for finding the mean.
7087              
7088             sub _mean {
7089 27 50   27   49 return 0 unless @_;
7090 27         44 _sum(@_) / @_;
7091             }
7092              
7093             # Method used to calculate the length of the hypotenuse of a right-angle
7094             # triangle. It is designed to avoid errors arising due to limited-precision
7095             # calculations performed on computers. E.g., with double-precision arithmetic:
7096             #
7097             # sqrt(3e200**2 + 4e200**2) # = Inf, due to overflow
7098             # _hypot(3e200, 4e200) # = 5e200, which is correct
7099             #
7100             # sqrt(3e-200**2 + 4e-200**2) # = 0, due to underflow
7101             # _hypot(3e-200, 4e-200) # = 5e-200, which is correct
7102             #
7103             # See https://en.wikipedia.org/wiki/Hypot
7104              
7105             sub _hypot {
7106 22     22   37 my @x = map { CORE::abs($_) } @_;
  46         91  
7107              
7108             # Compute the maximum value.
7109              
7110 22         50 my $max = _max(@x);
7111 22 50       50 return 0 if $max == 0;
7112              
7113             # Scale and square the values.
7114              
7115 22         34 for (@x) {
7116 46         68 $_ /= $max;
7117 46         79 $_ *= $_;
7118             }
7119              
7120 22         50 $max * sqrt(_sum(@x))
7121             }
7122              
7123             # _sumsq LIST
7124             #
7125             # Sum of squared absolute values.
7126              
7127             sub _sumsq {
7128 0     0   0 _sum(map { $_ * $_ } map { CORE::abs($_) } @_);
  0         0  
  0         0  
7129             }
7130              
7131             # _vecnorm P, LIST
7132             #
7133             # Vector P-norm. If the input is $x[0], $x[1], ..., then the output is
7134             #
7135             # (abs($x[0])**$p + abs($x[1])**$p + ...)**(1/$p)
7136              
7137             sub _vecnorm {
7138 46     46   57 my $p = shift;
7139 46         70 my @x = map { CORE::abs($_) } @_;
  80         139  
7140              
7141 46 100       143 return _sum(@x) if $p == 1;
7142              
7143 32         150 require Math::Trig;
7144 32         74 my $inf = Math::Trig::Inf();
7145              
7146 32 100       134 return _max(@x) if $p == $inf;
7147              
7148             # Compute the maximum value.
7149              
7150 18         25 my $max = 0;
7151 18         30 for (@x) {
7152 32 50       61 $max = $_ if $_ > $max;
7153             }
7154              
7155             # Scale and apply power function.
7156              
7157 18         29 for (@x) {
7158 32         47 $_ /= $max;
7159 32         58 $_ **= $p;
7160             }
7161              
7162 18         35 $max * _sum(@x) ** (1/$p);
7163             }
7164              
7165             # _min LIST
7166             #
7167             # Minimum value.
7168              
7169             sub _min {
7170 27     27   33 my $min = shift;
7171 27         45 for (@_) {
7172 60 100       102 $min = $_ if $_ < $min;
7173             }
7174              
7175 27         43 return $min;
7176             }
7177              
7178             # _max LIST
7179             #
7180             # Maximum value.
7181              
7182             sub _max {
7183 63     63   87 my $max = shift;
7184 63         116 for (@_) {
7185 94 100       185 $max = $_ if $_ > $max;
7186             }
7187              
7188 63         114 return $max;
7189             }
7190              
7191             # _median LIST
7192             #
7193             # Method for finding the median.
7194              
7195             sub _median {
7196 27     27   63 my @x = sort { $a <=> $b } @_;
  105         158  
7197 27 100       50 if (@x % 2) {
7198 15         37 $x[$#x / 2];
7199             } else {
7200 12         42 ($x[@x / 2] + $x[@x / 2 - 1]) / 2;
7201             }
7202             }
7203              
7204             # _any LIST
7205             #
7206             # Method that returns 1 if at least one value in LIST is non-zero and 0
7207             # otherwise.
7208              
7209             sub _any {
7210 27     27   44 for (@_) {
7211 28 100       65 return 1 if $_ != 0;
7212             }
7213 1         2 return 0;
7214             }
7215              
7216             # _all LIST
7217             #
7218             # Method that returns 1 if all values in LIST are non-zero and 0 otherwise.
7219              
7220             sub _all {
7221 27     27   47 for (@_) {
7222 76 100       134 return 0 if $_ == 0;
7223             }
7224 18         29 return 1;
7225             }
7226              
7227             # _cumsum LIST
7228             #
7229             # Cumulative sum. If the input is $x[0], $x[1], ..., then output element $y[$i]
7230             # is the sum of the elements $x[0], $x[1], ..., $x[$i].
7231              
7232             sub _cumsum {
7233 27     27   43 my @sum = ();
7234              
7235 27         31 my $sum = 0;
7236 27         32 my $c = 0;
7237              
7238 27         41 for (@_) {
7239 87         106 my $t = $sum + $_;
7240 87 100       137 if (CORE::abs($sum) >= CORE::abs($_)) {
7241 43         55 $c += ($sum - $t) + $_;
7242             } else {
7243 44         62 $c += ($_ - $t) + $sum;
7244             }
7245 87         100 $sum = $t;
7246 87         130 push @sum, $sum + $c;
7247             }
7248              
7249 27         54 return @sum;
7250             }
7251              
7252             # _cumprod LIST
7253             #
7254             # Cumulative product. If the input is $x[0], $x[1], ..., then output element
7255             # $y[$i] is the product of the elements $x[0], $x[1], ..., $x[$i].
7256              
7257             sub _cumprod {
7258 27     27   46 my @prod = shift;
7259 27         62 push @prod, $prod[-1] * $_ for @_;
7260 27         43 return @prod;
7261             }
7262              
7263             # _cummean LIST
7264             #
7265             # Cumulative mean. If the input is $x[0], $x[1], ..., then output element $y[$i]
7266             # is the mean of the elements $x[0], $x[1], ..., $x[$i].
7267              
7268             sub _cummean {
7269 27     27   38 my @mean = ();
7270 27         31 my $sum = 0;
7271 27         52 for my $i (0 .. $#_) {
7272 87         105 $sum += $_[$i];
7273 87         141 push @mean, $sum / ($i + 1);
7274             }
7275 27         58 return @mean;
7276             }
7277              
7278             # _cummean LIST
7279             #
7280             # Cumulative minimum. If the input is $x[0], $x[1], ..., then output element
7281             # $y[$i] is the minimum of the elements $x[0], $x[1], ..., $x[$i].
7282              
7283             sub _cummin {
7284 0     0   0 my @min = shift;
7285 0         0 for (@_) {
7286 0 0       0 push @min, $min[-1] < $_ ? $min[-1] : $_;
7287             }
7288 0         0 return @min;
7289             }
7290              
7291             # _cummax LIST
7292             #
7293             # Cumulative maximum. If the input is $x[0], $x[1], ..., then output element
7294             # $y[$i] is the maximum of the elements $x[0], $x[1], ..., $x[$i].
7295              
7296             sub _cummax {
7297 0     0   0 my @max = shift;
7298 0         0 for (@_) {
7299 0 0       0 push @max, $max[-1] > $_ ? $max[-1] : $_;
7300             }
7301 0         0 return @max;
7302             }
7303              
7304             # _cumany LIST
7305             #
7306             # Cumulative any. If the input is $x[0], $x[1], ..., then output element $y[$i]
7307             # is 1 if at least one of the elements $x[0], $x[1], ..., $x[$i] is non-zero,
7308             # and 0 otherwise.
7309              
7310             sub _cumany {
7311 27     27   41 my @any = ();
7312 27         42 for (@_) {
7313 28 100       50 if ($_ != 0) {
7314 26         46 push @any, (1) x (@_ - @any);
7315 26         39 last;
7316             }
7317 2         3 push @any, 0;
7318             }
7319 27         50 return @any;
7320             }
7321              
7322             # _cumall LIST
7323             #
7324             # Cumulative all. If the input is $x[0], $x[1], ..., then output element $y[$i]
7325             # is 1 if all of the elements $x[0], $x[1], ..., $x[$i] are non-zero, and 0
7326             # otherwise.
7327              
7328             sub _cumall {
7329 27     27   39 my @all = ();
7330 27         54 for (@_) {
7331 76 100       120 if ($_ == 0) {
7332 9         20 push @all, (0) x (@_ - @all);
7333 9         13 last;
7334             }
7335 67         94 push @all, 1;
7336             }
7337 27         48 return @all;
7338             }
7339              
7340             # _diff LIST
7341             #
7342             # Difference. If the input is $x[0], $x[1], ..., then output element $y[$i] =
7343             # $x[$i+1] - $x[$i].
7344              
7345             sub _diff {
7346 27     27   36 my @diff = ();
7347 27         46 for my $i (1 .. $#_) {
7348 60         99 push @diff, $_[$i] - $_[$i - 1];
7349             }
7350 27         49 return @diff;
7351             }
7352              
7353             =pod
7354              
7355             =back
7356              
7357             =head1 OVERLOADING
7358              
7359             The following operators are overloaded.
7360              
7361             =over 4
7362              
7363             =item C<+> and C<+=>
7364              
7365             Matrix or scalar addition. Unless one or both of the operands is a scalar, both
7366             operands must have the same size.
7367              
7368             $C = $A + $B; # assign $A + $B to $C
7369             $A += $B; # assign $A + $B to $A
7370              
7371             Note that
7372              
7373             =item C<-> and C<-=>
7374              
7375             Matrix or scalar subtraction. Unless one or both of the operands is a scalar,
7376             both operands must have the same size.
7377              
7378             $C = $A + $B; # assign $A - $B to $C
7379             $A += $B; # assign $A - $B to $A
7380              
7381             =item C<*> and C<*=>
7382              
7383             Matrix or scalar multiplication. Unless one or both of the operands is a scalar,
7384             the number of columns in the first operand must be equal to the number of rows
7385             in the second operand.
7386              
7387             $C = $A * $B; # assign $A * $B to $C
7388             $A *= $B; # assign $A * $B to $A
7389              
7390             =item C<**> and C<**=>
7391              
7392             Matrix power. The second operand must be a scalar.
7393              
7394             $C = $A * $B; # assign $A ** $B to $C
7395             $A *= $B; # assign $A ** $B to $A
7396              
7397             =item C<==>
7398              
7399             Equal to.
7400              
7401             $A == $B; # is $A equal to $B?
7402              
7403             =item C
7404              
7405             Not equal to.
7406              
7407             $A != $B; # is $A not equal to $B?
7408              
7409             =item C
7410              
7411             Negation.
7412              
7413             $B = -$A; # $B is the negative of $A
7414              
7415             =item C<~>
7416              
7417             Transpose.
7418              
7419             $B = ~$A; # $B is the transpose of $A
7420              
7421             =item C
7422              
7423             Absolute value.
7424              
7425             $B = abs $A; # $B contains absolute values of $A
7426              
7427             =item C
7428              
7429             Truncate to integer.
7430              
7431             $B = int $A; # $B contains only integers
7432              
7433             =back
7434              
7435             =head1 IMPROVING THE SOLUTION OF LINEAR SYSTEMS
7436              
7437             The methods that do an explicit or implicit matrix left division accept some
7438             additional parameters. If these parameters are specified, the matrix left
7439             division is done repeatedly in an iterative way, which often gives a better
7440             solution.
7441              
7442             =head2 Background
7443              
7444             The linear system of equations
7445              
7446             $A * $x = $y
7447              
7448             can be solved for C<$x> with
7449              
7450             $x = $y -> mldiv($A);
7451              
7452             Ideally C<$A * $x> should equal C<$y>, but due to numerical errors, this is not
7453             always the case. The following illustrates how to improve the solution C<$x>
7454             computed above:
7455              
7456             $r = $A -> mmuladd($x, -$y); # compute the residual $A*$x-$y
7457             $d = $r -> mldiv($A); # compute the delta for $x
7458             $x -= $d; # improve the solution $x
7459              
7460             This procedure is repeated, and at each step, the absolute error
7461              
7462             ||$A*$x - $y|| = ||$r||
7463              
7464             and the relative error
7465              
7466             ||$A*$x - $y|| / ||$y|| = ||$r|| / ||$y||
7467              
7468             are computed and compared to the tolerances. Once one of the stopping criteria
7469             is satisfied, the algorithm terminates.
7470              
7471             =head2 Stopping criteria
7472              
7473             The algorithm stops when at least one of the errors are within the specified
7474             tolerances or the maximum number of iterations is reached. If the maximum number
7475             of iterations is reached, but noen of the errors are within the tolerances, a
7476             warning is displayed and the best solution so far is returned.
7477              
7478             =head2 Parameters
7479              
7480             =over 4
7481              
7482             =item MaxIter
7483              
7484             The maximum number of iterations to perform. The value must be a positive
7485             integer. The default is 20.
7486              
7487             =item RelTol
7488              
7489             The limit for the relative error. The value must be a non-negative. The default
7490             value is 1e-19 when perl is compiled with long doubles or quadruple precision,
7491             and 1e-9 otherwise.
7492              
7493             =item AbsTol
7494              
7495             The limit for the absolute error. The value must be a non-negative. The default
7496             value is 0.
7497              
7498             =item Debug
7499              
7500             If this parameter does not affect when the algorithm terminates, but when set to
7501             non-zero, some information is displayed at each step.
7502              
7503             =back
7504              
7505             =head2 Example
7506              
7507             If
7508              
7509             $A = [[ 8, -8, -5, 6, -1, 3 ],
7510             [ -7, -1, 5, -9, 5, 6 ],
7511             [ -7, 8, 9, -2, -4, 3 ],
7512             [ 3, -4, 5, 5, 3, 3 ],
7513             [ 9, 8, -3, -4, 1, 6 ],
7514             [ -8, 9, -1, 3, 5, 2 ]];
7515              
7516             $y = [[ 80, -13 ],
7517             [ -2, 104 ],
7518             [ -57, -27 ],
7519             [ 47, -28 ],
7520             [ 5, 77 ],
7521             [ 91, 133 ]];
7522              
7523             the result of C<< $x = $y -> mldiv($A); >>, using double precision arithmetic,
7524             is the approximate solution
7525              
7526             $x = [[ -2.999999999999998, -5.000000000000000 ],
7527             [ -1.000000000000000, 3.000000000000001 ],
7528             [ -5.999999999999997, -8.999999999999996 ],
7529             [ 8.000000000000000, -2.000000000000003 ],
7530             [ 6.000000000000003, 9.000000000000002 ],
7531             [ 7.999999999999997, 8.999999999999995 ]];
7532              
7533             The residual C<< $res = $A -> mmuladd($x, -$y); >> is
7534              
7535             $res = [[ 1.24344978758018e-14, 1.77635683940025e-15 ],
7536             [ 8.88178419700125e-15, -5.32907051820075e-15 ],
7537             [ -1.24344978758018e-14, 1.77635683940025e-15 ],
7538             [ -7.10542735760100e-15, -4.08562073062058e-14 ],
7539             [ -1.77635683940025e-14, -3.81916720471054e-14 ],
7540             [ 1.24344978758018e-14, 8.43769498715119e-15 ]];
7541              
7542             and the delta C<< $dx = $res -> mldiv($A); >> is
7543              
7544             $dx = [[ -8.592098303124e-16, -2.86724066474914e-15 ],
7545             [ -7.92220125658508e-16, -2.99693950082398e-15 ],
7546             [ -2.22533360993874e-16, 3.03465504177947e-16 ],
7547             [ 6.47376093198353e-17, -1.12378127899388e-15 ],
7548             [ 6.35204502123966e-16, 2.40938179521241e-15 ],
7549             [ 1.55166908001001e-15, 2.08339859425849e-15 ]];
7550              
7551             giving the improved, and in this case exact, solution C<< $x -= $dx; >>,
7552              
7553             $x = [[ -3, -5 ],
7554             [ -1, 3 ],
7555             [ -6, -9 ],
7556             [ 8, -2 ],
7557             [ 6, 9 ],
7558             [ 8, 9 ]];
7559              
7560             =head1 SUBCLASSING
7561              
7562             The methods should work fine with any kind of numerical objects, provided that
7563             the assignment operator C<=> is overloaded, so that Perl knows how to create a
7564             copy.
7565              
7566             You can check the behaviour of the assignment operator by assigning a value to a
7567             new variable, modify the new variable, and check whether this also modifies the
7568             original value. Here is an example:
7569              
7570             $x = Some::Class -> new(0); # create object $x
7571             $y = $x; # create new variable $y
7572             $y++; # modify $y
7573             print "it's a clone\n" if $x != $y; # is $x modified?
7574              
7575             The subclass might need to implement some methods of its own. For instance, if
7576             each element is a complex number, a transpose() method needs to be implemented
7577             to take the complex conjugate of each value. An as_string() method might also be
7578             useful for displaying the matrix in a format more suitable for the subclass.
7579              
7580             Here is an example showing Math::Matrix::Complex, a fully-working subclass of
7581             Math::Matrix, where each element is a Math::Complex object.
7582              
7583             use strict;
7584             use warnings;
7585              
7586             package Math::Matrix::Complex;
7587              
7588             use Math::Matrix;
7589             use Scalar::Util 'blessed';
7590             use Math::Complex 1.57; # "=" didn't clone before 1.57
7591              
7592             our @ISA = ('Math::Matrix');
7593              
7594             # We need a new() method to make sure every element is an object.
7595              
7596             sub new {
7597             my $self = shift;
7598             my $x = $self -> SUPER::new(@_);
7599              
7600             my $sub = sub {
7601             defined(blessed($_[0])) && $_[0] -> isa('Math::Complex')
7602             ? $_[0]
7603             : Math::Complex -> new($_[0]);
7604             };
7605              
7606             return $x -> sapply($sub);
7607             }
7608              
7609             # We need a transpose() method, since the transpose of a matrix
7610             # with complex numbers also takes the conjugate of all elements.
7611              
7612             sub transpose {
7613             my $x = shift;
7614             my $y = $x -> SUPER::transpose(@_);
7615              
7616             return $y -> sapply(sub { ~$_[0] });
7617             }
7618              
7619             # We need an as_string() method, since our parent's methods
7620             # doesn't format complex numbers correctly.
7621              
7622             sub as_string {
7623             my $self = shift;
7624             my $out = "";
7625             for my $row (@$self) {
7626             for my $elm (@$row) {
7627             $out = $out . sprintf "%10s ", $elm;
7628             }
7629             $out = $out . sprintf "\n";
7630             }
7631             $out;
7632             }
7633              
7634             1;
7635              
7636             =head1 BUGS
7637              
7638             Please report any bugs through the web interface at
7639             L
7640             (requires login). We will be notified, and then you'll automatically be
7641             notified of progress on your bug as I make changes.
7642              
7643             =head1 SUPPORT
7644              
7645             You can find documentation for this module with the perldoc command.
7646              
7647             perldoc Math::Matrix
7648              
7649             You can also look for information at:
7650              
7651             =over 4
7652              
7653             =item * GitHub Source Repository
7654              
7655             L
7656              
7657             =item * RT: CPAN's request tracker
7658              
7659             L
7660              
7661             =item * CPAN Ratings
7662              
7663             L
7664              
7665             =item * MetaCPAN
7666              
7667             L
7668              
7669             =item * CPAN Testers Matrix
7670              
7671             L
7672              
7673             =back
7674              
7675             =head1 LICENSE AND COPYRIGHT
7676              
7677             Copyright (c) 2020, Peter John Acklam.
7678              
7679             Copyright (C) 2013, John M. Gamble , all rights reserved.
7680              
7681             Copyright (C) 2009, oshalla
7682             https://rt.cpan.org/Public/Bug/Display.html?id=42919
7683              
7684             Copyright (C) 2002, Bill Denney , all rights
7685             reserved.
7686              
7687             Copyright (C) 2001, Brian J. Watson , all rights reserved.
7688              
7689             Copyright (C) 2001, Ulrich Pfeifer , all rights reserved.
7690             Copyright (C) 1995, Universität Dortmund, all rights reserved.
7691              
7692             Copyright (C) 2001, Matthew Brett
7693              
7694             This program is free software; you may redistribute it and/or modify it under
7695             the same terms as Perl itself.
7696              
7697             =head1 AUTHORS
7698              
7699             Peter John Acklam Epjacklam@gmail.comE (2020)
7700              
7701             Ulrich Pfeifer Epfeifer@ls6.informatik.uni-dortmund.deE (1995-2013)
7702              
7703             Brian J. Watson Ebjbrew@power.netE
7704              
7705             Matthew Brett Ematthew.brett@mrc-cbu.cam.ac.ukE
7706              
7707             =cut
7708              
7709             1;