Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ Revision history for Math-Function-Interpolator
0.05 15/06/2014
method closest_three_points exported, could be usefull for the Mathmatician

0.06 18/06/2014
More intense test added to check module
1 change: 1 addition & 0 deletions MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ lib/Math/Function/Interpolator/Quadratic.pm
Makefile.PL
MANIFEST
README
t/02-intense_test.t
t/01-calculation.t
t/00-load.t
t/manifest.t
Expand Down
4 changes: 2 additions & 2 deletions lib/Math/Function/Interpolator.pm
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Math::Function::Interpolator - Interpolation made easy

=head1 VERSION

Version 0.05
Version 0.06

=head1 SYNOPSIS

Expand Down Expand Up @@ -54,7 +54,7 @@ HashRef of points for interpolations

=cut

our $VERSION = '0.05';
our $VERSION = '0.06';

# Automatically load all interpolate methods
has 'interpolate_classes' => (
Expand Down
142 changes: 142 additions & 0 deletions t/02-intense_test.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
use Test::More;
use Test::FailWarnings;
use Test::Exception;

use Math::Function::Interpolator;

my $interpolator = Math::Function::Interpolator->new(
points => {1=>2,2=>3,3=>4,4=>5,5=>6}
);

subtest "closest_three_points" => sub {
plan tests => 9;
my $o = Math::Function::Interpolator->new(points => {1 => 2});
my @points = (2, 3, 5, 1, 40, 89, 90, 99, 91);
my ($first, $second, $third) = $o->closest_three_points(6, \@points);
is($first, 5, "first number is correct for seek in_between(@points)");
is($second, 40, "second number is correct for seek in_between(@points)");
is($third, 89, "third number is correct for seek in_between(@points)");
($first, $second, $third) = $o->closest_three_points(0.2, \@points);
is($first, 1, "first number is correct for seek smaller than min(@points)");
is($second, 2, "second number is correct for seek smaller than min(@points)");
is($third, 3, "third number is correct for seek smaller than min(@points)");
($first, $second, $third) = $o->closest_three_points(100, \@points);
is($first, 90, "first number is correct for seek larger than max(@points)");
is($second, 91, "second number is correct for seek larger than max(@points)");
is($third, 99, "third number is correct for seek larger than max(@points)");
};

subtest "general checks for linear" => sub {
plan tests => 4;
my $o;
lives_ok { $o = Math::Function::Interpolator->new(points => {2 => 3, 4 => 5.5}) } "can instantiate object with 2 points";
lives_ok { $o->linear(2.4) } "can linear given an X";
throws_ok { $o->linear('abc') } qr/point_x must be numeric/, "dies when X is not a number";
throws_ok { Math::Function::Interpolator->new(points => {2 => 3,})->linear(1) } qr/cannot interpolate with fewer than 2 data points/,
"cannot linear linear equation with one data point";
};

subtest "verify linear interpolation and extrapolation" => sub {
plan tests => 4;
my $o = Math::Function::Interpolator->new(
points => {
1 => 3,
2 => 4.5,
3 => 6
});
is($o->linear(2.4), 5.1, "correctly interpolate y given x=2.4");
is($o->linear(1.4), 3.6, "correctly interpolate y given x=1.4");
is($o->linear(3.5), 6.75, "correctly extrapolate y given x=3.6");
is($o->linear(0.5), 2.25, "correctly extrapolate y given x=0.5");
};

subtest "general checks for quadratic" => sub {
plan tests => 4;
my $o;
lives_ok { $o = Math::Function::Interpolator->new(points => {2 => 3, 4 => 5.5, 6 => 8}) } "can instantiate object with 3 points";
lives_ok { $o->quadratic(2.4) } "can quadratic given an X";
throws_ok { $o->quadratic('abc') } qr/point_x must be numeric/, "dies when X is not a number";
throws_ok { Math::Function::Interpolator->new(points => {2 => 3, 4 => 5})->quadratic(1) }
qr/cannot interpolate with fewer than 3 data points/,
"cannot solve quadratic equation with two data point";
};

subtest "verify quadratic interpolation and extrapolation" => sub {
plan tests => 2;
my $points = {
6 => 11,
2 => 3,
-2 => 19,
};
my $o = Math::Function::Interpolator->new(points => $points);
is($o->quadratic(2.4), 2.72, "correctly interpolate y given x=2.4");
$points->{4} = 7;
my $o_new = Math::Function::Interpolator->new(points => $points);
lives_ok { $o_new->quadratic(2.4) } "can solve quadratic equation with 4 data points ";
};

subtest "general checks for cubic" => sub {
plan tests => 4;
my $o;
lives_ok { $o = Math::Function::Interpolator->new(points => {2 => 3, 4 => 5.5, 6 => 8, 7 => 9, 10 => 14}) } "can instantiate object with 5 points";
lives_ok { $o->cubic(2.4) } "can cubic given an X";
throws_ok { $o->cubic('abc') } qr/point_x must be numeric/, "dies when X is not a number";
throws_ok { Math::Function::Interpolator->new(points => {2 => 3, 4 => 5, 2 => 6, 4 => 11})->cubic(1) }
qr/cannot interpolate with fewer than 5 data points/, "cannot cubic equation with four data point";
};

subtest "cubic interpolation compared to Bloomberg" => sub {
plan tests => 8;
my $points = {
95 => 0.2780,
97.5 => 0.2670,
100 => 0.2563,
102.5 => 0.2461,
105 => 0.2364
};
my $bb = {
96 => 0.2736,
97 => 0.2692,
98 => 0.2649,
99 => 0.2606,
100 => 0.2563,
101 => 0.2521,
102 => 0.2481,
103 => 0.2441,
104 => 0.2402
};

my $o = Math::Function::Interpolator->new(points => $points);
foreach my $num (96 .. 104) {
next if grep { $_ == $num } keys %$points;
my $test = $o->cubic($num);
my $diff = abs($test - $bb->{$num});
cmp_ok($diff, "<", 0.0001, "match Bloomberg's interpolation for moneyness[$num] on DAX");
}
};

subtest "cubic extrapolation" => sub {
plan tests => 6;
my $points = {
95 => 0.2780,
97.5 => 0.2670,
100 => 0.2563,
102.5 => 0.2461,
105 => 0.2364
};
my $o = Math::Function::Interpolator->new(points => $points);
lives_ok { $o->cubic(80) } "can extrapolate";
my $first = $o->cubic(94);
my $second = $o->cubic(93);
my $third = $o->cubic(90);
cmp_ok($first, "<", $second, "linear extrapolation. In this case, linear increment");
cmp_ok($second, "<", $third, "linear extrapolation. In this case, linear increment");
lives_ok { $o->cubic(110) } "can extrapolate";
$first = $o->cubic(106);
$second = $o->cubic(107);
$third = $o->cubic(110);
cmp_ok($first, ">", $second, "linear extrapolation. In this case, linear decrement");
cmp_ok($second, ">", $third, "linear extrapolation. In this case, linear decrement");
};

done_testing;