File Coverage

blib/lib/Math/Function/Interpolator.pm
Criterion Covered Total %
statement 75 76 98.6
branch 10 14 71.4
condition n/a
subroutine 18 18 100.0
pod 6 6 100.0
total 109 114 95.6


line stmt bran cond sub pod time code
1             package Math::Function::Interpolator;
2              
3 2     2   100323 use 5.006;
  2         5  
4 2     2   6 use strict;
  2         2  
  2         34  
5 2     2   5 use warnings FATAL => 'all';
  2         6  
  2         85  
6              
7 2     2   6 use Carp qw(confess);
  2         3  
  2         71  
8 2     2   7 use Scalar::Util qw(looks_like_number);
  2         6  
  2         59  
9              
10 2     2   752 use Number::Closest::XS qw(find_closest_numbers_around);
  2         896  
  2         89  
11 2     2   869 use List::MoreUtils qw(pairwise indexes);
  2         13065  
  2         9  
12 2     2   948 use List::Util qw(min max);
  2         2  
  2         146  
13              
14 2     2   652 use Math::Function::Interpolator::Linear;
  2         2  
  2         46  
15 2     2   617 use Math::Function::Interpolator::Quadratic;
  2         4  
  2         52  
16 2     2   667 use Math::Function::Interpolator::Cubic;
  2         3  
  2         841  
17              
18             =head1 NAME
19              
20             Math::Function::Interpolator - Interpolation made easy
21              
22             =head1 SYNOPSIS
23              
24             use Math::Function::Interpolator;
25              
26             my $interpolator = Math::Function::Interpolator->new(
27             points => {1=>2,2=>3,3=>4}
28             );
29              
30             $interpolator->linear(2.5);
31              
32             $interpolator->quadratic(2.5);
33              
34             $interpolator->cubic(2.5);
35              
36             =head1 DESCRIPTION
37              
38             Math::Function::Interpolator helps you to do the interpolation calculation with linear, quadratic and cubic methods.
39              
40             1. Linear method (needs more than 1 data point)
41             1. Quadratic method (needs more than 2 data points)
42             1. Cubic method, it's a Cubic Spline method (needs more than 4 data points)
43              
44             =head1 FIELDS
45              
46             =head2 points (REQUIRED)
47              
48             HashRef of points for interpolations
49              
50             =cut
51              
52             our $VERSION = '1.01';
53              
54             =head1 METHODS
55              
56             =head2 new
57              
58             New instance method
59              
60             =cut
61              
62             sub new { ## no critic (RequireArgUnpacking)
63 17     17 1 19636 my $class = shift;
64 17 50       46 my %params_ref = ref($_[0]) ? %{$_[0]} : @_;
  0         0  
65              
66             confess "points are required to do interpolation"
67 17 100       49 unless $params_ref{'points'};
68              
69             # We can't interpolate properly on undef values so make sure we know
70             # they are missing by removing them entirely.
71 16         17 my $points = $params_ref{points};
72             $params_ref{points} = {
73 56         74 map { $_ => $points->{$_} }
74 16         37 grep { defined $points->{$_} } keys %$points
  56         71  
75             };
76              
77             my $self = {
78 16         42 _points => $params_ref{'points'},
79             _linear_obj => 0,
80             _cubic_obj => 0,
81             _quadratic_obj => 0
82             };
83 16         21 my $obj = bless $self, $class;
84              
85 16         43 return $obj;
86             }
87              
88             =head2 points
89              
90             points
91              
92             =cut
93              
94             sub points {
95 43     43 1 37 my ($self) = @_;
96 43         119 return $self->{'_points'};
97             }
98              
99             =head2 linear
100              
101             This method do the linear interpolation. It solves for point_y linearly given point_x and an array of points.
102             This method needs more than 1 data point.
103              
104             =cut
105              
106             sub linear {
107 1     1 1 6 my ($self, $x) = @_;
108 1         3 my $linear_obj = $self->{'_linear_obj'};
109 1 50       4 if (!$linear_obj) {
110 1         7 $linear_obj = Math::Function::Interpolator::Linear->new(points => $self->points);
111 1         3 $self->{'_linear_obj'} = $linear_obj;
112             }
113 1         6 return $linear_obj->linear($x);
114             }
115              
116             =head2 quadratic
117              
118             This method do the quadratic interpolation. It solves the interpolated_y value given point_x with 3 data points.
119             This method needs more than 2 data point.
120              
121             =cut
122              
123             sub quadratic {
124 1     1 1 2 my ($self, $x) = @_;
125 1         2 my $quadratic_obj = $self->{'_quadratic_obj'};
126 1 50       3 if (!$quadratic_obj) {
127 1         3 $quadratic_obj = Math::Function::Interpolator::Quadratic->new(points => $self->points);
128 1         24 $self->{'_quadratic_obj'} = $quadratic_obj;
129             }
130 1         6 return $quadratic_obj->quadratic($x);
131             }
132              
133             =head2 cubic
134              
135             This method do the cubic interpolation. It solves the interpolated_y given point_x and a minimum of 5 data points.
136             This method needs more than 4 data point.
137              
138             =cut
139              
140             sub cubic {
141 1     1 1 2 my ($self, $x) = @_;
142 1         2 my $cubic_obj = $self->{'_cubic_obj'};
143 1 50       3 if (!$cubic_obj) {
144 1         3 $cubic_obj = Math::Function::Interpolator::Cubic->new(points => $self->points);
145 1         2 $self->{'_cubic_obj'} = $cubic_obj;
146             }
147 1         4 return $cubic_obj->cubic($x);
148             }
149              
150             =head2 closest_three_points
151              
152             Returns the the closest three points to the sought point.
153             The third point is chosen based on the point which is closer to mid point
154              
155             =cut
156              
157             sub closest_three_points {
158 7     7 1 2236 my ($self, $sought, $all_points) = @_;
159              
160 7         9 my @ap = sort { $a <=> $b } @{$all_points};
  74         72  
  7         20  
161 7         8 my $length = scalar @ap;
162              
163             my ($first, $second) =
164 7         6 @{find_closest_numbers_around($sought, $all_points, 2)};
  7         33  
165 7 100   42   49 my @indexes = indexes { $first == $_ or $second == $_ } @ap;
  42         96  
166 7 100       40 my $third_index =
167             (max(@indexes) < $length - 2) ? max(@indexes) + 1 : min(@indexes) - 1;
168 7         23 my @sorted = sort { $a <=> $b } ($first, $second, $ap[$third_index]);
  18         26  
169              
170 7         24 return @sorted;
171             }
172              
173             =head1 AUTHOR
174              
175             Binary.com, C<< >>
176              
177             =head1 BUGS
178              
179             Please report any bugs or feature requests to C, or through
180             the web interface at L. I will be notified, and then you'll
181             automatically be notified of progress on your bug as I make changes.
182              
183              
184             =head1 SUPPORT
185              
186             You can find documentation for this module with the perldoc command.
187              
188             perldoc Math::Function::Interpolator
189              
190              
191             You can also look for information at:
192              
193             =over 4
194              
195             =item * RT: CPAN's request tracker (report bugs here)
196              
197             L
198              
199             =item * AnnoCPAN: Annotated CPAN documentation
200              
201             L
202              
203             =item * CPAN Ratings
204              
205             L
206              
207             =item * Search CPAN
208              
209             L
210              
211             =back
212              
213              
214             =head1 ACKNOWLEDGEMENTS
215              
216             =cut
217              
218             1; # End of Math::Function::Interpolator