File Coverage

blib/lib/Math/Matrix.pm
Criterion Covered Total %
statement 2055 2194 93.6
branch 919 1472 62.4
condition 120 255 47.0
subroutine 228 233 97.8
pod 187 187 100.0
total 3509 4341 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   1324787 use strict;
  124         980  
  124         3758  
6 124     124   642 use warnings;
  124         271  
  124         2984  
7              
8 124     124   601 use Carp;
  124         237  
  124         13185  
9 124     124   863 use Scalar::Util 'blessed';
  124         272  
  124         64501  
10              
11             our $VERSION = '0.93';
12             our $eps = 0.00001;
13              
14             use overload
15              
16             '+' => sub {
17 3     3   20 my ($x, $y, $swap) = @_;
18 3         7 $x -> add($y);
19             },
20              
21             '-' => sub {
22 6     6   47 my ($x, $y, $swap) = @_;
23 6 100       29 if ($swap) {
24 3 100 66     36 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 23     23   128 my ($x, $y, $swap) = @_;
34 23         54 $x -> mul($y);
35             },
36              
37             '**' => sub {
38 3     3   20 my ($x, $y, $swap) = @_;
39 3 100       19 if ($swap) {
40 1         3 my $class = ref $x;
41 1         4 return $class -> new($y) -> pow($x);
42             }
43 2         6 $x -> pow($y);
44             },
45              
46             '==' => sub {
47 2     2   13 my ($x, $y, $swap) = @_;
48 2         6 $x -> meq($y);
49             },
50              
51             '!=' => sub {
52 2     2   3852 my ($x, $y, $swap) = @_;
53 2         6 $x -> mne($y);
54             },
55              
56             'int' => sub {
57 2     2   14 my ($x, $y, $swap) = @_;
58 2         7 $x -> int();
59             },
60              
61             'abs' => sub {
62 1     1   9 my ($x, $y, $swap) = @_;
63 1         4 $x -> abs();
64             },
65              
66 124         2837 '~' => 'transpose',
67             '""' => 'as_string',
68 124     124   157053 '=' => 'clone';
  124         134572  
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 947     947 1 960421 my $that = shift;
158 947   66     4130 my $class = ref($that) || $that;
159 947         1653 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 947 100 100     2969 if (ref($that) && (@_ == 0)) {
165 11         85 @$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 936         1409 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 936 100 100     6093 if (@_ == 1 && !ref($_[0])) {
    100 66        
      100        
      100        
187 16         37 $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 908         4125 && @{$_[0]} > 0 && ref($_[0][0]) eq 'ARRAY')
198             {
199 643         1031 $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 277         665 $data = [ @_ ];
207             }
208              
209             # Sanity checking.
210              
211 936 100       2266 if (@$data) {
212 935         1442 my $nrow = @$data;
213 935         1219 my $ncol;
214              
215 935         2428 for my $i (0 .. $nrow - 1) {
216 1828         2596 my $row = $data -> [$i];
217              
218             # Verify that the row is a reference to an array.
219              
220 1828 50       3597 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 1828 100       3054 if ($i == 0) {
229 935         1800 $ncol = @$row;
230             } else {
231 893 50       1989 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 935 100       4183 @$self = map [ @$_ ], @$data if $ncol;
239             }
240             }
241              
242 947         2898 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 3486 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
297 3 50       9 croak "Too many arguments for ", (caller(0))[3] if @_ > 4;
298 3         6 my $class = shift;
299              
300 3 50       6 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         8 my $x = bless [], $class;
312 3         11 for my $i (0 .. $nrow - 1) {
313 10         36 for my $j (0 .. $ncol - 1) {
314 52         220 $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 129 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
342 2         5 my $class = shift;
343              
344 2 50       7 croak +(caller(0))[3], " is a class method, not an instance method"
345             if ref $class;
346              
347 2         6 my @args = ();
348 2         12 for (my $i = 0 ; $i <= $#_ ; ++$i) {
349 8         13 my $x = $_[$i];
350 8 50 33     41 $x = $class -> new($x)
351             unless defined(blessed($x)) && $x -> isa($class);
352 8 100       20 if ($x -> is_vector()) {
353 4         13 push @args, $x -> to_row();
354             } else {
355 4         13 push @args, $x;
356             }
357             }
358              
359 2         8 $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 98 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
384 1         3 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         5 $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 91     91 1 8691 my $self = shift;
406 91         152 my $ref = ref $self;
407 91   66     290 my $class = $ref || $self;
408              
409 91         124 my $n;
410 91 100       169 if (@_) {
411 88         136 $n = shift;
412             } else {
413 3 50       7 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 91         601 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 8829 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 8903 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 7277 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         8 my $class = shift;
465              
466 5         8 my $n = shift;
467 5         42 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 6856 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         10 my $class = shift;
492              
493 6 50       12 croak +(caller(0))[3], " is a class method, not an instance method"
494             if ref $class;
495              
496 6         10 my $c = shift;
497 6 100       24 my ($m, $n) = @_ == 0 ? (1, 1)
    100          
498             : @_ == 1 ? (@_, @_)
499             : (@_);
500 6 50       17 croak "The number of rows must be equal to the number of columns"
501             unless $m == $n;
502              
503 6         46 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 4303 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         21 my $self = shift;
524 13         42 $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 4262 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
543 5 50       16 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
544 5         9 my $self = shift;
545 5         13 $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 19509 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
564 5 50       15 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
565 5         7 my $self = shift;
566              
567 5         30 require Math::Trig;
568 5         31 my $inf = Math::Trig::Inf();
569 5         26 $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 4262 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
588 5 50       15 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
589 5         9 my $self = shift;
590              
591 5         27 require Math::Trig;
592 5         14 my $inf = Math::Trig::Inf();
593 5         21 my $nan = $inf - $inf;
594 5         13 $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 4101 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
614 33 50       66 croak "Too many arguments for ", (caller(0))[3] if @_ > 4;
615 33         54 my $class = shift;
616              
617 33 50       64 croak +(caller(0))[3], " is a class method, not an instance method"
618             if ref $class;
619              
620 33         51 my $c = shift;
621 33 100       106 my ($m, $n) = @_ == 0 ? (1, 1)
    100          
622             : @_ == 1 ? (@_, @_)
623             : (@_);
624              
625 33         247 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 12492 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
653 6 50       16 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
654 6         9 my $class = shift;
655              
656 6 50       13 croak +(caller(0))[3], " is a class method, not an instance method"
657             if ref $class;
658              
659 6 100       24 my ($nrow, $ncol) = @_ == 0 ? (1, 1)
    100          
660             : @_ == 1 ? (@_, @_)
661             : (@_);
662              
663 6         13 my $x = bless [], $class;
664 6         19 for my $i (0 .. $nrow - 1) {
665 10         16 for my $j (0 .. $ncol - 1) {
666 22         122 $x -> [$i][$j] = CORE::rand;
667             }
668             }
669              
670 6         17 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 23106 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
693 6 50       16 croak "Too many arguments for ", (caller(0))[3] if @_ > 4;
694 6         11 my $class = shift;
695              
696 6 50       13 croak +(caller(0))[3], " is a class method, not an instance method"
697             if ref $class;
698              
699 6         12 my ($min, $max);
700 6         7 my $lim = shift;
701 6 100       17 if (ref($lim) eq 'ARRAY') {
702 3         7 ($min, $max) = @$lim;
703             } else {
704 3         6 $min = 0;
705 3         5 $max = $lim;
706             }
707              
708 6 100       23 my ($nrow, $ncol) = @_ == 0 ? (1, 1)
    100          
709             : @_ == 1 ? (@_, @_)
710             : (@_);
711              
712 6         14 my $c = $max - $min + 1;
713 6         13 my $x = bless [], $class;
714 6         16 for my $i (0 .. $nrow - 1) {
715 14         23 for my $j (0 .. $ncol - 1) {
716 50         199 $x -> [$i][$j] = $min + CORE::int(CORE::rand($c));
717             }
718             }
719              
720 6         18 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 8381 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
743 6 50       14 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
744 6         13 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       24 my ($nrow, $ncol) = @_ == 0 ? (1, 1)
    100          
750             : @_ == 1 ? (@_, @_)
751             : (@_);
752              
753 6         10 my $nelm = $nrow * $ncol;
754 6         10 my $twopi = 2 * atan2 0, -1;
755              
756             # The following might generate one value more than we need.
757              
758 6         10 my $x = [];
759 6         16 for (my $k = 0 ; $k < $nelm ; $k += 2) {
760 13         75 my $c1 = sqrt(-2 * log(CORE::rand));
761 13         21 my $c2 = $twopi * CORE::rand;
762 13         68 push @$x, $c1 * cos($c2), $c1 * sin($c2);
763             }
764 6 100       18 pop @$x if @$x > $nelm;
765              
766 6         14 $x = bless [ $x ], $class;
767 6         21 $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 127 50   127 1 2828 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
782 127         198 my $x = shift;
783 127         208 my $class = ref $x;
784              
785 127 50       276 croak +(caller(0))[3], " is an instance method, not a class method"
786             unless $class;
787              
788 127         703 my $y = [ map [ @$_ ], @$x ];
789 127         341 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 2573 my $that = shift;
815 2   33     12 my $class = ref($that) || $that;
816 2         6 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         3 my $len = scalar @diag;
823 2 50       5 return undef if ($len == 0);
824              
825 2         8 for my $idx (0..$len-1) {
826 8         15 my @r = (0) x $len;
827 8         11 $r[$idx] = $diag[$idx];
828 8         10 push(@{$self}, [@r]);
  8         19  
829             }
830 2         6 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 7328 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       21 if (ref $_[0] eq "ARRAY") {
873 4         11 @main_d = @{$_[0]};
  4         9  
874              
875 4 100       11 if (ref $_[1] eq "ARRAY") {
876 3         5 @up_d = @{$_[1]};
  3         6  
877              
878 3 100       8 if (ref $_[2] eq "ARRAY") {
879 2         3 @low_d = @{$_[2]};
  2         4  
880             }
881             }
882             } else {
883 0         0 @main_d = @_;
884             }
885              
886 4         5 my $len = scalar @main_d;
887 4 50       10 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       13 @up_d = (1) x ($len -1) if (scalar @up_d == 0);
894 4 100       9 @low_d = @up_d if (scalar @low_d == 0);
895              
896             #
897             # First row...
898             #
899 4         8 my @arow = (0) x $len;
900 4         9 @arow[0..1] = ($main_d[0], $up_d[0]);
901 4         6 push (@{$self}, [@arow]);
  4         8  
902              
903             #
904             # Bulk of the matrix...
905             #
906 4         10 for my $idx (1 .. $#main_d - 1) {
907 8         13 my @r = (0) x $len;
908 8         21 @r[$idx-1 .. $idx+1] = ($low_d[$idx-1], $main_d[$idx], $up_d[$idx]);
909 8         12 push (@{$self}, [@r]);
  8         19  
910             }
911              
912             #
913             # Last row.
914             #
915 4         8 my @zrow = (0) x $len;
916 4         10 @zrow[$len-2..$len-1] = ($low_d[$#main_d -1], $main_d[$#main_d]);
917 4         6 push (@{$self}, [@zrow]);
  4         7  
918              
919 4         14 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 3743 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
935             #croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
936 4         7 my $class = shift;
937              
938 4         7 my $y = [];
939 4         6 my $nrowy = 0;
940 4         8 my $ncoly = 0;
941              
942 4         11 for my $i (0 .. $#_) {
943 9         17 my $x = $_[$i];
944              
945 9 100 66     43 $x = $class -> new($x)
946             unless defined(blessed($x)) && $x -> isa($class);
947              
948 9         22 my ($nrowx, $ncolx) = $x -> size();
949              
950             # Upper right submatrix.
951              
952 9         17 for my $i (0 .. $nrowy - 1) {
953 9         14 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         19 for my $j (0 .. $ncoly - 1) {
962 17         29 $y -> [$nrowy + $i][$j] = 0;
963             }
964             }
965              
966             # Lower right submatrix.
967              
968 9         15 for my $i (0 .. $nrowx - 1) {
969 11         17 for my $j (0 .. $ncolx - 1) {
970 13         27 $y -> [$nrowy + $i][$ncoly + $j] = $x -> [$i][$j];
971             }
972             }
973              
974 9         14 $nrowy += $nrowx;
975 9         17 $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 56 50   56 1 262 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
999 56 50       123 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1000 56         87 my $x = shift;
1001 56         151 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 111 50   111 1 344 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1016 111 50       208 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1017 111         171 my $x = shift;
1018 111 100       225 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 161 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1033 52 50       123 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1034 52         90 my $x = shift;
1035 52 100 100     122 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 191 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1050 73 50       152 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1051 73         122 my $x = shift;
1052 73 100       158 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 196 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1067 81 50       160 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1068 81         118 my $x = shift;
1069 81 100       188 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 78 50   78 1 197 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1084 78 50       161 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1085 78         110 my $x = shift;
1086 78         175 my ($nrow, $ncol) = $x -> size();
1087 78 100       292 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 139 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1108 50 50       114 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1109 50         77 my $x = shift;
1110              
1111 50         121 my ($nrow, $ncol) = $x -> size();
1112 50 100       126 return 0 unless $nrow == $ncol;
1113              
1114 44         128 for my $i (1 .. $nrow - 1) {
1115 100         155 for my $j (0 .. $i - 1) {
1116 232 100       540 return 0 unless $x -> [$i][$j] == $x -> [$j][$i];
1117             }
1118             }
1119              
1120 25         112 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 88 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1143 25 50       52 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1144 25         42 my $x = shift;
1145              
1146 25         62 my ($nrow, $ncol) = $x -> size();
1147 25 100       73 return 0 unless $nrow == $ncol;
1148              
1149             # Check the diagonal.
1150              
1151 22         62 for my $i (0 .. $nrow - 1) {
1152 38 100       152 return 0 unless $x -> [$i][$i] == 0;
1153             }
1154              
1155             # Check the off-diagonal.
1156              
1157 5         16 for my $i (1 .. $nrow - 1) {
1158 5         12 for my $j (0 .. $i - 1) {
1159 6 100       27 return 0 unless $x -> [$i][$j] == -$x -> [$j][$i];
1160             }
1161             }
1162              
1163 2         9 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 84 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1186 23 50       53 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1187 23         40 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 78 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1214 23 50       77 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1215 23         42 my $x = shift;
1216              
1217 23         53 my ($nrow, $ncol) = $x -> size();
1218 23 100       60 return 0 unless $nrow == $ncol;
1219              
1220             # Check the lower triangular part.
1221              
1222 20         63 for my $i (0 .. $nrow - 2) {
1223 34         52 my $first = $x -> [$i][0];
1224 34         62 for my $k (1 .. $nrow - $i - 1) {
1225 71 100       215 return 0 unless $x -> [$i + $k][$k] == $first;
1226             }
1227             }
1228              
1229             # Check the strictly upper triangular part.
1230              
1231 8         25 for my $j (1 .. $ncol - 2) {
1232 15         25 my $first = $x -> [0][$j];
1233 15         30 for my $k (1 .. $nrow - $j - 1) {
1234 33 100       75 return 0 unless $x -> [$k][$j + $k] == $first;
1235             }
1236             }
1237              
1238 7         32 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 92 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1254 25 50       66 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1255 25         41 my $x = shift;
1256 25         74 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 91 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1272 25 50       55 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1273 25         42 my $x = shift;
1274 25         87 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 179 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1290 75 50       136 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
1291 75         119 my $x = shift;
1292              
1293 75         173 my ($nrow, $ncol) = $x -> size();
1294              
1295             # An empty matrix contains no elements that are different from $c.
1296              
1297 75 100       180 return 1 if $nrow * $ncol == 0;
1298              
1299 72 100       143 my $c = @_ ? shift() : $x -> [0][0];
1300 72         185 for my $i (0 .. $nrow - 1) {
1301 78         127 for my $j (0 .. $ncol - 1) {
1302 147 100       719 return 0 if $x -> [$i][$j] != $c;
1303             }
1304             }
1305              
1306 3         12 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 78 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1322 25 50       52 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1323 25         47 my $x = shift;
1324              
1325 25         55 my ($nrow, $ncol) = $x -> size();
1326 25 100       74 return 0 unless $nrow == $ncol;
1327              
1328 22         79 for my $i (0 .. $nrow - 1) {
1329 24         44 for my $j (0 .. $ncol - 1) {
1330 36 100       164 return 0 if $x -> [$i][$j] != ($i == $j ? 1 : 0);
    100          
1331             }
1332             }
1333              
1334 3         14 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 87 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1356 25 50       57 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1357 25         38 my $x = shift;
1358              
1359 25         58 my ($nrow, $ncol) = $x -> size();
1360 25 100       78 return 0 unless $nrow == $ncol;
1361              
1362 22         61 my $imax = $nrow - 1;
1363 22         59 for my $i (0 .. $nrow - 1) {
1364 23         38 for my $j (0 .. $ncol - 1) {
1365 47 100       200 return 0 if $x -> [$i][$j] != ($i + $j == $imax ? 1 : 0);
    100          
1366             }
1367             }
1368              
1369 3         14 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 80 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1391 25 50       51 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1392 25         43 my $x = shift;
1393              
1394 25         61 my ($nrow, $ncol) = $x -> size();
1395              
1396 25         76 for my $i (0 .. $nrow - 1) {
1397 34         59 for my $j (0 .. $ncol - 1) {
1398 80         118 my $val = $x -> [$i][$j];
1399 80 100 100     291 return 0 if $val != 0 && $val != 1;
1400             }
1401             }
1402              
1403 5         22 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 91 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1425 25 50       53 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1426 25         38 my $x = shift;
1427              
1428 25         60 my ($nrow, $ncol) = $x -> size();
1429 25 100       79 return 0 unless $nrow == $ncol;
1430              
1431 22         63 my $rowsum = [ (0) x $nrow ];
1432 22         62 my $colsum = [ (0) x $ncol ];
1433              
1434 22         57 for my $i (0 .. $nrow - 1) {
1435 30         56 for my $j (0 .. $ncol - 1) {
1436 74         98 my $val = $x -> [$i][$j];
1437 74 100 100     261 return 0 if $val != 0 && $val != 1;
1438 57 100       124 if ($val == 1) {
1439 16 50       30 return 0 if ++$rowsum -> [$i] > 1;
1440 16 50       42 return 0 if ++$colsum -> [$j] > 1;
1441             }
1442             }
1443             }
1444              
1445 5         12 for my $i (0 .. $nrow - 1) {
1446 10 50       22 return 0 if $rowsum -> [$i] != 1;
1447 10 50       19 return 0 if $colsum -> [$i] != 1;
1448             }
1449              
1450 5         24 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 85 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         46 my $x = shift;
1468              
1469 25         55 my ($nrow, $ncol) = $x -> size();
1470              
1471 25         72 for my $i (0 .. $nrow - 1) {
1472 83         120 for my $j (0 .. $ncol - 1) {
1473 347 50       662 return 0 unless $x -> [$i][$j] == int $x -> [$i][$j];
1474             }
1475             }
1476              
1477 25         134 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 86 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1502 25 50       54 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1503 25         39 my $x = shift;
1504 25         67 $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 82 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1529 25 50       54 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1530 25         43 my $x = shift;
1531 25         59 $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 94 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1557 25 50       66 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1558 25         37 my $x = shift;
1559 25         63 $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 79 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1585 25 50       54 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1586 25         39 my $x = shift;
1587 25         60 $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 79 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1613 25 50       47 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1614 25         42 my $x = shift;
1615 25         62 $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 84 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1642 25 50       49 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1643 25         44 my $x = shift;
1644 25         62 $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 74 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         44 my $x = shift;
1672 25         64 $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 88 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1699 25 50       89 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1700 25         43 my $x = shift;
1701 25         61 $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 611 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
1728 225 50       396 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
1729 225         314 my $x = shift;
1730 225         382 my $class = ref $x;
1731              
1732 225         473 my ($nrow, $ncol) = $x -> size();
1733 225 100       598 return 0 unless $nrow == $ncol; # must be square
1734              
1735 198         308 my $k = shift; # bandwidth
1736 198 50       362 croak "Bandwidth can not be undefined" unless defined $k;
1737 198 50       416 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       540 return 0 if $nrow <= $k; # if the band doesn't fit inside
1745 136 100       380 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         241 for my $j ($k + 1 + $i .. $ncol - 1) {
1749 188 100 100     929 return 0 if ($x -> [$i][$j] != 0 ||
1750             $x -> [$j][$i] != 0);
1751             }
1752             }
1753              
1754 23         109 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 607 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
1786 225 50       403 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
1787 225         320 my $x = shift;
1788 225         370 my $class = ref $x;
1789              
1790 225         494 my ($nrow, $ncol) = $x -> size();
1791 225 100       622 return 0 unless $nrow == $ncol; # must be square
1792              
1793 198         271 my $k = shift; # bandwidth
1794 198 50       381 croak "Bandwidth can not be undefined" unless defined $k;
1795 198 50       341 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       670 return 0 if $nrow <= $k; # if the band doesn't fit inside
1803 136 100       383 return 1 if $nrow == $k + 1; # if the whole band fits exactly
1804              
1805             # Check upper part.
1806              
1807 106         310 for my $i (0 .. $nrow - $k - 2) {
1808 134         224 for my $j (0 .. $nrow - $k - 2 - $i) {
1809 210 100       702 return 0 if $x -> [$i][$j] != 0;
1810             }
1811             }
1812              
1813             # Check lower part.
1814              
1815 35         75 for my $i ($k + 1 .. $nrow - 1) {
1816 57         100 for my $j ($nrow - $i + $k .. $nrow - 1) {
1817 89 100       215 return 0 if $x -> [$i][$j] != 0;
1818             }
1819             }
1820              
1821 27         172 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 98 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1846 25 50       62 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1847 25         41 my $x = shift;
1848              
1849 25         64 my $nrow = $x -> nrow();
1850 25         61 my $ncol = $x -> ncol();
1851              
1852 25 100       70 return 0 unless $nrow == $ncol;
1853              
1854 22         67 for my $i (1 .. $nrow - 1) {
1855 30         61 for my $j (0 .. $i - 1) {
1856 37 100       154 return 0 unless $x -> [$i][$j] == 0;
1857             }
1858             }
1859              
1860 6         24 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       56 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1885 25         43 my $x = shift;
1886              
1887 25         59 my $nrow = $x -> nrow();
1888 25         55 my $ncol = $x -> ncol();
1889              
1890 25 100       107 return 0 unless $nrow == $ncol;
1891              
1892 22         63 for my $i (0 .. $nrow - 1) {
1893 36         70 for my $j (0 .. $i) {
1894 50 100       189 return 0 unless $x -> [$i][$j] == 0;
1895             }
1896             }
1897              
1898 2         15 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 84 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1922 25 50       58 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1923 25         40 my $x = shift;
1924              
1925 25         61 my $nrow = $x -> nrow();
1926 25         54 my $ncol = $x -> ncol();
1927              
1928 25 100       72 return 0 unless $nrow == $ncol;
1929              
1930 22         70 for my $i (0 .. $nrow - 1) {
1931 28         69 for my $j ($i + 1 .. $ncol - 1) {
1932 35 100       141 return 0 unless $x -> [$i][$j] == 0;
1933             }
1934             }
1935              
1936 6         26 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 84 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1960 25 50       60 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1961 25         38 my $x = shift;
1962              
1963 25         58 my $nrow = $x -> nrow();
1964 25         58 my $ncol = $x -> ncol();
1965              
1966 25 100       74 return 0 unless $nrow == $ncol;
1967              
1968 22         60 for my $i (0 .. $nrow - 1) {
1969 24         54 for my $j ($i .. $ncol - 1) {
1970 46 100       194 return 0 unless $x -> [$i][$j] == 0;
1971             }
1972             }
1973              
1974 2         9 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 86 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
1998 25 50       50 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
1999 25         37 my $x = shift;
2000              
2001 25         64 my $nrow = $x -> nrow();
2002 25         56 my $ncol = $x -> ncol();
2003              
2004 25 100       74 return 0 unless $nrow == $ncol;
2005              
2006 22         65 for my $i (1 .. $nrow - 1) {
2007 29         52 for my $j ($ncol - $i .. $ncol - 1) {
2008 34 100       145 return 0 unless $x -> [$i][$j] == 0;
2009             }
2010             }
2011              
2012 6         52 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 77 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2036 25 50       56 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2037 25         45 my $x = shift;
2038              
2039 25         56 my $nrow = $x -> nrow();
2040 25         60 my $ncol = $x -> ncol();
2041              
2042 25 100       82 return 0 unless $nrow == $ncol;
2043              
2044 22         61 for my $i (0 .. $nrow - 1) {
2045 34         65 for my $j ($ncol - $i - 1 .. $ncol - 1) {
2046 42 100       171 return 0 unless $x -> [$i][$j] == 0;
2047             }
2048             }
2049              
2050 2         11 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 85 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2074 25 50       53 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2075 25         39 my $x = shift;
2076              
2077 25         55 my $nrow = $x -> nrow();
2078 25         51 my $ncol = $x -> ncol();
2079              
2080 25 100       69 return 0 unless $nrow == $ncol;
2081              
2082 22         64 for my $i (0 .. $nrow - 1) {
2083 28         62 for my $j (0 .. $ncol - $i - 2) {
2084 39 100       145 return 0 unless $x -> [$i][$j] == 0;
2085             }
2086             }
2087              
2088 6         29 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 111 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2112 25 50       52 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2113 25         47 my $x = shift;
2114              
2115 25         54 my $nrow = $x -> nrow();
2116 25         52 my $ncol = $x -> ncol();
2117              
2118 25 100       78 return 0 unless $nrow == $ncol;
2119              
2120 22         76 for my $i (0 .. $nrow - 1) {
2121 24         42 for my $j (0 .. $ncol - $i - 1) {
2122 45 100       180 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 37 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         12 my ($m, $n) = $x -> size();
2160              
2161 4         7 my $I = [];
2162 4         7 my $J = [];
2163 4         9 for my $j (0 .. $n - 1) {
2164 6         11 for my $i (0 .. $m - 1) {
2165 12 100       25 next unless $x->[$i][$j];
2166 10         16 push @$I, $i;
2167 10         26 push @$J, $j;
2168             }
2169             }
2170              
2171 4 100       14 return $I, $J if wantarray;
2172              
2173 2         6 my $K = [ map { $m * $J -> [$_] + $I -> [$_] } 0 .. $#$I ];
  5         12  
2174 2         6 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       5 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2191 2         3 my $x = shift;
2192              
2193 2         14 require Math::Trig;
2194 2         6 my $pinf = Math::Trig::Inf(); # positiv infinity
2195 2         8 my $ninf = -$pinf; # negative infinity
2196              
2197 2         7 bless [ map { [
2198             map {
2199 2 100 100     21 $ninf < $_ && $_ < $pinf ? 1 : 0
  6         31  
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 14 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2218 2 50       6 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2219 2         3 my $x = shift;
2220              
2221 2         11 require Math::Trig;
2222 2         9 my $pinf = Math::Trig::Inf(); # positiv infinity
2223 2         8 my $ninf = -$pinf; # negative infinity
2224              
2225 2         6 bless [ map { [
2226             map {
2227 2 100 100     4 $_ == $pinf || $_ == $ninf ? 1 : 0;
  6         27  
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       5 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2246 2         4 my $x = shift;
2247              
2248 2 100       7 bless [ map [ map { $_ != $_ ? 1 : 0 } @$_ ], @$x ], ref $x;
  6         19  
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 93 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2266 12 50       26 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
2267 12         19 my $x = shift;
2268 12         42 $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 88 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2286 12 50       26 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
2287 12         18 my $x = shift;
2288 12         41 $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 90 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2305 12 50       28 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
2306 12         17 my $x = shift;
2307 12         40 $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 70 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         16 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 2087     2087 1 722868 my $self = shift;
2347 2087         2807 my $m = @{$self};
  2087         6195  
2348 2087 100       4344 my $n = $m ? @{$self->[0]} : 0;
  1918         3213  
2349 2087         5352 ($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 193 50   193 1 1339 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2364 193 50       379 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2365 193         261 my $x = shift;
2366 193 100       701 return @$x ? @$x * @{$x->[0]} : 0;
  164         793  
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 657 50   657 1 7284 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2381 657 50       1176 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2382 657         863 my $x = shift;
2383 657         1605 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 590 50   590 1 2114 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2398 590 50       1077 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2399 590         803 my $x = shift;
2400 590 100       1735 return @$x ? scalar(@{$x->[0]}) : 0;
  543         1339  
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 907 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       32 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 948 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2433 6 50       18 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2434 6         10 my $x = shift;
2435 6         13 my ($nrow, $ncol) = $x -> size();
2436 6         10 my $ndim = 0;
2437 6 100       14 ++$ndim if $nrow != 1;
2438 6 100       12 ++$ndim if $ncol != 1;
2439 6         22 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 4413 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
2473 18 50       46 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
2474 18         27 my $x = shift;
2475              
2476 18         36 my ($nrow, $ncol) = $x -> size();
2477              
2478 18         31 my $upper = 0;
2479 18         24 my $lower = 0;
2480              
2481 18         41 for my $i (0 .. $nrow - 1) {
2482 52         72 for my $j (0 .. $ncol - 1) {
2483 192 100       320 next if $x -> [$i][$j] == 0;
2484 146         178 my $dist = $j - $i;
2485 146 100       210 if ($dist > 0) {
2486 52 100       103 $upper = $dist if $dist > $upper;
2487             } else {
2488 94 100       170 $lower = $dist if $dist < $lower;
2489             }
2490             }
2491             }
2492              
2493 18         26 $lower = -$lower;
2494 18 100       47 return $lower, $upper if wantarray;
2495 9 50       21 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 132 my $x = shift;
2527 25         46 my $class = ref $x;
2528              
2529 25         36 my $ncol;
2530 25         47 my $z = bless [], $class; # initialize output
2531              
2532 25         62 for my $y ($x, @_) {
2533 63         141 my $ncoly = $y -> ncol();
2534 63 100       134 next if $ncoly == 0; # ignore empty $y
2535              
2536 44 100       89 if (defined $ncol) {
2537 22 50       64 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         144 push @$z, map [ @$_ ], @$y;
2544             }
2545              
2546 25         82 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 92     92 1 259 my $x = shift;
2565 92         169 my $class = ref $x;
2566              
2567 92         115 my $nrow;
2568 92         203 my $z = bless [], $class; # initialize output
2569              
2570 92         219 for my $y ($x, @_) {
2571 191         368 my $nrowy = $y -> nrow();
2572 191 100       387 next if $nrowy == 0; # ignore empty $y
2573              
2574 176 100       315 if (defined $nrow) {
2575 87 50       187 croak "All operands must have the same number of rows in ",
2576             (caller(0))[3] unless $nrowy == $nrow;
2577             } else {
2578 89         132 $nrow = $nrowy;
2579             }
2580              
2581 176         341 for my $i (0 .. $nrow - 1) {
2582 419         614 push @{ $z -> [$i] }, @{ $y -> [$i] };
  419         628  
  419         854  
2583             }
2584             }
2585              
2586 92         175 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 42 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
2604 4 50       24 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
2605 4         6 my $x = shift;
2606 4         8 my $class = ref $x;
2607              
2608 4         6 my $idx = shift;
2609 4 50       10 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         17 $idx = $idx -> to_row();
2614 3         6 $idx = $idx -> [0];
2615             } else {
2616 1         12 $idx = [ $idx ];
2617             }
2618              
2619 4         11 my ($nrowx, $ncolx) = $x -> size();
2620              
2621 4         6 my $y = [];
2622 4         9 for my $iy (0 .. $#$idx) {
2623 5         8 my $ix = $idx -> [$iy];
2624 5 50       12 croak "Row index value $ix too large for $nrowx-by-$ncolx matrix in ",
2625             (caller(0))[3] if $ix >= $nrowx;
2626 5         5 $y -> [$iy] = [ @{ $x -> [$ix] } ];
  5         13  
2627             }
2628              
2629 4         23 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 37 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
2647 4 50       10 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
2648 4         7 my $x = shift;
2649 4         6 my $class = ref $x;
2650              
2651 4         7 my $idx = shift;
2652 4 50       7 croak "Column index can not be undefined" unless defined $idx;
2653 4 100       10 if (ref $idx) {
2654 3 50 33     18 $idx = __PACKAGE__ -> new($idx)
2655             unless defined(blessed($idx)) && $idx -> isa($class);
2656 3         14 $idx = $idx -> to_row();
2657 3         5 $idx = $idx -> [0];
2658             } else {
2659 1         3 $idx = [ $idx ];
2660             }
2661              
2662 4         11 my ($nrowx, $ncolx) = $x -> size();
2663              
2664 4         6 my $y = [];
2665 4         11 for my $jy (0 .. $#$idx) {
2666 5         8 my $jx = $idx -> [$jy];
2667 5 50       11 croak "Column index value $jx too large for $nrowx-by-$ncolx matrix in ",
2668             (caller(0))[3] if $jx >= $ncolx;
2669 5         8 for my $i (0 .. $nrowx - 1) {
2670 20         47 $y -> [$i][$jy] = $x -> [$i][$jx];
2671             }
2672             }
2673              
2674 4         15 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 44 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         6 my $idxdel = shift;
2696 5 50       11 croak "Row index can not be undefined" unless defined $idxdel;
2697 5 100       8 if (ref $idxdel) {
2698 4 50 33     22 $idxdel = __PACKAGE__ -> new($idxdel)
2699             unless defined(blessed($idxdel)) && $idxdel -> isa($class);
2700 4         10 $idxdel = $idxdel -> to_row();
2701 4         9 $idxdel = $idxdel -> [0];
2702             } else {
2703 1         4 $idxdel = [ $idxdel ];
2704             }
2705              
2706 5         12 my $nrowx = $x -> nrow();
2707              
2708             # This should be made faster.
2709              
2710 5         10 my $idxget = [];
2711 5         8 for my $i (0 .. $nrowx - 1) {
2712 20         27 my $seen = 0;
2713 20         28 for my $idx (@$idxdel) {
2714 28 100       51 if ($i == int $idx) {
2715 9         10 $seen = 1;
2716 9         14 last;
2717             }
2718             }
2719 20 100       38 push @$idxget, $i unless $seen;
2720             }
2721              
2722 5         8 my $y = [];
2723 5         19 @$y = map [ @$_ ], @$x[ @$idxget ];
2724 5         18 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 44 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
2741 5 50       10 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
2742 5         10 my $x = shift;
2743 5         8 my $class = ref $x;
2744              
2745 5         7 my $idxdel = shift;
2746 5 50       10 croak "Column index can not be undefined" unless defined $idxdel;
2747 5 100       11 if (ref $idxdel) {
2748 4 50 33     21 $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         14 my ($nrowx, $ncolx) = $x -> size();
2757              
2758             # This should be made faster.
2759              
2760 5         10 my $idxget = [];
2761 5         11 for my $j (0 .. $ncolx - 1) {
2762 20         26 my $seen = 0;
2763 20         26 for my $idx (@$idxdel) {
2764 28 100       52 if ($j == int $idx) {
2765 9         10 $seen = 1;
2766 9         12 last;
2767             }
2768             }
2769 20 100       39 push @$idxget, $j unless $seen;
2770             }
2771              
2772 5         8 my $y = [];
2773 5 100       11 if (@$idxget) {
2774 4         8 for my $row (@$x) {
2775 16         23 push @$y, [ @{$row}[ @$idxget ] ];
  16         29  
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 59 my $self = shift;
2796 11         17 my $other = shift;
2797 11         46 my $result = $self->clone();
2798              
2799 11 50       26 return undef if scalar(@{$self}) != scalar(@{$other});
  11         23  
  11         28  
2800 11         20 for my $i (0 .. $#{$self}) {
  11         27  
2801 27         41 push @{$result->[$i]}, @{$other->[$i]};
  27         42  
  27         72  
2802             }
2803 11         34 $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 84 croak "Not enough input arguments" if @_ < 1;
2846 12         17 my $x = shift;
2847 12         21 my $class = ref $x;
2848              
2849 12         17 my $offs = 0;
2850 12         30 my $len = $x -> nrow();
2851 12         25 my $repl = $class -> new([]);
2852              
2853 12 100       26 if (@_) {
2854 10         15 $offs = shift;
2855 10 50       19 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       18 if (@_) {
2864 4         7 $len = shift;
2865 4 50       7 croak "Length can not be undefined" unless defined $len;
2866 4 50       9 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         7 $repl = $repl -> catrow(@_);
2875             }
2876             }
2877             }
2878              
2879 12         29 my $y = $x -> clone();
2880 12         26 my $z = $class -> new([]);
2881              
2882 12         35 @$z = splice @$y, $offs, $len, @$repl;
2883 12 100       59 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 22 50   22 1 119 croak "Not enough input arguments" if @_ < 1;
2922 22         42 my $x = shift;
2923 22         45 my $class = ref $x;
2924              
2925 22         56 my ($nrowx, $ncolx) = $x -> size();
2926              
2927 22         41 my $offs = 0;
2928 22         46 my $len = $ncolx;
2929 22         64 my $repl = $class -> new([]);
2930              
2931 22 100       55 if (@_) {
2932 20         39 $offs = shift;
2933 20 50       46 croak "Offset can not be undefined" unless defined $offs;
2934 20 50       42 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 20 100       52 if (@_) {
2942 14         25 $len = shift;
2943 14 50       32 croak "Length can not be undefined" unless defined $len;
2944 14 50       34 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 14 100       37 if (@_) {
2952 2         16 $repl = $repl -> catcol(@_);
2953             }
2954             }
2955             }
2956              
2957 22         54 my $y = $x -> clone();
2958 22         52 my $z = $class -> new([]);
2959              
2960 22 50       73 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 22 100 100     157 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 16 100       51 if ($repl -> is_empty()) {
2991 14         40 for my $i (0 .. $nrowx - 1) {
2992 47         60 @{ $z -> [$i] } = splice @{ $y -> [$i] }, $offs, $len;
  47         120  
  47         84  
2993             }
2994             } else {
2995 2         6 for my $i (0 .. $nrowx - 1) {
2996 4         6 @{ $z -> [$i] } = splice @{ $y -> [$i] }, $offs, $len, @{ $repl -> [$i] };
  4         9  
  4         7  
  4         10  
2997             }
2998             }
2999             }
3000              
3001 22 100       126 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 47 my $x = shift;
3019 5         9 my $class = ref $x;
3020              
3021 5         10 my $y = bless [], $class;
3022 5         14 my $ncolx = $x -> ncol();
3023 5 100       14 return $y if $ncolx == 0;
3024              
3025 4         12 for my $j (0 .. $ncolx - 1) {
3026 9         30 push @$y, [ map $_->[$j], @$x ];
3027             }
3028 4         12 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 29 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         41 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 69 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3063 25 50       53 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
3064 25         36 my $x = shift;
3065 25         51 my $class = ref $x;
3066              
3067 25         167 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 78 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3087 12 50       25 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3088 12         17 my $x = shift;
3089 12     20   62 $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 65 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3105 12 50       27 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3106 12         23 my $x = shift;
3107 12         19 my $class = ref $x;
3108              
3109 12         21 my $n = 1;
3110 12 100       24 if (@_) {
3111 10         17 $n = shift;
3112 10 100       23 if (ref $n) {
3113 2 100 66     22 $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         5 $n = $n -> [0][0];
3117             }
3118 10 50       27 croak "Argument must be an integer" unless $n == int $n;
3119             }
3120              
3121 12         22 my $y = [];
3122              
3123             # Rotate 0 degrees, i.e., clone.
3124              
3125 12         22 $n %= 4;
3126 12 100       49 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         12 my ($nrowx, $ncolx) = $x -> size();
3134 5         10 my $jmax = $ncolx - 1;
3135 5         10 for my $i (0 .. $nrowx - 1) {
3136 8         12 for my $j (0 .. $ncolx - 1) {
3137 24         50 $y -> [$jmax - $j][$i] = $x -> [$i][$j];
3138             }
3139             }
3140             }
3141              
3142             # Rotate 180 degrees.
3143              
3144             elsif ($n == 2) {
3145 3         59 $y = [ map [ reverse @$_ ], reverse @$x ];
3146             }
3147              
3148             # Rotate 270 degrees.
3149              
3150             elsif ($n == 3) {
3151 3         10 my ($nrowx, $ncolx) = $x -> size();
3152 3         6 my $imax = $nrowx - 1;
3153 3         8 for my $i (0 .. $nrowx - 1) {
3154 4         10 for my $j (0 .. $ncolx - 1) {
3155 12         25 $y -> [$j][$imax - $i] = $x -> [$i][$j];
3156             }
3157             }
3158             }
3159              
3160 12         36 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 27 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 36 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3192 2 50       8 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
3193 2         3 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 43 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         7 my $class = ref $x;
3232              
3233 5         9 my $y = shift;
3234 5 50 33     37 $y = __PACKAGE__ -> new($y)
3235             unless defined(blessed($y)) && $y -> isa(__PACKAGE__);
3236 5 50       15 croak "Input argument must contain two elements"
3237             unless $y -> nelm() == 2;
3238              
3239 5         11 my ($nrowx, $ncolx) = $x -> size();
3240              
3241 5         11 $y = $y -> to_col();
3242 5         10 my $nrowrep = $y -> [0][0];
3243 5         6 my $ncolrep = $y -> [1][0];
3244              
3245 5         8 my $z = [];
3246 5         11 for my $ix (0 .. $nrowx - 1) {
3247 8         15 for my $jx (0 .. $ncolx - 1) {
3248 24         32 for my $iy (0 .. $nrowrep - 1) {
3249 30         49 for my $jy (0 .. $ncolrep - 1) {
3250 36         49 my $iz = $ix * $nrowrep + $iy;
3251 36         40 my $jz = $jx * $ncolrep + $jy;
3252 36         58 $z -> [$iz][$jz] = $x -> [$ix][$jx];
3253             }
3254             }
3255             }
3256             }
3257              
3258 5         19 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 40 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
3293 5 50       11 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3294 5         8 my $x = shift;
3295 5         8 my $class = ref $x;
3296              
3297 5         8 my $y = shift;
3298 5 50 33     38 $y = __PACKAGE__ -> new($y)
3299             unless defined(blessed($y)) && $y -> isa(__PACKAGE__);
3300 5 50       17 croak "Input argument must contain two elements"
3301             unless $y -> nelm() == 2;
3302              
3303 5         12 my ($nrowx, $ncolx) = $x -> size();
3304              
3305 5         13 $y = $y -> to_col();
3306 5         7 my $nrowrep = $y -> [0][0];
3307 5         8 my $ncolrep = $y -> [1][0];
3308              
3309 5         9 my $z = [];
3310 5         10 for my $ix (0 .. $nrowx - 1) {
3311 8         11 for my $jx (0 .. $ncolx - 1) {
3312 24         41 for my $iy (0 .. $nrowrep - 1) {
3313 30         41 for my $jy (0 .. $ncolrep - 1) {
3314 36         47 my $iz = $iy * $nrowx + $ix;
3315 36         43 my $jz = $jy * $ncolx + $jx;
3316 36         59 $z -> [$iz][$jz] = $x -> [$ix][$jx];
3317             }
3318             }
3319             }
3320             }
3321              
3322 5         20 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 176 croak "Not enough arguments for ", (caller(0))[3] if @_ < 3;
3357 30 50       62 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
3358 30         48 my $x = shift;
3359 30         54 my $class = ref $x;
3360              
3361 30         85 my ($nrowx, $ncolx) = $x -> size();
3362 30         50 my $nelmx = $nrowx * $ncolx;
3363              
3364 30         54 my ($nrowy, $ncoly) = @_;
3365 30         40 my $nelmy = $nrowy * $ncoly;
3366              
3367 30 50       61 croak "when reshaping, the number of elements can not change in ",
3368             (caller(0))[3] unless $nelmx == $nelmy;
3369              
3370 30         49 my $y = [];
3371              
3372             # No reshaping; just clone.
3373              
3374 30 100 66     126 if ($nrowx == $nrowy && $ncolx == $ncoly) {
    100          
    100          
3375 5         22 $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         12 $y = [ map [ $_ ], @{ $x -> [0] } ];
  4         24  
3384             }
3385              
3386             # Reshape from a row vector to a matrix.
3387              
3388             else {
3389 6         11 my $k = 0;
3390 6         21 for my $j (0 .. $ncoly - 1) {
3391 15         30 for my $i (0 .. $nrowy - 1) {
3392 33         68 $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       22 if ($nrowy == 1) {
3403 3         10 $y = [[ map { @$_ } @$x ]];
  18         33  
3404             }
3405              
3406             # Reshape from a column vector to a matrix.
3407              
3408             else {
3409 3         9 my $k = 0;
3410 3         12 for my $j (0 .. $ncoly - 1) {
3411 9         19 for my $i (0 .. $nrowy - 1) {
3412 18         37 $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         24 for my $k (0 .. $nelmx - 1) {
3423 54         73 my $ix = $k % $nrowx;
3424 54         80 my $jx = ($k - $ix) / $nrowx;
3425 54         76 my $iy = $k % $nrowy;
3426 54         84 my $jy = ($k - $iy) / $nrowy;
3427 54         105 $y -> [$iy][$jy] = $x -> [$ix][$jx];
3428             }
3429             }
3430              
3431 30         101 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 108 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3451 30 50       95 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
3452 30         50 my $x = shift;
3453 30         113 my $class = ref $x;
3454              
3455 30         65 my $y = bless [], $class;
3456              
3457 30         76 my $ncolx = $x -> ncol();
3458 30 100       87 return $y if $ncolx == 0;
3459              
3460 25         68 for my $j (0 .. $ncolx - 1) {
3461 61         99 push @{ $y -> [0] }, map $_->[$j], @$x;
  61         193  
3462             }
3463 25         118 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 72 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3483 19 50       65 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
3484 19         27 my $x = shift;
3485              
3486 19         39 my $class = ref $x;
3487              
3488 19         38 my $y = bless [], $class;
3489              
3490 19         47 my $ncolx = $x -> ncol();
3491 19 100       49 return $y if $ncolx == 0;
3492              
3493 18         48 for my $j (0 .. $ncolx - 1) {
3494 43         144 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 22 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3525 4 50       24 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
3526 4         6 my $v = shift;
3527 4         8 my $class = ref $v;
3528              
3529 4         10 my $n = $v -> nelm();
3530 4         13 my $P = $class -> zeros($n, $n); # initialize output
3531 4 100       11 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         8 $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     27 croak "index out of range" unless 0 <= $j && $j < $n;
3539 9         15 $P -> [$i][$j] = 1;
3540             }
3541              
3542 3         16 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       10 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
3572 4         7 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         14 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         12 for my $i (0 .. $n - 1) {
3583 9         10 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       14 croak "invalid permutation matrix; more than one row has",
3588             " an element with value 1 in column $j" if $seen->[$j]++;
3589 9         13 $k = $j;
3590 9         14 next;
3591             }
3592 0         0 croak "invalid permutation matrix; element ($i,$j)",
3593             " is neither 0 nor 1";
3594             }
3595 9 50       17 croak "invalid permutation matrix; row $i has no element with value 1"
3596             unless defined $k;
3597 9         13 $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 94 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
3621 12 50       26 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3622 12         17 my $x = shift;
3623 12         21 my $class = ref $x;
3624              
3625 12         16 my $n = 0;
3626 12 100       23 if (@_) {
3627 10         14 $n = shift;
3628 10 50       22 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       23 croak "Argument must be an integer" unless $n == int $n;
3635             }
3636              
3637 12         30 my ($nrowx, $ncolx) = $x -> size();
3638              
3639 12         19 my $y = [];
3640 12         35 for my $i (0 .. $nrowx - 1) {
3641 30         49 for my $j (0 .. $ncolx - 1) {
3642 72 100       221 $y -> [$i][$j] = $j - $i >= $n ? $x -> [$i][$j] : 0;
3643             }
3644             }
3645              
3646 12         36 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 87 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         20 my $x = shift;
3669 12         16 my $class = ref $x;
3670              
3671 12         21 my $n = 0;
3672 12 100       24 if (@_) {
3673 10         14 $n = shift;
3674 10 50       21 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         24 for my $i (0 .. $nrowx - 1) {
3687 30         51 for my $j (0 .. $ncolx - 1) {
3688 72 100       148 $y -> [$i][$j] = $j - $i <= $n ? $x -> [$i][$j] : 0;
3689             }
3690             }
3691              
3692 12         30 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 106 my $self = shift;
3707 16         35 my $class = ref($self);
3708 16         27 my $result = [];
3709              
3710 16         91 for my $i (0 .. $#$self) {
3711 39         63 push @$result, [ @{$self->[$i]}[@_] ];
  39         105  
3712             }
3713              
3714 16         57 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 2156 my $self = shift;
3729 1         3 my @diag;
3730 1         2 my $idx = 0;
3731 1         3 my($m, $n) = $self->size();
3732              
3733 1 50       4 croak "Not a square matrix" if $m != $n;
3734              
3735 1         3 foreach my $r (@{$self}) {
  1         2  
3736 4         9 push @diag, $r->[$idx++];
3737             }
3738 1         4 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 1457 my $self = shift;
3753 1         4 my(@main_d, @up_d, @low_d);
3754 1         3 my($m, $n) = $self->size();
3755 1         3 my $idx = 0;
3756              
3757 1 50       4 croak "Not a square matrix" if $m != $n;
3758              
3759 1         3 foreach my $r (@{$self}) {
  1         3  
3760 4 100       8 push @low_d, $r->[$idx - 1] if ($idx > 0);
3761 4         8 push @main_d, $r->[$idx++];
3762 4 100       11 push @up_d, $r->[$idx] if ($idx < $m);
3763             }
3764 1         5 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 52 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
3791 8 50       17 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3792 8         15 my $x = shift;
3793 8         11 my $class = ref $x;
3794              
3795 8         28 my $y = shift;
3796 8 100 66     58 $y = $class -> new($y) unless defined(blessed($y)) && $y -> isa($class);
3797              
3798 8 100 100     22 $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 46 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
3816 5 50       17 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3817 5         9 my $x = shift;
3818 5         10 my $class = ref $x;
3819              
3820 5         7 my $y = shift;
3821 5 50 33     57 $y = $class -> new($y) unless defined(blessed($y)) && $y -> isa($class);
3822              
3823 5         20 my ($nrowx, $ncolx) = $x -> size();
3824 5         11 my ($nrowy, $ncoly) = $y -> size();
3825              
3826 5 50 33     25 croak "Can't add $nrowx-by-$ncolx matrix to $nrowy-by-$ncoly matrix"
3827             unless $nrowx == $nrowy && $ncolx == $ncoly;
3828              
3829 5         10 my $z = [];
3830 5         17 for my $i (0 .. $nrowx - 1) {
3831 7         14 for my $j (0 .. $ncolx - 1) {
3832 21         44 $z->[$i][$j] = $x->[$i][$j] + $y->[$i][$j];
3833             }
3834             }
3835              
3836 5         19 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 49 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
3854 9 50       20 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3855 9         11 my $x = shift;
3856              
3857 9     33   38 my $sub = sub { $_[0] + $_[1] };
  33         67  
3858 9         29 $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 60 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
3883 9 50       23 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3884 9         26 my $x = shift;
3885 9         34 my $class = ref $x;
3886              
3887 9         15 my $y = shift;
3888 9 100 66     75 $y = $class -> new($y) unless defined(blessed($y)) && $y -> isa($class);
3889              
3890 9 100 100     29 $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 36 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
3908 6 50       25 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3909 6         14 my $x = shift;
3910 6         51 my $class = ref $x;
3911              
3912 6         13 my $y = shift;
3913 6 50 33     54 $y = $class -> new($y) unless defined(blessed($y)) && $y -> isa($class);
3914              
3915 6         32 my ($nrowx, $ncolx) = $x -> size();
3916 6         19 my ($nrowy, $ncoly) = $y -> size();
3917              
3918 6 50 33     34 croak "Can't subtract $nrowy-by-$ncoly matrix from $nrowx-by-$ncolx matrix"
3919             unless $nrowx == $nrowy && $ncolx == $ncoly;
3920              
3921 6         11 my $z = [];
3922 6         20 for my $i (0 .. $nrowx - 1) {
3923 8         19 for my $j (0 .. $ncolx - 1) {
3924 24         54 $z->[$i][$j] = $x->[$i][$j] - $y->[$i][$j];
3925             }
3926             }
3927              
3928 6         20 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 67 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
3946 9 50       23 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
3947 9         16 my $x = shift;
3948              
3949 9     33   37 my $sub = sub { $_[0] - $_[1] };
  33         69  
3950 9         30 $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 11 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       12 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
3989 4         7 my $x = shift;
3990 4         83 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 27 50   27 1 84 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4026 27 50       56 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4027 27         43 my $x = shift;
4028 27         42 my $class = ref $x;
4029              
4030 27         40 my $y = shift;
4031 27 100 66     160 $y = $class -> new($y) unless defined(blessed($y)) && $y -> isa($class);
4032              
4033 27 100 100     66 $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 34 50   34 1 107 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4050 34 50       78 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4051 34         57 my $x = shift;
4052 34         64 my $class = ref $x;
4053              
4054 34         56 my $y = shift;
4055 34 50 33     228 $y = $class -> new($y) unless defined(blessed($y)) && $y -> isa($class);
4056              
4057 34         110 my $mx = $x -> nrow();
4058 34         85 my $nx = $x -> ncol();
4059              
4060 34         72 my $my = $y -> nrow();
4061 34         67 my $ny = $y -> ncol();
4062              
4063 34 50       77 croak "Can't multiply $mx-by-$nx matrix with $my-by-$ny matrix"
4064             unless $nx == $my;
4065              
4066 34         63 my $z = [];
4067 34         55 my $l = $nx - 1; # "inner length"
4068 34         118 for my $i (0 .. $mx - 1) {
4069 74         132 for my $j (0 .. $ny - 1) {
4070 192         621 $z -> [$i][$j] = _sum(map $x -> [$i][$_] * $y -> [$_][$j], 0 .. $l);
4071             }
4072             }
4073              
4074 34         170 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 112 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4090 12 50       30 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4091 12         19 my $x = shift;
4092              
4093 12     36   50 my $sub = sub { $_[0] * $_[1] };
  36         79  
4094 12         46 $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 24 croak "Not enough arguments for ", (caller(0))[3] if @_ < 3;
4118 2 50       6 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         4 my $y = shift;
4125 2 50 33     23 $y = $class -> new($y) unless defined(blessed($y)) && $y -> isa($class);
4126 2         5 my ($my, $ny) = $y -> size();
4127              
4128 2 50       6 croak "Can't multiply $mx-by-$nx matrix with $my-by-$ny matrix"
4129             unless $nx == $my;
4130              
4131 2         5 my $z = shift;
4132 2 50 33     13 $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         3 my $w = [];
4139 2         4 my $l = $nx - 1; # "inner length"
4140 2         6 for my $i (0 .. $mx - 1) {
4141 6         9 for my $j (0 .. $ny - 1) {
4142 12         44 $w -> [$i][$j]
4143             = _sum(map($x -> [$i][$_] * $y -> [$_][$j], 0 .. $l),
4144             $z -> [$i][$j]);
4145             }
4146             }
4147              
4148 2         7 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 43 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4167 4 50       12 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4168 4         6 my $x = shift;
4169 4         7 my $class = ref $x;
4170              
4171 4         6 my $y = shift;
4172 4 50 33     32 $y = $class -> new($y) unless defined(blessed($y)) && $y -> isa($class);
4173              
4174 4         15 my ($nrowx, $ncolx) = $x -> size();
4175 4         9 my ($nrowy, $ncoly) = $y -> size();
4176              
4177 4         8 my $z = bless [], $class;
4178              
4179 4         11 for my $ix (0 .. $nrowx - 1) {
4180 4         8 for my $jx (0 .. $ncolx - 1) {
4181 8         14 for my $iy (0 .. $nrowy - 1) {
4182 8         13 for my $jy (0 .. $ncoly - 1) {
4183 16         20 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         11 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 45 my $x = shift;
4204 8         29 $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 28 my $self = shift;
4220 7         14 my $factor = shift;
4221 7         17 my $result = $self->new();
4222              
4223 7         11 my $last = $#{$self->[0]};
  7         15  
4224 7         47 for my $i (0 .. $#{$self}) {
  7         22  
4225 13         58 for my $j (0 .. $last) {
4226 33         62 $result->[$i][$j] = $factor * $self->[$i][$j];
4227             }
4228             }
4229 7         31 $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         16 $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 13 50   13 1 59 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4280 13 50       427 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4281 13         22 my $x = shift;
4282 13         23 my $class = ref $x;
4283              
4284 13 50       32 croak "Invocand matrix must be square in ", (caller(0))[3]
4285             unless $x -> is_square();
4286              
4287 13         20 my $n = shift;
4288 13 50       26 croak "Exponent can not be undefined" unless defined $n;
4289 13 100       54 if (ref $n) {
4290 11 50 33     79 $n = $class -> new($n) unless defined(blessed($n)) && $n -> isa($class);
4291 11 50       30 croak "Exponent must be a scalar in ", (caller(0))[3]
4292             unless $n -> is_scalar();
4293 11         21 $n = $n -> [0][0];
4294             }
4295 13 50       29 croak "Exponent must be an integer" unless $n == int $n;
4296              
4297 13 100       29 return $class -> new([]) if $x -> is_empty();
4298              
4299 10         22 my ($nrowx, $ncolx) = $x -> size();
4300 10 100       26 return $class -> id($nrowx, $ncolx) if $n == 0;
4301 8 100       21 return $x -> clone() if $n == 1;
4302              
4303 6         12 my $neg = $n < 0;
4304 6 100       14 $n = -$n if $neg;
4305              
4306 6         17 my $y = $class -> id($nrowx, $ncolx);
4307 6         11 my $tmp = $x;
4308 6         11 while (1) {
4309 15         27 my $rem = $n % 2;
4310 15 100       42 $y *= $tmp if $rem;
4311 15         29 $n = ($n - $rem) / 2;
4312 15 100       33 last if $n == 0;
4313 9         19 $tmp = $tmp * $tmp;
4314             }
4315              
4316 6 100       20 $y = $y -> minv() if $neg;
4317              
4318 6         38 return $y;
4319             }
4320              
4321             =pod
4322              
4323             =item spow()
4324              
4325             Scalar (element by element) power function. This method doesn't require the
4326             matrices to have the same size.
4327              
4328             $z = $x -> spow($y);
4329              
4330             See also C>.
4331              
4332             =cut
4333              
4334             sub spow {
4335 4 50   4 1 42 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4336 4 50       11 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4337 4         7 my $x = shift;
4338              
4339 4     14   17 my $sub = sub { $_[0] ** $_[1] };
  14         36  
4340 4         13 $x -> sapply($sub, @_);
4341             }
4342              
4343             =pod
4344              
4345             =back
4346              
4347             =head3 Inversion
4348              
4349             =over 4
4350              
4351             =item inv()
4352              
4353             This is an alias for C>.
4354              
4355             =cut
4356              
4357             sub inv {
4358 1     1 1 8 my $x = shift;
4359 1         4 $x -> minv();
4360             }
4361              
4362             =pod
4363              
4364             =item invert()
4365              
4366             Invert a Matrix using C.
4367              
4368             =cut
4369              
4370             sub invert {
4371 1     1 1 3 my $M = shift;
4372 1         6 my ($m, $n) = $M->size;
4373 1 50       5 croak "Can't invert $m-by-$n matrix; matrix must be square"
4374             if $m != $n;
4375 1         3 my $I = $M->new_identity($n);
4376 1         14 ($M->concat($I))->solve;
4377             }
4378              
4379             =pod
4380              
4381             =item minv()
4382              
4383             Matrix inverse. Invert a matrix.
4384              
4385             $y = $x -> inv();
4386              
4387             See the section L for a list of
4388             additional parameters that can be used for trying to obtain a better solution
4389             through iteration.
4390              
4391             =cut
4392              
4393             sub minv {
4394 4 50   4 1 40 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
4395             #croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
4396 4         8 my $x = shift;
4397 4         9 my $class = ref $x;
4398              
4399 4         14 my $n = $x -> nrow();
4400 4         14 return $class -> id($n) -> mldiv($x, @_);
4401             }
4402              
4403             =pod
4404              
4405             =item sinv()
4406              
4407             Scalar (element by element) inverse. Invert each element in a matrix.
4408              
4409             $y = $x -> sinv();
4410              
4411             =cut
4412              
4413             sub sinv {
4414 2 50   2 1 34 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
4415 2 50       8 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
4416 2         4 my $x = shift;
4417              
4418 2         51 bless [ map [ map 1/$_, @$_ ], @$x ], ref $x;
4419             }
4420              
4421             =pod
4422              
4423             =item mldiv()
4424              
4425             Matrix left division. Returns the solution x of the linear system of equations
4426             A*x = y, by computing A^(-1)*y.
4427              
4428             $x = $y -> mldiv($A);
4429              
4430             This method also handles overdetermined and underdetermined systems. There are
4431             three cases
4432              
4433             =over 4
4434              
4435             =item *
4436              
4437             If A is a square matrix, then
4438              
4439             x = A\y = inv(A)*y
4440              
4441             so that A*x = y to within round-off accuracy.
4442              
4443             =item *
4444              
4445             If A is an M-by-N matrix where M > N, then A\y is computed as
4446              
4447             A\y = (A'*A)\(A'*y) = inv(A'*A)*(A'*y)
4448              
4449             where A' denotes the transpose of A. The returned matrix is the least squares
4450             solution to the linear system of equations A*x = y, if it exists. The matrix
4451             A'*A must be non-singular.
4452              
4453             =item *
4454              
4455             If A is an where M < N, then A\y is computed as
4456              
4457             A\y = A'*((A*A')\y)
4458              
4459             This solution is not unique. The matrix A*A' must be non-singular.
4460              
4461             =back
4462              
4463             See the section L for a list of
4464             additional parameters that can be used for trying to obtain a better solution
4465             through iteration.
4466              
4467             =cut
4468              
4469             sub mldiv {
4470 12 50   12 1 61 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4471             #croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4472 12         22 my $y = shift;
4473 12         24 my $class = ref $y;
4474              
4475 12         19 my $A = shift;
4476 12 50 33     107 $A = $class -> new($A) unless defined(blessed($A)) && $A -> isa($class);
4477              
4478 12         45 my ($m, $n) = $A -> size();
4479              
4480 12 100       47 if ($m > $n) {
    100          
4481              
4482             # If A is an M-by-N matrix where M > N, i.e., an overdetermined system,
4483             # compute (A'*A)\(A'*y) by doing a one level deep recursion.
4484              
4485 1         5 my $At = $A -> transpose();
4486 1         4 return $At -> mmul($y) -> mldiv($At -> mmul($A), @_);
4487              
4488             } elsif ($m < $n) {
4489              
4490             # If A is an M-by-N matrix where M < N, i.e., and underdetermined
4491             # system, compute A'*((A*A')\y) by doing a one level deep recursion.
4492             # This solution is not unique.
4493              
4494 1         9 my $At = $A -> transpose();
4495 1         4 return $At -> mldiv($At -> mmul($A), @_);
4496             }
4497              
4498             # If extra arguments are given ...
4499              
4500 10 50       29 if (@_) {
4501              
4502 0         0 require Config;
4503 0         0 my $max_iter = 20;
4504             my $rel_tol = ($Config::Config{uselongdouble} ||
4505 0 0 0     0 $Config::Config{usequadmath}) ? 1e-19 : 1e-9;
4506 0         0 my $abs_tol = 0;
4507 0         0 my $debug;
4508              
4509 0         0 while (@_) {
4510 0         0 my $param = shift;
4511 0 0       0 croak "parameter name can not be undefined" unless defined $param;
4512              
4513 0 0       0 croak "missing value for parameter '$param'" unless @_;
4514 0         0 my $value = shift;
4515              
4516 0 0       0 if ($param eq 'MaxIter') {
4517 0 0       0 croak "value for parameter 'MaxIter' can not be undefined"
4518             unless defined $value;
4519 0 0 0     0 croak "value for parameter 'MaxIter' must be a positive integer"
4520             unless $value > 0 && $value == int $value;
4521 0         0 $max_iter = $value;
4522 0         0 next;
4523             }
4524              
4525 0 0       0 if ($param eq 'RelTol') {
4526 0 0       0 croak "value for parameter 'RelTol' can not be undefined"
4527             unless defined $value;
4528 0 0       0 croak "value for parameter 'RelTol' must be non-negative"
4529             unless $value >= 0;
4530 0         0 $rel_tol = $value;
4531 0         0 next;
4532             }
4533              
4534 0 0       0 if ($param eq 'AbsTol') {
4535 0 0       0 croak "value for parameter 'AbsTol' can not be undefined"
4536             unless defined $value;
4537 0 0       0 croak "value for parameter 'AbsTol' must be non-negative"
4538             unless $value >= 0;
4539 0         0 $abs_tol = $value;
4540 0         0 next;
4541             }
4542              
4543 0 0       0 if ($param eq 'Debug') {
4544 0         0 $debug = $value;
4545 0         0 next;
4546             }
4547              
4548 0         0 croak "unknown parameter '$param'";
4549             }
4550              
4551 0 0       0 if ($debug) {
4552 0         0 printf "\n";
4553 0         0 printf "max_iter = %24d\n", $max_iter;
4554 0         0 printf "rel_tol = %24.15e\n", $rel_tol;
4555 0         0 printf "abs_tol = %24.15e\n", $abs_tol;
4556             }
4557              
4558 0         0 my $y_norm = _hypot(map { @$_ } @$y);
  0         0  
4559              
4560 0         0 my $x = $y -> mldiv($A);
4561              
4562 0         0 my $x_best;
4563             my $iter_best;
4564 0         0 my $abs_err_best;
4565 0         0 my $rel_err_best;
4566              
4567 0         0 for (my $iter = 1 ; ; $iter++) {
4568              
4569             # Compute the residuals.
4570              
4571 0         0 my $r = $A -> mmuladd($x, -$y);
4572              
4573             # Compute the errors.
4574              
4575 0         0 my $r_norm = _hypot(map @$_, @$r);
4576 0         0 my $abs_err = $r_norm;
4577 0 0       0 my $rel_err = $y_norm == 0 ? $r_norm : $r_norm / $y_norm;
4578              
4579 0 0       0 if ($debug) {
4580 0         0 printf "\n";
4581 0         0 printf "iter = %24d\n", $iter;
4582 0         0 printf "r_norm = %24.15e\n", $r_norm;
4583 0         0 printf "y_norm = %24.15e\n", $y_norm;
4584 0         0 printf "abs_err = %24.15e\n", $abs_err;
4585 0         0 printf "rel_err = %24.15e\n", $rel_err;
4586             }
4587              
4588             # See if this is the first round or we have an new all-time best.
4589              
4590 0 0 0     0 if ($iter == 1 ||
      0        
4591             $abs_err < $abs_err_best ||
4592             $rel_err < $rel_err_best)
4593             {
4594 0         0 $x_best = $x;
4595 0         0 $iter_best = $iter;
4596 0         0 $abs_err_best = $abs_err;
4597 0         0 $rel_err_best = $rel_err;
4598             }
4599              
4600 0 0 0     0 if ($abs_err_best <= $abs_tol || $rel_err_best <= $rel_tol) {
4601 0         0 last;
4602             } else {
4603              
4604             # If we still haven't got the desired result, but have reached
4605             # the maximum number of iterations, display a warning.
4606              
4607 0 0       0 if ($iter == $max_iter) {
4608 0         0 carp "mldiv() stopped because the maximum number of",
4609             " iterations (max. iter = $max_iter) was reached without",
4610             " converging to any of the desired tolerances (",
4611             "rel_tol = ", $rel_tol, ", ",
4612             "abs_tol = ", $abs_tol, ").",
4613             " The best iterate (iter. = ", $iter_best, ") has",
4614             " a relative residual of ", $rel_err_best, " and",
4615             " an absolute residual of ", $abs_err_best, ".";
4616 0         0 last;
4617             }
4618             }
4619              
4620             # Compute delta $x.
4621              
4622 0         0 my $d = $r -> mldiv($A);
4623              
4624             # Compute the improved solution $x.
4625              
4626 0         0 $x -= $d;
4627             }
4628              
4629 0 0       0 return $x_best, $rel_err_best, $abs_err_best, $iter_best if wantarray;
4630 0         0 return $x_best;
4631             }
4632              
4633             # If A is an M-by-M, compute A\y directly.
4634              
4635 10 50       35 croak "mldiv(): sizes don't match" unless $y -> nrow() == $n;
4636              
4637             # Create the augmented matrix.
4638              
4639 10         36 my $x = $A -> catcol($y);
4640              
4641             # Perform forward elimination.
4642              
4643 10         20 my ($rowperm, $colperm);
4644 10         19 eval { ($x, $rowperm, $colperm) = $x -> felim_fp() };
  10         46  
4645 10 50       89 croak "mldiv(): matrix is singular or close to singular" if $@;
4646              
4647             # Perform backward substitution.
4648              
4649 10         21 eval { $x = $x -> bsubs() };
  10         30  
4650 10 50       29 croak "mldiv(): matrix is singular or close to singular" if $@;
4651              
4652             # Remove left half to keep only the augmented matrix.
4653              
4654 10         40 $x = $x -> splicecol(0, $n);
4655              
4656             # Reordering the rows is only necessary when full (complete) pivoting is
4657             # used above. If partial pivoting is used, this reordeing could be skipped,
4658             # but it executes so fast that it causes no harm to do it anyway.
4659              
4660 10         39 @$x[ @$colperm ] = @$x;
4661              
4662 10         49 return $x;
4663             }
4664              
4665             =pod
4666              
4667             =item sldiv()
4668              
4669             Scalar (left) division.
4670              
4671             $x -> sldiv($y);
4672              
4673             For scalars, there is no difference between left and right division, so this is
4674             just an alias for C>.
4675              
4676             =cut
4677              
4678             sub sldiv {
4679 2     2 1 9 my $x = shift;
4680 2         6 $x -> sdiv(@_)
4681             }
4682              
4683             =pod
4684              
4685             =item mrdiv()
4686              
4687             Matrix right division. Returns the solution x of the linear system of equations
4688             x*A = y, by computing x = y/A = y*inv(A) = (A'\y')', where A' and y' denote the
4689             transpose of A and y, respectively, and \ is matrix left division (see
4690             C>).
4691              
4692             $x = $y -> mrdiv($A);
4693              
4694             See the section L for a list of
4695             additional parameters that can be used for trying to obtain a better solution
4696             through iteration.
4697              
4698             =cut
4699              
4700             sub mrdiv {
4701 1 50   1 1 20 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4702             #croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4703 1         2 my $y = shift;
4704 1         2 my $class = ref $y;
4705              
4706 1         3 my $A = shift;
4707 1 50 33     14 $A = $class -> new($A) unless defined(blessed($A)) && $A -> isa($class);
4708              
4709 1         8 $y -> transpose() -> mldiv($A -> transpose(), @_) -> transpose();
4710             }
4711              
4712             =pod
4713              
4714             =item srdiv()
4715              
4716             Scalar (right) division.
4717              
4718             $x -> srdiv($y);
4719              
4720             For scalars, there is no difference between left and right division, so this is
4721             just an alias for C>.
4722              
4723             =cut
4724              
4725             sub srdiv {
4726 2     2 1 12 my $x = shift;
4727 2         6 $x -> sdiv(@_)
4728             }
4729              
4730             =pod
4731              
4732             =item sdiv()
4733              
4734             Scalar division. Performs scalar (element by element) division.
4735              
4736             $x -> sdiv($y);
4737              
4738             =cut
4739              
4740             sub sdiv {
4741 6 50   6 1 32 croak "Not enough arguments for ", (caller(0))[3] if @_ < 2;
4742 6 50       14 croak "Too many arguments for ", (caller(0))[3] if @_ > 2;
4743 6         9 my $x = shift;
4744              
4745 6     126   23 my $sub = sub { $_[0] / $_[1] };
  126         250  
4746 6         17 $x -> sapply($sub, @_);
4747             }
4748              
4749             =pod
4750              
4751             =item mpinv()
4752              
4753             Matrix pseudo-inverse, C<(A'*A)^(-1)*A'>, where "C<'>" is the transpose
4754             operator.
4755              
4756             See the section L for a list of
4757             additional parameters that can be used for trying to obtain a better solution
4758             through iteration.
4759              
4760             =cut
4761              
4762             sub mpinv {
4763 2     2 1 21 my $A = shift;
4764              
4765 2         6 my $At = $A -> transpose();
4766 2         8 return $At -> mldiv($At -> mmul($A), @_);
4767             }
4768              
4769             =pod
4770              
4771             =item pinv()
4772              
4773             This is an alias for C>.
4774              
4775             =cut
4776              
4777             sub pinv {
4778 1     1 1 7 my $x = shift;
4779 1         4 $x -> mpinv();
4780             }
4781              
4782             =pod
4783              
4784             =item pinvert()
4785              
4786             This is an alias for C>.
4787              
4788             =cut
4789              
4790             sub pinvert {
4791 0     0 1 0 my $x = shift;
4792 0         0 $x -> mpinv();
4793             }
4794              
4795             =pod
4796              
4797             =item solve()
4798              
4799             Solves a equation system given by the matrix. The number of colums must be
4800             greater than the number of rows. If variables are dependent from each other,
4801             the second and all further of the dependent coefficients are 0. This means the
4802             method can handle such systems. The method returns a matrix containing the
4803             solutions in its columns or B in case of error.
4804              
4805             =cut
4806              
4807             sub solve {
4808 3     3 1 22 my $self = shift;
4809 3         7 my $class = ref($self);
4810              
4811 3         6 my $m = $self->clone();
4812 3         5 my $mr = $#{$m};
  3         7  
4813 3         6 my $mc = $#{$m->[0]};
  3         14  
4814 3         7 my $f;
4815             my $try;
4816              
4817 3 50       9 return undef if $mc <= $mr;
4818 3         8 ROW: for(my $i = 0; $i <= $mr; $i++) {
4819 9         12 $try=$i;
4820             # make diagonal element nonzero if possible
4821 9         25 while (abs($m->[$i]->[$i]) < $eps) {
4822 0 0       0 last ROW if $try++ > $mr;
4823 0         0 my $row = splice(@{$m},$i,1);
  0         0  
4824 0         0 push(@{$m}, $row);
  0         0  
4825             }
4826              
4827             # normalize row
4828 9         12 $f = $m->[$i]->[$i];
4829 9         21 for (my $k = 0; $k <= $mc; $k++) {
4830 42         83 $m->[$i]->[$k] /= $f;
4831             }
4832             # subtract multiple of designated row from other rows
4833 9         20 for (my $j = 0; $j <= $mr; $j++) {
4834 27 100       62 next if $i == $j;
4835 18         25 $f = $m->[$j]->[$i];
4836 18         34 for (my $k = 0; $k <= $mc; $k++) {
4837 84         168 $m->[$j]->[$k] -= $m->[$i]->[$k] * $f;
4838             }
4839             }
4840             }
4841              
4842             # Answer is in augmented column
4843 3         10 $class -> new([ @{ $m -> transpose }[$mr+1 .. $mc] ]) -> transpose;
  3         21  
4844             }
4845              
4846             =pod
4847              
4848             =back
4849              
4850             =head3 Factorisation
4851              
4852             =over 4
4853              
4854             =item chol()
4855              
4856             Cholesky decomposition.
4857              
4858             $L = $A -> chol();
4859              
4860             Every symmetric, positive definite matrix A can be decomposed into a product of
4861             a unique lower triangular matrix L and its transpose, so that A = L*L', where L'
4862             denotes the transpose of L. L is called the Cholesky factor of A.
4863              
4864             =cut
4865              
4866             sub chol {
4867 2     2 1 23 my $x = shift;
4868 2         4 my $class = ref $x;
4869              
4870 2 50       6 croak "Input matrix must be a symmetric" unless $x -> is_symmetric();
4871              
4872 2         13 my $y = [ map [ (0) x @$x ], @$x ]; # matrix of zeros
4873 2         6 for my $i (0 .. $#$x) {
4874 7         24 for my $j (0 .. $i) {
4875 16         25 my $z = $x->[$i][$j];
4876 16         38 $z -= $y->[$i][$_] * $y->[$j][$_] for 0 .. $j;
4877 16 100       25 if ($i == $j) {
4878 7 50       14 croak "Matrix is not positive definite" if $z < 0;
4879 7         16 $y->[$i][$j] = sqrt($z);
4880             } else {
4881 9 50       17 croak "Matrix is not positive definite" if $y->[$j][$j] == 0;
4882 9         15 $y->[$i][$j] = $z / $y->[$j][$j];
4883             }
4884             }
4885             }
4886 2         7 bless $y, $class;
4887             }
4888              
4889             =pod
4890              
4891             =back
4892              
4893             =head3 Miscellaneous matrix functions
4894              
4895             =over 4
4896              
4897             =item transpose()
4898              
4899             Returns the transposed matrix. This is the matrix where colums and rows of the
4900             argument matrix are swapped.
4901              
4902             A subclass implementing matrices of complex numbers should provide a
4903             C> method that takes the complex conjugate of each element.
4904              
4905             =cut
4906              
4907             sub transpose {
4908 34     34 1 226 my $x = shift;
4909 34         62 my $class = ref $x;
4910              
4911 34         63 my $y = bless [], $class;
4912 34         92 my $ncolx = $x -> ncol();
4913 34 100       106 return $y if $ncolx == 0;
4914              
4915 30         76 for my $j (0 .. $ncolx - 1) {
4916 88         281 push @$y, [ map $_->[$j], @$x ];
4917             }
4918 30         104 return $y;
4919             }
4920              
4921             =pod
4922              
4923             =item minormatrix()
4924              
4925             Minor matrix. The (i,j) minor matrix of a matrix is identical to the original
4926             matrix except that row i and column j has been removed.
4927              
4928             $y = $x -> minormatrix($i, $j);
4929              
4930             See also C>.
4931              
4932             =cut
4933              
4934             sub minormatrix {
4935 37 50   37 1 96 croak "Not enough arguments for ", (caller(0))[3] if @_ < 3;
4936 37 50       70 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
4937 37         43 my $x = shift;
4938 37         70 my $class = ref $x;
4939              
4940 37         65 my ($m, $n) = $x -> size();
4941              
4942 37         53 my $i = shift;
4943 37 50 33     138 croak "Row index value $i outside of $m-by-$n matrix"
4944             unless 0 <= $i && $i < $m;
4945              
4946 37         52 my $j = shift;
4947 37 50 33     118 croak "Column index value $j outside of $m-by-$n matrix"
4948             unless 0 <= $j && $j < $n;
4949              
4950             # We could just use the following, which is simpler, but also slower:
4951             #
4952             # $x -> delrow($i) -> delcol($j);
4953              
4954 37         88 my @rowidx = 0 .. $m - 1;
4955 37         62 splice @rowidx, $i, 1;
4956              
4957 37         66 my @colidx = 0 .. $n - 1;
4958 37         61 splice @colidx, $j, 1;
4959              
4960 37         53 bless [ map [ @{$_}[@colidx] ], @{$x}[@rowidx] ], $class;
  74         245  
  37         73  
4961             }
4962              
4963             =pod
4964              
4965             =item minor()
4966              
4967             Minor. The (i,j) minor of a matrix is the determinant of the (i,j) minor matrix.
4968              
4969             $y = $x -> minor($i, $j);
4970              
4971             See also C>.
4972              
4973             =cut
4974              
4975             sub minor {
4976 36 50   36 1 4417 croak "Not enough arguments for ", (caller(0))[3] if @_ < 3;
4977 36 50       77 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
4978 36         48 my $x = shift;
4979              
4980 36 50       93 croak "Matrix must be square" unless $x -> is_square();
4981              
4982 36         79 $x -> minormatrix(@_) -> determinant();
4983             }
4984              
4985             =pod
4986              
4987             =item cofactormatrix()
4988              
4989             Cofactor matrix. Element (i,j) in the cofactor matrix is the (i,j) cofactor,
4990             which is (-1)^(i+j) multiplied by the determinant of the (i,j) minor matrix.
4991              
4992             $y = $x -> cofactormatrix();
4993              
4994             =cut
4995              
4996             sub cofactormatrix {
4997 4 50   4 1 32 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
4998 4 50       12 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
4999 4         8 my $x = shift;
5000              
5001 4         14 my ($m, $n) = $x -> size();
5002 4 50       12 croak "matrix must be square" unless $m == $n;
5003              
5004 4         8 my $y = [];
5005 4         12 for my $i (0 .. $m - 1) {
5006 6         12 for my $j (0 .. $n - 1) {
5007 18         62 $y -> [$i][$j] = (-1) ** ($i + $j) * $x -> minor($i, $j);
5008             }
5009             }
5010              
5011 4         16 bless $y;
5012             }
5013              
5014             =pod
5015              
5016             =item cofactor()
5017              
5018             Cofactor. The (i,j) cofactor of a matrix is (-1)**(i+j) times the (i,j) minor of
5019             the matrix.
5020              
5021             $y = $x -> cofactor($i, $j);
5022              
5023             =cut
5024              
5025             sub cofactor {
5026 9 50   9 1 4100 croak "Not enough arguments for ", (caller(0))[3] if @_ < 3;
5027 9 50       21 croak "Too many arguments for ", (caller(0))[3] if @_ > 3;
5028 9         14 my $x = shift;
5029              
5030 9         24 my ($m, $n) = $x -> size();
5031 9 50       20 croak "matrix must be square" unless $m == $n;
5032              
5033 9         15 my ($i, $j) = @_;
5034 9         39 (-1) ** ($i + $j) * $x -> minor($i, $j);
5035             }
5036              
5037             =pod
5038              
5039             =item adjugate()
5040              
5041             Adjugate of a matrix. The adjugate, also called classical adjoint or adjunct, of
5042             a square matrix is the transpose of the cofactor matrix.
5043              
5044             $y = $x -> adjugate();
5045              
5046             =cut
5047              
5048             sub adjugate {
5049 2 50   2 1 29 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5050 2 50       5 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
5051 2         5 my $x = shift;
5052              
5053 2         7 $x -> cofactormatrix() -> transpose();
5054             }
5055              
5056             =pod
5057              
5058             =item det()
5059              
5060             Determinant. Returns the determinant of a matrix. The matrix must be square.
5061              
5062             $y = $x -> det();
5063              
5064             The matrix is computed by forward elimination, which might cause round-off
5065             errors. So for example, the determinant might be a non-integer even for an
5066             integer matrix.
5067              
5068             =cut
5069              
5070             sub det {
5071 59 50   59 1 169 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5072 59 50       112 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
5073 59         95 my $x = shift;
5074 59         96 my $class = ref $x;
5075              
5076 59         111 my ($nrowx, $ncolx) = $x -> size();
5077 59 50       121 croak "matrix must be square" unless $nrowx == $ncolx;
5078              
5079             # Create the augmented matrix.
5080              
5081 59         133 $x = $x -> catcol($class -> id($nrowx));
5082              
5083             # Perform forward elimination.
5084              
5085 59         168 my ($iperm, $jperm, $iswap, $jswap);
5086 59         87 eval { ($x, $iperm, $jperm, $iswap, $jswap) = $x -> felim_fp() };
  59         139  
5087              
5088             # Compute the product of the elements on the diagonal.
5089              
5090 59         200 my $det = 1;
5091 59         144 for (my $i = 0 ; $i < $nrowx ; ++$i) {
5092 140 100       332 last if ($det *= $x -> [$i][$i]) == 0;
5093             }
5094              
5095             # Adjust the sign according to the number of inversions.
5096              
5097 59 100       150 $det = ($iswap + $jswap) % 2 ? -$det : $det;
5098              
5099 59         249 return $det;
5100             }
5101              
5102             =pod
5103              
5104             =item determinant()
5105              
5106             This is an alias for C>.
5107              
5108             =cut
5109              
5110             sub determinant {
5111 56     56 1 104 my $x = shift;
5112 56         148 $x -> det(@_);
5113             }
5114              
5115             =pod
5116              
5117             =item detr()
5118              
5119             Determinant. Returns the determinant of a matrix. The matrix must be square.
5120              
5121             $y = $x -> determinant();
5122              
5123             The determinant is computed by recursion, so it is generally much slower than
5124             C>.
5125              
5126             =cut
5127              
5128             sub detr {
5129 3     3 1 16 my $x = shift;
5130 3         7 my $class = ref($x);
5131 3         7 my $imax = $#$x;
5132 3         5 my $jmax = $#{$x->[0]};
  3         6  
5133              
5134 3 50       11 return undef unless $imax == $jmax; # input must be a square matrix
5135              
5136             # Matrix is 3 × 3
5137              
5138             return
5139 3 100       19 $x -> [0][0] * ($x -> [1][1] * $x -> [2][2] - $x -> [1][2] * $x -> [2][1])
5140             - $x -> [0][1] * ($x -> [1][0] * $x -> [2][2] - $x -> [1][2] * $x -> [2][0])
5141             + $x -> [0][2] * ($x -> [1][0] * $x -> [2][1] - $x -> [1][1] * $x -> [2][0])
5142             if $imax == 2;
5143              
5144             # Matrix is 2 × 2
5145              
5146 2 50       5 return $x -> [0][0] * $x -> [1][1] - $x -> [1][0] * $x -> [0][1]
5147             if $imax == 1;
5148              
5149             # Matrix is 1 × 1
5150              
5151 2 100       6 return $x -> [0][0] if $imax == 0;
5152              
5153             # Matrix is N × N for N > 3.
5154              
5155 1         2 my $det = 0;
5156              
5157             # Create a matrix with column 0 removed. We only need to do this once.
5158 1         6 my $x0 = bless [ map [ @{$_}[1 .. $jmax] ], @$x ], $class;
  5         16  
5159              
5160 1         4 for my $i (0 .. $imax) {
5161              
5162             # Create a matrix with row $i and column 0 removed.
5163 5         13 my $x1 = bless [ map [ @$_ ], @{$x0}[ 0 .. $i-1, $i+1 .. $imax ] ], $class;
  5         25  
5164              
5165 5         12 my $term = $x1 -> determinant();
5166 5 100       22 $term *= $i % 2 ? -$x->[$i][0] : $x->[$i][0];
5167              
5168 5         17 $det += $term;
5169             }
5170              
5171 1         14 return $det;
5172             }
5173              
5174             =pod
5175              
5176             =back
5177              
5178             =head3 Elementwise mathematical functions
5179              
5180             These method work on each element of a matrix.
5181              
5182             =over 4
5183              
5184             =item int()
5185              
5186             Truncate to integer. Truncates each element to an integer.
5187              
5188             $y = $x -> int();
5189              
5190             This function is effectivly the same as
5191              
5192             $y = $x -> map(sub { int });
5193              
5194             =cut
5195              
5196             sub int {
5197 4 50   4 1 28 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5198 4 50       10 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
5199 4         6 my $x = shift;
5200              
5201 4         61 bless [ map [ map int($_), @$_ ], @$x ], ref $x;
5202             }
5203              
5204             =pod
5205              
5206             =item floor()
5207              
5208             Round to negative infinity. Rounds each element to negative infinity.
5209              
5210             $y = $x -> floor();
5211              
5212             =cut
5213              
5214             sub floor {
5215 2 50   2 1 27 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5216 2 50       6 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
5217 2         4 my $x = shift;
5218              
5219 2         46 bless [ map { [
5220             map {
5221 6         11 my $ix = CORE::int($_);
  24         36  
5222 24 100       49 ($ix <= $_) ? $ix : $ix - 1;
5223             } @$_
5224             ] } @$x ], ref $x;
5225             }
5226              
5227             =pod
5228              
5229             =item ceil()
5230              
5231             Round to positive infinity. Rounds each element to positive infinity.
5232              
5233             $y = $x -> int();
5234              
5235             =cut
5236              
5237             sub ceil {
5238 2 50   2 1 27 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5239 2 50       6 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
5240 2         5 my $x = shift;
5241              
5242 2         42 bless [ map { [
5243             map {
5244 6         11 my $ix = CORE::int($_);
  24         34  
5245 24 100       49 ($ix >= $_) ? $ix : $ix + 1;
5246             } @$_
5247             ] } @$x ], ref $x;
5248             }
5249              
5250             =pod
5251              
5252             =item abs()
5253              
5254             Absolute value. The absolute value of each element.
5255              
5256             $y = $x -> abs();
5257              
5258             This is effectivly the same as
5259              
5260             $y = $x -> map(sub { abs });
5261              
5262             =cut
5263              
5264             sub abs {
5265 3 50   3 1 37 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5266 3 50       10 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
5267 3         4 my $x = shift;
5268              
5269 3         78 bless [ map [ map abs($_), @$_ ], @$x ], ref $x;
5270             }
5271              
5272             =pod
5273              
5274             =item sign()
5275              
5276             Sign function. Apply the sign function to each element.
5277              
5278             $y = $x -> sign();
5279              
5280             This is effectivly the same as
5281              
5282             $y = $x -> map(sub { $_ <=> 0 });
5283              
5284             =cut
5285              
5286             sub sign {
5287 2 50   2 1 12 croak "Not enough arguments for ", (caller(0))[3] if @_ < 1;
5288 2 50       6 croak "Too many arguments for ", (caller(0))[3] if @_ > 1;
5289 2         3 my $x = shift;
5290              
5291 2         7 bless [ map [ map { $_ <=> 0 } @$_ ], @$x ], ref $x;
  24         41  
5292             }
5293              
5294             =pod
5295              
5296             =back
5297              
5298             =head3 Columnwise or rowwise mathematical functions
5299              
5300             These method work along each column or row of a matrix. Some of these methods
5301             return a matrix with the same size as the invocand matrix. Other methods
5302             collapse the dimension, so that, e.g., if the method is applied to the first
5303             dimension a I

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

5304             the second dimension, it becomes a I

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

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

-by-I matrix becomes

5306             a (I

-1)-by-I or a I

-by-(I-1) matrix.

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