File Coverage

blib/lib/Statistics/SparseVector.pm
Criterion Covered Total %
statement 117 140 83.5
branch 21 28 75.0
condition 4 6 66.6
subroutine 22 27 81.4
pod 18 23 78.2
total 182 224 81.2


line stmt bran cond sub pod time code
1             package Statistics::SparseVector;
2              
3             ##---------------------------------------------------------------------------##
4             ## Author:
5             ## Hugo WL ter Doest terdoest@cs.utwente.nl
6             ## Description: module for sparse bitvectors
7             ## method names equal that of Bit::Vector
8             ##
9             ##---------------------------------------------------------------------------##
10             ## Copyright (C) 1998, 1999 Hugo WL ter Doest terdoest@cs.utwente.nl
11             ##
12             ## This library is free software; you can redistribute it and/or modify
13             ## it under the terms of the GNU General Public License as published by
14             ## the Free Software Foundation; either version 2 of the License, or
15             ## (at your option) any later version.
16             ##
17             ## This library is distributed in the hope that it will be useful,
18             ## but WITHOUT ANY WARRANTY; without even the implied warranty of
19             ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20             ## GNU General Public License for more details.
21             ##
22             ## You should have received a copy of the GNU Library General Public
23             ## License along with this program; if not, write to the Free Software
24             ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25             ##---------------------------------------------------------------------------##
26              
27              
28 4     4   664 use strict;
  4         8  
  4         145  
29 4         440 use vars qw($VERSION
30             @ISA
31             @EXPORT
32 4     4   22 @EXPORT_OK);
  4         8  
33             use overload
34 4         44 '++' => \&increment,
35             '=' => \&Clone,
36 4     4   7672 '""' => \&stringify;
  4         5131  
