line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# ABSTRACT: Uniform use of Math::MatrixReal and Math::GSL::Matrix. |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
27928
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
45
|
|
4
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
53
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package Math::Matrix::MaybeGSL; |
7
|
|
|
|
|
|
|
$Math::Matrix::MaybeGSL::VERSION = '0.006'; |
8
|
1
|
|
|
1
|
|
10
|
use parent 'Exporter'; |
|
1
|
|
|
|
|
1540
|
|
|
1
|
|
|
|
|
8
|
|
9
|
|
|
|
|
|
|
our @EXPORT = qw{Matrix}; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
use overload |
12
|
1
|
|
|
|
|
11
|
'*=' => '_assign_multiply', |
13
|
|
|
|
|
|
|
'*' => '_multiply', |
14
|
1
|
|
|
1
|
|
84
|
'fallback' => undef; |
|
1
|
|
|
|
|
2
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
sub _choose_matrix_module { |
17
|
1
|
50
|
|
1
|
|
7
|
return 'Math::GSL::Matrix' if $INC{'Math/GSL/Matrix.pm'}; |
18
|
1
|
50
|
|
|
|
5
|
return 'Math::MatrixReal' if $INC{'Math/MatrixReal.pm'}; |
19
|
|
|
|
|
|
|
|
20
|
1
|
|
|
|
|
2
|
my @err; |
21
|
|
|
|
|
|
|
|
22
|
1
|
50
|
|
|
|
2
|
return 'Math::GSL::Matrix' if eval { |
23
|
1
|
|
|
|
|
11
|
require Math::GSL; |
24
|
0
|
|
|
|
|
0
|
require Math::GSL::Matrix; |
25
|
0
|
|
|
|
|
0
|
1; |
26
|
|
|
|
|
|
|
}; |
27
|
1
|
|
|
|
|
648
|
push @err, "Error loading Math::GSL::Matrix: $@"; |
28
|
|
|
|
|
|
|
|
29
|
1
|
50
|
|
|
|
3
|
return 'Math::MatrixReal' if eval { require Math::MatrixReal; 1; }; |
|
1
|
|
|
|
|
9
|
|
|
1
|
|
|
|
|
38469
|
|
30
|
0
|
|
|
|
|
0
|
push @err, "Error loading Math::MatrixReal: $@"; |
31
|
|
|
|
|
|
|
|
32
|
0
|
|
|
|
|
0
|
die join( "\n", "Couldn't load a Matrix module:", @err ); |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
5
|
|
|
5
|
1
|
8982
|
sub Matrix { __PACKAGE__ } |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub _call { |
38
|
49
|
|
|
49
|
|
119
|
my ($method, $obj, @args) = @_; |
39
|
49
|
|
|
|
|
311
|
$obj->{matrix}->$method(@args); |
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub isGSL { |
43
|
0
|
|
|
0
|
1
|
0
|
our $matrix_module; |
44
|
0
|
|
|
|
|
0
|
return $matrix_module eq "Math::GSL::Matrix"; |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
BEGIN { |
48
|
1
|
|
|
1
|
|
5
|
our $matrix_module = _choose_matrix_module(); |
49
|
|
|
|
|
|
|
my %functions |
50
|
|
|
|
|
|
|
= ( |
51
|
|
|
|
|
|
|
'any' => { |
52
|
|
|
|
|
|
|
new => sub { |
53
|
1
|
|
|
1
|
|
4
|
my (undef, $rows, $cols) = @_; |
54
|
1
|
|
|
|
|
8
|
return _new( $matrix_module->new($rows, $cols) ); |
55
|
|
|
|
|
|
|
}, |
56
|
1
|
|
|
1
|
|
1085
|
dim => sub { _call(dim => @_) }, |
57
|
1
|
|
|
1
|
|
643
|
each => sub { _new(_call(each => @_)) }, |
58
|
|
|
|
|
|
|
}, |
59
|
|
|
|
|
|
|
'Math::GSL::Matrix' => { |
60
|
0
|
|
|
|
|
0
|
assign => sub { _call(set_elem => ($_[0], $_[1]-1, $_[2]-1, $_[3])); }, |
61
|
0
|
|
|
|
|
0
|
element => sub { _call(get_elem => ($_[0], $_[1]-1, $_[2]-1, $_[3])); }, |
62
|
0
|
|
|
|
|
0
|
new_from_cols => sub { _new(_gsl_new_from_cols($_[1])) }, |
63
|
0
|
|
|
|
|
0
|
new_from_rows => sub { _new(_gsl_new_from_rows($_[1])) }, |
64
|
0
|
|
|
|
|
0
|
vconcat => sub { _new(_call(vconcat => $_[0], $_[1]{matrix})) }, |
65
|
0
|
|
|
|
|
0
|
hconcat => sub { _new(_call(hconcat => $_[0], $_[1]{matrix})) }, |
66
|
0
|
|
|
|
|
0
|
write => sub { _gsl_write(@_) }, |
67
|
0
|
|
|
|
|
0
|
read => sub { _gsl_read($_[1]) }, |
68
|
|
|
|
|
|
|
max => sub { |
69
|
0
|
0
|
|
|
|
0
|
if (wantarray) { |
70
|
0
|
|
|
|
|
0
|
my ($v, @pos) = _call(max => @_); |
71
|
0
|
|
|
|
|
0
|
return ($v, map { $_ + 1 } @pos); |
|
0
|
|
|
|
|
0
|
|
72
|
|
|
|
|
|
|
} else { |
73
|
0
|
|
|
|
|
0
|
return scalar(_call(max => @_)); |
74
|
|
|
|
|
|
|
}; |
75
|
|
|
|
|
|
|
}, |
76
|
|
|
|
|
|
|
min => sub { |
77
|
0
|
0
|
|
|
|
0
|
if (wantarray) { |
78
|
0
|
|
|
|
|
0
|
my ($v, @pos) = _call(min => @_); |
79
|
0
|
|
|
|
|
0
|
return ($v, map { $_ + 1 } @pos); |
|
0
|
|
|
|
|
0
|
|
80
|
|
|
|
|
|
|
} else { |
81
|
0
|
|
|
|
|
0
|
return scalar(_call(min => @_)); |
82
|
|
|
|
|
|
|
}; |
83
|
|
|
|
|
|
|
}, |
84
|
|
|
|
|
|
|
}, |
85
|
|
|
|
|
|
|
'Math::MatrixReal' => { |
86
|
1
|
|
|
1
|
|
1247
|
assign => sub { _call(assign => @_); }, |
87
|
46
|
|
|
46
|
|
31659
|
element => sub { _call(element => @_); }, |
88
|
2
|
|
|
2
|
|
16
|
new_from_cols => sub { _new( $matrix_module->new_from_cols($_[1])) }, |
89
|
1
|
|
|
1
|
|
7
|
new_from_rows => sub { _new( $matrix_module->new_from_rows($_[1])) }, |
90
|
1
|
|
|
1
|
|
532
|
vconcat => sub { _new( ~((~$_[0]{matrix}) . (~$_[1]{matrix})) ) }, |
91
|
1
|
|
|
1
|
|
14
|
hconcat => sub { _new( $_[0]{matrix} . $_[1]{matrix} ) }, |
92
|
1
|
|
|
1
|
|
597
|
write => sub { _mreal_write(@_) }, |
93
|
1
|
|
|
1
|
|
5
|
read => sub { _mreal_read($_[1]) }, |
94
|
1
|
|
|
1
|
|
424
|
max => sub { _mreal_max($_[0]{matrix}) }, |
95
|
1
|
|
|
1
|
|
1261
|
min => sub { _mreal_min($_[0]{matrix}) }, |
96
|
|
|
|
|
|
|
}, |
97
|
1
|
|
|
|
|
145
|
); |
98
|
|
|
|
|
|
|
|
99
|
1
|
|
|
1
|
|
1537
|
no strict 'refs'; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
328
|
|
100
|
|
|
|
|
|
|
|
101
|
1
|
|
|
|
|
3
|
for my $func (keys %{$functions{$matrix_module}}) { |
|
1
|
|
|
|
|
8
|
|
102
|
|
|
|
|
|
|
# Use Sub::Install later? |
103
|
10
|
|
|
|
|
20
|
$_ = __PACKAGE__ . "::$func"; |
104
|
10
|
|
|
|
|
55
|
*$_ = $functions{$matrix_module}{$func}; |
105
|
|
|
|
|
|
|
} |
106
|
1
|
|
|
|
|
4
|
for my $func (keys %{$functions{any}}) { |
|
1
|
|
|
|
|
4
|
|
107
|
|
|
|
|
|
|
# Use Sub::Install later? |
108
|
3
|
|
|
|
|
8
|
$_ = __PACKAGE__ . "::$func"; |
109
|
3
|
|
|
|
|
2439
|
*$_ = $functions{any}{$func}; |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
sub _mreal_max { |
115
|
1
|
|
|
1
|
|
20
|
my $matrix = shift; |
116
|
1
|
|
|
|
|
6
|
my ($rs, $cs) = $matrix->dim(); |
117
|
1
|
50
|
33
|
|
|
14
|
return $matrix->max() if ($rs == 1 || $cs == 1); |
118
|
|
|
|
|
|
|
|
119
|
1
|
|
|
|
|
3
|
my ($m, $r, $c, $v) = ($matrix->[0], 1, 1, undef); |
120
|
|
|
|
|
|
|
|
121
|
1
|
|
|
|
|
3
|
for my $i (1..$rs) { |
122
|
2
|
|
|
|
|
4
|
for my $j (1..$cs) { |
123
|
4
|
50
|
66
|
|
|
19
|
if (!$v || $v < $m->[$i-1][$j-1]) { |
124
|
4
|
|
|
|
|
3
|
$r = $i; |
125
|
4
|
|
|
|
|
5
|
$c = $j; |
126
|
4
|
|
|
|
|
10
|
$v = $m->[$i-1][$j-1]; |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
1
|
50
|
|
|
|
4
|
return wantarray ? ($v, $r, $c) : $v; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub _mreal_min { |
135
|
1
|
|
|
1
|
|
3
|
my $matrix = shift; |
136
|
1
|
|
|
|
|
4
|
my ($rs, $cs) = $matrix->dim(); |
137
|
1
|
50
|
33
|
|
|
13
|
return $matrix->min() if ($rs == 1 || $cs == 1); |
138
|
|
|
|
|
|
|
|
139
|
1
|
|
|
|
|
3
|
my ($m, $r, $c, $v) = ($matrix->[0], 1, 1, undef); |
140
|
|
|
|
|
|
|
|
141
|
1
|
|
|
|
|
3
|
for my $i (1..$rs) { |
142
|
2
|
|
|
|
|
6
|
for my $j (1..$cs) { |
143
|
4
|
100
|
66
|
|
|
90
|
if (!$v || $v > $m->[$i-1][$j-1]) { |
144
|
1
|
|
|
|
|
2
|
$r = $i; |
145
|
1
|
|
|
|
|
2
|
$c = $j; |
146
|
1
|
|
|
|
|
2
|
$v = $m->[$i-1][$j-1]; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
|
151
|
1
|
50
|
|
|
|
5
|
return wantarray ? ($v, $r, $c) : $v; |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
sub _gsl_new_from_cols { |
155
|
0
|
|
|
0
|
|
0
|
my $cols = shift; |
156
|
|
|
|
|
|
|
|
157
|
0
|
|
|
|
|
0
|
my $nr_columns = scalar(@$cols); |
158
|
0
|
|
|
|
|
0
|
my $nr_rows = 0; |
159
|
0
|
|
|
|
|
0
|
for my $row (@$cols) { |
160
|
0
|
0
|
|
|
|
0
|
$nr_rows = scalar(@$row) if @$row > $nr_rows; |
161
|
|
|
|
|
|
|
} |
162
|
0
|
|
|
|
|
0
|
my $m = Math::GSL::Matrix->new($nr_rows, $nr_columns); |
163
|
0
|
|
|
|
|
0
|
for my $r (0..$nr_rows - 1) { |
164
|
0
|
|
|
|
|
0
|
for my $c (0..$nr_columns - 1) { |
165
|
0
|
|
0
|
|
|
0
|
$m->set_elem($r, $c, $cols->[$c][$r] || 0); |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
} |
168
|
0
|
|
|
|
|
0
|
return $m; |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
sub _gsl_new_from_rows { |
172
|
0
|
|
|
0
|
|
0
|
my $rows = shift; |
173
|
|
|
|
|
|
|
|
174
|
0
|
|
|
|
|
0
|
my $nr_rows = scalar(@$rows); |
175
|
0
|
|
|
|
|
0
|
my $nr_columns = 0; |
176
|
0
|
|
|
|
|
0
|
for my $col (@$rows) { |
177
|
0
|
0
|
|
|
|
0
|
$nr_columns = scalar(@$col) if @$col > $nr_columns; |
178
|
|
|
|
|
|
|
} |
179
|
0
|
|
|
|
|
0
|
my $m = Math::GSL::Matrix->new($nr_rows, $nr_columns); |
180
|
0
|
|
|
|
|
0
|
for my $c (0..$nr_columns - 1) { |
181
|
0
|
|
|
|
|
0
|
for my $r (0..$nr_rows - 1) { |
182
|
0
|
|
0
|
|
|
0
|
$m->set_elem($r, $c, $rows->[$r][$c] || 0); |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
} |
185
|
0
|
|
|
|
|
0
|
return $m; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
sub _new { |
189
|
11
|
|
|
11
|
|
2821
|
my $mat = shift; |
190
|
11
|
|
|
|
|
109
|
return bless { matrix => $mat }, __PACKAGE__; |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
sub _assign_multiply { |
194
|
0
|
|
|
0
|
|
0
|
my($object,$argument) = @_; |
195
|
|
|
|
|
|
|
|
196
|
0
|
|
|
|
|
0
|
return( &_multiply($object,$argument,undef) ); |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
sub _multiply { |
200
|
3
|
|
|
3
|
|
1380
|
my ($object, $argument, $flag) = @_; |
201
|
|
|
|
|
|
|
|
202
|
3
|
100
|
|
|
|
13
|
$argument = $argument->{matrix} if ref $argument eq __PACKAGE__; |
203
|
3
|
50
|
|
|
|
10
|
$object = $object->{matrix} if ref $object eq __PACKAGE__; |
204
|
|
|
|
|
|
|
|
205
|
3
|
100
|
66
|
|
|
17
|
if ((defined $flag) && $flag) { |
206
|
1
|
|
|
|
|
4
|
return _new($argument * $object); |
207
|
|
|
|
|
|
|
} else { |
208
|
2
|
|
|
|
|
7
|
return _new($object * $argument); |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
sub _mreal_write { |
213
|
1
|
|
|
1
|
|
3
|
my ($m, $filename) = @_; |
214
|
|
|
|
|
|
|
|
215
|
1
|
|
|
|
|
3
|
my $matrix = $m->{matrix}; |
216
|
|
|
|
|
|
|
|
217
|
1
|
50
|
|
|
|
197
|
open my $fh, ">", $filename or |
218
|
|
|
|
|
|
|
die "Could not create file '$filename': $!"; |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
# probably faster than creating a full string in memory |
221
|
1
|
|
|
|
|
7
|
my ($rows, $cols) = $matrix->dim(); |
222
|
|
|
|
|
|
|
|
223
|
1
|
|
|
|
|
13
|
for my $r (0..$rows-1) { |
224
|
2
|
|
|
|
|
7
|
for my $c (0..$cols-1) { |
225
|
4
|
|
|
|
|
15
|
print $fh $matrix->[0][$r][$c]; |
226
|
4
|
100
|
|
|
|
15
|
print $fh "\t" unless $c == $cols-1; |
227
|
|
|
|
|
|
|
} |
228
|
2
|
|
|
|
|
8
|
print $fh "\n"; |
229
|
|
|
|
|
|
|
} |
230
|
1
|
|
|
|
|
75
|
close $fh; |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
sub _mreal_read { |
234
|
1
|
|
|
1
|
|
3
|
my $filename = shift; |
235
|
|
|
|
|
|
|
|
236
|
1
|
|
|
|
|
2
|
my $m = []; |
237
|
|
|
|
|
|
|
|
238
|
1
|
50
|
|
|
|
35
|
open my $fh, "<", $filename or |
239
|
|
|
|
|
|
|
die "could not open file '$filename': $!"; |
240
|
|
|
|
|
|
|
|
241
|
1
|
|
|
|
|
29
|
while (<$fh>) { |
242
|
2
|
|
|
|
|
4
|
chomp; |
243
|
2
|
|
|
|
|
14
|
push @$m, [split /\s+/]; |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
|
246
|
1
|
|
|
|
|
8
|
return _new( Math::MatrixReal->new_from_rows($m) ); |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
sub _gsl_read { |
250
|
0
|
|
|
0
|
|
|
my $filename = shift; |
251
|
|
|
|
|
|
|
|
252
|
0
|
0
|
|
|
|
|
die "$filename does not exist" unless -f $filename; |
253
|
|
|
|
|
|
|
|
254
|
0
|
|
|
|
|
|
my $fh = Math::GSL::gsl_fopen($filename, "r"); |
255
|
0
|
0
|
|
|
|
|
die "error opening file $filename for reading" unless $fh; |
256
|
|
|
|
|
|
|
|
257
|
0
|
|
|
|
|
|
my $dim = Math::GSL::Matrix::gsl_matrix_alloc(1, 2); |
258
|
0
|
|
|
|
|
|
my $err = Math::GSL::Matrix::gsl_matrix_fread($fh, $dim); |
259
|
0
|
0
|
|
|
|
|
die "error reading matrix" if $err; |
260
|
|
|
|
|
|
|
|
261
|
0
|
|
|
|
|
|
my $m = Math::GSL::Matrix::gsl_matrix_alloc( |
262
|
|
|
|
|
|
|
Math::GSL::Matrix::gsl_matrix_get($dim, 0, 0), |
263
|
|
|
|
|
|
|
Math::GSL::Matrix::gsl_matrix_get($dim, 0, 1)); |
264
|
0
|
|
|
|
|
|
$err = Math::GSL::Matrix::gsl_matrix_fread($fh, $m); |
265
|
0
|
0
|
|
|
|
|
die "error reading matrix" if $err; |
266
|
|
|
|
|
|
|
|
267
|
0
|
|
|
|
|
|
Math::GSL::Matrix::gsl_matrix_free($dim); |
268
|
|
|
|
|
|
|
|
269
|
0
|
|
|
|
|
|
Math::GSL::gsl_fclose($fh); |
270
|
0
|
|
|
|
|
|
_new( Math::GSL::Matrix->new($m) ); |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
sub _gsl_write { |
274
|
0
|
|
|
0
|
|
|
my ($self, $filename) = @_; |
275
|
|
|
|
|
|
|
|
276
|
0
|
|
|
|
|
|
my $fh = Math::GSL::gsl_fopen($filename, "w"); |
277
|
0
|
0
|
|
|
|
|
die "error opening file: $filename" unless $fh; |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
# create a temporary matrix with the main matrix dimensions |
280
|
0
|
|
|
|
|
|
my $dim = Math::GSL::Matrix::gsl_matrix_alloc(1, 2); |
281
|
0
|
|
|
|
|
|
my ($rows, $cols) = $self->dim; |
282
|
0
|
|
|
|
|
|
Math::GSL::Matrix::gsl_matrix_set($dim, 0, 0, $rows); |
283
|
0
|
|
|
|
|
|
Math::GSL::Matrix::gsl_matrix_set($dim, 0, 1, $cols); |
284
|
|
|
|
|
|
|
|
285
|
0
|
|
|
|
|
|
my $err = Math::GSL::Matrix::gsl_matrix_fwrite($fh, $dim); |
286
|
0
|
0
|
|
|
|
|
die "error gsl-writting matrix" if $err; |
287
|
|
|
|
|
|
|
|
288
|
0
|
|
|
|
|
|
Math::GSL::Matrix::gsl_matrix_free($dim); |
289
|
|
|
|
|
|
|
|
290
|
0
|
|
|
|
|
|
$err = Math::GSL::Matrix::gsl_matrix_fwrite($fh, $self->{matrix}->raw); |
291
|
0
|
0
|
|
|
|
|
die "error gsl-writting matrix" if $err; |
292
|
|
|
|
|
|
|
|
293
|
0
|
|
|
|
|
|
Math::GSL::gsl_fclose($fh); |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
1; |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
__END__ |