File Coverage

blib/lib/Math/Wavelet/Haar.pm
Criterion Covered Total %
statement 77 77 100.0
branch 9 16 56.2
condition n/a
subroutine 9 9 100.0
pod 4 5 80.0
total 99 107 92.5


line stmt bran cond sub pod time code
1             package Math::Wavelet::Haar;
2              
3 1     1   20739 use 5.005005;
  1         3  
  1         30  
4 1     1   5 use strict;
  1         1  
  1         29  
5 1     1   4 use warnings;
  1         5  
  1         34  
6              
7 1     1   1093 use Storable qw(dclone);
  1         3760  
  1         1082  
8              
9             require Exporter;
10              
11             our @ISA = qw(Exporter);
12              
13             # Items to export into callers namespace by default. Note: do not export
14             # names by default without a very good reason. Use EXPORT_OK instead.
15             # Do not simply export all your public functions/methods/constants.
16              
17             # This allows declaration use Wavelet::Haar ':all';
18             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
19             # will save memory.
20             our %EXPORT_TAGS = ( 'all' => [ qw(
21             transform1D
22             transform2D
23             detransform1D
24             detransform2D
25             ) ] );
26              
27             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
28              
29             our @EXPORT = qw(
30             );
31              
32             our $VERSION = '0.06';
33              
34             # Preloaded methods go here.
35              
36             sub transform1D
37             {
38 18     18 1 775 my @input=@_;
39 18 50       39 return if (!is_power2(scalar(@input)));
40 18         52 my @output=(0)x@_;
41              
42 18         27 my $length=@input>>1;
43            
44 18         27 for (; ; $length >>= 1) {
45             #length=2^n, WITH DECREASING n
46            
47 38         75 for my $i (0..$length-1)
48             {
49 62         117 my $sum = $input[$i*2]+$input[$i*2+1];
50 62         105 my $difference = $input[$i*2]-$input[$i*2+1];
51 62         70 $output[$i] = $sum;
52 62         132 $output[$length+$i] = $difference;
53             }
54 38 100       142 return @output if ($length == 1) ;
55            
56             #//Swap arrays to do next iteration
57 20         101 @input[0..$length*2]=@output[0..$length*2];
58             }
59             }
60              
61             sub is_power2
62             {
63 40 50   40 0 246 $_[0] && ($_[0]-1&$_[0] ) == 0
64             }
65              
66             sub transform2D
67             {
68 2     2 1 3137 my @input = @{dclone(\@_)};
  2         211  
69              
70 2         8 my $length = @_;
71            
72 2         4 my $width = @{$input[0]};
  2         4  
73 2 50       8 return if (!is_power2($width));
74 2         9 for (1..$length-1)
75             {
76 6 50       9 return if (@{$input[$_]} != $width);
  6         25  
77             }
78            
79             #do the X direction
80 2         8 for (0..$length-1)
81             {
82 8         10 @{$input[$_]} = transform1D(@{$input[$_]});
  8         30  
  8         24  
83             }
84            
85 2         8 for my $i (0..$width-1)
86             {
87 8         15 my @col = map { $_->[$i] } @input;
  32         63  
88            
89 8         22 @col = transform1D(@col);
90            
91 8         21 for my $l (0..$#col)
92             {
93 32         64 $input[$l]->[$i] = $col[$l];
94             }
95             }
96            
97 2         13 return @input;
98             }
99              
100             sub detransform1D
101             {
102 18     18 1 2705 my @input=@_;
103 18 50       34 return if (!is_power2(scalar(@input)));
104 18         36 my @output=@input;
105              
106 18         25 my $length=1;
107            
108 18         41 for (; $length<=@input>>1; $length <<= 1)
109             {
110 38         117 for my $i (0..$length-1)
111             {
112 62         96 my $x = ($input[$i] + $input[$i+$length])/2;
113 62         83 my $y = ($input[$i] - $input[$i+$length])/2;
114 62         71 $output[$i*2] = $x;
115 62         120 $output[$i*2+1] = $y;
116             }
117             #//Swap arrays to do next iteration
118 38         131 @input = @output;
119             }
120            
121 18         59 return @input;
122             }
123              
124             sub detransform2D
125             {
126 2     2 1 2275 my @input = @{dclone(\@_)};
  2         173  
127 2         8 my $length = @_;
128            
129 2         4 my $width = @{$input[0]};
  2         5  
130 2 50       566 return if (!is_power2($width));
131 2         9 for (1..$length-1)
132             {
133 6 50       6 return if (@{$input[$_]} != $width);
  6         19  
134             }
135            
136             #do the X direction
137 2         6 for (0..$length-1)
138             {
139 8         10 @{$input[$_]} = detransform1D(@{$input[$_]});
  8         27  
  8         16  
140             }
141            
142 2         5 for my $i (0..$width-1)
143             {
144 8         12 my @col = map { $_->[$i] } @input;
  32         51  
145            
146 8         15 @col = detransform1D(@col);
147            
148 8         16 for my $l (0..$#col)
149             {
150 32         54 $input[$l]->[$i] = $col[$l];
151             }
152             }
153            
154 2         10 return @input;
155             }
156              
157             # Autoload methods go after =cut, and are processed by the autosplit program.
158              
159             1;
160             __END__