File Coverage

blib/lib/Tie/VecArray.pm
Criterion Covered Total %
statement 58 63 92.0
branch 8 10 80.0
condition n/a
subroutine 18 19 94.7
pod 1 1 100.0
total 85 93 91.4


line stmt bran cond sub pod time code
1             package Tie::VecArray;
2              
3 1     1   851 use strict;
  1         2  
  1         44  
4 1     1   6 use vars qw($VERSION);
  1         2  
  1         66  
5             $VERSION = '0.03';
6              
7 1     1   1002 use POSIX qw(ceil);
  1         8508  
  1         6  
8              
9 1     1   1307 use constant BITS => 0;
  1         3  
  1         74  
10 1     1   5 use constant VEC => 1;
  1         2  
  1         44  
11 1     1   5 use constant SIZE => 2;
  1         2  
  1         40  
12 1     1   6 use base qw(Tie::Array);
  1         1  
  1         983  
13              
14             # Let's not require Filter::cpp.
15 1     1   1435 BEGIN { eval 'use Filter::cpp' }
  1     1   622  
  0         0  
  0         0  
16             sub _IDX2BYTES {
17 1     1   1 my Tie::VecArray $self = shift;
18 1         2 my $idx = shift;
19             #define _IDX2BYTES($self, $idx) \
20 1         5 ceil($idx * ($self->[BITS]/8))
21             }
22              
23             sub _BYTES2IDX {
24 2     2   2 my Tie::VecArray $self = shift;
25 2         4 my $bytes = shift;
26             #define _BYES2IDX($self, $bytes) \
27 2         25 ceil($bytes * 8 / $self->[BITS])
28             }
29              
30              
31             =pod
32              
33             =head1 NAME
34              
35             Tie::VecArray - An array interface to a bit vector.
36              
37              
38             =head1 SYNOPSIS
39              
40             require Tie::VecArray;
41            
42             $vector = '';
43             vec($vector, 0, 32) = 33488897;
44              
45             # Tie the vector to an array as 8 bits.
46             $obj = tie @array, 'Tie::VecArray', 8, $vector;
47              
48             @array[0..3] = qw(1 255 256 -1);
49              
50             # SURPRISE! Its 1, 255, 0, 255!
51             print @array[0..3];
52              
53             # Look at the same vector as a 32 bit vector.
54             $obj->bits(32);
55              
56             # Back to 33488897
57             print $array[0];
58              
59              
60             =head1 DESCRIPTION
61              
62             This module implements an array interface to a bit vector.
63              
64             =head2 Method
65              
66             =over 4
67              
68             =item B
69              
70             $vec_obj = tie(@array, 'Tie::VecArray', $bits);
71             $vec_obj = tie(@array, 'Tie::VecArray', $bits, $vec);
72              
73             Creates a new @array tied to a bit vector. $bits is the number of
74             bits which will be passed to C to interpret the vector.
75              
76             If $vec is given that will be used as the bit vector, otherwise the
77             vector will start out empty.
78              
79             =cut
80              
81              
82             sub TIEARRAY {
83 2     2   470 my($class, $bits, $vec) = @_;
84              
85 1     1   6 no strict 'refs';
  1         2  
  1         698  
86 2         7 my Tie::VecArray $self = bless [], $class;
87              
88 2 50       8 $vec = '' unless defined $vec;
89              
90 2         10 $self->[BITS] = $bits;
91 2         3 $self->[VEC] = $vec;
92 2         8 $self->[SIZE] = _BYTES2IDX($self, length $vec);
93              
94 2         9 return $self;
95             }
96              
97              
98             =pod
99              
100             =item B
101              
102             $bits = $vec_obj->bits;
103             $vec_obj->bits($bits);
104              
105             Get/set the bit size we'll use to interpret the vector.
106              
107             When setting the bit size the length of the array might be ambiguous.
108             (For instance, going from a one bit vector with five entries to a two
109             bit vector... do you have two or three entries?) The length of the
110             array will always round up. This can cause odd things to happen.
111             Consider:
112              
113             $vec_obj = tie @vec, 'Tie::VecArray', 1;
114              
115             # A one bit vector with 5 entries.
116             @vec[0..4] = (1) x 5;
117              
118             # prints a size of 5, as expected.
119             print scalar @vec;
120              
121             # Switch to two bit interpretation.
122             $vec_obj->bits(2);
123              
124             # This returns 3 since it will round up.
125             print scalar @vec;
126              
127             # Switch back to one bit.
128             $vec_obj->bits(1);
129              
130             # Whoops, 6!
131             print scalar @vec;
132              
133             =cut
134              
135             sub bits {
136 4     4 1 365 my Tie::VecArray $self = shift;
137 4 100       12 if(@_) {
138 3         4 my $bits = shift;
139 3         13 $self->[SIZE] = ceil($self->[SIZE] * $self->[BITS] / $bits);
140 3         7 $self->[BITS] = $bits;
141             }
142 4         14 return $self->[BITS];
143             }
144              
145              
146             #'#
147              
148             sub FETCH {
149 3     3   34 my Tie::VecArray $self = shift;
150 3         12 return vec($self->[VEC], $_[0], $self->[BITS]);
151             }
152              
153             sub STORE {
154 7     7   21 my Tie::VecArray $self = shift;
155 7 100       21 $self->[SIZE] = $_[0] + 1 if $self->[SIZE] < $_[0] + 1;
156 7         35 return vec($self->[VEC], $_[0], $self->[BITS]) = $_[1];
157             }
158              
159             sub FETCHSIZE {
160 12     12   689 my Tie::VecArray $self = shift;
161 12         50 return $self->[SIZE];
162             }
163              
164             sub STORESIZE {
165 2     2   7 my Tie::VecArray $self = shift;
166 2         2 my $new_size = shift;
167 2 100       8 if( $self->[SIZE] > $new_size ) {
168             # clip the vector down to size.
169 1         3 my $new_length = _IDX2BYTES($self, $new_size);
170 1 50       7 substr($self->[VEC], $new_length) = '' if
171             $new_length < length $self->[VEC];
172             }
173            
174 2         7 $self->[SIZE] = $new_size;
175             }
176              
177             sub CLEAR {
178 0     0     my Tie::VecArray $self = shift;
179 0           $self->[VEC] = '';
180 0           $self->[SIZE] = 0;
181             }
182              
183              
184             =back
185              
186             =pod
187              
188             =head1 CAVEATS
189              
190             =over 4
191              
192             =item B
193              
194             Due to the sluggishness of perl's tie interface, this module is about
195             8 times slower than using direct calls with C. Suck. If you
196             care alot about speed, don't use this module. If you care about easy
197             bit vector access or low memory usage, use this module.
198              
199             =item B
200              
201             $vec_array[$i][$j] = $num; isn't going to work. A future class will
202             cover this possibility.
203              
204             =head1 AUTHOR
205              
206             Michael G Schwern
207              
208              
209             =head1 SEE ALSO
210              
211             L, L
212              
213             =cut
214              
215             1;