#!/usr/bin/perl -w # test inf/NaN handling all in one place # Thanx to Jarkko for the excellent explanations and the tables use Test; use strict; BEGIN { chdir 't' if -d 't'; unshift @INC, '../lib'; } BEGIN { $| = 1; # to locate the testing files my $location = $0; $location =~ s/inf_nan.t//i; if ($ENV{PERL_CORE}) { @INC = qw(../t/lib); # testing with the core distribution } unshift @INC, '../lib'; # for testing manually if (-d 't') { chdir 't'; require File::Spec; unshift @INC, File::Spec->catdir(File::Spec->updir, $location); } else { unshift @INC, $location; } print "# INC = @INC\n"; # values groups oprators classes tests plan tests => 7 * 6 * 5 * 4 * 2 + 7 * 6 * 2 * 4 * 1; # bmod } use Math::BigInt; use Math::BigFloat; use Math::BigInt::Subclass; use Math::BigFloat::Subclass; my @classes = qw/Math::BigInt Math::BigFloat Math::BigInt::Subclass Math::BigFloat::Subclass /; my (@args,$x,$y,$z); # + foreach (qw/ -inf:-inf:-inf -1:-inf:-inf -0:-inf:-inf 0:-inf:-inf 1:-inf:-inf inf:-inf:NaN NaN:-inf:NaN -inf:-1:-inf -1:-1:-2 -0:-1:-1 0:-1:-1 1:-1:0 inf:-1:inf NaN:-1:NaN -inf:0:-inf -1:0:-1 -0:0:0 0:0:0 1:0:1 inf:0:inf NaN:0:NaN -inf:1:-inf -1:1:0 -0:1:1 0:1:1 1:1:2 inf:1:inf NaN:1:NaN -inf:inf:NaN -1:inf:inf -0:inf:inf 0:inf:inf 1:inf:inf inf:inf:inf NaN:inf:NaN -inf:NaN:NaN -1:NaN:NaN -0:NaN:NaN 0:NaN:NaN 1:NaN:NaN inf:NaN:NaN NaN:NaN:NaN /) { @args = split /:/,$_; for my $class (@classes) { $x = $class->new($args[0]); $y = $class->new($args[1]); $args[2] = '0' if $args[2] eq '-0'; # BigInt/Float hasn't got -0 my $r = $x->badd($y); print "# x $class $args[0] + $args[1] should be $args[2] but is $x\n", if !ok ($x->bstr(),$args[2]); print "# r $class $args[0] + $args[1] should be $args[2] but is $r\n", if !ok ($x->bstr(),$args[2]); } } # - foreach (qw/ -inf:-inf:NaN -1:-inf:inf -0:-inf:inf 0:-inf:inf 1:-inf:inf inf:-inf:inf NaN:-inf:NaN -inf:-1:-inf -1:-1:0 -0:-1:1 0:-1:1 1:-1:2 inf:-1:inf NaN:-1:NaN -inf:0:-inf -1:0:-1 -0:0:-0 0:0:0 1:0:1 inf:0:inf NaN:0:NaN -inf:1:-inf -1:1:-2 -0:1:-1 0:1:-1 1:1:0 inf:1:inf NaN:1:NaN -inf:inf:-inf -1:inf:-inf -0:inf:-inf 0:inf:-inf 1:inf:-inf inf:inf:NaN NaN:inf:NaN -inf:NaN:NaN -1:NaN:NaN -0:NaN:NaN 0:NaN:NaN 1:NaN:NaN inf:NaN:NaN NaN:NaN:NaN /) { @args = split /:/,$_; for my $class (@classes) { $x = $class->new($args[0]); $y = $class->new($args[1]); $args[2] = '0' if $args[2] eq '-0'; # BigInt/Float hasn't got -0 my $r = $x->bsub($y); print "# x $class $args[0] - $args[1] should be $args[2] but is $x\n" if !ok ($x->bstr(),$args[2]); print "# r $class $args[0] - $args[1] should be $args[2] but is $r\n" if !ok ($r->bstr(),$args[2]); } } # * foreach (qw/ -inf:-inf:inf -1:-inf:inf -0:-inf:NaN 0:-inf:NaN 1:-inf:-inf inf:-inf:-inf NaN:-inf:NaN -inf:-1:inf -1:-1:1 -0:-1:0 0:-1:-0 1:-1:-1 inf:-1:-inf NaN:-1:NaN -inf:0:NaN -1:0:-0 -0:0:-0 0:0:0 1:0:0 inf:0:NaN NaN:0:NaN -inf:1:-inf -1:1:-1 -0:1:-0 0:1:0 1:1:1 inf:1:inf NaN:1:NaN -inf:inf:-inf -1:inf:-inf -0:inf:NaN 0:inf:NaN 1:inf:inf inf:inf:inf NaN:inf:NaN -inf:NaN:NaN -1:NaN:NaN -0:NaN:NaN 0:NaN:NaN 1:NaN:NaN inf:NaN:NaN NaN:NaN:NaN /) { @args = split /:/,$_; for my $class (@classes) { $x = $class->new($args[0]); $y = $class->new($args[1]); $args[2] = '0' if $args[2] eq '-0'; # BigInt/Float hasn't got -0 $args[2] = '0' if $args[2] eq '-0'; # BigInt hasn't got -0 my $r = $x->bmul($y); print "# x $class $args[0] * $args[1] should be $args[2] but is $x\n" if !ok ($x->bstr(),$args[2]); print "# r $class $args[0] * $args[1] should be $args[2] but is $r\n" if !ok ($r->bstr(),$args[2]); } } # / foreach (qw/ -inf:-inf:NaN -1:-inf:0 -0:-inf:0 0:-inf:-0 1:-inf:-0 inf:-inf:NaN NaN:-inf:NaN -inf:-1:inf -1:-1:1 -0:-1:0 0:-1:-0 1:-1:-1 inf:-1:-inf NaN:-1:NaN -inf:0:-inf -1:0:-inf -0:0:NaN 0:0:NaN 1:0:inf inf:0:inf NaN:0:NaN -inf:1:-inf -1:1:-1 -0:1:-0 0:1:0 1:1:1 inf:1:inf NaN:1:NaN -inf:inf:NaN -1:inf:-0 -0:inf:-0 0:inf:0 1:inf:0 inf:inf:NaN NaN:inf:NaN -inf:NaN:NaN -1:NaN:NaN -0:NaN:NaN 0:NaN:NaN 1:NaN:NaN inf:NaN:NaN NaN:NaN:NaN /) { @args = split /:/,$_; for my $class (@classes) { $x = $class->new($args[0]); $y = $class->new($args[1]); $args[2] = '0' if $args[2] eq '-0'; # BigInt/Float hasn't got -0 my $t = $x->copy(); my $tmod = $t->copy(); # bdiv in scalar context my $r = $x->bdiv($y); print "# x $class $args[0] / $args[1] should be $args[2] but is $x\n" if !ok ($x->bstr(),$args[2]); print "# r $class $args[0] / $args[1] should be $args[2] but is $r\n" if !ok ($r->bstr(),$args[2]); # bmod and bdiv in list context my ($d,$rem) = $t->bdiv($y); # bdiv in list context print "# t $class $args[0] / $args[1] should be $args[2] but is $t\n" if !ok ($t->bstr(),$args[2]); print "# d $class $args[0] / $args[1] should be $args[2] but is $d\n" if !ok ($d->bstr(),$args[2]); # bmod my $m = $tmod->bmod($y); # bmod() agrees with bdiv? print "# m $class $args[0] % $args[1] should be $rem but is $m\n" if !ok ($m->bstr(),$rem->bstr()); # bmod() return agrees with set value? print "# o $class $args[0] % $args[1] should be $m ($rem) but is $tmod\n" if !ok ($tmod->bstr(),$m->bstr()); } }