File Coverage

blib/lib/Math/Cephes/Matrix.pm
Criterion Covered Total %
statement 139 147 94.5
branch 19 34 55.8
condition 7 11 63.6
subroutine 17 18 94.4
pod 1 15 6.6
total 183 225 81.3


line stmt bran cond sub pod time code
1             package Math::Cephes::Matrix;
2 1     1   9008 use strict;
  1         2  
  1         42  
3 1     1   13 use warnings;
  1         2  
  1         58  
4 1     1   6 use vars qw(@EXPORT_OK $VERSION);
  1         4  
  1         3943  
5              
6             require Exporter;
7             *import = \&Exporter::import;
8             @EXPORT_OK = qw(mat);
9              
10             $VERSION = '0.5308';
11              
12             require Math::Cephes;
13              
14             sub new {
15 15     15 0 209378 my ($caller, $arr) = @_;
16 15         33 my $refer = ref($caller);
17 15   66     62 my $class = $refer || $caller;
18 15 50 66     55 die "Must supply data for the matrix"
19             unless ($refer or $arr);
20 15 100       36 unless ($refer) {
21 14 50 33     69 die "Please supply an array of arrays for the matrix data"
22             unless (ref($arr) eq 'ARRAY' and ref($arr->[0]) eq 'ARRAY');
23 14         24 my $n = scalar @$arr;
24 14         24 my $m = scalar @{$arr->[0]};
  14         28  
25 14 50       32 die "Matrices must be square" unless $m == $n;
26             }
27 15         30 my ($coef, $n);
28 15 100       33 if ($refer) {
29 1         3 $n = $caller->{n};
30 1         2 my $cdata = $caller->{coef};
31 1         4 foreach (@$cdata) {
32 3         10 push @$coef, [ @$_];
33             }
34             }
35             else {
36 14         33 ($coef, $n) = ($arr, scalar @$arr);
37             }
38 15         103 bless { coef => $coef,
39             n => $n,
40             }, $class;
41             }
42              
43             sub mat {
44 0     0 0 0 return Math::Cephes::Matrix->new(shift);
45             }
46              
47             sub mat_to_vec {
48 4     4 0 7 my $self = shift;
49 4         11 my ($M, $n) = ($self->{coef}, $self->{n});
50 4         7 my $A = [];
51 4         14 for (my $i=0; $i<$n; $i++) {
52 12         30 for (my $j=0; $j<$n; $j++) {
53 36         57 my $index = $i*$n+$j;
54 36         108 $A->[$index] = $M->[$i]->[$j];
55             }
56             }
57 4         9 return $A;
58             }
59              
60             sub vec_to_mat {
61 4     4 0 10 my ($self, $X) = @_;
62 4         9 my $n = $self->{n};
63 4         17 my $I = [];
64 4         14 for (my $i=0; $i<$n; $i++) {
65 12         28 for (my $j=0; $j<$n; $j++) {
66 36         55 my $index = $i*$n+$j;
67 36         100 $I->[$i]->[$j] = $X->[$index];
68             }
69             }
70 4         10 return $I;
71             }
72              
73             sub check {
74 12     12 0 27 my ($self, $B) = @_;
75 12         30 my $na = $self->{n};
76 12         29 my $ref = ref($B);
77 12 100       38 if ($ref eq 'Math::Cephes::Matrix') {
    50          
78             die "Matrices must be of the same size"
79 7 50       32 unless $B->{n} == $na;
80 7         20 return $B->coef;
81             }
82             elsif ($ref eq 'ARRAY') {
83 5         10 my $nb = scalar @$B;
84 5         31 my $ref0 = ref($B->[0]);
85 5 50       29 if ($ref0 eq 'ARRAY') {
    50          
86 0         0 my $m = scalar @{$B->[0]};
  0         0  
87 0 0       0 die "Can only use square matrices" unless $m == $nb;
88 0 0       0 die "Can only use matrices of the same size"
89             unless $na == $nb;
90 0         0 return $B;
91             }
92             elsif (not $ref0) {
93 5 50       13 die "Can only use vectors of the same size" unless $nb == $na;
94 5         17 return $B;
95             }
96             else {
97 0         0 die "Unknown reference '$ref0' for data";
98             }
99             }
100             else {
101 0         0 die "Unknown reference '$ref' for data";
102             }
103             }
104              
105             sub coef {
106 18     18 0 67 return $_[0]->{coef};
107             }
108              
109             sub clr {
110 2     2 0 208 my $self = shift;
111 2   100     10 my $what = shift || 0;
112 2         5 my $n = $self->{n};
113 2         5 my $B = [];
114 2         34 for (my $i=0; $i<$n; $i++) {
115 6         21 for (my $j=0; $j<$n; $j++) {
116 18         49 $B->[$i]->[$j] = $what;
117             }
118             }
119 2         9 $self->{coef} = $B;
120             }
121              
122             sub simq {
123 1     1 0 11 my ($self, $B) = @_;
124 1         6 $B = $self->check($B);
125 1         4 my ($M, $n) = ($self->{coef}, $self->{n});
126 1 50       4 die "Must supply an array reference for B" unless ref($B) eq 'ARRAY';
127 1         4 my $A = $self->mat_to_vec();
128 1         8 my $X = [split //, 0 x $n];
129 1         6 my $IPS = [split //, 0 x $n];
130 1         3 my $flag = 0;
131 1         49 my $ret = Math::Cephes::simq($A, $B, $X, $n, $flag, $IPS);
132 1 50       9 return $ret ? undef : $X;
133             }
134              
135              
136             sub inv {
137 2     2 0 52 my $self = shift;
138 2         8 my ($M, $n) = ($self->{coef}, $self->{n});
139 2         5 my $A = $self->mat_to_vec();
140 2         18 my $X = [split //, 0 x ($n*$n)];
141 2         10 my $B = [split //, 0 x $n];
142 2         27 my $IPS = [split //, 0 x $n];
143 2         5 my $flag = 0;
144 2         43 my $ret = Math::Cephes::minv($A, $X, $n, $B, $IPS);
145 2 50       8 return undef if $ret;
146 2         8 my $I = $self->vec_to_mat($X);
147 2         7 return Math::Cephes::Matrix->new($I);
148             }
149              
150             sub transp {
151 1     1 0 121 my $self = shift;
152 1         4 my ($M, $n) = ($self->{coef}, $self->{n});
153 1         3 my $A = $self->mat_to_vec();
154 1         18 my $T = [split //, 0 x ($n*$n)];
155 1         17 Math::Cephes::mtransp($n, $A, $T);
156 1         4 my $R = $self->vec_to_mat($T);
157 1         4 return Math::Cephes::Matrix->new($R);
158             }
159              
160             sub add {
161 1     1 1 75 my ($self, $B) = @_;
162 1         5 $B = $self->check($B);
163 1         3 my ($A, $n) = ($self->{coef}, $self->{n});
164 1         2 my $C = [];
165 1         5 for (my $i=0; $i<$n; $i++) {
166 3         7 for (my $j=0; $j<$n; $j++) {
167 9         28 $C->[$i]->[$j] = $A->[$i]->[$j] + $B->[$i]->[$j];
168             }
169             }
170 1         14 return Math::Cephes::Matrix->new($C);
171             }
172              
173             sub sub {
174 1     1 0 143 my ($self, $B) = @_;
175 1         4 $B = $self->check($B);
176 1         4 my ($A, $n) = ($self->{coef}, $self->{n});
177 1         2 my $C = [];
178 1         7 for (my $i=0; $i<$n; $i++) {
179 3         9 for (my $j=0; $j<$n; $j++) {
180 9         25 $C->[$i]->[$j] = $A->[$i]->[$j] - $B->[$i]->[$j];
181             }
182             }
183 1         4 return Math::Cephes::Matrix->new($C);
184             }
185              
186             sub mul {
187 8     8 0 594 my ($self, $B) = @_;
188 8         20 $B = $self->check($B);
189 8         20 my ($A, $n) = ($self->{coef}, $self->{n});
190 8         39 my $C = [];
191 8 100       20 if (ref($B->[0]) eq 'ARRAY') {
192 4         13 for (my $i=0; $i<$n; $i++) {
193 12         28 for (my $j=0; $j<$n; $j++) {
194 36         79 for (my $m=0; $m<$n; $m++) {
195 108         334 $C->[$i]->[$j] += $A->[$i]->[$m] * $B->[$m]->[$j];
196             }
197             }
198             }
199 4         10 return Math::Cephes::Matrix->new($C);
200             }
201             else {
202 4         12 for (my $i=0; $i<$n; $i++) {
203 12         28 for (my $m=0; $m<$n; $m++) {
204 36         137 $C->[$i] += $A->[$i]->[$m] * $B->[$m];
205             }
206             }
207 4         14 return $C;
208             }
209             }
210              
211             sub div {
212 1     1 0 176 my ($self, $B) = @_;
213 1         4 $B = $self->check($B);
214 1         4 my $C = Math::Cephes::Matrix->new($B)->inv();
215 1         6 my $D = $self->mul($C);
216 1         6 return $D;
217             }
218              
219             sub eigens {
220 1     1 0 6 my $self = shift;
221 1         4 my ($M, $n) = ($self->{coef}, $self->{n});
222 1         2 my $A = [];
223 1         5 for (my $i=0; $i<$n; $i++) {
224 3         8 for (my $j=0; $j<$n; $j++) {
225 9         21 my $index = ($i*$i+$i)/2 + $j;
226 9         26 $A->[$index] = $M->[$i]->[$j];
227             }
228             }
229 1         10 my $EV1 = [split //, 0 x ($n*$n)];
230 1         6 my $E = [split //, 0 x $n];
231 1         4 my $IPS = [split //, 0 x $n];
232 1         24 Math::Cephes::eigens($A, $EV1, $E, $n);
233 1         4 my $EV = $self->vec_to_mat($EV1);
234 1         5 return ($E, Math::Cephes::Matrix->new($EV));
235             }
236              
237             1;
238              
239             __END__