1 package Math
::GSL
::Test
;
3 use base
qw(DynaLoader);
7 use Math
::GSL
::Errno qw
/:all/;
8 use Math
::GSL
::Machine qw
/:all/;
9 use Math
::GSL
::Const qw
/:all/;
10 use Math
::GSL
::Sys qw
/gsl_nan gsl_isnan gsl_isinf/;
21 use constant GSL_IS_WINDOWS
=> ($^O
=~ /MSWin32/i) ?
1 : 0 ;
25 Math::GSL::Test - Assertions and such
30 use Math::GSL::Test qw/:all/;
31 ok_similar($x,$y, $msg, $eps);
42 printf "result->err: %.18g\n", $r->{err
};
43 printf "result->val: %.18g\n", $r->{val
};
48 Returns true if current system is Windows-like.
52 sub is_windows
() { GSL_IS_WINDOWS
}
54 =head2 is_similar($x,$y;$eps,$similarity_function)
57 is_similar($x, $y, 1e-7);
58 is_similar($x,$y, 1e-3, sub { ... } );
60 Return true if $x and $y are within $eps of each other, i.e.
64 If passed a code reference $similarity_function, it will pass $x and $y as parameters to it and
67 $similarity_function->($x,$y_) <= $eps
69 The default value of $eps is 1e-8. Don't try sending anything to the moon with this value...
74 my ($x,$y, $eps, $similarity_function) = @_;
76 if (ref $x eq 'ARRAY' && ref $y eq 'ARRAY') {
78 warn "is_similar(): argument of different lengths, $#$x != $#$y !!!";
82 my $delta = (gsl_isnan
($x->[$_]) or gsl_isnan
($y->[$_])) ? gsl_nan
() : abs($x->[$_] - $y->[$_]);
84 warn "\n\tElements start differing at index $_, delta = $delta\n";
85 warn qq{\t\t\
$x->[$_] = } . $x->[$_] . "\n";
86 warn qq{\t\t\
$y->[$_] = } . $y->[$_] . "\n";
93 if( ref $similarity_function eq 'CODE') {
94 $similarity_function->($x,$y) <= $eps ?
return 1 : return 0;
95 } elsif( defined $x && defined $y) {
96 my $delta = (gsl_isnan
($x) or gsl_isnan
($y)) ? gsl_nan
() : abs($x-$y);
97 $delta > $eps ?
warn qq{\t\t\
$x=$x\n\t\t\
$y=$y\n\t\tdelta
=$delta\n} && return 0 : return 1;
104 # this is a huge hack
107 my ($results,$class) = @_;
108 # GSL uses a factor of 100
110 my $eps = 2048*$Math::GSL
::Machine
::GSL_DBL_EPSILON
; # TOL3
112 local $Test::Builder
::Level
= $Test::Builder
::Level
+ 1;
114 croak
"Usage: verify_results(%results, \$class)" unless $class;
115 while (my($code,$expected)=each %$results){
116 my $r = Math
::GSL
::SF
::gsl_sf_result_struct
->new;
117 my $status = eval qq{${class}::$code};
119 ok
(0, qq{'$code' died
} ) if !defined $status;
121 if ( defined $r && $code =~ /_e\(.*\$r/) {
123 $eps = $factor*$r->{err
};
124 $res = abs($x-$expected);
128 print "got $code = $x\n";
129 printf "expected : %.18g\n", $expected ;
130 printf "difference : %.18g\n", $res;
131 printf "unexpected error of %.18g\n", $res-$eps if ($res-$eps>0);
134 ok
( gsl_isnan
($expected), "'$expected'?='$x'" );
135 } elsif(gsl_isinf
($x)) {
136 ok
( gsl_isinf
($expected), "'$expected'?='$x'" );
138 ok
( $res <= $eps, "$code ?= $x,\nres= +-$res, eps=$eps" );
145 my ($results,$class) = @_;
146 local $Test::Builder
::Level
= $Test::Builder
::Level
+ 1;
147 croak
"Usage: verify(%results, \$class)" unless $class;
148 while (my($code,$result)=each %$results){
149 my $x = eval qq{${class}::$code};
154 ($expected,$eps)=@
$result;
156 ($expected,$eps)=($result,1e-8);
158 my $res = abs($x - $expected);
161 ok
( gsl_isnan
($expected), "'$expected'?='$x'" );
162 } elsif(gsl_isinf
($x)) {
163 ok
( gsl_isinf
($expected), "'$expected'?='$x'" );
165 ok
( $res <= $eps, "$code ?= $x,\nres= +-$res, eps=$eps" );
170 =head2 ok_status( $got_status; $expected_status )
172 ok_status( $status ); # defaults to checking for $GSL_SUCCESS
174 ok_status( $status, $GSL_ECONTINUE );
176 Pass a test if the GSL status codes match, with a default expected status of $GSL_SUCCESS. This
177 function also stringifies the status codes into meaningful messages when it fails.
182 my ($got, $expected) = @_;
183 local $Test::Builder
::Level
= $Test::Builder
::Level
+ 1;
184 $expected ||= $GSL_SUCCESS;
185 ok
( defined $got && $got == $expected, gsl_strerror
(int($got)) );
188 =head2 ok_similar( $x, $y, $msg, $eps)
191 ok_similar( $x, $y, 'reason');
192 ok_similar( $x, $y, 'reason', 1e-4);
194 Pass a test if is_similar($x,$y,$msg,$eps) is true, otherwise fail.
199 my ($x,$y, $msg, $eps) = @_;
200 local $Test::Builder
::Level
= $Test::Builder
::Level
+ 1;
201 ok
(is_similar
($x,$y,$eps), $msg);
204 sub is_similar_relative
{
205 my ($x,$y, $eps) = @_;
206 return is_similar
($x,$y,$eps, sub { abs( ($_[0] - $_[1])/abs($_[1]) ) } );
209 sub ok_similar_relative
{
210 my ($x,$y, $msg, $eps,) = @_;
211 local $Test::Builder
::Level
= $Test::Builder
::Level
+ 1;
212 ok
(is_similar_relative
($x,$y,$eps), $msg );