#!perl
use
strict;
use
warnings;
use
Test::More;
my
$count
= 128;
plan(($^O eq
'os390'
) ? (
skip_all
=>
'takes too long on os390'
)
: (
tests
=>
$count
*4));
my
$length
= 128;
# If you get a failure here, please re-run the test with the printed seed
# value as input "perl t/mbi_rand.t seed" and send me the output
my
$seed
=
@ARGV
== 1 ?
$ARGV
[0] :
int
(
rand
(1165537));
#diag(" seed: $seed\n");
srand
(
$seed
);
my
$_base_len
;
my
@_base_len
;
#diag(" lib: ", Math::BigInt->config('lib'));
if
(Math::BigInt->config(
'lib'
) =~ /::Calc/) {
$_base_len
= Math::BigInt::Calc->_base_len();
@_base_len
= Math::BigInt::Calc->_base_len();
#diag("base len: $_base_len (scalar context)");
#diag("base len: @_base_len (list contex)");
}
my
(
$A
,
$B
,
$A_str
,
$B_str
,
$AdivB
,
$AmodB
,
$A_len
,
$B_len
);
my
$two
= Math::BigInt->new(2);
for
(
my
$i
= 0;
$i
<
$count
;
$i
++) {
#diag("");
# length of A and B
$A_len
=
int
(
rand
(
$length
) + 1);
$B_len
=
int
(
rand
(
$length
) + 1);
$A_str
=
''
;
$B_str
=
''
;
# We create the numbers from "patterns", e.g. get a random number and a
# random count and string them together. This means things like
# "100000999999999999911122222222" are much more likely. If we just strung
# together digits, we would end up with "1272398823211223" etc. It also
# means that we get more frequently equal numbers or other special cases.
while
(
length
(
$A_str
) <
$A_len
) {
$A_str
.=
int
(
rand
(100)) x
int
(
rand
(16));
}
while
(
length
(
$B_str
) <
$B_len
) {
$B_str
.=
int
(
rand
(100)) x
int
(
rand
(16));
}
$A_str
=~ s/^0+(?=\d)//;
$B_str
=~ s/^0+(?=\d)//;
#diag(" As: $A_str");
#diag(" Bs: $B_str");
$A
= Math::BigInt->new(
$A_str
);
$B
= Math::BigInt->new(
$B_str
);
#diag(" A: $A");
#diag(" B: $B");
SKIP: {
skip
'$A and/or $B are zero.'
, 4
if
$A
->is_zero() ||
$B
->is_zero();
# check that int(A / B) * B + A % B == A holds for all inputs
# $X = ($A / $B) * $B + 2 * ($A % $B) - ($A % $B);
(
$AdivB
,
$AmodB
) =
$A
->copy()->bdiv(
$B
);
#diag(" A / B: $AdivB");
#diag(" A % B: $AmodB");
is(
$AdivB
*
$B
+
$two
*
$AmodB
-
$AmodB
,
$A_str
,
"AdivB * B + 2 * AmodB - AmodB == A"
);
if
(is(
$AdivB
*
$B
/
$B
,
$AdivB
,
"AdivB * B / B == AdivB"
)) {
if
(Math::BigInt->config(
'lib'
) =~ /::Calc/) {
#diag("AdivB->[-1]: ", $AdivB->{value}->[-1]);
#diag(" B->[-1]: ", $B->{value}->[-1]);
}
}
# swap 'em and try this, too
# $X = ($B/$A)*$A + $B % $A;
(
$AdivB
,
$AmodB
) =
$B
->copy()->bdiv(
$A
);
# print "check: $AdivB $AmodB";
is(
$AdivB
*
$A
+
$two
*
$AmodB
-
$AmodB
,
$B_str
,
"AdivB * A + 2 * AmodB - AmodB == B"
);
is(
$AdivB
*
$A
/
$A
,
$AdivB
,
"AdivB * A / A == AdivB"
);
}
}