Comparing BigInt.pm and BigFloat.pm, it looks like the y-x is supposed to only happen when x != 0. This change to line 1994-2002 at the bottom of bmod seems to work:
if ($neg != 0) # one of them negative => correct in place
{
if (!$MBI->_is_zero($x->{_m}))
{
my $r = $y - $x;
$x->{_m} = $r->{_m};
$x->{_e} = $r->{_e};
$x->{_es} = $r->{_es};
$x->{sign} = '+' if $MBI->_is_zero($x->{_m}); # fix sign for -0
$x->bnorm();
}
}
The following test failed with the old code, and passes with the new:
perl -Iblib/lib -Iblib/arch -MMath::BigInt -MMath::BigFloat -E 'foreach my $x (0 .. 50) { foreach my $y (1 .. 50) { my($fx,$fy,$ix,$iy) = (Math::BigFloat->new(-$x), Math::BigFloat->new($y), Math::BigInt->new(-$x), Math::BigInt->new($y)); my $f = $fx % $fy; my $i = $ix % $iy; die "$ix $iy $f $i\n" unless $f == $i; } }'
The standard test suite passes with the patch.