File Coverage

blib/lib/Matrix/Simple.pm
Criterion Covered Total %
statement 12 164 7.3
branch 0 48 0.0
condition 0 11 0.0
subroutine 4 14 28.5
pod 10 10 100.0
total 26 247 10.5


line stmt bran cond sub pod time code
1             package Matrix::Simple;
2            
3 1     1   65925 use strict;
  1         3  
  1         31  
4 1     1   6 use warnings;
  1         2  
  1         32  
5 1     1   6 use vars qw{@EXPORT $VERSION @ISA};
  1         2  
  1         61  
6 1     1   5 use Exporter;
  1         1  
  1         1778  
7            
8             @EXPORT = qw{stand det tran adj num_mult inv sub add mult show};
9             $VERSION = qq{1.04};
10             @ISA = qw{Exporter};
11            
12             #=====================================================================
13            
14             #some subroutines as follows :
15            
16             #=====================================================================
17            
18             #Standardize data into two-dimensional array form
19             sub stand{
20 0     0 1   my @matrix;
21 0 0         if(@_ == 1){
    0          
22 0           my ($file) = @_;
23 0 0         open my $fh_data, '<', $file or die "can't open $file:$!";
24 0           while(<$fh_data>){
25 0           chomp;
26 0 0         next unless $_;
27 0           push @matrix, [ split ];
28             }
29 0           close $fh_data;
30             }
31             elsif(@_ >= 3){
32 0 0         if(@_ > 3){
33 0           print "The parameters of entered are too many!\n";
34 0           print "The first three parameters are used by default!\n";
35             }
36 0           my ($data, $row, $col) = @_;
37 0 0         if(@$data != $row*$col){
38 0           print "Error: the number of data isn't equal to the number of rows multiplied by the number of columns!\n";
39 0           return 'error';
40             }
41 0           for(my $i = 0; $i < @$data; $i += $col){
42 0           push @matrix, [ @{$data}[$i .. $i+$col-1] ];
  0            
43             }
44             }
45             else{
46 0           print "The parameters of entered is incorrect!\n";
47 0           return 'error';
48             }
49 0           return \@matrix;
50             }
51            
52             #Calculate the determinant of a matrix by Laplace expansion
53             sub det{
54 0     0 1   my $matrix = shift;
55 0 0         if(@$matrix != @{$matrix->[0]}){
  0            
56 0           warn "Can't calculate the determinant of the matrix: matrix isn't a square matrix!\n";
57 0           return 'error';
58             }
59 0   0       our $value = shift || 0;
60 0           foreach my $k (0 .. $#{$matrix->[0]}){
  0            
61 0           my $element = ((-1)**($k))*$matrix->[0][$k];
62 0           my $low_order;
63 0           foreach my $i (1 .. $#$matrix){
64 0           foreach my $j (0 .. $#{$matrix->[$i]}){
  0            
65 0 0         next if $k == $j;
66 0           push @{$low_order->[$i-1]}, $matrix->[$i][$j];
  0            
67             }
68             }
69 0           $low_order->[0][$_] *= $element foreach 0 .. $#{$low_order->[0]};
  0            
70 0 0         if(@$low_order == 1){
71 0 0         $value += defined $low_order->[0][0] ? $low_order->[0][0] : $matrix->[0][0];
72             }
73             else{
74 0           &det($low_order, $value);
75             }
76             }
77 0           return $value;
78             }
79            
80             #Get the transposed matrix of the matrix
81             sub tran{
82 0     0 1   my $original = shift;
83 0           my @transpose;
84 0           foreach my $i (0 .. $#$original){
85 0           foreach my $j (0 .. $#{$original->[$i]}){
  0            
86 0           $transpose[$j][$i] = $original->[$i][$j];
87             }
88             }
89 0           return \@transpose;
90             }
91            
92             #Get the adjugate matrix of the matrix
93             sub adj{
94 0     0 1   my $matrix = shift;
95 0 0         if(@$matrix != @{$matrix->[0]}){
  0            
96 0           warn "Can't get the adjugate matrix of the matrix: matrix isn't a square matrix!\n";
97 0           return 'error';
98             }
99 0 0         if(@$matrix == 1){
100 0           warn "The matrix is a first-order matrix!\n";
101 0           return 'error';
102             }
103 0           my @adjugate_tmp;
104 0           foreach my $i (0 .. $#$matrix){
105 0           foreach my $j (0 .. $#{$matrix->[$i]}){
  0            
106 0           my @tmp;
107 0           foreach my $p (0 .. $#$matrix){
108 0           foreach my $q (0 .. $#{$matrix->[$i]}){
  0            
109 0 0 0       push @tmp, $matrix->[$p][$q] if $p != $i and $q != $j;
110             }
111             }
112 0           my @low_order;
113 0           for(my $n = 0; $n < @tmp; $n += $#{$matrix->[0]}){
  0            
114 0           push @low_order, [ @tmp[$n .. $n+$#{$matrix->[0]}-1] ];
  0            
115             }
116 0           $adjugate_tmp[$i][$j] = ((-1)**($i+$j))*&det(\@low_order);
117             }
118             }
119 0           my $adjugate = &tran(\@adjugate_tmp);
120 0           return $adjugate;
121             }
122            
123             #Multiplication of number and matrix
124             sub num_mult{
125 0     0 1   my ($num, $matrix) = @_;
126 0           my @result;
127 0           foreach my $i (0 .. $#$matrix){
128 0           foreach my $j (0 .. $#{$matrix->[$i]}){
  0            
129 0           $result[$i][$j] = $num*$matrix->[$i][$j];
130             }
131             }
132 0           return \@result;
133             }
134            
135             #Get the inverse matrix of the matrix
136             sub inv{
137 0     0 1   my ($matrix, $round) = @_;
138 0 0         $round = 2 unless defined $round;
139 0           my $det_value = &det($matrix);
140 0 0         if($det_value == 0){
141 0           warn "Can't get the inverse matrix of the matrix: the determinant of the matrix is 0!\n";
142 0           return 'error';
143             }
144 0 0         if($det_value eq 'error'){
145 0           return 'error';
146             }
147 0 0         if(@$matrix == 1){
148 0           my $digit = sprintf "%.${round}f", 1/$det_value;
149 0           my @inverse = ([$digit]);
150 0           return \@inverse;
151             }
152 0           my $adjugate = &adj($matrix);
153 0           my $inverse = &num_mult(1/$det_value, $adjugate);
154 0           foreach my $i (0 .. $#$inverse){
155 0           foreach my $j (0 .. $#{$inverse->[$i]}){
  0            
156 0           $inverse->[$i][$j] = sprintf "%.${round}f", $inverse->[$i][$j];
157             }
158             }
159 0           return $inverse;
160             }
161            
162             #Subtraction of matrix and matrix
163             sub sub{
164 0     0 1   my ($matrix_1, $matrix_2) = @_;
165 0 0 0       if(@$matrix_1 != @$matrix_2 or @{$matrix_1->[0]} != @{$matrix_2->[0]}){
  0            
  0            
166 0           warn "These two matrices can't be subtracted!\n";
167 0           return 'error';
168             }
169 0           my @result;
170 0           foreach my $i (0 .. $#$matrix_1){
171 0           foreach my $j (0 .. $#{$matrix_1->[$i]}){
  0            
172 0           $result[$i][$j] = $matrix_1->[$i][$j] - $matrix_2->[$i][$j];
173             }
174             }
175 0           return \@result;
176             }
177            
178             #Addition of matrix and matrix
179             sub add{
180 0     0 1   my ($matrix_1, $matrix_2) = @_;
181 0 0 0       if(@$matrix_1 != @$matrix_2 or @{$matrix_1->[0]} != @{$matrix_2->[0]}){
  0            
  0            
182 0           warn "These two matrices can't be added!\n";
183 0           return 'error';
184             }
185 0           my @result;
186 0           foreach my $i (0 .. $#$matrix_1){
187 0           foreach my $j (0 .. $#{$matrix_1->[$i]}){
  0            
188 0           $result[$i][$j] = $matrix_1->[$i][$j] + $matrix_2->[$i][$j];
189             }
190             }
191 0           return \@result;
192             }
193            
194             #Multiplication of matrix and matrix
195             sub mult{
196 0     0 1   my ($matrix_1, $matrix_2) = @_;
197 0 0         if(@{$matrix_1->[0]} != @$matrix_2){
  0            
198 0           warn "These two matrices can't be multiplied!\n";
199 0           return 'error';
200             }
201 0           my @result;
202 0           foreach my $i (0 .. $#$matrix_1){
203 0           foreach my $j (0 .. $#{$matrix_2->[0]}){
  0            
204 0           foreach my $k (0 .. $#$matrix_2){
205 0           $result[$i][$j] += $matrix_1->[$i][$k]*$matrix_2->[$k][$j];
206             }
207             }
208             }
209 0           return \@result;
210             }
211            
212             #Show matrix to specified place
213             sub show{
214 0     0 1   my ($matrix, $place) = @_;
215 0 0         if(defined $place){
216 0 0         open my $fh_matrix, '>', $place or die "can't generate $place:$!";
217 0           foreach my $i (0 .. $#$matrix){
218 0           foreach my $j (0 .. $#{$matrix->[$i]}){
  0            
219 0 0         print $fh_matrix $matrix->[$i][$j], $j != $#{$matrix->[$i]} ? "\t" : "\n";
  0            
220             }
221             }
222 0           close $fh_matrix;
223             }
224             else{
225 0           foreach my $i (0 .. $#$matrix){
226 0           foreach my $j (0 .. $#{$matrix->[$i]}){
  0            
227 0 0         print $matrix->[$i][$j], $j != $#{$matrix->[$i]} ? "\t" : "\n";
  0            
228             }
229             }
230             }
231             }
232            
233             1;
234            
235             __END__