line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Math::MatrixReal::Ext1; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
688
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
32
|
|
4
|
1
|
|
|
1
|
|
1387
|
use Math::MatrixReal; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
use Carp; |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
use base qw/Math::MatrixReal/; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
our $VERSION = '0.07'; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
sub new_from_cols { |
12
|
|
|
|
|
|
|
my $this = shift; |
13
|
|
|
|
|
|
|
my $extra_args = ( @_ > 1 && ref($_[-1]) eq 'HASH' ) ? pop : {}; |
14
|
|
|
|
|
|
|
$extra_args->{_type} = 'column'; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
return $this->_new_from_rows_or_cols(@_, $extra_args ); |
17
|
|
|
|
|
|
|
} |
18
|
|
|
|
|
|
|
sub new_from_columns { |
19
|
|
|
|
|
|
|
my $this = shift; |
20
|
|
|
|
|
|
|
$this->new_from_cols(@_); |
21
|
|
|
|
|
|
|
} |
22
|
|
|
|
|
|
|
sub new_from_rows { |
23
|
|
|
|
|
|
|
my $this = shift; |
24
|
|
|
|
|
|
|
my $extra_args = ( @_ > 1 && ref($_[-1]) eq 'HASH' ) ? pop : {}; |
25
|
|
|
|
|
|
|
$extra_args->{_type} = 'row'; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
return $this->_new_from_rows_or_cols(@_, $extra_args ); |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub _new_from_rows_or_cols { |
31
|
|
|
|
|
|
|
my $proto = shift; |
32
|
|
|
|
|
|
|
my $class = ref($proto) || $proto; |
33
|
|
|
|
|
|
|
my $ref_to_vectors = shift; |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# these additional args are internal at the moment, |
36
|
|
|
|
|
|
|
# but in the future the user could pass e.g. {pad=>1} to |
37
|
|
|
|
|
|
|
# request padding |
38
|
|
|
|
|
|
|
my $args = pop; |
39
|
|
|
|
|
|
|
my $vector_type = $args->{_type}; |
40
|
|
|
|
|
|
|
die "Internal ".__PACKAGE__." error" unless $vector_type =~ /^(row|column)$/; |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
# step back one frame because this private method is |
43
|
|
|
|
|
|
|
# not how the user called it |
44
|
|
|
|
|
|
|
my $caller_subname = (caller(1))[3]; |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# note--this die() could be inconvenient if someone had something |
47
|
|
|
|
|
|
|
# really fancy that knew how to be dereffed as an array |
48
|
|
|
|
|
|
|
# (can you do that with a tied scalar?), but I'm not putting |
49
|
|
|
|
|
|
|
# the rest of the world through an eval--they can just |
50
|
|
|
|
|
|
|
# deref and pass a reference themselves. If that ever happens |
51
|
|
|
|
|
|
|
# we can add an arg to skip this check |
52
|
|
|
|
|
|
|
croak "$caller_subname: need a reference to an array of ${vector_type}s" unless ref($ref_to_vectors) eq 'ARRAY'; |
53
|
|
|
|
|
|
|
my @vectors = @{$ref_to_vectors}; |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
my $matrix; |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
my $other_type = {row=>'column', column=>'row'}->{$vector_type}; |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
my %matrix_dim = ( |
60
|
|
|
|
|
|
|
$vector_type => scalar( @vectors ), |
61
|
|
|
|
|
|
|
$other_type => 0, # we will correct this in a bit |
62
|
|
|
|
|
|
|
); |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
# row and column indices are one based |
65
|
|
|
|
|
|
|
my $current_vector_count = 1; |
66
|
|
|
|
|
|
|
foreach my $current_vector (@vectors) { |
67
|
|
|
|
|
|
|
# dimension is one-based, so we're |
68
|
|
|
|
|
|
|
# starting with one here and incrementing |
69
|
|
|
|
|
|
|
# as we go. The other dimension is fixed (for now, until |
70
|
|
|
|
|
|
|
# we add the 'pad' option), and gets set later |
71
|
|
|
|
|
|
|
my $ref = ref( $current_vector ) ; |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
if ( $ref eq '' ) { |
74
|
|
|
|
|
|
|
# we hope this is a properly formatted Math::MatrixReal string, |
75
|
|
|
|
|
|
|
# but if not we just let the Math::MatrixReal die() do it's |
76
|
|
|
|
|
|
|
# thing |
77
|
|
|
|
|
|
|
$current_vector = $class->new_from_string( $current_vector ); |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
elsif ( $ref eq 'ARRAY' ) { |
80
|
|
|
|
|
|
|
my @array = @$current_vector; |
81
|
|
|
|
|
|
|
croak "$caller_subname: one $vector_type you gave me was a ref to an array with no elements" unless @array ; |
82
|
|
|
|
|
|
|
# we need to create the right kind of string based on whether |
83
|
|
|
|
|
|
|
# they said they were sending us rows or columns: |
84
|
|
|
|
|
|
|
if ($vector_type eq 'row') { |
85
|
|
|
|
|
|
|
$current_vector = $class->new_from_string( '[ '. join( " ", @array) ." ]\n" ); |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
else { |
88
|
|
|
|
|
|
|
$current_vector = $class->new_from_string( '[ '. join( " ]\n[ ", @array) ." ]\n" ); |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
elsif ( $ref ne 'HASH' and $current_vector->isa('Math::MatrixReal') ) { |
92
|
|
|
|
|
|
|
# it's already a Math::MatrixReal something. |
93
|
|
|
|
|
|
|
# we don't need to do anything, it will all |
94
|
|
|
|
|
|
|
# work out |
95
|
|
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
else { |
97
|
|
|
|
|
|
|
# we have no idea, error time! |
98
|
|
|
|
|
|
|
croak "$caller_subname: I only know how to deal with array refs, strings, and things that inherit from Math::MatrixReal\n"; |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# starting now we know $current_vector isa Math::MatrixReal thingy |
102
|
|
|
|
|
|
|
my @vector_dims = $current_vector->dim; |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
#die unless the appropriate dimension is 1 |
105
|
|
|
|
|
|
|
croak "$caller_subname: I don't accept $other_type vectors" |
106
|
|
|
|
|
|
|
unless ($vector_dims[ $vector_type eq 'row' ? 0 : 1 ] == 1) ; |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
# the other dimension is the length of our vector |
109
|
|
|
|
|
|
|
my $length = $vector_dims[ $vector_type eq 'row' ? 1 : 0 ]; |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# set the "other" dimension to the length of this |
112
|
|
|
|
|
|
|
# vector the first time through |
113
|
|
|
|
|
|
|
$matrix_dim{$other_type} ||= $length; |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
# die unless length of this vector matches the first length |
116
|
|
|
|
|
|
|
croak "$caller_subname: one $vector_type has [$length] elements and another one had [$matrix_dim{$other_type}]--all of the ${vector_type}s passed in must have the same dimension" |
117
|
|
|
|
|
|
|
unless ($length == $matrix_dim{$other_type}) ; |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# create the matrix the first time through |
120
|
|
|
|
|
|
|
$matrix ||= $class->new($matrix_dim{row}, $matrix_dim{column}); |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# step along the vector assigning the value of each element |
123
|
|
|
|
|
|
|
# to the correct place in the matrix we're building |
124
|
|
|
|
|
|
|
foreach my $element_index ( 1..$length ){ |
125
|
|
|
|
|
|
|
# args for vector assignment: |
126
|
|
|
|
|
|
|
# initialize both to one and reset the correct |
127
|
|
|
|
|
|
|
# one below |
128
|
|
|
|
|
|
|
my ($v_r, $v_c) = (1,1); |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
# args for matrix assignment |
131
|
|
|
|
|
|
|
my ($row_index, $column_index, $value); |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
if ($vector_type eq 'row') { |
134
|
|
|
|
|
|
|
$row_index = $current_vector_count; |
135
|
|
|
|
|
|
|
$v_c = $column_index = $element_index; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
else { |
138
|
|
|
|
|
|
|
$v_r = $row_index = $element_index; |
139
|
|
|
|
|
|
|
$column_index = $current_vector_count; |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
$value = $current_vector->element($v_r, $v_c); |
142
|
|
|
|
|
|
|
$matrix->assign($row_index, $column_index, $value); |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
$current_vector_count ++ ; |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
return $matrix; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
1; |
151
|
|
|
|
|
|
|
__END__ |