File Coverage

blib/lib/Math/SparseVector.pm
Criterion Covered Total %
statement 90 116 77.5
branch 18 32 56.2
condition 1 3 33.3
subroutine 18 19 94.7
pod 0 15 0.0
total 127 185 68.6


line stmt bran cond sub pod time code
1             package Math::SparseVector;
2              
3 1     1   34454 use 5.008005;
  1         5  
  1         447  
4 1     1   7 use strict;
  1         5  
  1         39  
5 1     1   5 use warnings;
  1         8  
  1         284  
6              
7             require Exporter;
8              
9             our @ISA = qw(Exporter);
10              
11             # Items to export into callers namespace by default. Note: do not export
12             # names by default without a very good reason. Use EXPORT_OK instead.
13             # Do not simply export all your public functions/methods/constants.
14              
15             # This allows declaration use Math::SparseVector ':all';
16             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
17             # will save memory.
18             our %EXPORT_TAGS = ( 'all' => [ qw(
19            
20             ) ] );
21              
22             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
23              
24             our @EXPORT = qw(
25            
26             );
27              
28             our $VERSION = '0.03';
29              
30             use overload
31 1         7 '++' => 'incr',
32             '+' => 'add',
33 1     1   3864 'fallback' => undef;
  1         1172  
34              
35             # sparse vector contructor
36             # creates an empty sparse vector
37             sub new
38             {
39 8     8 0 577 my $class = shift;
40 8         13 my $self = {};
41 8         14 bless($self,$class);
42 8         18 return $self;
43             }
44              
45             # sets value at given index
46             sub set
47             {
48 46     46 0 108 my $self = shift;
49 46         39 my $key = shift;
50 46         37 my $value = shift;
51 46 50 33     119 if(!defined $key || !defined $value)
52             {
53 0         0 print STDERR "Usage: vector->set(key,value)\n";
54 0         0 exit;
55             }
56 46 50       69 if($value==0)
57             {
58 0         0 print STDERR "Can not store 0 in the Math::SparseVector.\n";
59 0         0 exit;
60             }
61 46         106 $self->{$key} = $value;
62             }
63              
64             # returns value at given index
65             sub get
66             {
67 67     67 0 68 my $self = shift;
68 67         64 my $key = shift;
69 67 50       101 if(!defined $key)
70             {
71 0         0 print STDERR "Usage: vector->get(key)\n";
72 0         0 exit;
73             }
74 67 50       117 if(defined $self->{$key})
75             {
76 67         216 return $self->{$key};
77             }
78 0         0 return 0;
79             }
80              
81             # returns indices of non-zero values in sorted order
82             sub keys
83             {
84 24     24 0 25 my $self = shift;
85 24         25 my @indices = keys %{$self};
  24         132  
86 24         52 my @sorted = sort {$a <=> $b} @indices;
  176         191  
87 24         66 return @sorted;
88             }
89              
90             # returns 1 if the vector is empty
91             sub isnull
92             {
93 3     3 0 373 my $self = shift;
94 3         9 my @indices = $self->keys;
95 3 100       10 if(scalar(@indices)==0)
96             {
97 2         9 return 1;
98             }
99 1         5 return 0;
100             }
101              
102             # prints sparse vector
103             sub print
104             {
105 0     0 0 0 my $self = shift;
106 0         0 foreach my $ind ($self->keys)
107             {
108 0         0 print "$ind " . $self->get($ind) . " ";
109             }
110 0         0 print "\n";
111             }
112              
113             # returns the equivalent string form
114             sub stringify
115             {
116 10     10 0 233 my $self = shift;
117 10         13 my $str="";
118 10         14 foreach my $ind ($self->keys)
119             {
120 49         81 $str.= "$ind " . $self->get($ind) . " ";
121             }
122 10         14 chop $str;
123 10         35 return $str;
124             }
125              
126             # increments value at given index
127             sub incr
128             {
129 1     1 0 2 my $self = shift;
130 1         2 my $key = shift;
131 1 50       4 if(!defined $key)
132             {
133 0         0 print STDERR "Usage: vector->incr(key)\n";
134 0         0 exit;
135             }
136 1         4 $self->{$key}++;
137             }
138              
139             # adds 2 sparse vectors
140             sub add
141             {
142 2     2 0 6 my $self = shift;
143 2         3 my $v2 = shift;
144 2 50       8 if(!defined $v2)
145             {
146 0         0 print STDERR "Usage: v1->add(v2)\n";
147 0         0 exit;
148             }
149 2         7 foreach my $key ($v2->keys)
150             {
151 13 100       22 if(defined $self->{$key})
152             {
153 5         6 $self->{$key}+=$v2->get($key);
154             }
155             else
156             {
157 8         27 $self->{$key}=$v2->get($key);
158             }
159             }
160             }
161              
162             # returns the norm
163             sub norm
164             {
165 2     2 0 4 my $self = shift;
166 2         3 my $sum = 0;
167 2         3 foreach my $key ($self->keys)
168             {
169 12         11 my $value = $self->{$key};
170 12         15 $sum += $value ** 2;
171             }
172 2         13 return sqrt $sum;
173             }
174              
175             # normalizes given sparse vector
176             sub normalize
177             {
178 1     1 0 1 my $self = shift;
179 1         4 my $vnorm = $self->norm;
180 1 50       4 if($vnorm != 0)
181             {
182 1         5 $self->div($vnorm);
183             }
184             }
185              
186             sub dot
187             {
188 1     1 0 4 my $self = shift;
189 1         1 my $v2 = shift;
190 1 50       3 if(!defined $v2)
191             {
192 0         0 print STDERR "Usage: v1->dot(v2)\n";
193 0         0 exit;
194             }
195 1         2 my $dotprod = 0;
196              
197             # optimize to do lesser comparisons by looping on
198             # the smaller vector
199 1 50       2 if (scalar($v2->keys) < scalar($self->keys)) {
200             # v2 is smaller
201 1         6 foreach my $key ($v2->keys)
202             {
203 5 100       12 if(defined $self->{$key})
204             {
205 3         5 $dotprod += $v2->get($key) * $self->{$key};
206             }
207             }
208             } else {
209             # self is smaller or equal to v2
210 0         0 foreach my $key ($self->keys)
211             {
212 0 0       0 if(defined $v2->{$key})
213             {
214 0         0 $dotprod += $v2->get($key) * $self->{$key};
215             }
216             }
217             }
218              
219 1         3 return $dotprod;
220             }
221              
222             # divides each vector entry by a given divisor
223             sub div
224             {
225 2     2 0 2 my $self = shift;
226 2         3 my $divisor = shift;
227 2 50       4 if(!defined $divisor)
228             {
229 0         0 print STDERR "Usage: v1->div(DIVISOR)\n";
230 0         0 exit;
231             }
232 2 50       4 if($divisor==0)
233             {
234 0         0 print STDERR "Divisor 0 not allowed in Math::SparseVector::div().\n";
235 0         0 exit;
236             }
237 2         99 foreach my $key ($self->keys)
238             {
239 12         17 $self->{$key}/=$divisor;
240             }
241             }
242              
243             # adds a given sparse vector to a binary sparse vector
244             sub binadd
245             {
246 1     1 0 3 my $v1 = shift;
247 1         2 my $v2 = shift;
248              
249 1 50       4 if(!defined $v2)
250             {
251 0         0 print STDERR "Usage: v1->binadd(v2)\n";
252 0         0 exit;
253             }
254              
255 1         3 foreach my $key ($v2->keys)
256             {
257 6         9 $v1->{$key}=1;
258             }
259             }
260              
261             # deallocates all the vector entries
262             sub free
263             {
264 5     5 0 6 my $self = shift;
265 5         4 %{$self}=();
  5         12  
266 5         3 undef %{$self};
  5         13  
267             }
268              
269             1;
270             __END__