File Coverage

blib/lib/Math/PhaseOnlyCorrelation.pm
Criterion Covered Total %
statement 72 72 100.0
branch 8 8 100.0
condition n/a
subroutine 15 15 100.0
pod 2 2 100.0
total 97 97 100.0


line stmt bran cond sub pod time code
1             package Math::PhaseOnlyCorrelation;
2              
3 6     6   44826 use warnings;
  6         14  
  6         192  
4 6     6   28 use strict;
  6         11  
  6         158  
5 6     6   28 use Carp;
  6         14  
  6         503  
6 6     6   32 use Exporter;
  6         10  
  6         178  
7 6     6   5086 use Math::FFT;
  6         29761  
  6         262  
8 6     6   7198 use List::MoreUtils qw/mesh/;
  6         8093  
  6         789  
9              
10 6     6   43 use vars qw/$VERSION @ISA @EXPORT_OK/;
  6         9  
  6         474  
11              
12             BEGIN {
13 6     6   16 $VERSION = '0.06';
14 6         81 @ISA = qw{Exporter};
15 6         4451 @EXPORT_OK = qw{poc poc_without_fft};
16             }
17              
18             sub poc_without_fft {
19 8     8 1 25696 my ( $f, $g ) = @_;
20              
21 8 100       52 croak 'Both of length of array must be equal.' if ( $#$f != $#$g );
22 7         31 return _poc( $f, $g, $#$f );
23             }
24              
25             sub poc {
26 5     5 1 18001 my ( $ref_f, $ref_g ) = @_;
27              
28 5         6 my @f = @{$ref_f};
  5         11  
29 5         9 my @g = @{$ref_g};
  5         12  
30              
31 5         13 my ( $length, $f, $g ) = _adjust_array_length( \@f, \@g );
32 5         21 my $image_array = _get_zero_array($length);
33 5         42 @f = mesh( @$f, @$image_array );
34 5         29 @g = mesh( @$g, @$image_array );
35              
36 5         29 my $f_fft = Math::FFT->new( \@f );
37 5         129 my $g_fft = Math::FFT->new( \@g );
38              
39 5         77 my $result = poc_without_fft( $f_fft->cdft(), $g_fft->cdft() );
40 4         15 my $result_fft = Math::FFT->new($result);
41              
42 4         88 return $result_fft->invcdft($result);
43             }
44              
45             sub _poc {
46 7     7   16 my ( $f, $g, $length ) = @_;
47              
48 7         28 my $result;
49 7         24 for ( my $i = 0 ; $i <= $length ; $i += 2 ) {
50 56         256 my $f_abs =
51             sqrt( $f->[$i] * $f->[$i] + $f->[ $i + 1 ] * $f->[ $i + 1 ] );
52 56         108 my $g_abs =
53             sqrt( $g->[$i] * $g->[$i] + $g->[ $i + 1 ] * $g->[ $i + 1 ] );
54 56         75 my $f_real = $f->[$i] / $f_abs;
55 56         67 my $f_image = $f->[ $i + 1 ] / $f_abs;
56 56         66 my $g_real = $g->[$i] / $g_abs;
57 56         74 my $g_image = $g->[ $i + 1 ] / $g_abs;
58 56         102 $result->[$i] = ( $f_real * $g_real + $f_image * $g_image );
59 56         176 $result->[ $i + 1 ] = ( $f_image * $g_real - $f_real * $g_image );
60             }
61 7         21 return $result;
62             }
63              
64             sub _get_zero_array {
65 9     9   2357 my $length = shift;
66              
67 9 100       55 croak "$!" if $length <= -1;
68              
69 8         9 my $array;
70 8         44 $array->[$_] = 0 for 0 .. $length;
71 8         19 return $array;
72             }
73              
74             sub _adjust_array_length {
75 10     10   11602 my ( $array1, $array2 ) = @_;
76              
77 10         17 my $length = -1;
78 10 100       41 if ( $#$array1 == $#$array2 ) {
    100          
79 5         31 $length = $#$array1;
80             }
81             elsif ( $#$array1 > $#$array2 ) {
82 2         5 ( $length, $array2 ) = _adjust_array( $array1, $array2 );
83             }
84             else {
85 3         12 ( $length, $array1 ) = _adjust_array( $array2, $array1 );
86             }
87              
88 10         29 return ( $length, $array1, $array2 );
89             }
90              
91             sub _adjust_array {
92 5     5   9 my ( $longer, $shorter ) = @_;
93 5         24 return ( $#$longer, _zero_fill( $shorter, $#$longer ) );
94             }
95              
96             sub _zero_fill {
97 7     7   997 my ( $array, $max ) = @_;
98              
99 7         11 my @array = @{$array};
  7         15  
100 7         36 $array[$_] = 0 for ( $#$array + 1 ) .. ($max);
101              
102 7         22 return \@array;
103             }
104             1;
105              
106             __END__