#!perl -T use warnings; use strict; use Test::More tests => 14; use lib 'lib'; use Math::Function::Roots qw(bisection epsilon last_iter max_iter); epsilon( 0 ); is( epsilon(), 0, "epsilon: set/get" ); epsilon( -1 ); is( epsilon(), 0, "epsilon: minimum" ); ok( bisection( sub{ shift() + 1 }, -5, 10 ) eq -1, "bisection: linear equation" ); is( last_iter(), 54 ); # Root of f(x) = x+1 should be -1 ok( bisection( sub{ my $x = shift; $x**2 - 25}, -10, -1 ) eq -5, "bisection: negative root of x**2-25"); max_iter( 5 ); is( max_iter(), 5, "max_iter: set/get"); { $SIG{__WARN__} = sub {}; bisection( sub{ my $x = shift; $x**2 - 25}, -10, -1 ); $SIG{__WARN__} = ''; } is( last_iter(), 5 ); # shouldn't execute with bad a/b eval { bisection( sub {shift()}, 1, 2 ) }; like( $@, qr/^Bad range/, "bisection: bad range" ); # test finding perfect exit value is( bisection( sub{ shift() - 1}, 0, 4 ), 1, "bisection: perfect exit"); is( last_iter(), 2, "perfect exit takes 2 iterations"); # Test standard use with normal epsilon max_iter(50_000); my $e_test = .0001; cmp_ok( abs( bisection( sub{ 2*shift()+2 }, -10, 10, epsilon => $e_test ) + 1 ), '<=', $e_test, "normal bisection" ); # These two test should have the same answer, testing the two ways # of setting epsilon, global and local epsilon( $e_test ); cmp_ok( abs( bisection( sub{ 2*shift()+2 }, -10, 10 ) + 1 ), '<=', $e_test, "normal bisection" ); # Same as the above max_iter test, just testing the other # way max_iter can be set { $SIG{__WARN__} = sub {}; bisection( sub{ my $x = shift; $x**2 - 25}, -10, -1, max_iter => 5 ); $SIG{__WARN__} = ''; } is( last_iter(), 5 ); # The global max_iter should not have been touched is( max_iter(), 50_000, "global max_iter unchanged" ); TODO: { local $TODO = "Would like to handle sub references as below with the same prototype as above"; sub times2{ 2*shift(); } #Need to be commented out because prototype checking happens at compile time #is( bisection( \×2, -5, 5 ), 0, "sub reference test"); my $ref = sub {2*shift()}; #is( bisection( $ref, -5, 5 ), 0, "sub ref 2"); $ref = \×2; #is( bisection( $ref, -5, 5 ), 0, "sub ref 3"); };