37             require Exporter;
38             require AutoLoader;
39              
40             @ISA = qw(Exporter AutoLoader);
41             # Items to export into callers namespace by default. Note: do not export
42             # names by default without a very good reason. Use EXPORT_OK instead.
43             # Do not simply export all your public functions/methods/constants.
44             @EXPORT = qw(
45            
46             );
47             $VERSION = '0.2';
48              
49              
50             # Preloaded methods go here.
51              
52             # necessary for overloading ""
53             # in turn required by Data::Dumper that wants to stringify variables
54             sub stringify {
55 0     0 0 0 my($self) = @_;
56              
57 0         0 return($self);
58             }
59              
60              
61             # create a new bitvector
62             # all bits are `off'
63             sub new {
64 2305     2305 1 3329 my($this, $n) = @_;
65              
66             # for calling $self->new($someth):
67 2305   33     8501 my $class = ref($this) || $this;
68 2305         3470 my $self = {};
69 2305         3716 bless $self, $class;
70 2305         5367 $self->{N} = $n;
71             # $self->{VECTOR} = {};
72 2305         4599 return($self);
73             }
74              
75              
76             # create a copy of a bitvector and return it
77             sub Clone {
78 4     4 1 4 my($self) = @_;
79              
80 4         5 my($new);
81              
82 4         9 $new = Statistics::SparseVector->new($self->{N});
83 4         7 bless $new, ref($self);
84 4         5 for (keys %{$self->{VECTOR}}) {
  4         17  
85 17         34 $new->{VECTOR}{$_} = $self->{VECTOR}{$_};
86             }
87 4         9 return($new);
88             }
89              
90              
91             # is called right before Perl destroys a bitvector
92             # this happens automatically if a vector has zero references
93             sub DESTROY {
94 1798     1798   6613 my($self) = @_;
95             }
96              
97              
98             # creates a new vector from a bitstring
99             # checks for whitespace separators
100             sub new_vec {
101 2100     2100 0 3474 my($this, $n, $vector, $vectype) = @_;
102              
103 2100         2360 my($i,
104             @ints,
105             $int,
106             $self,
107             $sep);
108              
109 2100         2404 $sep = '';
110 2100 50       6962 if ($vector =~ /\s+/) {
111 2100         3178 $sep = '\s+';
112             }
113 2100         15895 @ints = split(/$sep/, $vector);
114 2100 50       5023 if ($#ints+1 != $n) {
115 0         0 die "inconsistent call to new_vec\n";
116             }
117 2100         5702 $self = $this->new($n);
118 2100         2721 $i = 0;
119 2100         4876 while (@ints) {
120 20300         28769 $int = shift(@ints);
121 20300 100       42095 if ($int > 0) {
122 11319 100       32231 $self->{VECTOR}{$i} = ($vectype eq "binary") ? 1 : $int;
123             }
124 20300         39494 $i++;
125             }
126 2100         7288 return($self);
127             }
128              
129              
130             # the value at position $col
131             sub weight {
132 1592781     1592781 0 2191303 my($self, $col) = @_;
133              
134 1592781         4307033 return($self->{VECTOR}{$col});
135             }
136              
137              
138             # we assume a bit is `on' if its value is defined
139             sub bit_test {
140 602990     602990 1 809290 my($self, $i) = @_;
141              
142 602990         2117036 return(defined($self->{VECTOR}{$i}));
143             }
144              
145              
146             # turning off a bit is making its value undefined
147             sub Bit_Off {
148 0     0 1 0 my($self, $i) = @_;
149              
150 0         0 undef $self->{VECTOR}{$i};
151             }
152              
153              
154             # turns on a bit
155             sub Bit_On {
156 2     2 1 9 my($self, $i) = @_;
157              
158 2         8 $self->{VECTOR}{$i} = 1;
159             }
160              
161              
162             # increment integer at position $i by one
163             sub Inc {
164 0     0 1 0 my($self, $i) = @_;
165              
166 0         0 $self->{VECTOR}{$i}++;
167             }
168              
169              
170             # flips a bit, i.e. makes it undef if it is defined,
171             # and makes it defined if it is undefined
172             sub bit_flip {
173 7306     7306 1 9555 my($self, $i) = @_;
174              
175 7306 100       14341 if (defined($self->{VECTOR}{$i})) {
176 3600         10210 undef $self->{VECTOR}{$i};
177             }
178             else {
179 3706         10745 $self->{VECTOR}{$i} = 1;
180             }
181             }
182              
183              
184             # increases the integer value of the bitvector by one
185             sub increment {
186 77952     77952 1 109011 my($self) = @_;
187              
188 77952         84510 my($carry, $i);
189              
190 77952         86271 $carry = 0;
191 77952         84074 $i = 0;
192             do {
193 155869 100       331953 if (defined($self->{VECTOR}{$i})) {
194 77934         116336 undef $self->{VECTOR}{$i};
195 77934         94022 $carry = 1;
196             }
197             else {
198 77935         116684 $self->{VECTOR}{$i} = 1;
199 77935         89564 $carry = 0;
200             }
201 155869         796118 $i++;
202 77952   100     84450 } until (($carry == 0) || ($i == $self->{N}));
203             }
204              
205              
206             # fills the set
207             sub Fill {
208 16     16 1 27 my($self) = @_;
209              
210 16         27 my $i;
211              
212 16         58 for ($i = 0; $i < $self->{N}; $i++) {
213 160         573 $self->{VECTOR}{$i} = 1;
214             }
215             }
216              
217              
218             # clears the vector
219             sub Empty {
220 16     16 1 29 my($self) = @_;
221            
222 16         77 undef $self->{VECTOR};
223             }
224              
225              
226             # returns a bitstring
227             sub to_Bin {
228 2533     2533 1 3425 my($self, $sep) = @_;
229              
230 2533         6291 my($s, $i);
231              
232 2533         3784 $s = "";
233 2533         7064 for ($i = 0; $i < $self->{N}; $i++) {
234 553500 100       1152997 if (defined($self->{VECTOR}{$i})) {
235 16944         55382 $s = "1$sep" . $s;
236             }
237             else {
238 536556         2125666 $s = "0$sep" . $s;
239             }
240             }
241 2533         9842 return($s);
242             }
243              
244              
245             # returns a bitstring
246             sub to_Int {
247 0     0 0 0 my($self) = @_;
248              
249 0         0 my($s, $i);
250              
251 0         0 $s = "";
252 0         0 for ($i = 0; $i < $self->{N}; $i++) {
253 0 0       0 if (defined($self->{VECTOR}{$i})) {
254 0         0 $s .= "$self->{VECTOR}{$i} ";
255             }
256             else {
257 0         0 $s .= "0 ";
258             }
259             }
260 0         0 return($s);
261             }
262              
263              
264             # returns a comma-separated list of features that are on
265             sub to_Enum {
266 2     2 1 11 my($self) = @_;
267              
268 2         3 return(join(',', keys(%{$self->{VECTOR}})));
  2         9  
269             }
270              
271              
272             # expects a comma-separated list of numbers
273             sub new_Enum {
274 0     0 1 0 my($this, $n, $s) = @_;
275              
276 0         0 my($self);
277              
278 0         0 $self = $this->new($n);
279 0         0 for (split(/,/,$s)) {
280 0         0 $self->{VECTOR}{$_} = 1
281             }
282 0         0 return($self);
283             }
284              
285              
286             # returns the length of the vector
287             sub Size {
288 264     264 1 412 my($self) = @_;
289              
290 264         1390 return($self->{N});
291             }
292              
293              
294             # NOTA BENE: THIS ROUTINE HAS BUGS
295             # $len1 >= 0, $len2 >= 0, $vec2->Size() >= $off2 >= 0
296             # $vec1->Size() >= $off1 >= 0
297             # $vec1 may be undefined
298             # $len1 + $off1 < $vec->Size()
299             sub Interval_Substitute {
300 4     4 0 8 my($vec2, $vec1, $off2, $len2, $off1, $len1) = @_;
301              
302 4         4 my($i,
303             $oldvec2);
304              
305             # save $vec2 in $oldvec2
306 4         10 $oldvec2 = $vec2->Clone();
307             # determine the new length for $vec2
308 4 100       8 if ($off2 == $vec2->Size()) {
309             # we are appending bits from source $vec1
310 2         4 $vec2->{N} += $len1;
311             }
312             else {
313             # we are inserting bits from $vec1
314 2         3 $vec2->{N} += $len1 - $len2;
315             }
316             # target $vec2 changes only from $off2
317             # copy the new bits from the source $vec1
318 4 50       10 if (defined($vec1)) { # we have source bits
319 4         12 for ($i = $off2; $i < $off2 + $len1; $i++) {
320 14 100       33 if (defined($vec1->{VECTOR}{$i - $off2 + $off1})) {
321 3         12 $vec2->{VECTOR}{$i} = $vec1->{VECTOR}{$i - $off2 + $off1};
322             }
323             else {
324 11         33 undef $vec2->{VECTOR}{$i};
325             }
326             }
327             }
328             # append the rest of $oldvec2
329             # index $i runs for $oldvec2, we correct for $vec2
330 4         12 for ($i = $off2 + $len2; $i < $oldvec2->{N}; $i++) {
331 1 50       4 if (defined($oldvec2->{VECTOR}{$i})) {
332 1         4 $vec2->{VECTOR}{$i-$len2+$len1} = $oldvec2->{VECTOR}{$i};
333             }
334             else {
335 0         0 undef $vec2->{VECTOR}{$i-$len2+$len1};
336             }
337             }
338 4         7 undef $oldvec2;
339             # print "$vec2->to_Bin()\n"
340             }
341              
342              
343             # removes a column from the vector
344             sub delete_column {
345 2000     2000 1 2228 my($self, $col) = @_;
346              
347 2000         1994 my($i);
348              
349 2000         4339 for ($i = 0; $i < $self->{N} - 1; $i++) {
350 26800 50       70435 if ($i >= $col) {
351 0         0 $self->{VECTOR}{$i} = $self->{VECTOR}{$i + 1};
352             }
353             }
354 2000         3181 undef $self->{VECTOR}{$self->{N}-1};
355 2000         6140 $self->{N}--;
356             }
357              
358              
359             sub insert_column {
360 2800     2800 1 3463 my($self, $pos, $val) = @_;
361              
362 2800         2499 my($i);
363              
364 2800         3182 $self->{N}++;
365 2800         6019 for ($i = $self->{N}-1; $i > $pos; $i--) {
366 34700         91587 $self->{VECTOR}{$i} = $self->{VECTOR}{$i - 1};
367             }
368 2800         10855 $self->{VECTOR}{$pos} = $val;
369             }
370              
371              
372             # returns an array of indices of set bits
373             sub indices {
374 235316     235316 1 300476 my($self) = @_;
375              
376 235316         261777 return(grep(defined($self->{VECTOR}{$_}), keys(%{$self->{VECTOR}})));
  235316         1866352  
377             # return(keys(%{$self->{VECTOR}}));
378             }
379              
380              
381             # the sum of the values
382             sub Norm {
383 966870     966870 1 1144384 my($self) = @_;
384              
385 966870         941398 my($n);
386              
387 966870         986094 $n = 0;
388 966870         1017520 for (values(%{$self->{VECTOR}})) {
  966870         2481856  
389 11527063 100       20452743 if (defined($_)) {
390 6588829         8700459 $n += $_;
391             }
392             }
393 966870         3046926 return($n);
394             }
395              
396              
397             # Autoload methods go after =cut, and are processed by the autosplit program.
398              
399             1;
400              
401             __END__