diff options
author | Rafael Garcia-Suarez <rgarciasuarez@gmail.com> | 2004-02-19 21:17:10 +0000 |
---|---|---|
committer | Rafael Garcia-Suarez <rgarciasuarez@gmail.com> | 2004-02-19 21:17:10 +0000 |
commit | 9b924220109ab5ca4ffe2f23c240236dc5a723c2 (patch) | |
tree | 69c11d167bab8903a99a104bdf2a59ab8f7343b6 /lib/Math/BigInt | |
parent | b6a15bc5202dd52395ce566b43e1490d38dc2141 (diff) | |
download | perl-9b924220109ab5ca4ffe2f23c240236dc5a723c2.tar.gz |
Upgrade to prereleases of Math::BigInt 1.70 and
Math::BigRat 0.12, by Tels.
p4raw-id: //depot/perl@22344
Diffstat (limited to 'lib/Math/BigInt')
-rw-r--r-- | lib/Math/BigInt/Calc.pm | 175 | ||||
-rw-r--r-- | lib/Math/BigInt/CalcEmu.pm | 358 | ||||
-rw-r--r-- | lib/Math/BigInt/t/bare_mbf.t | 2 | ||||
-rw-r--r-- | lib/Math/BigInt/t/bare_mbi.t | 2 | ||||
-rw-r--r-- | lib/Math/BigInt/t/bare_mif.t | 2 | ||||
-rw-r--r-- | lib/Math/BigInt/t/bigfltpm.inc | 33 | ||||
-rwxr-xr-x | lib/Math/BigInt/t/bigfltpm.t | 4 | ||||
-rw-r--r-- | lib/Math/BigInt/t/bigintc.t | 358 | ||||
-rw-r--r-- | lib/Math/BigInt/t/bigintpm.inc | 36 | ||||
-rwxr-xr-x | lib/Math/BigInt/t/bigintpm.t | 2 | ||||
-rw-r--r-- | lib/Math/BigInt/t/bigints.t | 67 | ||||
-rw-r--r-- | lib/Math/BigInt/t/biglog.t | 11 | ||||
-rw-r--r-- | lib/Math/BigInt/t/calling.t | 19 | ||||
-rw-r--r-- | lib/Math/BigInt/t/config.t | 2 | ||||
-rw-r--r-- | lib/Math/BigInt/t/mbimbf.inc | 24 | ||||
-rw-r--r-- | lib/Math/BigInt/t/mbimbf.t | 7 | ||||
-rw-r--r-- | lib/Math/BigInt/t/req_mbfw.t | 5 | ||||
-rwxr-xr-x | lib/Math/BigInt/t/sub_mbf.t | 2 | ||||
-rwxr-xr-x | lib/Math/BigInt/t/sub_mbi.t | 2 | ||||
-rw-r--r-- | lib/Math/BigInt/t/sub_mif.t | 2 | ||||
-rw-r--r-- | lib/Math/BigInt/t/upgrade.inc | 12 | ||||
-rw-r--r-- | lib/Math/BigInt/t/upgrade.t | 2 | ||||
-rw-r--r-- | lib/Math/BigInt/t/use_mbfw.t | 8 | ||||
-rw-r--r-- | lib/Math/BigInt/t/with_sub.t | 5 |
24 files changed, 464 insertions, 676 deletions
diff --git a/lib/Math/BigInt/Calc.pm b/lib/Math/BigInt/Calc.pm index 1dd7619be2..f2f0c87466 100644 --- a/lib/Math/BigInt/Calc.pm +++ b/lib/Math/BigInt/Calc.pm @@ -6,7 +6,7 @@ use strict; use vars qw/$VERSION/; -$VERSION = '0.38'; +$VERSION = '0.40'; # Package to store unsigned big integers in decimal and do math with them @@ -31,6 +31,9 @@ $VERSION = '0.38'; ############################################################################## # global constants, flags and accessory + +# announce that we are compatible with MBI v1.70 and up +sub api_version () { 1; } # constants for easier life my $nan = 'NaN'; @@ -70,9 +73,6 @@ sub _base_len $RBASE = abs('1e-'.$BASE_LEN_SMALL); # see USE_MUL $MAX_VAL = $MBASE-1; - #print "BASE_LEN: $BASE_LEN MAX_VAL: $MAX_VAL BASE: $BASE RBASE: $RBASE "; - #print "BASE_LEN_SMALL: $BASE_LEN_SMALL MBASE: $MBASE\n"; - undef &_mul; undef &_div; @@ -82,14 +82,12 @@ sub _base_len # & here. if ($caught == 2) # 2 { - # print "# use mul\n"; # must USE_MUL since we cannot use DIV *{_mul} = \&_mul_use_mul; *{_div} = \&_div_use_mul; } else # 0 or 1 { - # print "# use div\n"; # can USE_DIV instead *{_mul} = \&_mul_use_div; *{_div} = \&_div_use_div; @@ -190,22 +188,21 @@ sub _new # (ref to string) return ref to num_array # Convert a number from string format (without sign) to internal base # 1ex format. Assumes normalized value as input. - my $d = $_[1]; - my $il = length($$d)-1; + my $il = length($_[1])-1; # < BASE_LEN due len-1 above - return [ int($$d) ] if $il < $BASE_LEN; # shortcut for short numbers + return [ int($_[1]) ] if $il < $BASE_LEN; # shortcut for short numbers # this leaves '00000' instead of int 0 and will be corrected after any op [ reverse(unpack("a" . ($il % $BASE_LEN+1) - . ("a$BASE_LEN" x ($il / $BASE_LEN)), $$d)) ]; + . ("a$BASE_LEN" x ($il / $BASE_LEN)), $_[1])) ]; } BEGIN { - $AND_MASK = __PACKAGE__->_new( \( 2 ** $AND_BITS )); - $XOR_MASK = __PACKAGE__->_new( \( 2 ** $XOR_BITS )); - $OR_MASK = __PACKAGE__->_new( \( 2 ** $OR_BITS )); + $AND_MASK = __PACKAGE__->_new( ( 2 ** $AND_BITS )); + $XOR_MASK = __PACKAGE__->_new( ( 2 ** $XOR_BITS )); + $OR_MASK = __PACKAGE__->_new( ( 2 ** $OR_BITS )); } sub _zero @@ -226,6 +223,12 @@ sub _two [ 2 ]; } +sub _ten + { + # create a 10 (used internally for shifting) + [ 10 ]; + } + sub _copy { # make a true copy @@ -260,14 +263,15 @@ sub _str $ret .= substr($z.$ar->[$l],-$BASE_LEN); # fastest way I could think of $l--; } - \$ret; + $ret; } sub _num { - # Make a number (scalar int/float) from a BigInt object + # Make a number (scalar int/float) from a BigInt object my $x = $_[1]; - return $x->[0] if scalar @$x == 1; # below $BASE + + return 0+$x->[0] if scalar @$x == 1; # below $BASE my $fac = 1; my $num = 0; foreach (@$x) @@ -354,7 +358,6 @@ sub _sub my $car = 0; my $i; my $j = 0; if (!$s) { - #print "case 2\n"; for $i (@$sx) { last unless defined $sy->[$j] || $car; @@ -363,7 +366,6 @@ sub _sub # might leave leading zeros, so fix that return __strip_zeros($sx); } - #print "case 1 (swap)\n"; for $i (@$sx) { # we can't do an early out if $x is < than $y, since we @@ -976,6 +978,9 @@ sub _zeros # check each array elem in _m for having 0 at end as long as elem == 0 # Upon finding a elem != 0, stop my $x = $_[1]; + + return 0 if scalar @$x == 1 && $x->[0] == 0; + my $zeros = 0; my $elem; foreach my $e (@$x) { @@ -997,33 +1002,38 @@ sub _zeros sub _is_zero { - # return true if arg (BINT or num_str) is zero (array '+', '0') - my $x = $_[1]; - - (((scalar @$x == 1) && ($x->[0] == 0))) <=> 0; + # return true if arg is zero + (((scalar @{$_[1]} == 1) && ($_[1]->[0] == 0))) <=> 0; } sub _is_even { - # return true if arg (BINT or num_str) is even - my $x = $_[1]; - (!($x->[0] & 1)) <=> 0; + # return true if arg is even + (!($_[1]->[0] & 1)) <=> 0; } sub _is_odd { - # return true if arg (BINT or num_str) is even - my $x = $_[1]; - - (($x->[0] & 1)) <=> 0; + # return true if arg is even + (($_[1]->[0] & 1)) <=> 0; } sub _is_one { - # return true if arg (BINT or num_str) is one (array '+', '1') - my $x = $_[1]; + # return true if arg is one + (scalar @{$_[1]} == 1) && ($_[1]->[0] == 1) <=> 0; + } + +sub _is_two + { + # return true if arg is two + (scalar @{$_[1]} == 1) && ($_[1]->[0] == 2) <=> 0; + } - (scalar @$x == 1) && ($x->[0] == 1) <=> 0; +sub _is_ten + { + # return true if arg is ten + (scalar @{$_[1]} == 1) && ($_[1]->[0] == 10) <=> 0; } sub __strip_zeros @@ -1086,8 +1096,6 @@ sub _check ############################################################################### -############################################################################### -# some optional routines to make BigInt faster sub _mod { @@ -1160,7 +1168,7 @@ sub _rsft if ($n != 10) { - $n = _new($c,\$n); return _div($c,$x, _pow($c,$n,$y)); + $n = _new($c,$n); return _div($c,$x, _pow($c,$n,$y)); } # shortcut (faster) for shifting by 10) @@ -1208,7 +1216,7 @@ sub _lsft if ($n != 10) { - $n = _new($c,\$n); return _mul($c,$x, _pow($c,$n,$y)); + $n = _new($c,$n); return _mul($c,$x, _pow($c,$n,$y)); } # shortcut (faster) for shifting by 10) since we are in base 10eX @@ -1260,7 +1268,7 @@ sub _pow my $pow2 = _one(); - my $y_bin = ${_as_bin($c,$cy)}; $y_bin =~ s/^0b//; + my $y_bin = _as_bin($c,$cy); $y_bin =~ s/^0b//; my $len = length($y_bin); while (--$len > 0) { @@ -1354,6 +1362,8 @@ sub _fac $cx; # return result } +############################################################################# + sub _log_int { # calculate integer log of $x to base $base @@ -1422,7 +1432,7 @@ sub _log_int my $a; my $base_mul = _mul($c, _copy($c,$base), $base); - while (($a = _acmp($x,$trial,$x_org)) < 0) + while (($a = _acmp($c,$trial,$x_org)) < 0) { _mul($c,$trial,$base_mul); _add($c, $x, [2]); } @@ -1433,7 +1443,7 @@ sub _log_int # overstepped the result _dec($c, $x); _div($c,$trial,$base); - $a = _acmp($x,$trial,$x_org); + $a = _acmp($c,$trial,$x_org); if ($a > 0) { _dec($c, $x); @@ -1507,7 +1517,7 @@ sub _sqrt # an even better guess. Not implemented yet. Does it improve performance? $x->[$l--] = 0 while ($l >= 0); # all other digits of guess are zero - print "start x= ",${_str($c,$x)},"\n" if DEBUG; + print "start x= ",_str($c,$x),"\n" if DEBUG; my $two = _two(); my $last = _zero(); my $lastlast = _zero(); @@ -1519,7 +1529,7 @@ sub _sqrt $last = _copy($c,$x); _add($c,$x, _div($c,_copy($c,$y),$x)); _div($c,$x, $two ); - print " x= ",${_str($c,$x)},"\n" if DEBUG; + print " x= ",_str($c,$x),"\n" if DEBUG; } print "\nsteps in sqrt: $steps, " if DEBUG; _dec($c,$x) if _acmp($c,$y,_mul($c,_copy($c,$x),$x)) < 0; # overshot? @@ -1556,7 +1566,7 @@ sub _root # if $n is a power of two, we can repeatedly take sqrt($X) and find the # proper result, because sqrt(sqrt($x)) == root($x,4) my $b = _as_bin($c,$n); - if ($$b =~ /0b1(0+)$/) + if ($b =~ /0b1(0+)$/) { my $count = CORE::length($1); # 0b100 => len('00') => 2 my $cnt = $count; # counter for loop @@ -1658,13 +1668,13 @@ sub _and ($y1, $yr) = _div($c,$y1,$mask); # make ints() from $xr, $yr - # this is when the AND_BITS are greater tahn $BASE and is slower for + # this is when the AND_BITS are greater than $BASE and is slower for # small (<256 bits) numbers, but faster for large numbers. Disabled # due to KISS principle # $b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; } # $b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; } -# _add($c,$x, _mul($c, _new( $c, \($xrr & $yrr) ), $m) ); +# _add($c,$x, _mul($c, _new( $c, ($xrr & $yrr) ), $m) ); # 0+ due to '&' doesn't work in strings _add($c,$x, _mul($c, [ 0+$xr->[0] & 0+$yr->[0] ], $m) ); @@ -1694,7 +1704,7 @@ sub _xor # make ints() from $xr, $yr (see _and()) #$b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; } #$b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; } - #_add($c,$x, _mul($c, _new( $c, \($xrr ^ $yrr) ), $m) ); + #_add($c,$x, _mul($c, _new( $c, ($xrr ^ $yrr) ), $m) ); # 0+ due to '^' doesn't work in strings _add($c,$x, _mul($c, [ 0+$xr->[0] ^ 0+$yr->[0] ], $m) ); @@ -1730,7 +1740,7 @@ sub _or # make ints() from $xr, $yr (see _and()) # $b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; } # $b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; } -# _add($c,$x, _mul($c, _new( $c, \($xrr | $yrr) ), $m) ); +# _add($c,$x, _mul($c, _new( $c, ($xrr | $yrr) ), $m) ); # 0+ due to '|' doesn't work in strings _add($c,$x, _mul($c, [ 0+$xr->[0] | 0+$yr->[0] ], $m) ); @@ -1754,7 +1764,7 @@ sub _as_hex if (@$x == 1) { my $t = sprintf("0x%x",$x->[0]); - return \$t; + return $t; } my $x1 = _copy($c,$x); @@ -1778,7 +1788,7 @@ sub _as_hex $es = reverse $es; $es =~ s/^[0]+//; # strip leading zeros $es = '0x' . $es; - \$es; + $es; } sub _as_bin @@ -1790,12 +1800,12 @@ sub _as_bin # handle zero case for older Perls if ($] <= 5.005 && @$x == 1 && $x->[0] == 0) { - my $t = '0b0'; return \$t; + my $t = '0b0'; return $t; } if (@$x == 1 && $] >= 5.006) { my $t = sprintf("0b%b",$x->[0]); - return \$t; + return $t; } my $x1 = _copy($c,$x); @@ -1819,7 +1829,7 @@ sub _as_bin $es = reverse $es; $es =~ s/^[0]+//; # strip leading zeros $es = '0b' . $es; - \$es; + $es; } sub _from_hex @@ -1831,12 +1841,12 @@ sub _from_hex my $m = [ 0x10000 ]; # 16 bit at a time my $x = _zero(); - my $len = length($$hs)-2; + my $len = length($hs)-2; $len = int($len/4); # 4-digit parts, w/o '0x' my $val; my $i = -4; while ($len >= 0) { - $val = substr($$hs,$i,4); + $val = substr($hs,$i,4); $val =~ s/^[+-]?0x// if $len == 0; # for last part only because $val = hex($val); # hex does not like wrong chars $i -= 4; $len --; @@ -1854,13 +1864,13 @@ sub _from_bin # instead of converting X (8) bit at a time, it is faster to "convert" the # number to hex, and then call _from_hex. - my $hs = $$bs; + my $hs = $bs; $hs =~ s/^[+-]?0b//; # remove sign and 0b my $l = length($hs); # bits $hs = '0' x (8-($l % 8)) . $hs if ($l % 8) != 0; # padd left side w/ 0 my $h = unpack('H*', pack ('B*', $hs)); # repack as hex - $c->_from_hex(\('0x'.$h)); + $c->_from_hex('0x'.$h); } ############################################################################## @@ -1918,7 +1928,7 @@ sub _modpow my $acc = _copy($c,$num); my $t = _one(); - my $expbin = ${_as_bin($c,$exp)}; $expbin =~ s/^0b//; + my $expbin = _as_bin($c,$exp); $expbin =~ s/^0b//; my $len = length($expbin); while (--$len >= 0) { @@ -1934,6 +1944,20 @@ sub _modpow $num; } +sub _gcd + { + # greatest common divisor + my ($c,$x,$y) = @_; + + while (! _is_zero($c,$y)) + { + my $t = _copy($c,$y); + $y = _mod($c, $x, $y); + $x = $t; + } + $x; + } + ############################################################################## ############################################################################## @@ -1966,11 +1990,14 @@ version like 'Pari'. =head1 METHODS The following functions MUST be defined in order to support the use by -Math::BigInt: +Math::BigInt v1.70 or later: + api_version() return API version, minimum 1 for v1.70 _new(string) return ref to new object from ref to decimal string _zero() return a new object with value 0 _one() return a new object with value 1 + _two() return a new object with value 2 + _ten() return a new object with value 10 _str(obj) return ref to a string representing the object _num(obj) returns a Perl integer/floating point number @@ -2000,7 +2027,9 @@ Math::BigInt: _len(obj) returns count of the decimal digits of the object _digit(obj,n) returns the n'th decimal digit of object - _is_one(obj) return true if argument is +1 + _is_one(obj) return true if argument is 1 + _is_two(obj) return true if argument is 2 + _is_ten(obj) return true if argument is 10 _is_zero(obj) return true if argument is 0 _is_even(obj) return true if argument is even (0,2,4,6..) _is_odd(obj) return true if argument is odd (1,3,5,7..) @@ -2010,14 +2039,10 @@ Math::BigInt: _check(obj) check whether internal representation is still intact return 0 for ok, otherwise error message as string -The following functions are optional, and can be defined if the underlying lib -has a fast way to do them. If undefined, Math::BigInt will use pure Perl (hence -slow) fallback routines to emulate these: - _from_hex(str) return ref to new object from ref to hexadecimal string _from_bin(str) return ref to new object from ref to binary string - _as_hex(str) return ref to scalar string containing the value as + _as_hex(str) return string containing the value as unsigned hex string, with the '0x' prepended. Leading zeros must be stripped. _as_bin(str) Like as_hex, only as binary string containing only @@ -2025,27 +2050,19 @@ slow) fallback routines to emulate these: '0b' must be prepended. _rsft(obj,N,B) shift object in base B by N 'digits' right - For unsupported bases B, return undef to signal failure _lsft(obj,N,B) shift object in base B by N 'digits' left - For unsupported bases B, return undef to signal failure _xor(obj1,obj2) XOR (bit-wise) object 1 with object 2 Note: XOR, AND and OR pad with zeros if size mismatches _and(obj1,obj2) AND (bit-wise) object 1 with object 2 _or(obj1,obj2) OR (bit-wise) object 1 with object 2 - _signed_or - _signed_and - _signed_xor - _mod(obj,obj) Return remainder of div of the 1st by the 2nd object _sqrt(obj) return the square root of object (truncated to int) _root(obj) return the n'th (n >= 3) root of obj (truncated to int) _fac(obj) return factorial of object 1 (1*2*3*4..) _pow(obj,obj) return object 1 to the power of object 2 return undef for NaN - _gcd(obj,obj) return Greatest Common Divisor of two objects - _zeros(obj) return number of trailing decimal zeros _modinv return inverse modulus _modpow return modulus of power ($x ** $y) % $z @@ -2055,6 +2072,16 @@ slow) fallback routines to emulate these: 1 : result is exactly RESULT 0 : result was truncated to RESULT undef : unknown whether result is exactly RESULT + _gcd(obj,obj) return Greatest Common Divisor of two objects + +The following functions are optional, and can be defined if the underlying lib +has a fast way to do them. If undefined, Math::BigInt will use pure Perl (hence +slow) fallback routines to emulate these: + + _signed_or + _signed_and + _signed_xor + Input strings come in as unsigned but with prefix (i.e. as '123', '0xabc' or '0b1101'). @@ -2072,11 +2099,6 @@ returning a different reference. Return values are always references to objects, strings, or true/false for comparisation routines. -Exceptions are C<_lsft()> and C<_rsft()>, which return undef if they can not -shift the argument. This is used to delegate shifting of bases different than -the one you can support back to Math::BigInt, which will use some generic code -to calculate the result. - =head1 WRAP YOUR OWN If you want to port your own favourite c-lib for big numbers to the @@ -2103,6 +2125,7 @@ Original math code by Mark Biggar, rewritten by Tels L<http://bloodgate.com/> in late 2000. Seperated from BigInt and shaped API with the help of John Peacock. Fixed, sped-up and enhanced by Tels http://bloodgate.com 2001-2003. +Further streamlining (api_version 1) by Tels 2004. =head1 SEE ALSO diff --git a/lib/Math/BigInt/CalcEmu.pm b/lib/Math/BigInt/CalcEmu.pm index c95b32fb3b..9f7fd16434 100644 --- a/lib/Math/BigInt/CalcEmu.pm +++ b/lib/Math/BigInt/CalcEmu.pm @@ -5,7 +5,7 @@ use strict; # use warnings; # dont use warnings for older Perls use vars qw/$VERSION/; -$VERSION = '0.03'; +$VERSION = '0.04'; package Math::BigInt; @@ -18,141 +18,6 @@ BEGIN $CALC_EMU = Math::BigInt->config()->{'lib'}; } -sub __emu_blog - { - my ($self,$x,$base,@r) = @_; - - return $x->bnan() if $x->is_zero() || $base->is_zero() || $base->is_one(); - - my $acmp = $x->bacmp($base); - return $x->bone('+',@r) if $acmp == 0; - return $x->bzero(@r) if $acmp < 0 || $x->is_one(); - - # blog($x,$base) ** $base + $y = $x - - # this trial multiplication is very fast, even for large counts (like for - # 2 ** 1024, since this still requires only 1024 very fast steps - # (multiplication of a large number by a very small number is very fast)) - # See Calc for an even faster algorightmn - my $x_org = $x->copy(); # preserve orgx - $x->bzero(); # keep ref to $x - my $trial = $base->copy(); - while ($trial->bacmp($x_org) <= 0) - { - $trial->bmul($base); $x->binc(); - } - $x->round(@r); - } - -sub __emu_bmodinv - { - my ($self,$x,$y,@r) = @_; - - my ($u, $u1) = ($self->bzero(), $self->bone()); - my ($a, $b) = ($y->copy(), $x->copy()); - - # first step need always be done since $num (and thus $b) is never 0 - # Note that the loop is aligned so that the check occurs between #2 and #1 - # thus saving us one step #2 at the loop end. Typical loop count is 1. Even - # a case with 28 loops still gains about 3% with this layout. - my $q; - ($a, $q, $b) = ($b, $a->bdiv($b)); # step #1 - # Euclid's Algorithm (calculate GCD of ($a,$b) in $a and also calculate - # two values in $u and $u1, we use only $u1 afterwards) - my $sign = 1; # flip-flop - while (!$b->is_zero()) # found GCD if $b == 0 - { - # the original algorithm had: - # ($u, $u1) = ($u1, $u->bsub($u1->copy()->bmul($q))); # step #2 - # The following creates exact the same sequence of numbers in $u1, - # except for the sign ($u1 is now always positive). Since formerly - # the sign of $u1 was alternating between '-' and '+', the $sign - # flip-flop will take care of that, so that at the end of the loop - # we have the real sign of $u1. Keeping numbers positive gains us - # speed since badd() is faster than bsub() and makes it possible - # to have the algorithmn in Calc for even more speed. - - ($u, $u1) = ($u1, $u->badd($u1->copy()->bmul($q))); # step #2 - $sign = - $sign; # flip sign - - ($a, $q, $b) = ($b, $a->bdiv($b)); # step #1 again - } - - # If the gcd is not 1, then return NaN! It would be pointless to have - # called bgcd to check this first, because we would then be performing - # the same Euclidean Algorithm *twice* in case the gcd is 1. - return $x->bnan() unless $a->is_one(); - - $u1->bneg() if $sign != 1; # need to flip? - - $u1->bmod($y); # calc result - $x->{value} = $u1->{value}; # and copy over to $x - $x->{sign} = $u1->{sign}; # to modify in place - $x->round(@r); - } - -sub __emu_bmodpow - { - my ($self,$num,$exp,$mod,@r) = @_; - - # in the trivial case, - return $num->bzero(@r) if $mod->is_one(); - return $num->bone('+',@r) if $num->is_zero() or $num->is_one(); - - # $num->bmod($mod); # if $x is large, make it smaller first - my $acc = $num->copy(); # but this is not really faster... - - $num->bone(); # keep ref to $num - - my $expbin = $exp->as_bin(); $expbin =~ s/^[-]?0b//; # ignore sign and prefix - my $len = CORE::length($expbin); - while (--$len >= 0) - { - $num->bmul($acc)->bmod($mod) if substr($expbin,$len,1) eq '1'; - $acc->bmul($acc)->bmod($mod); - } - - $num->round(@r); - } - -sub __emu_bfac - { - my ($self,$x,@r) = @_; - - return $x->bone('+',@r) if $x->is_zero() || $x->is_one(); # 0 or 1 => 1 - - my $n = $x->copy(); - $x->bone(); - # seems we need not to temp. clear A/P of $x since the result is the same - my $f = $self->new(2); - while ($f->bacmp($n) < 0) - { - $x->bmul($f); $f->binc(); - } - $x->bmul($f,@r); # last step and also round result - } - -sub __emu_bpow - { - my ($self,$x,$y,@r) = @_; - - return $x->bone('+',@r) if $y->is_zero(); - return $x->round(@r) if $x->is_one() || $y->is_one(); - return $x->round(@r) if $x->is_zero(); # 0**y => 0 (if not y <= 0) - - my $pow2 = $self->bone(); - my $y_bin = $y->as_bin(); $y_bin =~ s/^0b//; - my $len = CORE::length($y_bin); - while (--$len > 0) - { - $pow2->bmul($x) if substr($y_bin,$len,1) eq '1'; # is odd? - $x->bmul($x); - } - $x->bmul($pow2); - $x->round(@r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0; - $x; - } - sub __emu_band { my ($self,$x,$y,$sx,$sy,@r) = @_; @@ -194,26 +59,29 @@ sub __emu_band $bx = reverse $bx; $by = reverse $by; - # cut the longer string to the length of the shorter one (the result would - # be 0 due to AND anyway) + # padd the shorter string + my $xx = "\x00"; $xx = "\x0f" if $sx == -1; + my $yy = "\x00"; $yy = "\x0f" if $sy == -1; my $diff = CORE::length($bx) - CORE::length($by); if ($diff > 0) { - $bx = substr($bx,0,CORE::length($by)); + # if $yy eq "\x00", we can cut $bx, otherwise we need to padd $by + $by .= $yy x $diff; } elsif ($diff < 0) { - $by = substr($by,0,CORE::length($bx)); + # if $xx eq "\x00", we can cut $by, otherwise we need to padd $bx + $bx .= $xx x abs($diff); } - + # and the strings together my $r = $bx & $by; # and reverse the result again $bx = reverse $r; - # one of $x or $y was negative, so need to flip bits in the result - # in both cases (one or two of them negative, or both positive) we need + # One of $x or $y was negative, so need to flip bits in the result. + # In both cases (one or two of them negative, or both positive) we need # to get the characters back. if ($sign == 1) { @@ -224,20 +92,12 @@ sub __emu_band $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/; } + # leading zeros will be stripped by _from_hex() $bx = '0x' . $bx; - if ($CALC_EMU->can('_from_hex')) - { - $x->{value} = $CALC_EMU->_from_hex( \$bx ); - } - else - { - $r = $self->new($bx); - $x->{value} = $r->{value}; - } + $x->{value} = $CALC_EMU->_from_hex( $bx ); # calculate sign of result $x->{sign} = '+'; - #$x->{sign} = '-' if $sx == $sy && $sx == -1 && !$x->is_zero(); $x->{sign} = '-' if $sign == 1 && !$x->is_zero(); $x->bdec() if $sign == 1; @@ -317,16 +177,13 @@ sub __emu_bior $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/; } + # leading zeros will be stripped by _from_hex() $bx = '0x' . $bx; - if ($CALC_EMU->can('_from_hex')) - { - $x->{value} = $CALC_EMU->_from_hex( \$bx ); - } - else - { - $r = $self->new($bx); - $x->{value} = $r->{value}; - } + $x->{value} = $CALC_EMU->_from_hex( $bx ); + + # calculate sign of result + $x->{sign} = '+'; + $x->{sign} = '-' if $sign == 1 && !$x->is_zero(); # if one of X or Y was negative, we need to decrement result $x->bdec() if $sign == 1; @@ -406,16 +263,9 @@ sub __emu_bxor $bx =~ tr/\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00/fedcba9876543210/; } + # leading zeros will be stripped by _from_hex() $bx = '0x' . $bx; - if ($CALC_EMU->can('_from_hex')) - { - $x->{value} = $CALC_EMU->_from_hex( \$bx ); - } - else - { - $r = $self->new($bx); - $x->{value} = $r->{value}; - } + $x->{value} = $CALC_EMU->_from_hex( $bx ); # calculate sign of result $x->{sign} = '+'; @@ -426,170 +276,6 @@ sub __emu_bxor $x->round(@r); } -sub __emu_bsqrt - { - my ($self,$x,@r) = @_; - - # this is slow: - return $x->round(@r) if $x->is_zero(); # 0,1 => 0,1 - - return $x->bone('+',@r) if $x < 4; # 1,2,3 => 1 - my $y = $x->copy(); - my $l = int($x->length()/2); - - $x->bone(); # keep ref($x), but modify it - $x->blsft($l,10) if $l != 0; # first guess: 1.('0' x (l/2)) - - my $last = $self->bzero(); - my $two = $self->new(2); - my $lastlast = $self->bzero(); - #my $lastlast = $x+$two; - while ($last != $x && $lastlast != $x) - { - $lastlast = $last; $last = $x->copy(); - $x->badd($y / $x); - $x->bdiv($two); - } - $x->bdec() if $x * $x > $y; # overshot? - $x->round(@r); - } - -sub __emu_broot - { - my ($self,$x,$y,@r) = @_; - - return $x->bsqrt() if $y->bacmp(2) == 0; # 2 => square root - - # since we take at least a cubic root, and only 8 ** 1/3 >= 2 (==2): - return $x->bone('+',@r) if $x < 8; # $x=2..7 => 1 - - my $num = $x->numify(); - - if ($num <= 1000000) - { - $x = $self->new( int ( sprintf ("%.8f", $num ** (1 / $y->numify() )))); - return $x->round(@r); - } - - # if $n is a power of two, we can repeatedly take sqrt($X) and find the - # proper result, because sqrt(sqrt($x)) == root($x,4) - # See Calc.pm for more details - my $b = $y->as_bin(); - if ($b =~ /0b1(0+)$/) - { - my $count = CORE::length($1); # 0b100 => len('00') => 2 - my $cnt = $count; # counter for loop - my $shift = $self->new(6); - $x->blsft($shift); # add some zeros (even amount) - while ($cnt-- > 0) - { - # 'inflate' $X by adding more zeros - $x->blsft($shift); - # calculate sqrt($x), $x is now a bit too big, again. In the next - # round we make even bigger, again. - $x->bsqrt($x); - } - # $x is still to big, so truncate result - $x->brsft($shift); - } - else - { - # trial computation by starting with 2,4,6,8,10 etc until we overstep - my $step; - my $trial = $self->new(2); - my $two = $self->new(2); - my $s_128 = $self->new(128); - - local undef $Math::BigInt::accuracy; - local undef $Math::BigInt::precision; - - # while still to do more than X steps - do - { - $step = $self->new(2); - while ( $trial->copy->bpow($y)->bacmp($x) < 0) - { - $step->bmul($two); - $trial->badd($step); - } - - # hit exactly? - if ( $trial->copy->bpow($y)->bacmp($x) == 0) - { - $x->{value} = $trial->{value}; # make copy while preserving ref to $x - return $x->round(@r); - } - # overstepped, so go back on step - $trial->bsub($step); - } while ($step > $s_128); - - $step = $two->copy(); - while ( $trial->copy->bpow($y)->bacmp($x) < 0) - { - $trial->badd($step); - } - - # not hit exactly? - if ( $x->bacmp( $trial->copy()->bpow($y) ) < 0) - { - $trial->bdec(); - } - # copy result into $x (preserve ref) - $x->{value} = $trial->{value}; - } - $x->round(@r); - } - -sub __emu_as_hex - { - my ($self,$x,$s) = @_; - - return '0x0' if $x->is_zero(); - - my $x1 = $x->copy()->babs(); my ($xr,$x10000,$h,$es); - if ($] >= 5.006) - { - $x10000 = $self->new (0x10000); $h = 'h4'; - } - else - { - $x10000 = $self->new (0x1000); $h = 'h3'; - } - while (!$x1->is_zero()) - { - ($x1, $xr) = bdiv($x1,$x10000); - $es .= unpack($h,pack('v',$xr->numify())); - } - $es = reverse $es; - $es =~ s/^[0]+//; # strip leading zeros - $s . '0x' . $es; - } - -sub __emu_as_bin - { - my ($self,$x,$s) = @_; - - return '0b0' if $x->is_zero(); - - my $x1 = $x->copy()->babs(); my ($xr,$x10000,$b,$es); - if ($] >= 5.006) - { - $x10000 = $self->new (0x10000); $b = 'b16'; - } - else - { - $x10000 = $self->new (0x1000); $b = 'b12'; - } - while (!$x1->is_zero()) - { - ($x1, $xr) = bdiv($x1,$x10000); - $es .= unpack($b,pack('v',$xr->numify())); - } - $es = reverse $es; - $es =~ s/^[0]+//; # strip leading zeros - $s . '0b' . $es; - } - ############################################################################## ############################################################################## @@ -622,7 +308,7 @@ the same terms as Perl itself. =head1 AUTHORS -(c) Tels http://bloodgate.com 2003 - based on BigInt code by +(c) Tels http://bloodgate.com 2003, 2004 - based on BigInt code by Tels from 2001-2003. =head1 SEE ALSO diff --git a/lib/Math/BigInt/t/bare_mbf.t b/lib/Math/BigInt/t/bare_mbf.t index 08ac4c2ad4..9f946717d2 100644 --- a/lib/Math/BigInt/t/bare_mbf.t +++ b/lib/Math/BigInt/t/bare_mbf.t @@ -27,7 +27,7 @@ BEGIN } print "# INC = @INC\n"; - plan tests => 1772; + plan tests => 1814; } use Math::BigFloat lib => 'BareCalc'; diff --git a/lib/Math/BigInt/t/bare_mbi.t b/lib/Math/BigInt/t/bare_mbi.t index 0cc055e2c2..6514e1ec43 100644 --- a/lib/Math/BigInt/t/bare_mbi.t +++ b/lib/Math/BigInt/t/bare_mbi.t @@ -26,7 +26,7 @@ BEGIN } print "# INC = @INC\n"; - plan tests => 2770; + plan tests => 2832; } use Math::BigInt lib => 'BareCalc'; diff --git a/lib/Math/BigInt/t/bare_mif.t b/lib/Math/BigInt/t/bare_mif.t index 00629fd9a5..0cc1de9365 100644 --- a/lib/Math/BigInt/t/bare_mif.t +++ b/lib/Math/BigInt/t/bare_mif.t @@ -28,7 +28,7 @@ BEGIN } print "# INC = @INC\n"; - plan tests => 679 + plan tests => 684 + 1; # our own tests } diff --git a/lib/Math/BigInt/t/bigfltpm.inc b/lib/Math/BigInt/t/bigfltpm.inc index 34d264a911..d307ee6a27 100644 --- a/lib/Math/BigInt/t/bigfltpm.inc +++ b/lib/Math/BigInt/t/bigfltpm.inc @@ -30,7 +30,7 @@ while (<DATA>) { @args = split(/:/,$_,99); $ans = pop(@args); } - $try = "\$x = $class->new('$args[0]');"; + $try = "\$x = $class->new(\"$args[0]\");"; if ($f eq "fnorm") { $try .= "\$x;"; @@ -142,7 +142,7 @@ while (<DATA>) # trailing zeros #print $ans1->_trailing_zeros(),"\n"; print "# Has trailing zeros after '$try'\n" - if !ok ($ans1->{_m}->_trailing_zeros(), 0); + if !ok ($CL->_zeros( $ans1->{_m}), 0); } } } # end pattern or string @@ -165,9 +165,11 @@ ok ($y,1200); ok ($x,1200); my $monster = '1e1234567890123456789012345678901234567890'; -# new +# new and exponent ok ($class->new($monster)->bsstr(), '1e+1234567890123456789012345678901234567890'); +ok ($class->new($monster)->exponent(), + '1234567890123456789012345678901234567890'); # cmp ok ($class->new($monster) > 0,1); @@ -176,6 +178,11 @@ ok ($class->new($monster)->bsub( $monster),0); ok ($class->new($monster)->bmul(2)->bsstr(), '2e+1234567890123456789012345678901234567890'); +# mantissa +$monster = '1234567890123456789012345678901234567890e2'; +ok ($class->new($monster)->mantissa(), + '123456789012345678901234567890123456789'); + ############################################################################### # zero,inf,one,nan @@ -476,6 +483,18 @@ abc:NaN -3e111:-3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -4e-1111:-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004 &fpow +NaN:1:NaN +1:NaN:NaN +NaN:-1:NaN +-1:NaN:NaN +NaN:-21:NaN +-21:NaN:NaN +NaN:21:NaN +21:NaN:NaN +0:0:1 +0:1:0 +0:9:0 +0:-2:inf 2:2:4 1:2:1 1:3:1 @@ -491,6 +510,14 @@ abc:123.456:NaN -inf:123.45:-inf +inf:-123.45:inf -inf:-123.45:-inf +-2:2:4 +-2:3:-8 +-2:4:16 +-2:5:-32 +-3:2:9 +-3:3:-27 +-3:4:81 +-3:5:-243 # 2 ** 0.5 == sqrt(2) # 1.41..7 and not 1.4170 since fallback (bsqrt(9) is '3', not 3.0...0) 2:0.5:1.41421356237309504880168872420969807857 diff --git a/lib/Math/BigInt/t/bigfltpm.t b/lib/Math/BigInt/t/bigfltpm.t index 84741bad23..3fce4605b3 100755 --- a/lib/Math/BigInt/t/bigfltpm.t +++ b/lib/Math/BigInt/t/bigfltpm.t @@ -26,7 +26,7 @@ BEGIN } print "# INC = @INC\n"; - plan tests => 1772 + plan tests => 1814 + 2; # own tests } @@ -38,6 +38,6 @@ $class = "Math::BigFloat"; $CL = "Math::BigInt::Calc"; ok ($class->config()->{class},$class); -ok ($class->config()->{with},'Math::BigInt'); +ok ($class->config()->{with}, $CL); require 'bigfltpm.inc'; # all tests here for sharing diff --git a/lib/Math/BigInt/t/bigintc.t b/lib/Math/BigInt/t/bigintc.t index 1f0804cf9c..f0aa66dea0 100644 --- a/lib/Math/BigInt/t/bigintc.t +++ b/lib/Math/BigInt/t/bigintc.t @@ -8,15 +8,11 @@ BEGIN $| = 1; chdir 't' if -d 't'; unshift @INC, '../lib'; # for running manually + plan tests => 308; } use Math::BigInt::Calc; -BEGIN - { - plan tests => 300; - } - my ($BASE_LEN, $AND_BITS, $XOR_BITS, $OR_BITS, $BASE_LEN_SMALL, $MAX_VAL) = Math::BigInt::Calc->_base_len(); @@ -31,52 +27,59 @@ print "# IOR_BITS = $OR_BITS\n"; my $C = 'Math::BigInt::Calc'; # pass classname to sub's # _new and _str -my $x = $C->_new(\"123"); my $y = $C->_new(\"321"); -ok (ref($x),'ARRAY'); ok (${$C->_str($x)},123); ok (${$C->_str($y)},321); +my $x = $C->_new("123"); my $y = $C->_new("321"); +ok (ref($x),'ARRAY'); ok ($C->_str($x),123); ok ($C->_str($y),321); ############################################################################### # _add, _sub, _mul, _div -ok (${$C->_str($C->_add($x,$y))},444); -ok (${$C->_str($C->_sub($x,$y))},123); -ok (${$C->_str($C->_mul($x,$y))},39483); -ok (${$C->_str($C->_div($x,$y))},123); +ok ($C->_str($C->_add($x,$y)),444); +ok ($C->_str($C->_sub($x,$y)),123); +ok ($C->_str($C->_mul($x,$y)),39483); +ok ($C->_str($C->_div($x,$y)),123); ############################################################################### # check that mul/div doesn't change $y # and returns the same reference, not something new -ok (${$C->_str($C->_mul($x,$y))},39483); -ok (${$C->_str($x)},39483); ok (${$C->_str($y)},321); +ok ($C->_str($C->_mul($x,$y)),39483); +ok ($C->_str($x),39483); ok ($C->_str($y),321); -ok (${$C->_str($C->_div($x,$y))},123); -ok (${$C->_str($x)},123); ok (${$C->_str($y)},321); +ok ($C->_str($C->_div($x,$y)),123); +ok ($C->_str($x),123); ok ($C->_str($y),321); -$x = $C->_new(\"39483"); +$x = $C->_new("39483"); my ($x1,$r1) = $C->_div($x,$y); ok ("$x1","$x"); $C->_inc($x1); ok ("$x1","$x"); -ok (${$C->_str($r1)},'0'); +ok ($C->_str($r1),'0'); -$x = $C->_new(\"39483"); # reset +$x = $C->_new("39483"); # reset ############################################################################### -my $z = $C->_new(\"2"); -ok (${$C->_str($C->_add($x,$z))},39485); +my $z = $C->_new("2"); +ok ($C->_str($C->_add($x,$z)),39485); my ($re,$rr) = $C->_div($x,$y); -ok (${$C->_str($re)},123); ok (${$C->_str($rr)},2); +ok ($C->_str($re),123); ok ($C->_str($rr),2); # is_zero, _is_one, _one, _zero ok ($C->_is_zero($x)||0,0); ok ($C->_is_one($x)||0,0); -ok (${$C->_str($C->_zero())},"0"); -ok (${$C->_str($C->_one())},"1"); +ok ($C->_str($C->_zero()),"0"); +ok ($C->_str($C->_one()),"1"); -# _two() (only used internally) -ok (${$C->_str($C->_two())},"2"); +# _two() and _ten() +ok ($C->_str($C->_two()),"2"); +ok ($C->_str($C->_ten()),"10"); +ok ($C->_is_ten($C->_two()),0); +ok ($C->_is_two($C->_two()),1); +ok ($C->_is_ten($C->_ten()),1); +ok ($C->_is_two($C->_ten()),0); ok ($C->_is_one($C->_one()),1); +ok ($C->_is_one($C->_two()),0); +ok ($C->_is_one($C->_ten()),0); ok ($C->_is_one($C->_zero()) || 0,0); @@ -89,35 +92,35 @@ ok ($C->_is_odd($C->_one()),1); ok ($C->_is_odd($C->_zero())||0,0); ok ($C->_is_even($C->_one()) || 0,0); ok ($C->_is_even($C->_zero()),1); # _len -$x = $C->_new(\"1"); ok ($C->_len($x),1); -$x = $C->_new(\"12"); ok ($C->_len($x),2); -$x = $C->_new(\"123"); ok ($C->_len($x),3); -$x = $C->_new(\"1234"); ok ($C->_len($x),4); -$x = $C->_new(\"12345"); ok ($C->_len($x),5); -$x = $C->_new(\"123456"); ok ($C->_len($x),6); -$x = $C->_new(\"1234567"); ok ($C->_len($x),7); -$x = $C->_new(\"12345678"); ok ($C->_len($x),8); -$x = $C->_new(\"123456789"); ok ($C->_len($x),9); - -$x = $C->_new(\"8"); ok ($C->_len($x),1); -$x = $C->_new(\"21"); ok ($C->_len($x),2); -$x = $C->_new(\"321"); ok ($C->_len($x),3); -$x = $C->_new(\"4321"); ok ($C->_len($x),4); -$x = $C->_new(\"54321"); ok ($C->_len($x),5); -$x = $C->_new(\"654321"); ok ($C->_len($x),6); -$x = $C->_new(\"7654321"); ok ($C->_len($x),7); -$x = $C->_new(\"87654321"); ok ($C->_len($x),8); -$x = $C->_new(\"987654321"); ok ($C->_len($x),9); +$x = $C->_new("1"); ok ($C->_len($x),1); +$x = $C->_new("12"); ok ($C->_len($x),2); +$x = $C->_new("123"); ok ($C->_len($x),3); +$x = $C->_new("1234"); ok ($C->_len($x),4); +$x = $C->_new("12345"); ok ($C->_len($x),5); +$x = $C->_new("123456"); ok ($C->_len($x),6); +$x = $C->_new("1234567"); ok ($C->_len($x),7); +$x = $C->_new("12345678"); ok ($C->_len($x),8); +$x = $C->_new("123456789"); ok ($C->_len($x),9); + +$x = $C->_new("8"); ok ($C->_len($x),1); +$x = $C->_new("21"); ok ($C->_len($x),2); +$x = $C->_new("321"); ok ($C->_len($x),3); +$x = $C->_new("4321"); ok ($C->_len($x),4); +$x = $C->_new("54321"); ok ($C->_len($x),5); +$x = $C->_new("654321"); ok ($C->_len($x),6); +$x = $C->_new("7654321"); ok ($C->_len($x),7); +$x = $C->_new("87654321"); ok ($C->_len($x),8); +$x = $C->_new("987654321"); ok ($C->_len($x),9); for (my $i = 1; $i < 9; $i++) { my $a = "$i" . '0' x ($i-1); - $x = $C->_new(\$a); + $x = $C->_new($a); print "# Tried len '$a'\n" unless ok ($C->_len($x),$i); } # _digit -$x = $C->_new(\"123456789"); +$x = $C->_new("123456789"); ok ($C->_digit($x,0),9); ok ($C->_digit($x,1),8); ok ($C->_digit($x,2),7); @@ -128,201 +131,202 @@ ok ($C->_digit($x,-3),3); # _copy foreach (qw/ 1 12 123 1234 12345 123456 1234567 12345678 123456789/) { - $x = $C->_new(\"$_"); - ok (${$C->_str($C->_copy($x))},"$_"); - ok (${$C->_str($x)},"$_"); # did _copy destroy original x? + $x = $C->_new("$_"); + ok ($C->_str($C->_copy($x)),"$_"); + ok ($C->_str($x),"$_"); # did _copy destroy original x? } # _zeros -$x = $C->_new(\"1256000000"); ok ($C->_zeros($x),6); -$x = $C->_new(\"152"); ok ($C->_zeros($x),0); -$x = $C->_new(\"123000"); ok ($C->_zeros($x),3); +$x = $C->_new("1256000000"); ok ($C->_zeros($x),6); +$x = $C->_new("152"); ok ($C->_zeros($x),0); +$x = $C->_new("123000"); ok ($C->_zeros($x),3); +$x = $C->_new("0"); ok ($C->_zeros($x),0); # _lsft, _rsft -$x = $C->_new(\"10"); $y = $C->_new(\"3"); -ok (${$C->_str($C->_lsft($x,$y,10))},10000); -$x = $C->_new(\"20"); $y = $C->_new(\"3"); -ok (${$C->_str($C->_lsft($x,$y,10))},20000); +$x = $C->_new("10"); $y = $C->_new("3"); +ok ($C->_str($C->_lsft($x,$y,10)),10000); +$x = $C->_new("20"); $y = $C->_new("3"); +ok ($C->_str($C->_lsft($x,$y,10)),20000); -$x = $C->_new(\"128"); $y = $C->_new(\"4"); -ok (${$C->_str($C->_lsft($x,$y,2))}, 128 << 4); +$x = $C->_new("128"); $y = $C->_new("4"); +ok ($C->_str($C->_lsft($x,$y,2)), 128 << 4); -$x = $C->_new(\"1000"); $y = $C->_new(\"3"); -ok (${$C->_str($C->_rsft($x,$y,10))},1); -$x = $C->_new(\"20000"); $y = $C->_new(\"3"); -ok (${$C->_str($C->_rsft($x,$y,10))},20); -$x = $C->_new(\"256"); $y = $C->_new(\"4"); -ok (${$C->_str($C->_rsft($x,$y,2))},256 >> 4); +$x = $C->_new("1000"); $y = $C->_new("3"); +ok ($C->_str($C->_rsft($x,$y,10)),1); +$x = $C->_new("20000"); $y = $C->_new("3"); +ok ($C->_str($C->_rsft($x,$y,10)),20); +$x = $C->_new("256"); $y = $C->_new("4"); +ok ($C->_str($C->_rsft($x,$y,2)),256 >> 4); -$x = $C->_new(\"6411906467305339182857313397200584952398"); -$y = $C->_new(\"45"); -ok (${$C->_str($C->_rsft($x,$y,10))},0); +$x = $C->_new("6411906467305339182857313397200584952398"); +$y = $C->_new("45"); +ok ($C->_str($C->_rsft($x,$y,10)),0); # _acmp -$x = $C->_new(\"123456789"); -$y = $C->_new(\"987654321"); +$x = $C->_new("123456789"); +$y = $C->_new("987654321"); ok ($C->_acmp($x,$y),-1); ok ($C->_acmp($y,$x),1); ok ($C->_acmp($x,$x),0); ok ($C->_acmp($y,$y),0); -$x = $C->_new(\"12"); -$y = $C->_new(\"12"); +$x = $C->_new("12"); +$y = $C->_new("12"); ok ($C->_acmp($x,$y),0); -$x = $C->_new(\"21"); +$x = $C->_new("21"); ok ($C->_acmp($x,$y),1); ok ($C->_acmp($y,$x),-1); -$x = $C->_new(\"123456789"); -$y = $C->_new(\"1987654321"); +$x = $C->_new("123456789"); +$y = $C->_new("1987654321"); ok ($C->_acmp($x,$y),-1); ok ($C->_acmp($y,$x),+1); -$x = $C->_new(\"1234567890123456789"); -$y = $C->_new(\"987654321012345678"); +$x = $C->_new("1234567890123456789"); +$y = $C->_new("987654321012345678"); ok ($C->_acmp($x,$y),1); ok ($C->_acmp($y,$x),-1); ok ($C->_acmp($x,$x),0); ok ($C->_acmp($y,$y),0); -$x = $C->_new(\"1234"); -$y = $C->_new(\"987654321012345678"); +$x = $C->_new("1234"); +$y = $C->_new("987654321012345678"); ok ($C->_acmp($x,$y),-1); ok ($C->_acmp($y,$x),1); ok ($C->_acmp($x,$x),0); ok ($C->_acmp($y,$y),0); # _modinv -$x = $C->_new(\"8"); -$y = $C->_new(\"5033"); +$x = $C->_new("8"); +$y = $C->_new("5033"); my ($xmod,$sign) = $C->_modinv($x,$y); -ok (${$C->_str($xmod)},'629'); # -629 % 5033 == 4404 +ok ($C->_str($xmod),'629'); # -629 % 5033 == 4404 ok ($sign, '-'); # _div -$x = $C->_new(\"3333"); $y = $C->_new(\"1111"); -ok (${$C->_str(scalar $C->_div($x,$y))},3); -$x = $C->_new(\"33333"); $y = $C->_new(\"1111"); ($x,$y) = $C->_div($x,$y); -ok (${$C->_str($x)},30); ok (${$C->_str($y)},3); -$x = $C->_new(\"123"); $y = $C->_new(\"1111"); -($x,$y) = $C->_div($x,$y); ok (${$C->_str($x)},0); ok (${$C->_str($y)},123); +$x = $C->_new("3333"); $y = $C->_new("1111"); +ok ($C->_str(scalar $C->_div($x,$y)),3); +$x = $C->_new("33333"); $y = $C->_new("1111"); ($x,$y) = $C->_div($x,$y); +ok ($C->_str($x),30); ok ($C->_str($y),3); +$x = $C->_new("123"); $y = $C->_new("1111"); +($x,$y) = $C->_div($x,$y); ok ($C->_str($x),0); ok ($C->_str($y),123); # _num foreach (qw/1 12 123 1234 12345 1234567 12345678 123456789 1234567890/) { - $x = $C->_new(\"$_"); - ok (ref($x)||'','ARRAY'); ok (${$C->_str($x)},"$_"); + $x = $C->_new("$_"); + ok (ref($x)||'','ARRAY'); ok ($C->_str($x),"$_"); $x = $C->_num($x); ok (ref($x)||'',''); ok ($x,$_); } # _sqrt -$x = $C->_new(\"144"); ok (${$C->_str($C->_sqrt($x))},'12'); -$x = $C->_new(\"144000000000000"); ok (${$C->_str($C->_sqrt($x))},'12000000'); +$x = $C->_new("144"); ok ($C->_str($C->_sqrt($x)),'12'); +$x = $C->_new("144000000000000"); ok ($C->_str($C->_sqrt($x)),'12000000'); # _root -$x = $C->_new(\"81"); my $n = $C->_new(\"3"); # 4*4*4 = 64, 5*5*5 = 125 -ok (${$C->_str($C->_root($x,$n))},'4'); # 4.xx => 4.0 -$x = $C->_new(\"81"); $n = $C->_new(\"4"); # 3*3*3*3 == 81 -ok (${$C->_str($C->_root($x,$n))},'3'); +$x = $C->_new("81"); my $n = $C->_new("3"); # 4*4*4 = 64, 5*5*5 = 125 +ok ($C->_str($C->_root($x,$n)),'4'); # 4.xx => 4.0 +$x = $C->_new("81"); $n = $C->_new("4"); # 3*3*3*3 == 81 +ok ($C->_str($C->_root($x,$n)),'3'); # _pow (and _root) -$x = $C->_new(\"0"); $n = $C->_new(\"3"); # 0 ** y => 0 -ok (${$C->_str($C->_pow($x,$n))}, 0); -$x = $C->_new(\"3"); $n = $C->_new(\"0"); # x ** 0 => 1 -ok (${$C->_str($C->_pow($x,$n))}, 1); -$x = $C->_new(\"1"); $n = $C->_new(\"3"); # 1 ** y => 1 -ok (${$C->_str($C->_pow($x,$n))}, 1); -$x = $C->_new(\"5"); $n = $C->_new(\"1"); # x ** 1 => x -ok (${$C->_str($C->_pow($x,$n))}, 5); +$x = $C->_new("0"); $n = $C->_new("3"); # 0 ** y => 0 +ok ($C->_str($C->_pow($x,$n)), 0); +$x = $C->_new("3"); $n = $C->_new("0"); # x ** 0 => 1 +ok ($C->_str($C->_pow($x,$n)), 1); +$x = $C->_new("1"); $n = $C->_new("3"); # 1 ** y => 1 +ok ($C->_str($C->_pow($x,$n)), 1); +$x = $C->_new("5"); $n = $C->_new("1"); # x ** 1 => x +ok ($C->_str($C->_pow($x,$n)), 5); -$x = $C->_new(\"81"); $n = $C->_new(\"3"); # 81 ** 3 == 531441 -ok (${$C->_str($C->_pow($x,$n))},81 ** 3); +$x = $C->_new("81"); $n = $C->_new("3"); # 81 ** 3 == 531441 +ok ($C->_str($C->_pow($x,$n)),81 ** 3); -ok (${$C->_str($C->_root($x,$n))},81); +ok ($C->_str($C->_root($x,$n)),81); -$x = $C->_new(\"81"); -ok (${$C->_str($C->_pow($x,$n))},81 ** 3); -ok (${$C->_str($C->_pow($x,$n))},'150094635296999121'); # 531441 ** 3 == +$x = $C->_new("81"); +ok ($C->_str($C->_pow($x,$n)),81 ** 3); +ok ($C->_str($C->_pow($x,$n)),'150094635296999121'); # 531441 ** 3 == -ok (${$C->_str($C->_root($x,$n))},'531441'); -ok (${$C->_str($C->_root($x,$n))},'81'); +ok ($C->_str($C->_root($x,$n)),'531441'); +ok ($C->_str($C->_root($x,$n)),'81'); -$x = $C->_new(\"81"); $n = $C->_new(\"14"); -ok (${$C->_str($C->_pow($x,$n))},'523347633027360537213511521'); -ok (${$C->_str($C->_root($x,$n))},'81'); +$x = $C->_new("81"); $n = $C->_new("14"); +ok ($C->_str($C->_pow($x,$n)),'523347633027360537213511521'); +ok ($C->_str($C->_root($x,$n)),'81'); -$x = $C->_new(\"523347633027360537213511520"); -ok (${$C->_str($C->_root($x,$n))},'80'); +$x = $C->_new("523347633027360537213511520"); +ok ($C->_str($C->_root($x,$n)),'80'); -$x = $C->_new(\"523347633027360537213511522"); -ok (${$C->_str($C->_root($x,$n))},'81'); +$x = $C->_new("523347633027360537213511522"); +ok ($C->_str($C->_root($x,$n)),'81'); my $res = [ qw/ 9 31 99 316 999 3162 9999/ ]; # 99 ** 2 = 9801, 999 ** 2 = 998001 etc for my $i (2 .. 9) { - $x = '9' x $i; $x = $C->_new(\$x); - $n = $C->_new(\"2"); + $x = '9' x $i; $x = $C->_new($x); + $n = $C->_new("2"); my $rc = '9' x ($i-1). '8' . '0' x ($i-1) . '1'; print "# _pow( ", '9' x $i, ", 2) \n" unless - ok (${$C->_str($C->_pow($x,$n))},$rc); + ok ($C->_str($C->_pow($x,$n)),$rc); if ($i <= 7) { - $x = '9' x $i; $x = $C->_new(\$x); - $n = '9' x $i; $n = $C->_new(\$n); + $x = '9' x $i; $x = $C->_new($x); + $n = '9' x $i; $n = $C->_new($n); print "# _root( ", '9' x $i, ", ", 9 x $i, ") \n" unless - ok (${$C->_str($C->_root($x,$n))},'1'); + ok ($C->_str($C->_root($x,$n)),'1'); - $x = '9' x $i; $x = $C->_new(\$x); - $n = $C->_new(\"2"); + $x = '9' x $i; $x = $C->_new($x); + $n = $C->_new("2"); print "# _root( ", '9' x $i, ", ", 9 x $i, ") \n" unless - ok (${$C->_str($C->_root($x,$n))}, $res->[$i-2]); + ok ($C->_str($C->_root($x,$n)), $res->[$i-2]); } } ############################################################################## # _fac -$x = $C->_new(\"0"); ok (${$C->_str($C->_fac($x))},'1'); -$x = $C->_new(\"1"); ok (${$C->_str($C->_fac($x))},'1'); -$x = $C->_new(\"2"); ok (${$C->_str($C->_fac($x))},'2'); -$x = $C->_new(\"3"); ok (${$C->_str($C->_fac($x))},'6'); -$x = $C->_new(\"4"); ok (${$C->_str($C->_fac($x))},'24'); -$x = $C->_new(\"5"); ok (${$C->_str($C->_fac($x))},'120'); -$x = $C->_new(\"10"); ok (${$C->_str($C->_fac($x))},'3628800'); -$x = $C->_new(\"11"); ok (${$C->_str($C->_fac($x))},'39916800'); -$x = $C->_new(\"12"); ok (${$C->_str($C->_fac($x))},'479001600'); -$x = $C->_new(\"13"); ok (${$C->_str($C->_fac($x))},'6227020800'); +$x = $C->_new("0"); ok ($C->_str($C->_fac($x)),'1'); +$x = $C->_new("1"); ok ($C->_str($C->_fac($x)),'1'); +$x = $C->_new("2"); ok ($C->_str($C->_fac($x)),'2'); +$x = $C->_new("3"); ok ($C->_str($C->_fac($x)),'6'); +$x = $C->_new("4"); ok ($C->_str($C->_fac($x)),'24'); +$x = $C->_new("5"); ok ($C->_str($C->_fac($x)),'120'); +$x = $C->_new("10"); ok ($C->_str($C->_fac($x)),'3628800'); +$x = $C->_new("11"); ok ($C->_str($C->_fac($x)),'39916800'); +$x = $C->_new("12"); ok ($C->_str($C->_fac($x)),'479001600'); +$x = $C->_new("13"); ok ($C->_str($C->_fac($x)),'6227020800'); # test that _fac modifes $x in place for small arguments -$x = $C->_new(\"3"); $C->_fac($x); ok (${$C->_str($x)},'6'); -$x = $C->_new(\"13"); $C->_fac($x); ok (${$C->_str($x)},'6227020800'); +$x = $C->_new("3"); $C->_fac($x); ok ($C->_str($x),'6'); +$x = $C->_new("13"); $C->_fac($x); ok ($C->_str($x),'6227020800'); ############################################################################## # _inc and _dec foreach (qw/1 11 121 1231 12341 1234561 12345671 123456781 1234567891/) { - $x = $C->_new(\"$_"); $C->_inc($x); - print "# \$x = ",${$C->_str($x)},"\n" - unless ok (${$C->_str($x)},substr($_,0,length($_)-1) . '2'); - $C->_dec($x); ok (${$C->_str($x)},$_); + $x = $C->_new("$_"); $C->_inc($x); + print "# \$x = ",$C->_str($x),"\n" + unless ok ($C->_str($x),substr($_,0,length($_)-1) . '2'); + $C->_dec($x); ok ($C->_str($x),$_); } foreach (qw/19 119 1219 12319 1234519 12345619 123456719 1234567819/) { - $x = $C->_new(\"$_"); $C->_inc($x); - print "# \$x = ",${$C->_str($x)},"\n" - unless ok (${$C->_str($x)},substr($_,0,length($_)-2) . '20'); - $C->_dec($x); ok (${$C->_str($x)},$_); + $x = $C->_new("$_"); $C->_inc($x); + print "# \$x = ",$C->_str($x),"\n" + unless ok ($C->_str($x),substr($_,0,length($_)-2) . '20'); + $C->_dec($x); ok ($C->_str($x),$_); } foreach (qw/999 9999 99999 9999999 99999999 999999999 9999999999 99999999999/) { - $x = $C->_new(\"$_"); $C->_inc($x); - print "# \$x = ",${$C->_str($x)},"\n" - unless ok (${$C->_str($x)}, '1' . '0' x (length($_))); - $C->_dec($x); ok (${$C->_str($x)},$_); + $x = $C->_new("$_"); $C->_inc($x); + print "# \$x = ",$C->_str($x),"\n" + unless ok ($C->_str($x), '1' . '0' x (length($_))); + $C->_dec($x); ok ($C->_str($x),$_); } -$x = $C->_new(\"1000"); $C->_inc($x); ok (${$C->_str($x)},'1001'); -$C->_dec($x); ok (${$C->_str($x)},'1000'); +$x = $C->_new("1000"); $C->_inc($x); ok ($C->_str($x),'1001'); +$C->_dec($x); ok ($C->_str($x),'1000'); my $BL; { @@ -332,45 +336,45 @@ my $BL; $x = '1' . '0' x $BL; $z = '1' . '0' x ($BL-1); $z .= '1'; -$x = $C->_new(\$x); $C->_inc($x); ok (${$C->_str($x)},$z); +$x = $C->_new($x); $C->_inc($x); ok ($C->_str($x),$z); $x = '1' . '0' x $BL; $z = '9' x $BL; -$x = $C->_new(\$x); $C->_dec($x); ok (${$C->_str($x)},$z); +$x = $C->_new($x); $C->_dec($x); ok ($C->_str($x),$z); # should not happen: -# $x = $C->_new(\"-2"); $y = $C->_new(\"4"); ok ($C->_acmp($x,$y),-1); +# $x = $C->_new("-2"); $y = $C->_new("4"); ok ($C->_acmp($x,$y),-1); ############################################################################### # _mod -$x = $C->_new(\"1000"); $y = $C->_new(\"3"); -ok (${$C->_str(scalar $C->_mod($x,$y))},1); -$x = $C->_new(\"1000"); $y = $C->_new(\"2"); -ok (${$C->_str(scalar $C->_mod($x,$y))},0); +$x = $C->_new("1000"); $y = $C->_new("3"); +ok ($C->_str(scalar $C->_mod($x,$y)),1); +$x = $C->_new("1000"); $y = $C->_new("2"); +ok ($C->_str(scalar $C->_mod($x,$y)),0); # _and, _or, _xor -$x = $C->_new(\"5"); $y = $C->_new(\"2"); -ok (${$C->_str(scalar $C->_xor($x,$y))},7); -$x = $C->_new(\"5"); $y = $C->_new(\"2"); -ok (${$C->_str(scalar $C->_or($x,$y))},7); -$x = $C->_new(\"5"); $y = $C->_new(\"3"); -ok (${$C->_str(scalar $C->_and($x,$y))},1); +$x = $C->_new("5"); $y = $C->_new("2"); +ok ($C->_str(scalar $C->_xor($x,$y)),7); +$x = $C->_new("5"); $y = $C->_new("2"); +ok ($C->_str(scalar $C->_or($x,$y)),7); +$x = $C->_new("5"); $y = $C->_new("3"); +ok ($C->_str(scalar $C->_and($x,$y)),1); # _from_hex, _from_bin -ok (${$C->_str(scalar $C->_from_hex(\"0xFf"))},255); -ok (${$C->_str(scalar $C->_from_bin(\"0b10101011"))},160+11); +ok ($C->_str( $C->_from_hex("0xFf")),255); +ok ($C->_str( $C->_from_bin("0b10101011")),160+11); # _as_hex, _as_bin -ok (${$C->_str(scalar $C->_from_hex( $C->_as_hex( $C->_new(\"128"))))}, 128); -ok (${$C->_str(scalar $C->_from_bin( $C->_as_bin( $C->_new(\"128"))))}, 128); -ok (${$C->_str(scalar $C->_from_hex( $C->_as_hex( $C->_new(\"0"))))}, 0); -ok (${$C->_str(scalar $C->_from_bin( $C->_as_bin( $C->_new(\"0"))))}, 0); -ok ( ${$C->_as_hex( $C->_new(\"0"))}, '0x0'); -ok ( ${$C->_as_bin( $C->_new(\"0"))}, '0b0'); -ok ( ${$C->_as_hex( $C->_new(\"12"))}, '0xc'); -ok ( ${$C->_as_bin( $C->_new(\"12"))}, '0b1100'); +ok ($C->_str( $C->_from_hex( $C->_as_hex( $C->_new("128")))), 128); +ok ($C->_str( $C->_from_bin( $C->_as_bin( $C->_new("128")))), 128); +ok ($C->_str( $C->_from_hex( $C->_as_hex( $C->_new("0")))), 0); +ok ($C->_str( $C->_from_bin( $C->_as_bin( $C->_new("0")))), 0); +ok ($C->_as_hex( $C->_new("0")), '0x0'); +ok ($C->_as_bin( $C->_new("0")), '0b0'); +ok ($C->_as_hex( $C->_new("12")), '0xc'); +ok ($C->_as_bin( $C->_new("12")), '0b1100'); # _check -$x = $C->_new(\"123456789"); +$x = $C->_new("123456789"); ok ($C->_check($x),0); ok ($C->_check(123),'123 is not a reference'); diff --git a/lib/Math/BigInt/t/bigintpm.inc b/lib/Math/BigInt/t/bigintpm.inc index 4e526676b8..cdefea633a 100644 --- a/lib/Math/BigInt/t/bigintpm.inc +++ b/lib/Math/BigInt/t/bigintpm.inc @@ -1683,6 +1683,13 @@ abc:1:abc:NaN 111111111111111111111111111111:111111111111111111111111111111:0 12345678901234567890:12345678901234567890:0 &bgcd +inf:12:NaN +-inf:12:NaN +12:inf:NaN +12:-inf:NaN +inf:inf:NaN +inf:-inf:NaN +-inf:-inf:NaN abc:abc:NaN abc:+0:NaN +0:abc:NaN @@ -1693,6 +1700,10 @@ abc:+0:NaN +2:+3:1 +3:+2:1 -3:+2:1 +-3:-2:1 +-144:-60:12 +144:-60:12 +144:60:12 100:625:25 4096:81:1 1034:804:2 @@ -1717,12 +1728,16 @@ abc:0:NaN +281474976710656:0:0 +281474976710656:1:0 +281474976710656:+281474976710656:281474976710656 +281474976710656:-1:281474976710656 -2:-3:-4 -1:-1:-1 -6:-6:-6 -7:-4:-8 -7:4:0 -4:7:4 +# negative argument is bitwise shorter than positive [perl #26559] +30:-3:28 +123:-1:123 # equal arguments are treated special, so also do some test with unequal ones 0xFFFF:0xFFFF:0x0xFFFF 0xFFFFFF:0xFFFFFF:0x0xFFFFFF @@ -1754,6 +1769,11 @@ abc:0:NaN -6:-6:-6 -7:4:-3 -4:7:-1 ++281474976710656:-1:-1 +30:-3:-1 +30:-4:-2 +300:-76:-68 +-76:300:-68 # equal arguments are treated special, so also do some test with unequal ones 0xFFFF:0xFFFF:0x0xFFFF 0xFFFFFF:0xFFFFFF:0x0xFFFFFF @@ -1802,6 +1822,10 @@ abc:0:NaN -4:7:-5 4:-7:-3 -4:-7:5 +30:-3:-29 +30:-4:-30 +300:-76:-360 +-76:300:-360 # equal arguments are treated special, so also do some test with unequal ones 0xFFFF:0xFFFF:0 0xFFFFFF:0xFFFFFF:0 @@ -1916,8 +1940,8 @@ abc:12:NaN 0:0:1 0:1:0 0:2:0 -0:-1:NaN -0:-2:NaN +0:-1:inf +0:-2:inf 1:0:1 1:1:1 1:2:1 @@ -1960,6 +1984,14 @@ abc:12:NaN 10:9:1000000000 10:20:100000000000000000000 123456:2:15241383936 +-2:2:4 +-2:3:-8 +-2:4:16 +-2:5:-32 +-3:2:9 +-3:3:-27 +-3:4:81 +-3:5:-243 &length 100:3 10:2 diff --git a/lib/Math/BigInt/t/bigintpm.t b/lib/Math/BigInt/t/bigintpm.t index 0ffa4a298a..50fca1dbf1 100755 --- a/lib/Math/BigInt/t/bigintpm.t +++ b/lib/Math/BigInt/t/bigintpm.t @@ -10,7 +10,7 @@ BEGIN my $location = $0; $location =~ s/bigintpm.t//; unshift @INC, $location; # to locate the testing files chdir 't' if -d 't'; - plan tests => 2770; + plan tests => 2832; } use Math::BigInt; diff --git a/lib/Math/BigInt/t/bigints.t b/lib/Math/BigInt/t/bigints.t index 6b21a75487..de073e21e5 100644 --- a/lib/Math/BigInt/t/bigints.t +++ b/lib/Math/BigInt/t/bigints.t @@ -36,24 +36,24 @@ use Math::BigInt::Scalar; my $C = 'Math::BigInt::Scalar'; # pass classname to sub's # _new and _str -my $x = $C->_new(\"123"); my $y = $C->_new(\"321"); -ok (ref($x),'SCALAR'); ok (${$C->_str($x)},123); ok (${$C->_str($y)},321); +my $x = $C->_new("123"); my $y = $C->_new("321"); +ok (ref($x),'SCALAR'); ok ($C->_str($x),123); ok ($C->_str($y),321); # _add, _sub, _mul, _div -ok (${$C->_str($C->_add($x,$y))},444); -ok (${$C->_str($C->_sub($x,$y))},123); -ok (${$C->_str($C->_mul($x,$y))},39483); -ok (${$C->_str($C->_div($x,$y))},123); +ok ($C->_str($C->_add($x,$y)),444); +ok ($C->_str($C->_sub($x,$y)),123); +ok ($C->_str($C->_mul($x,$y)),39483); +ok ($C->_str($C->_div($x,$y)),123); -ok (${$C->_str($C->_mul($x,$y))},39483); -ok (${$C->_str($x)},39483); -ok (${$C->_str($y)},321); -my $z = $C->_new(\"2"); -ok (${$C->_str($C->_add($x,$z))},39485); +ok ($C->_str($C->_mul($x,$y)),39483); +ok ($C->_str($x),39483); +ok ($C->_str($y),321); +my $z = $C->_new("2"); +ok ($C->_str($C->_add($x,$z)),39485); my ($re,$rr) = $C->_div($x,$y); -ok (${$C->_str($re)},123); ok (${$C->_str($rr)},2); +ok ($C->_str($re),123); ok ($C->_str($rr),2); # is_zero, _is_one, _one, _zero ok ($C->_is_zero($x),0); @@ -67,7 +67,7 @@ ok ($C->_is_odd($C->_one()),1); ok ($C->_is_odd($C->_zero()),0); ok ($C->_is_even($C->_one()),0); ok ($C->_is_even($C->_zero()),1); # _digit -$x = $C->_new(\"123456789"); +$x = $C->_new("123456789"); ok ($C->_digit($x,0),9); ok ($C->_digit($x,1),8); ok ($C->_digit($x,2),7); @@ -76,47 +76,44 @@ ok ($C->_digit($x,-2),2); ok ($C->_digit($x,-3),3); # _copy -$x = $C->_new(\"12356"); -ok (${$C->_str($C->_copy($x))},12356); +$x = $C->_new("12356"); +ok ($C->_str($C->_copy($x)),12356); # _acmp -$x = $C->_new(\"123456789"); -$y = $C->_new(\"987654321"); +$x = $C->_new("123456789"); +$y = $C->_new("987654321"); ok ($C->_acmp($x,$y),-1); ok ($C->_acmp($y,$x),1); ok ($C->_acmp($x,$x),0); ok ($C->_acmp($y,$y),0); # _div -$x = $C->_new(\"3333"); $y = $C->_new(\"1111"); -ok (${$C->_str( scalar $C->_div($x,$y))},3); -$x = $C->_new(\"33333"); $y = $C->_new(\"1111"); ($x,$y) = $C->_div($x,$y); -ok (${$C->_str($x)},30); ok (${$C->_str($y)},3); -$x = $C->_new(\"123"); $y = $C->_new(\"1111"); -($x,$y) = $C->_div($x,$y); ok (${$C->_str($x)},0); ok (${$C->_str($y)},123); +$x = $C->_new("3333"); $y = $C->_new("1111"); +ok ($C->_str( scalar $C->_div($x,$y)),3); +$x = $C->_new("33333"); $y = $C->_new("1111"); ($x,$y) = $C->_div($x,$y); +ok ($C->_str($x),30); ok ($C->_str($y),3); +$x = $C->_new("123"); $y = $C->_new("1111"); +($x,$y) = $C->_div($x,$y); ok ($C->_str($x),0); ok ($C->_str($y),123); # _num -$x = $C->_new(\"12345"); $x = $C->_num($x); ok (ref($x)||'',''); ok ($x,12345); +$x = $C->_new("12345"); $x = $C->_num($x); ok (ref($x)||'',''); ok ($x,12345); # _len -$x = $C->_new(\"12345"); $x = $C->_len($x); ok (ref($x)||'',''); ok ($x,5); +$x = $C->_new("12345"); $x = $C->_len($x); ok (ref($x)||'',''); ok ($x,5); # _and, _or, _xor -$x = $C->_new(\"3"); $y = $C->_new(\"4"); ok (${$C->_str( $C->_or($x,$y))},7); -$x = $C->_new(\"1"); $y = $C->_new(\"4"); ok (${$C->_str( $C->_xor($x,$y))},5); -$x = $C->_new(\"7"); $y = $C->_new(\"3"); ok (${$C->_str( $C->_and($x,$y))},3); +$x = $C->_new("3"); $y = $C->_new("4"); ok ($C->_str( $C->_or($x,$y)),7); +$x = $C->_new("1"); $y = $C->_new("4"); ok ($C->_str( $C->_xor($x,$y)),5); +$x = $C->_new("7"); $y = $C->_new("3"); ok ($C->_str( $C->_and($x,$y)),3); # _pow -$x = $C->_new(\"2"); $y = $C->_new(\"4"); ok (${$C->_str( $C->_pow($x,$y))},16); -$x = $C->_new(\"2"); $y = $C->_new(\"5"); ok (${$C->_str( $C->_pow($x,$y))},32); -$x = $C->_new(\"3"); $y = $C->_new(\"3"); ok (${$C->_str( $C->_pow($x,$y))},27); +$x = $C->_new("2"); $y = $C->_new("4"); ok ($C->_str( $C->_pow($x,$y)),16); +$x = $C->_new("2"); $y = $C->_new("5"); ok ($C->_str( $C->_pow($x,$y)),32); +$x = $C->_new("3"); $y = $C->_new("3"); ok ($C->_str( $C->_pow($x,$y)),27); -# should not happen: -# $x = $C->_new(\"-2"); $y = $C->_new(\"4"); ok ($C->_acmp($x,$y),-1); - # _check -$x = $C->_new(\"123456789"); +$x = $C->_new("123456789"); ok ($C->_check($x),0); ok ($C->_check(123),'123 is not a reference'); diff --git a/lib/Math/BigInt/t/biglog.t b/lib/Math/BigInt/t/biglog.t index 9ed9c2a3d7..cba26435d3 100644 --- a/lib/Math/BigInt/t/biglog.t +++ b/lib/Math/BigInt/t/biglog.t @@ -37,7 +37,7 @@ BEGIN } print "# INC = @INC\n"; - plan tests => 50; + plan tests => 53; } use Math::BigFloat; @@ -45,7 +45,7 @@ use Math::BigInt; my $cl = "Math::BigFloat"; -# these tests are now really fast, since they collapse to blog(10), basically +# These tests are now really fast, since they collapse to blog(10), basically # Don't attempt to run them with older versions. You are warned. # $x < 0 => NaN @@ -99,6 +99,11 @@ ok ($cl->new('10')->bpow('0.6',10), '3.981071706'); # blog should handle bigint input ok (Math::BigFloat::blog(Math::BigInt->new(100),10), 2); +# some integer results +ok ($cl->new(2)->bpow(32)->blog(2), '32'); # 2 ** 32 +ok ($cl->new(3)->bpow(32)->blog(3), '32'); # 3 ** 32 +ok ($cl->new(2)->bpow(65)->blog(2), '65'); # 2 ** 65 + # test for bug in bsqrt() not taking negative _e into account test_bpow ('200','0.5',10, '14.14213562'); test_bpow ('20','0.5',10, '4.472135955'); @@ -127,7 +132,7 @@ sub test_bpow { my ($x,$y,$scale,$result) = @_; - print "# Tried: $x->bpow($y,$scale);\n" + print "# Tried: $x->bpow($y,$scale);\n" unless ok ($cl->new($x)->bpow($y,$scale),$result); } diff --git a/lib/Math/BigInt/t/calling.t b/lib/Math/BigInt/t/calling.t index 3b0ff41dd4..71c6b48c97 100644 --- a/lib/Math/BigInt/t/calling.t +++ b/lib/Math/BigInt/t/calling.t @@ -30,7 +30,7 @@ BEGIN unshift @INC, $location; } print "# INC = @INC\n"; - my $tests = 161; + my $tests = 160; plan tests => $tests; if ($] < 5.006) { @@ -95,11 +95,12 @@ while (<DATA>) $class = 'Math::BigInt'; +# XXX TODO this test does not work/fail. # test whether use Math::BigInt qw/version/ works -$try = "use $class ($version.'1');"; -$try .= ' $x = $class->new(123); $x = "$x";'; -eval $try; -ok_undef ( $_ ); # should result in error! +#$try = "use $class ($version.'1');"; +#$try .= ' $x = $class->new(123); $x = "$x";'; +#eval $try; +#ok_undef ( $x ); # should result in error! # test whether fallback to calc works $try = "use $class ($version,'lib','foo, bar , ');"; @@ -122,14 +123,6 @@ $try = "use $class ($version,'LiB','$class\::Scalar');"; $try .= ' $x = 2**10; $x = "$x";'; $ans = eval $try; ok ( $ans, "1024"); -# test wether calc => undef (array element not existing) works -# no longer supported -#$try = "use $class ($version,'LIB');"; -#$try = "require $class; $class\::import($version,'CALC');"; -#$try .= " \$x = $class\->new(2)**10; \$x = ".'"$x";'; -#print "$try\n"; -#$ans = eval $try; ok ( $ans, 1024); - # all done ############################################################################### diff --git a/lib/Math/BigInt/t/config.t b/lib/Math/BigInt/t/config.t index 5c480536bd..da75344f2a 100644 --- a/lib/Math/BigInt/t/config.t +++ b/lib/Math/BigInt/t/config.t @@ -51,7 +51,7 @@ $cfg = $mbf->config(); ok (ref($cfg),'HASH'); ok ($cfg->{lib},'Math::BigInt::Calc'); -ok ($cfg->{with},$mbi); +ok ($cfg->{with},'Math::BigInt::Calc'); ok ($cfg->{lib_version}, $Math::BigInt::Calc::VERSION); ok ($cfg->{class},$mbf); ok ($cfg->{upgrade}||'',''); diff --git a/lib/Math/BigInt/t/mbimbf.inc b/lib/Math/BigInt/t/mbimbf.inc index 192b1cc4bf..b9c94c4900 100644 --- a/lib/Math/BigInt/t/mbimbf.inc +++ b/lib/Math/BigInt/t/mbimbf.inc @@ -264,9 +264,9 @@ foreach my $c ($mbi,$mbf) ok ($c->bpow(2,16),65536); ok ($c->bpow(2,$c->new(16)),65536); -# ok ($c->new(2**15)->brsft(1),2**14); -# ok ($c->brsft(2**15,1),2**14); -# ok ($c->brsft(2**15,$c->new(1)),2**14); + ok ($c->new(2**15)->brsft(1),2**14); + ok ($c->brsft(2**15,1),2**14); + ok ($c->brsft(2**15,$c->new(1)),2**14); ok ($c->new(2**13)->blsft(1),2**14); ok ($c->blsft(2**13,1),2**14); @@ -544,6 +544,17 @@ $x = $mbf->new('12340'); $x->bfround(2); ok ($x,'12340'); $x = $mbi->new('1234'); $x->accuracy(3); $x->bfround(-2); ok_undef ($x->{_a}); +# test that bfround() and bround() work with large numbers + +$x = $mbf->new(1)->bdiv(5678,undef,-63); +ok ($x, '0.000176118351532229658330398027474462839027826699542092286016203'); + +$x = $mbf->new(1)->bdiv(5678,undef,-90); +ok ($x, '0.000176118351532229658330398027474462839027826699542092286016202888340965128566396618527651'); + +$x = $mbf->new(1)->bdiv(5678,80); +ok ($x, '0.00017611835153222965833039802747446283902782669954209228601620288834096512856639662'); + ############################################################################### # rounding with already set precision/accuracy @@ -565,8 +576,9 @@ ok ($x->{_a},2); # mantissa/exponent format and A/P $x = $mbf->new('12345.678'); $x->accuracy(4); ok ($x,'12350'); ok ($x->{_a},4); ok_undef ($x->{_p}); -ok_undef ($x->{_m}->{_a}); ok_undef ($x->{_e}->{_a}); -ok_undef ($x->{_m}->{_p}); ok_undef ($x->{_e}->{_p}); + +#ok_undef ($x->{_m}->{_a}); ok_undef ($x->{_e}->{_a}); +#ok_undef ($x->{_m}->{_p}); ok_undef ($x->{_e}->{_p}); # check for no A/P in case of fallback # result @@ -792,7 +804,7 @@ while (<DATA>) $try .= "\$x->$f(\$y);"; - # print "trying $try\n"; + # print "trying $try\n"; $rc = eval $try; # convert hex/binary targets to decimal if ($ans =~ /^(0x0x|0b0b)/) diff --git a/lib/Math/BigInt/t/mbimbf.t b/lib/Math/BigInt/t/mbimbf.t index 17cd712b0f..fae3c8cf9c 100644 --- a/lib/Math/BigInt/t/mbimbf.t +++ b/lib/Math/BigInt/t/mbimbf.t @@ -31,12 +31,12 @@ BEGIN } print "# INC = @INC\n"; - plan tests => 679 + plan tests => 684 + 23; # own tests } -use Math::BigInt 1.63; -use Math::BigFloat 1.38; +use Math::BigInt 1.70; +use Math::BigFloat 1.43; use vars qw/$mbi $mbf/; @@ -95,7 +95,6 @@ foreach my $class (qw/Math::BigInt Math::BigFloat/) $class->accuracy(undef); # reset for further tests $class->precision(undef); } - # bug with flog(Math::BigFloat,Math::BigInt) $x = Math::BigFloat->new(100); $x = $x->blog(Math::BigInt->new(10)); diff --git a/lib/Math/BigInt/t/req_mbfw.t b/lib/Math/BigInt/t/req_mbfw.t index b216c797d9..025722d277 100644 --- a/lib/Math/BigInt/t/req_mbfw.t +++ b/lib/Math/BigInt/t/req_mbfw.t @@ -34,12 +34,13 @@ BEGIN # normal require that calls import automatically (we thus have MBI afterwards) require Math::BigFloat; my $x = Math::BigFloat->new(1); ++$x; ok ($x,2); -ok (Math::BigFloat->config()->{with}, 'Math::BigInt' ); +ok (Math::BigFloat->config()->{with}, 'Math::BigInt::Calc' ); # now override Math::BigFloat->import ( with => 'Math::BigInt::Subclass' ); -ok (Math::BigFloat->config()->{with}, 'Math::BigInt::Subclass' ); +# thw with argument is ignored +ok (Math::BigFloat->config()->{with}, 'Math::BigInt::Calc' ); # all tests done diff --git a/lib/Math/BigInt/t/sub_mbf.t b/lib/Math/BigInt/t/sub_mbf.t index 91fda9762a..9a8b9a396c 100755 --- a/lib/Math/BigInt/t/sub_mbf.t +++ b/lib/Math/BigInt/t/sub_mbf.t @@ -26,7 +26,7 @@ BEGIN } print "# INC = @INC\n"; - plan tests => 1772 + plan tests => 1814 + 6; # + our own tests } diff --git a/lib/Math/BigInt/t/sub_mbi.t b/lib/Math/BigInt/t/sub_mbi.t index 16968d4847..3e831c5fe4 100755 --- a/lib/Math/BigInt/t/sub_mbi.t +++ b/lib/Math/BigInt/t/sub_mbi.t @@ -26,7 +26,7 @@ BEGIN } print "# INC = @INC\n"; - plan tests => 2770 + plan tests => 2832 + 5; # +5 own tests } diff --git a/lib/Math/BigInt/t/sub_mif.t b/lib/Math/BigInt/t/sub_mif.t index cbaf06a97c..cd0c863075 100644 --- a/lib/Math/BigInt/t/sub_mif.t +++ b/lib/Math/BigInt/t/sub_mif.t @@ -28,7 +28,7 @@ BEGIN } print "# INC = @INC\n"; - plan tests => 679; + plan tests => 684; } use Math::BigInt::Subclass; diff --git a/lib/Math/BigInt/t/upgrade.inc b/lib/Math/BigInt/t/upgrade.inc index 49dbf91823..4799420fd8 100644 --- a/lib/Math/BigInt/t/upgrade.inc +++ b/lib/Math/BigInt/t/upgrade.inc @@ -1263,8 +1263,8 @@ abc:12:NaN 0:0:1 0:1:0 0:2:0 -0:-1:NaN -0:-2:NaN +0:-1:inf +0:-2:inf 1:0:1 1:1:1 1:2:1 @@ -1297,6 +1297,14 @@ abc:12:NaN -1:-2:1 -1:-3:-1 -1:-4:1 +-2:2:4 +-2:3:-8 +-2:4:16 +-2:5:-32 +-3:2:9 +-3:3:-27 +-3:4:81 +-3:5:-243 10:2:100 10:3:1000 10:4:10000 diff --git a/lib/Math/BigInt/t/upgrade.t b/lib/Math/BigInt/t/upgrade.t index 3fc4067259..a06aec352e 100644 --- a/lib/Math/BigInt/t/upgrade.t +++ b/lib/Math/BigInt/t/upgrade.t @@ -26,7 +26,7 @@ BEGIN } print "# INC = @INC\n"; - plan tests => 2082 + plan tests => 2098 + 2; # our own tests } diff --git a/lib/Math/BigInt/t/use_mbfw.t b/lib/Math/BigInt/t/use_mbfw.t index d58de047f2..c6a047143e 100644 --- a/lib/Math/BigInt/t/use_mbfw.t +++ b/lib/Math/BigInt/t/use_mbfw.t @@ -29,7 +29,7 @@ BEGIN } print "# INC = @INC\n"; - plan tests => 3; + plan tests => 2; } @@ -41,12 +41,12 @@ BEGIN use Math::BigFloat with => 'Math::BigInt::Subclass', lib => 'BareCalc'; -ok (Math::BigFloat->config()->{with}, 'Math::BigInt::Subclass' ); +ok (Math::BigFloat->config()->{with}, 'Math::BigInt::BareCalc' ); -ok ($Math::BigInt::Subclass::lib, 'BareCalc' ); +# ok ($Math::BigInt::Subclass::lib, 'BareCalc' ); # it never arrives here, but that is a design decision in SubClass -ok (Math::BigInt->config->{lib}, 'Math::BigInt::Calc' ); +ok (Math::BigInt->config->{lib}, 'Math::BigInt::BareCalc' ); # all tests done diff --git a/lib/Math/BigInt/t/with_sub.t b/lib/Math/BigInt/t/with_sub.t index a3af404f55..d7391d94ae 100644 --- a/lib/Math/BigInt/t/with_sub.t +++ b/lib/Math/BigInt/t/with_sub.t @@ -28,7 +28,7 @@ BEGIN } print "# INC = @INC\n"; - plan tests => 1772 + plan tests => 1814 + 1; } @@ -38,6 +38,7 @@ use vars qw ($class $try $x $y $f @args $ans $ans1 $ans1_str $setup $CL); $class = "Math::BigFloat"; $CL = "Math::BigInt::Calc"; -ok (Math::BigFloat->config()->{with}, 'Math::BigInt::Subclass'); +# the with argument is ignored +ok (Math::BigFloat->config()->{with}, 'Math::BigInt::Calc'); require 'bigfltpm.inc'; # all tests here for sharing |