diff --git a/Makefile.PL b/Makefile.PL index e7a4b7a..e8b512b 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -18,8 +18,6 @@ WriteMakefile( 'Test::More' => 0, 'Test::FailWarnings' => 0, 'Test::Exception' => 0, - 'Module::Runtime' => 0, - 'Module::Pluggable' => 0, 'Carp' => 0, 'List::MoreUtils' => 0, 'List::Util' => 0, diff --git a/lib/Math/Function/Interpolator.pm b/lib/Math/Function/Interpolator.pm index e4742cf..a5d8064 100644 --- a/lib/Math/Function/Interpolator.pm +++ b/lib/Math/Function/Interpolator.pm @@ -11,13 +11,17 @@ use Number::Closest::XS qw(find_closest_numbers_around); use List::MoreUtils qw(pairwise indexes); use List::Util qw(min max); +use Math::Function::Interpolator::Linear; +use Math::Function::Interpolator::Quadratic; +use Math::Function::Interpolator::Cubic; + =head1 NAME Math::Function::Interpolator - Interpolation made easy =head1 VERSION -Version 0.08 +Version 0.09 =head1 SYNOPSIS @@ -45,7 +49,7 @@ HashRef of points for interpolations =cut -our $VERSION = '0.08'; +our $VERSION = '0.09'; =head1 METHODS @@ -72,36 +76,15 @@ sub new { my $self = { _points => $params_ref{'points'}, - _classes_loaded => 0 + _linear_obj => 0, + _cubic_obj => 0, + _quadratic_obj => 0 }; my $obj = bless $self, $class; - if ( $class =~/Interpolator$/i ){ - # Load all interpolator classes when only made object from main - # Interpolator classes - $obj->_load_interpolator_classes(); - } - return $obj; } -sub _load_interpolator_classes { - my ( $self ) = @_; - - use Module::Runtime; - use Module::Pluggable - sub_name => 'interpolate_methods', - search_path => ['Math::Function::Interpolator'], - ; - - my @modules = $self->interpolate_methods(); - foreach my $module (@modules) { - Module::Runtime::require_module($module); - } - $self->{'_classes_loaded'} = 1; - return 1; -} - =head2 points points @@ -121,9 +104,14 @@ This method do the linear interpolation. It solves for point_y linearly given po sub linear { my ( $self, $x ) = @_; - return Math::Function::Interpolator::Linear->new( - points => $self->points - )->linear( $x ); + my $linear_obj = $self->{'_linear_obj'}; + if ( !$linear_obj ){ + $linear_obj = Math::Function::Interpolator::Linear->new( + points => $self->points + ); + $self->{'_linear_obj'} = $linear_obj; + } + return $linear_obj->linear( $x ); } =head2 quadratic @@ -134,9 +122,14 @@ This method do the quadratic interpolation. It solves the interpolated_y value g sub quadratic { my ( $self, $x ) = @_; - return Math::Function::Interpolator::Quadratic->new( - points => $self->points - )->quadratic( $x ); + my $quadratic_obj = $self->{'_quadratic_obj'}; + if ( !$quadratic_obj ) { + $quadratic_obj = Math::Function::Interpolator::Quadratic->new( + points => $self->points + ); + $self->{'_quadratic_obj'} = $quadratic_obj; + } + return $quadratic_obj->quadratic( $x ); } =head2 cubic @@ -147,9 +140,14 @@ This method do the cubic interpolation. It solves the interpolated_y given point sub cubic { my ( $self, $x ) = @_; - return Math::Function::Interpolator::Cubic->new( - points => $self->points - )->cubic( $x ); + my $cubic_obj = $self->{'_cubic_obj'}; + if ( !$cubic_obj ) { + $cubic_obj = Math::Function::Interpolator::Cubic->new( + points => $self->points + ); + $self->{'_cubic_obj'} = $cubic_obj; + } + return $cubic_obj->cubic( $x ); } =head2 closest_three_points diff --git a/lib/Math/Function/Interpolator/Cubic.pm b/lib/Math/Function/Interpolator/Cubic.pm index 59c2b10..5dd5610 100644 --- a/lib/Math/Function/Interpolator/Cubic.pm +++ b/lib/Math/Function/Interpolator/Cubic.pm @@ -4,9 +4,9 @@ use 5.006; use strict; use warnings FATAL => 'all'; -our $VERSION = '0.03'; +our $VERSION = '0.04'; -use parent 'Math::Function::Interpolator'; +our @ISA = qw(Math::Function::Interpolator); use Carp qw(confess); use List::MoreUtils qw(pairwise indexes); @@ -41,13 +41,17 @@ HashRef of points for interpolations =cut sub _sorted_Xs { - my ($self) = @_; - return [ sort { $a <=> $b } keys %{ $self->points } ]; + my ( $self ) = @_; + return $self->{'_sorted_Xs'} if $self->{'_sorted_Xs'}; + $self->{'_sorted_Xs'} = [ sort { $a <=> $b } keys %{ $self->points } ]; + return $self->{'_sorted_Xs'}; } sub _spline_points { my ($self) = @_; + return $self->{'_spline_points'} if $self->{'_spline_points'}; + my $points_ref = $self->points; my $Xs = $self->_sorted_Xs; my @Ys = map { $points_ref->{$_} } @$Xs; @@ -81,7 +85,9 @@ sub _spline_points { my %y_2derivative_combined = pairwise { $a => $b } @$Xs, @y_2derivative; - return \%y_2derivative_combined; + $self->{'_spline_points'} = \%y_2derivative_combined; + + return $self->{'_spline_points'}; } sub _extrapolate_spline { diff --git a/lib/Math/Function/Interpolator/Linear.pm b/lib/Math/Function/Interpolator/Linear.pm index caec316..eee61fb 100644 --- a/lib/Math/Function/Interpolator/Linear.pm +++ b/lib/Math/Function/Interpolator/Linear.pm @@ -4,9 +4,9 @@ use 5.006; use strict; use warnings FATAL => 'all'; -use parent 'Math::Function::Interpolator'; +our @ISA = qw(Math::Function::Interpolator); -our $VERSION = '0.03'; +our $VERSION = '0.04'; use Carp qw(confess); use Number::Closest::XS qw(find_closest_numbers_around); diff --git a/lib/Math/Function/Interpolator/Quadratic.pm b/lib/Math/Function/Interpolator/Quadratic.pm index 19469af..bdb12c5 100644 --- a/lib/Math/Function/Interpolator/Quadratic.pm +++ b/lib/Math/Function/Interpolator/Quadratic.pm @@ -4,14 +4,13 @@ use 5.006; use strict; use warnings FATAL => 'all'; -our $VERSION = '0.04'; +our $VERSION = '0.05'; -use parent 'Math::Function::Interpolator'; +our @ISA = qw(Math::Function::Interpolator); use Carp qw(confess); use Math::Cephes::Matrix qw(mat); use Scalar::Util qw(looks_like_number); -use Try::Tiny; =head1 NAME @@ -66,8 +65,8 @@ sub quadratic { my $y = [ map { $ap->{$_} } @points ]; my $solution; - try { $solution = $abc->simq($y) } - catch { confess 'Insoluble matrix: ' . $_; }; + eval { $solution = $abc->simq($y) }; + confess 'Insoluble matrix: ' . $_ if $@; my ( $a, $b, $c ) = @$solution; return ( $a * ( $x**2 ) + $b * $x + $c );