File Coverage

blib/lib/Math/Function/Interpolator.pm
Criterion Covered Total %
statement 72 73 98.6
branch 10 14 71.4
condition n/a
subroutine 16 16 100.0
pod 6 6 100.0
total 104 109 95.4


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