1# -*- mode: perl; -*- 2 3use strict; 4use warnings; 5 6use Test::More; 7 8my $count = 128; 9 10plan(($^O eq 'os390') ? (skip_all => 'takes too long on os390') 11 : (tests => $count*4)); 12 13use Math::BigInt only => 'Calc'; 14 15my $length = 128; 16 17# If you get a failure here, please re-run the test with the printed seed 18# value as input "perl t/mbi_rand.t seed" and send me the output 19 20my $seed = @ARGV == 1 ? $ARGV[0] : int(rand(1165537)); 21#diag(" seed: $seed\n"); 22srand($seed); 23 24my $_base_len; 25my @_base_len; 26 27#diag(" lib: ", Math::BigInt->config('lib')); 28if (Math::BigInt->config('lib') =~ /::Calc/) { 29 $_base_len = Math::BigInt::Calc->_base_len(); 30 @_base_len = Math::BigInt::Calc->_base_len(); 31 #diag("base len: $_base_len (scalar context)"); 32 #diag("base len: @_base_len (list contex)"); 33} 34 35my ($A, $B, $A_str, $B_str, $AdivB, $AmodB, $A_len, $B_len); 36my $two = Math::BigInt->new(2); 37for (my $i = 0; $i < $count; $i++) { 38 #diag(""); 39 40 # length of A and B 41 $A_len = int(rand($length) + 1); 42 $B_len = int(rand($length) + 1); 43 $A_str = ''; 44 $B_str = ''; 45 46 # We create the numbers from "patterns", e.g. get a random number and a 47 # random count and string them together. This means things like 48 # "100000999999999999911122222222" are much more likely. If we just strung 49 # together digits, we would end up with "1272398823211223" etc. It also 50 # means that we get more frequently equal numbers or other special cases. 51 52 while (length($A_str) < $A_len) { 53 $A_str .= int(rand(100)) x int(rand(16)); 54 } 55 while (length($B_str) < $B_len) { 56 $B_str .= int(rand(100)) x int(rand(16)); 57 } 58 59 $A_str =~ s/^0+(?=\d)//; 60 $B_str =~ s/^0+(?=\d)//; 61 #diag(" As: $A_str"); 62 #diag(" Bs: $B_str"); 63 $A = Math::BigInt->new($A_str); 64 $B = Math::BigInt->new($B_str); 65 #diag(" A: $A"); 66 #diag(" B: $B"); 67 68 SKIP: { 69 skip '$A and/or $B are zero.', 4 if $A->is_zero() || $B->is_zero(); 70 71 # check that int(A / B) * B + A % B == A holds for all inputs 72 73 # $X = ($A / $B) * $B + 2 * ($A % $B) - ($A % $B); 74 75 ($AdivB, $AmodB) = $A->copy()->bdiv($B); 76 77 #diag(" A / B: $AdivB"); 78 #diag(" A % B: $AmodB"); 79 80 is($AdivB * $B + $two * $AmodB - $AmodB, $A_str, 81 "AdivB * B + 2 * AmodB - AmodB == A"); 82 83 if (is($AdivB * $B / $B, $AdivB, "AdivB * B / B == AdivB")) { 84 if (Math::BigInt->config('lib') =~ /::Calc/) { 85 #diag("AdivB->[-1]: ", $AdivB->{value}->[-1]); 86 #diag(" B->[-1]: ", $B->{value}->[-1]); 87 } 88 } 89 90 # swap 'em and try this, too 91 # $X = ($B/$A)*$A + $B % $A; 92 ($AdivB, $AmodB) = $B->copy()->bdiv($A); 93 # print "check: $AdivB $AmodB"; 94 95 is($AdivB * $A + $two * $AmodB - $AmodB, $B_str, 96 "AdivB * A + 2 * AmodB - AmodB == B"); 97 98 is($AdivB * $A / $A, $AdivB, "AdivB * A / A == AdivB"); 99 } 100} 101