From Code to Community: Sponsoring The Perl and Raku Conference 2025 Learn more

use strict;
use Test::More tests => 1 + 3*14*14 + 3*11*11 + 3*9*9 + 108 + 1749;
BEGIN { use_ok "Data::Integer", qw(
nint_sgn sint_sgn uint_sgn
nint_abs sint_abs uint_abs
nint_cmp sint_cmp uint_cmp
nint_min sint_min uint_min
nint_max sint_max uint_max
nint_neg sint_neg uint_neg
nint_add sint_add uint_add
nint_sub sint_sub uint_sub
min_sint max_sint max_uint
nint_is_sint nint_is_uint
); }
sub nint_is($$) {
my($tval, $cval) = @_;
my $tval0 = $tval;
ok defined($tval) && ref(\$tval) eq "SCALAR" &&
int($tval0) == $tval0 && "$tval" eq "$cval" &&
((my $tval1 = $tval) <=> 0) == ((my $cval1 = $cval) <=> 0) &&
do { use integer; $tval == $cval },
"$tval match $cval";
}
my @values = (
min_sint,
do { use integer; min_sint|1 },
do { use integer; min_sint>>1 },
-0x123,
-1,
0,
1,
0x123,
min_sint>>1,
max_sint&~1,
max_sint,
min_sint|0,
max_uint&~1,
max_uint,
);
for(my $ia = @values; $ia--; ) {
for(my $ib = @values; $ib--; ) {
my($a, $b) = @values[$ia, $ib];
is nint_cmp($a, $b), $ia <=> $ib;
nint_is nint_min($a, $b), ($ia < $ib ? $a : $b);
nint_is nint_max($a, $b), ($ia < $ib ? $b : $a);
if(nint_is_sint($a) && nint_is_sint($b)) {
is sint_cmp($a, $b), $ia <=> $ib;
nint_is sint_min($a, $b), ($ia < $ib ? $a : $b);
nint_is sint_max($a, $b), ($ia < $ib ? $b : $a);
}
if(nint_is_uint($a) && nint_is_uint($b)) {
is uint_cmp($a, $b), $ia <=> $ib;
nint_is uint_min($a, $b), ($ia < $ib ? $a : $b);
nint_is uint_max($a, $b), ($ia < $ib ? $b : $a);
}
}
}
foreach([ 0, 0, 0 ],
[ 1, 1, -1 ],
[ -1, -1, 1 ],
[ 0x123, 1, -0x123 ],
[ -0x123, -1, 0x123 ],
[ max_sint, 1, do { use integer; min_sint|1 } ],
[ do { use integer; min_sint|1 }, -1, max_sint ],
[ min_sint|0, 1, min_sint ],
[ min_sint, -1, min_sint|0 ],
[ min_sint|1, 1, undef ],
[ min_sint|0x123, 1, undef ],
[ max_uint, 1, undef ],
) {
my($a, $sgn, $neg) = @$_;
my $abs = (my $ta = $a) >= 0 ? $a : $neg;
{
is nint_sgn($a), $sgn;
nint_is nint_abs($a), $abs;
my $r = eval { nint_neg($a) };
if(defined $neg) {
is $@, "";
nint_is $r, $neg;
} else {
like $@, qr/\Ainteger overflow/;
}
}
if(nint_is_sint($a)) {
is sint_sgn($a), $sgn;
my $ra = eval { sint_abs($a) };
if(nint_is_sint($abs)) {
is $@, "";
nint_is $ra, $abs;
} else {
like $@, qr/\Ainteger overflow/;
}
my $r = eval { sint_neg($a) };
if(defined($neg) && nint_is_sint($neg)) {
is $@, "";
nint_is $r, $neg;
} else {
like $@, qr/\Ainteger overflow/;
}
}
if(nint_is_uint($a)) {
is uint_sgn($a), $sgn;
nint_is uint_abs($a), $abs;
my $r = eval { uint_neg($a) };
if(defined($neg) && nint_is_uint($neg)) {
is $@, "";
nint_is $r, $neg;
} else {
like $@, qr/\Ainteger overflow/;
}
}
}
foreach([ undef, max_uint, min_sint ],
[ undef, max_uint&~1, min_sint ],
[ undef, max_uint, do { use integer; min_sint|1 } ],
[ undef, min_sint|0, min_sint ],
[ undef, min_sint|0, do { use integer; min_sint|2 } ],
[ undef, max_uint, -1 ],
[ undef, max_sint, min_sint ],
[ undef, min_sint|0, do { use integer; min_sint|1 } ],
[ undef, max_uint, 0 ],
[ undef, max_sint&~1, min_sint ],
[ undef, max_sint, do { use integer; min_sint|1 } ],
[ undef, min_sint|0, do { use integer; min_sint|2 } ],
[ undef, max_uint, 1 ],
[ undef, 2, min_sint ],
[ undef, 3, do { use integer; min_sint|1 } ],
[ undef, max_sint, -3 ],
[ undef, min_sint|1, -1 ],
[ undef, min_sint|2, 0 ],
[ undef, min_sint|3, 1 ],
[ undef, max_uint&~1, max_sint&~3 ],
[ undef, max_uint, max_sint&~2 ],
[ undef, 1, min_sint ],
[ undef, 2, do { use integer; min_sint|1 } ],
[ undef, max_sint, -2 ],
[ undef, min_sint|0, -1 ],
[ undef, min_sint|1, 0 ],
[ undef, min_sint|2, 1 ],
[ undef, max_uint&~1, max_sint&~2 ],
[ undef, max_uint, max_sint&~1 ],
[ min_sint, min_sint, undef ],
[ min_sint, do { use integer; min_sint|1 }, undef ],
[ min_sint, -1, undef ],
[ min_sint, 0, min_sint ],
[ min_sint, 1, do { use integer; min_sint|1 } ],
[ min_sint, max_sint, -1 ],
[ min_sint, min_sint|0, 0 ],
[ min_sint, min_sint|1, 1 ],
[ min_sint, max_uint&~1, max_sint&~1 ],
[ min_sint, max_uint, max_sint ],
[ min_sint, undef, min_sint|0 ],
[ min_sint, undef, max_uint&~1 ],
[ min_sint, undef, max_uint ],
[ do { use integer; min_sint|1 }, do { use integer; min_sint|1 }, undef ],
[ do { use integer; min_sint|1 }, do { use integer; min_sint|2 }, undef ],
[ do { use integer; min_sint|1 }, -2, undef ],
[ do { use integer; min_sint|1 }, -1, min_sint ],
[ do { use integer; min_sint|1 }, 0, do { use integer; min_sint|1 } ],
[ do { use integer; min_sint|1 }, 1, do { use integer; min_sint|2 } ],
[ do { use integer; min_sint|1 }, max_sint&~1, -1 ],
[ do { use integer; min_sint|1 }, max_sint, 0 ],
[ do { use integer; min_sint|1 }, min_sint|0, 1 ],
[ do { use integer; min_sint|1 }, max_uint&~2, max_sint&~1 ],
[ do { use integer; min_sint|1 }, max_uint&~1, max_sint ],
[ do { use integer; min_sint|1 }, max_uint, min_sint|0 ],
[ do { use integer; min_sint|1 }, undef, max_uint&~1 ],
[ do { use integer; min_sint|1 }, undef, max_uint ],
[ do { use integer; min_sint|~(min_sint>>1) }, do { use integer; min_sint|~(min_sint>>1) }, undef ],
[ do { use integer; min_sint|~(min_sint>>1) }, do { use integer; min_sint>>1 }, undef ],
[ do { use integer; min_sint|~(min_sint>>1) }, do { use integer; (min_sint>>1)|1 }, min_sint ],
[ do { use integer; min_sint|~(min_sint>>1) }, do { use integer; (min_sint>>1)|2 }, do { use integer; min_sint|1 } ],
[ do { use integer; min_sint|~(min_sint>>1) }, min_sint>>1, -1 ],
[ do { use integer; min_sint|~(min_sint>>1) }, (min_sint>>1)|1, 0 ],
[ do { use integer; min_sint|~(min_sint>>1) }, (min_sint>>1)|2, 1 ],
[ do { use integer; min_sint|~(min_sint>>1) }, max_sint&~1, (max_sint>>1)&~2 ],
[ do { use integer; min_sint|~(min_sint>>1) }, max_sint, (max_sint>>1)&~1 ],
[ do { use integer; min_sint|~(min_sint>>1) }, min_sint|0, max_sint>>1 ],
[ do { use integer; min_sint>>1 }, do { use integer; min_sint>>1 }, min_sint ],
[ do { use integer; min_sint>>1 }, do { use integer; (min_sint>>1)|1 }, do { use integer; min_sint|1 } ],
[ do { use integer; min_sint>>1 }, max_sint>>1, -1 ],
[ do { use integer; min_sint>>1 }, min_sint>>1, 0 ],
[ do { use integer; min_sint>>1 }, (min_sint>>1)|1, 1 ],
[ do { use integer; min_sint>>1 }, max_sint&~1, (max_sint>>1)&~1 ],
[ do { use integer; min_sint>>1 }, max_sint, max_sint>>1 ],
[ do { use integer; min_sint>>1 }, min_sint|0, min_sint>>1, ],
[ do { use integer; (min_sint>>1)|1 }, do { use integer; (min_sint>>1)|1 }, do { use integer; min_sint|2 } ],
[ do { use integer; (min_sint>>1)|1 }, (max_sint>>1)&~1, -1 ],
[ do { use integer; (min_sint>>1)|1 }, max_sint>>1, 0 ],
[ do { use integer; (min_sint>>1)|1 }, min_sint>>1, 1 ],
[ do { use integer; (min_sint>>1)|1 }, max_sint&~1, max_sint>>1 ],
[ do { use integer; (min_sint>>1)|1 }, max_sint, min_sint>>1, ],
[ do { use integer; (min_sint>>1)|1 }, min_sint|0, (min_sint>>1)|1 ],
[ -0x123, -0x123, -0x246 ],
[ -0x123, -1, -0x124 ],
[ -0x123, 0, -0x123 ],
[ -0x123, 1, -0x122 ],
[ -0x123, 0x122, -1 ],
[ -0x123, 0x123, 0 ],
[ -0x123, 0x124, 1 ],
[ -0x123, max_sint&~1, max_sint&~0x124 ],
[ -0x123, max_sint, max_sint&~0x123 ],
[ -0x123, min_sint|0, max_sint&~0x122 ],
[ -0x123, min_sint|0x121, max_sint&~1 ],
[ -0x123, min_sint|0x122, max_sint ],
[ -0x123, min_sint|0x123, min_sint|0 ],
[ -0x123, max_uint&~1, max_uint&~0x124 ],
[ -0x123, max_uint, max_uint&~0x123 ],
[ -0x123, undef, max_uint&~0x122 ],
[ -0x123, undef, max_uint&~1 ],
[ -0x123, undef, max_uint ],
[ -1, -1, -2 ],
[ -1, 0, -1 ],
[ -1, 1, 0 ],
[ -1, 0x123, 0x122 ],
[ -1, max_sint&~1, max_sint&~2 ],
[ -1, max_sint, max_sint&~1 ],
[ -1, min_sint|0, max_sint ],
[ -1, min_sint|1, min_sint|0 ],
[ -1, max_uint&~1, max_uint&~2 ],
[ -1, max_uint, max_uint&~1 ],
[ -1, undef, max_uint ],
[ 0, 0, 0 ],
[ 0, 1, 1 ],
[ 0, 0x123, 0x123 ],
[ 0, max_sint&~1, max_sint&~1 ],
[ 0, max_sint, max_sint ],
[ 0, min_sint|0, min_sint|0 ],
[ 0, max_uint&~1, max_uint&~1 ],
[ 0, max_uint, max_uint ],
[ 1, 1, 2 ],
[ 1, 0x123, 0x124 ],
[ 1, max_sint&~1, max_sint ],
[ 1, max_sint, min_sint|0 ],
[ 1, min_sint|0, min_sint|1 ],
[ 1, max_uint&~1, max_uint ],
[ 1, max_uint, undef ],
[ 0x123, 0x123, 0x246 ],
[ 0x123, max_sint&~0x124, max_sint&~1 ],
[ 0x123, max_sint&~0x123, max_sint ],
[ 0x123, max_sint&~0x122, min_sint|0 ],
[ 0x123, max_sint&~1, min_sint|0x121 ],
[ 0x123, max_sint, min_sint|0x122 ],
[ 0x123, min_sint|0, min_sint|0x123 ],
[ 0x123, max_uint&~0x124, max_uint&~1 ],
[ 0x123, max_uint&~0x123, max_uint ],
[ 0x123, max_uint&~0x122, undef ],
[ 0x123, max_uint&~1, undef ],
[ 0x123, max_uint, undef ],
[ max_sint>>1, max_sint>>1, max_sint&~1 ],
[ max_sint>>1, min_sint>>1, max_sint ],
[ max_sint>>1, (min_sint>>1)|1, min_sint|0 ],
[ max_sint>>1, max_uint&~1, undef ],
[ max_sint>>1, max_uint, undef ],
[ min_sint>>1, min_sint>>1, min_sint|0 ],
[ min_sint>>1, (min_sint>>1)|1, min_sint|1 ],
[ min_sint>>1, max_uint&~1, undef ],
[ min_sint>>1, max_uint, undef ],
[ max_sint&~1, max_sint&~1, max_uint&~3 ],
[ max_sint&~1, max_sint, max_uint&~2 ],
[ max_sint&~1, min_sint|0, max_uint&~1 ],
[ max_sint&~1, min_sint|1, max_uint ],
[ max_sint&~1, min_sint|2, undef ],
[ max_sint&~1, max_uint&~1, undef ],
[ max_sint&~1, max_uint, undef ],
[ max_sint, max_sint, max_uint&~1 ],
[ max_sint, min_sint|0, max_uint ],
[ max_sint, min_sint|1, undef ],
[ max_sint, max_uint&~1, undef ],
[ max_sint, max_uint, undef ],
[ min_sint|0, min_sint|0, undef ],
[ min_sint|0, max_uint&~1, undef ],
[ min_sint|0, max_uint, undef ],
[ max_uint&~1, max_uint&~1, undef ],
[ max_uint&~1, max_uint, undef ],
[ max_uint, max_uint, undef ],
) {
my($a, $b, $c) = @$_;
if(defined($a) && defined($b)) {
{
my $r = eval { nint_add($a, $b) };
if(defined $c) {
is $@, "";
nint_is $r, $c;
} else {
like $@, qr/\Ainteger overflow/;
}
$r = eval { nint_add($b, $a) };
if(defined $c) {
is $@, "";
nint_is $r, $c;
} else {
like $@, qr/\Ainteger overflow/;
}
}
if(nint_is_sint($a) && nint_is_sint($b)) {
my $r = eval { sint_add($a, $b) };
if(defined($c) && nint_is_sint($c)) {
is $@, "";
nint_is $r, $c;
} else {
like $@, qr/\Ainteger overflow/;
}
$r = eval { sint_add($b, $a) };
if(defined($c) && nint_is_sint($c)) {
is $@, "";
nint_is $r, $c;
} else {
like $@, qr/\Ainteger overflow/;
}
}
if(nint_is_uint($a) && nint_is_uint($b)) {
my $r = eval { uint_add($a, $b) };
if(defined($c) && nint_is_uint($c)) {
is $@, "";
nint_is $r, $c;
} else {
like $@, qr/\Ainteger overflow/;
}
$r = eval { uint_add($b, $a) };
if(defined($c) && nint_is_uint($c)) {
is $@, "";
nint_is $r, $c;
} else {
like $@, qr/\Ainteger overflow/;
}
}
}
if(defined($a) && defined($c)) {
{
my $r = eval { nint_sub($c, $a) };
if(defined $b) {
is $@, "";
nint_is $r, $b;
} else {
like $@, qr/\Ainteger overflow/;
}
}
if(nint_is_sint($a) && nint_is_sint($c)) {
my $r = eval { sint_sub($c, $a) };
if(defined($b) && nint_is_sint($b)) {
is $@, "";
nint_is $r, $b;
} else {
like $@, qr/\Ainteger overflow/;
}
}
if(nint_is_uint($a) && nint_is_uint($c)) {
my $r = eval { uint_sub($c, $a) };
if(defined($b) && nint_is_uint($b)) {
is $@, "";
nint_is $r, $b;
} else {
like $@, qr/\Ainteger overflow/;
}
}
}
if(defined($b) && defined($c)) {
{
my $r = eval { nint_sub($c, $b) };
if(defined $a) {
is $@, "";
nint_is $r, $a;
} else {
like $@, qr/\Ainteger overflow/;
}
}
if(nint_is_sint($b) && nint_is_sint($c)) {
my $r = eval { sint_sub($c, $b) };
if(defined($a) && nint_is_sint($a)) {
is $@, "";
nint_is $r, $a;
} else {
like $@, qr/\Ainteger overflow/;
}
}
if(nint_is_uint($b) && nint_is_uint($c)) {
my $r = eval { uint_sub($c, $b) };
if(defined($a) && nint_is_uint($a)) {
is $@, "";
nint_is $r, $a;
} else {
like $@, qr/\Ainteger overflow/;
}
}
}
}
1;