diff options
Diffstat (limited to 'Master/tlpkg/tlperl/lib/Math/BigInt.pm')
-rw-r--r-- | Master/tlpkg/tlperl/lib/Math/BigInt.pm | 599 |
1 files changed, 384 insertions, 215 deletions
diff --git a/Master/tlpkg/tlperl/lib/Math/BigInt.pm b/Master/tlpkg/tlperl/lib/Math/BigInt.pm index f97e4380798..62c021ecf71 100644 --- a/Master/tlpkg/tlperl/lib/Math/BigInt.pm +++ b/Master/tlpkg/tlperl/lib/Math/BigInt.pm @@ -6,7 +6,7 @@ package Math::BigInt; # # The following hash values are used: -# value: unsigned int with actual value (as a Math::BigInt::Calc or similiar) +# value: unsigned int with actual value (as a Math::BigInt::Calc or similar) # sign : +,-,NaN,+inf,-inf # _a : accuracy # _p : precision @@ -16,9 +16,9 @@ package Math::BigInt; # underlying lib might change the reference! my $class = "Math::BigInt"; -use 5.006; +use 5.006002; -$VERSION = '1.89_01'; +$VERSION = '1.994'; @ISA = qw(Exporter); @EXPORT_OK = qw(objectify bgcd blcm); @@ -30,7 +30,7 @@ use vars qw/$round_mode $accuracy $precision $div_scale $rnd_mode use strict; # Inside overload, the first arg is always an object. If the original code had -# it reversed (like $x = 2 * $y), then the third paramater is true. +# it reversed (like $x = 2 * $y), then the third parameter is true. # In some cases (like add, $x = $x + 2 is the same as $x = 2 + $x) this makes # no difference, but in some cases it does. @@ -172,8 +172,8 @@ $_trap_nan = 0; # are NaNs ok? set w/ config() $_trap_inf = 0; # are infs ok? set w/ config() my $nan = 'NaN'; # constants for easier life -my $CALC = 'Math::BigInt::FastCalc'; # module to do the low level math - # default is FastCalc.pm +my $CALC = 'Math::BigInt::Calc'; # module to do the low level math + # default is Calc.pm my $IMPORT = 0; # was import() called yet? # used to make require work my %WARN; # warn only once for low-level libs @@ -799,7 +799,7 @@ sub bone } ############################################################################## -# string conversation +# string conversion sub bsstr { @@ -931,7 +931,7 @@ sub round # Round $self according to given parameters, or given second argument's # parameters or global defaults - # for speed reasons, _find_round_parameters is embeded here: + # for speed reasons, _find_round_parameters is embedded here: my ($self,$a,$p,$r,@args) = @_; # $a accuracy, if given by caller @@ -989,7 +989,7 @@ sub round { $self->bfround(int($p),$r) if !defined $self->{_p} || $self->{_p} <= $p; } - # bround() or bfround() already callled bnorm() if nec. + # bround() or bfround() already called bnorm() if nec. $self; } @@ -1260,7 +1260,7 @@ sub blog # objectify is costly, so avoid it if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) { - ($self,$x,$base,@r) = objectify(1,ref($x),@_); + ($self,$x,$base,@r) = objectify(2,@_); } return $x if $x->modify('blog'); @@ -1320,18 +1320,17 @@ sub bnok } else { - # ( 7 ) 7! 7*6*5 * 4*3*2*1 7 * 6 * 5 - # ( - ) = --------- = --------------- = --------- - # ( 3 ) 3! (7-3)! 3*2*1 * 4*3*2*1 3 * 2 * 1 + # ( 7 ) 7! 1*2*3*4 * 5*6*7 5 * 6 * 7 6 7 + # ( - ) = --------- = --------------- = --------- = 5 * - * - + # ( 3 ) (7-3)! 3! 1*2*3*4 * 1*2*3 1 * 2 * 3 2 3 - # compute n - k + 2 (so we start with 5 in the example above) - my $z = $x - $y; - if (!$z->is_one()) + if (!$y->is_zero()) { + my $z = $x - $y; $z->binc(); my $r = $z->copy(); $z->binc(); my $d = $self->new(2); - while ($z->bacmp($x) <= 0) # f < x ? + while ($z->bacmp($x) <= 0) # f <= x ? { $r->bmul($z); $r->bdiv($d); $z->binc(); $d->binc(); @@ -1375,11 +1374,11 @@ sub bexp else { $x = $u; } } -sub blcm - { +sub blcm + { # (BINT or num_str, BINT or num_str) return BINT # does not modify arguments, but returns new object - # Lowest Common Multiplicator + # Lowest Common Multiple my $y = shift; my ($x); if (ref($y)) @@ -1403,7 +1402,7 @@ sub bgcd { # (BINT or num_str, BINT or num_str) return BINT # does not modify arguments, but returns new object - # GCD -- Euclids algorithm, variant C (Knuth Vol 3, pg 341 ff) + # GCD -- Euclid's algorithm, variant C (Knuth Vol 3, pg 341 ff) my $y = shift; $y = $class->new($y) if !ref($y); @@ -1498,13 +1497,13 @@ sub is_even sub is_positive { - # return true when arg (BINT or num_str) is positive (>= 0) + # return true when arg (BINT or num_str) is positive (> 0) my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_); return 1 if $x->{sign} eq '+inf'; # +inf is positive - + # 0+ is neither positive nor negative - ($x->{sign} eq '+' && !$x->is_zero()) ? 1 : 0; + ($x->{sign} eq '+' && !$x->is_zero()) ? 1 : 0; } sub is_negative @@ -1574,12 +1573,7 @@ sub bmuladd # (BINT or num_str, BINT or num_str, BINT or num_str) return BINT # set up parameters - my ($self,$x,$y,$z,@r) = (ref($_[0]),@_); - # objectify is costly, so avoid it - if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) - { - ($self,$x,$y,$z,@r) = objectify(3,@_); - } + my ($self,$x,$y,$z,@r) = objectify(3,@_); return $x if $x->modify('bmuladd'); @@ -1654,7 +1648,7 @@ sub _div_inf if (($x->is_nan() || $y->is_nan()) || ($x->is_zero() && $y->is_zero())); - # +-inf / +-inf == NaN, reminder also NaN + # +-inf / +-inf == NaN, remainder also NaN if (($x->{sign} =~ /^[+-]inf$/) && ($y->{sign} =~ /^[+-]inf$/)) { return wantarray ? ($x->bnan(),$self->bnan()) : $x->bnan(); @@ -1786,10 +1780,12 @@ sub bmod sub bmodinv { - # Modular inverse. given a number which is (hopefully) relatively - # prime to the modulus, calculate its inverse using Euclid's - # alogrithm. If the number is not relatively prime to the modulus - # (i.e. their gcd is not one) then NaN is returned. + # Return modular multiplicative inverse: z is the modular inverse of x (mod + # y) if and only if x*z (mod y) = 1 (mod y). If the modulus y is larger than + # one, x and z are relative primes (i.e., their greatest common divisor is + # one). + # + # If no modular multiplicative inverse exists, NaN is returned. # set up parameters my ($self,$x,$y,@r) = (undef,@_); @@ -1801,52 +1797,153 @@ sub bmodinv return $x if $x->modify('bmodinv'); - return $x->bnan() - if ($y->{sign} ne '+' # -, NaN, +inf, -inf - || $x->is_zero() # or num == 0 - || $x->{sign} !~ /^[+-]$/ # or num NaN, inf, -inf - ); - - # put least residue into $x if $x was negative, and thus make it positive - $x->bmod($y) if $x->{sign} eq '-'; - - my $sign; - ($x->{value},$sign) = $CALC->_modinv($x->{value},$y->{value}); - return $x->bnan() if !defined $x->{value}; # in case no GCD found - return $x if !defined $sign; # already real result - $x->{sign} = $sign; # flip/flop see below - $x->bmod($y); # calc real result - $x; + # Return NaN if one or both arguments is +inf, -inf, or nan. + + return $x->bnan() if ($y->{sign} !~ /^[+-]$/ || + $x->{sign} !~ /^[+-]$/); + + # Return NaN if $y is zero; 1 % 0 makes no sense. + + return $x->bnan() if $y->is_zero(); + + # Return 0 in the trivial case. $x % 1 or $x % -1 is zero for all finite + # integers $x. + + return $x->bzero() if ($y->is_one() || + $y->is_one('-')); + + # Return NaN if $x = 0, or $x modulo $y is zero. The only valid case when + # $x = 0 is when $y = 1 or $y = -1, but that was covered above. + # + # Note that computing $x modulo $y here affects the value we'll feed to + # $CALC->_modinv() below when $x and $y have opposite signs. E.g., if $x = + # 5 and $y = 7, those two values are fed to _modinv(), but if $x = -5 and + # $y = 7, the values fed to _modinv() are $x = 2 (= -5 % 7) and $y = 7. + # The value if $x is affected only when $x and $y have opposite signs. + + $x->bmod($y); + return $x->bnan() if $x->is_zero(); + + # Compute the modular multiplicative inverse of the absolute values. We'll + # correct for the signs of $x and $y later. Return NaN if no GCD is found. + + ($x->{value}, $x->{sign}) = $CALC->_modinv($x->{value}, $y->{value}); + return $x->bnan() if !defined $x->{value}; + + # Library inconsistency workaround: _modinv() in Math::BigInt::GMP versions + # <= 1.32 return undef rather than a "+" for the sign. + + $x->{sign} = '+' unless defined $x->{sign}; + + # When one or both arguments are negative, we have the following + # relations. If x and y are positive: + # + # modinv(-x, -y) = -modinv(x, y) + # modinv(-x, y) = y - modinv(x, y) = -modinv(x, y) (mod y) + # modinv( x, -y) = modinv(x, y) - y = modinv(x, y) (mod -y) + + # We must swap the sign of the result if the original $x is negative. + # However, we must compensate for ignoring the signs when computing the + # inverse modulo. The net effect is that we must swap the sign of the + # result if $y is negative. + + $x -> bneg() if $y->{sign} eq '-'; + + # Compute $x modulo $y again after correcting the sign. + + $x -> bmod($y) if $x->{sign} ne $y->{sign}; + + return $x; } sub bmodpow { - # takes a very large number to a very large exponent in a given very - # large modulus, quickly, thanks to binary exponentation. Supports - # negative exponents. + # Modular exponentiation. Raises a very large number to a very large exponent + # in a given very large modulus quickly, thanks to binary exponentiation. + # Supports negative exponents. my ($self,$num,$exp,$mod,@r) = objectify(3,@_); return $num if $num->modify('bmodpow'); - # check modulus for valid values - return $num->bnan() if ($mod->{sign} ne '+' # NaN, - , -inf, +inf - || $mod->is_zero()); + # When the exponent 'e' is negative, use the following relation, which is + # based on finding the multiplicative inverse 'd' of 'b' modulo 'm': + # + # b^(-e) (mod m) = d^e (mod m) where b*d = 1 (mod m) - # check exponent for valid values - if ($exp->{sign} =~ /\w/) - { - # i.e., if it's NaN, +inf, or -inf... - return $num->bnan(); - } + $num->bmodinv($mod) if ($exp->{sign} eq '-'); - $num->bmodinv ($mod) if ($exp->{sign} eq '-'); + # Check for valid input. All operands must be finite, and the modulus must be + # non-zero. - # check num for valid values (also NaN if there was no inverse but $exp < 0) - return $num->bnan() if $num->{sign} !~ /^[+-]$/; + return $num->bnan() if ($num->{sign} =~ /NaN|inf/ || # NaN, -inf, +inf + $exp->{sign} =~ /NaN|inf/ || # NaN, -inf, +inf + $mod->{sign} =~ /NaN|inf/ || # NaN, -inf, +inf + $mod->is_zero()); + + # Compute 'a (mod m)', ignoring the signs on 'a' and 'm'. If the resulting + # value is zero, the output is also zero, regardless of the signs on 'a' and + # 'm'. + + my $value = $CALC->_modpow($num->{value}, $exp->{value}, $mod->{value}); + my $sign = '+'; + + # If the resulting value is non-zero, we have four special cases, depending + # on the signs on 'a' and 'm'. + + unless ($CALC->_is_zero($value)) { + + # There is a negative sign on 'a' (= $num**$exp) only if the number we + # are exponentiating ($num) is negative and the exponent ($exp) is odd. + + if ($num->{sign} eq '-' && $exp->is_odd()) { + + # When both the number 'a' and the modulus 'm' have a negative sign, + # use this relation: + # + # -a (mod -m) = -(a (mod m)) + + if ($mod->{sign} eq '-') { + $sign = '-'; + } + + # When only the number 'a' has a negative sign, use this relation: + # + # -a (mod m) = m - (a (mod m)) + + else { + # Use copy of $mod since _sub() modifies the first argument. + my $mod = $CALC->_copy($mod->{value}); + $value = $CALC->_sub($mod, $value); + $sign = '+'; + } + + } else { + + # When only the modulus 'm' has a negative sign, use this relation: + # + # a (mod -m) = (a (mod m)) - m + # = -(m - (a (mod m))) + + if ($mod->{sign} eq '-') { + # Use copy of $mod since _sub() modifies the first argument. + my $mod = $CALC->_copy($mod->{value}); + $value = $CALC->_sub($mod, $value); + $sign = '-'; + } + + # When neither the number 'a' nor the modulus 'm' have a negative + # sign, directly return the already computed value. + # + # (a (mod m)) + + } - # $mod is positive, sign on $exp is ignored, result also positive - $num->{value} = $CALC->_modpow($num->{value},$exp->{value},$mod->{value}); - $num; + } + + $num->{value} = $value; + $num->{sign} = $sign; + + return $num; } ############################################################################### @@ -2560,7 +2657,7 @@ sub objectify { $k = $a[0]->new($k); } - elsif (!defined $up && ref($k) ne $a[0]) + elsif (ref($k) ne $a[0] and !defined $up || ref $k ne $up) { # foreign object, try to convert to integer $k->can('as_number') ? $k = $k->as_number() : $k = $a[0]->new($k); @@ -2640,7 +2737,7 @@ sub import { $_ =~ tr/a-zA-Z0-9://cd; # limit to sane characters } - push @c, \'FastCalc', \'Calc' # if all fail, try these + push @c, \'Calc' # if all fail, try these if $warn_or_die < 2; # but not for "only" $CALC = ''; # signal error foreach my $l (@c) @@ -2752,93 +2849,145 @@ sub import # import done } -sub from_hex - { - # create a bigint from a hexadecimal string - my ($self, $hs) = @_; +sub from_hex { + # Create a bigint from a hexadecimal string. + + my ($self, $str) = @_; - my $rc = __from_hex($hs); + if ($str =~ s/ + ^ + ( [+-]? ) + (0?x)? + ( + [0-9a-fA-F]* + ( _ [0-9a-fA-F]+ )* + ) + $ + //x) + { + # Get a "clean" version of the string, i.e., non-emtpy and with no + # underscores or invalid characters. - return $self->bnan() unless defined $rc; + my $sign = $1; + my $chrs = $3; + $chrs =~ tr/_//d; + $chrs = '0' unless CORE::length $chrs; - $rc; - } + # Initialize output. -sub from_bin - { - # create a bigint from a hexadecimal string - my ($self, $bs) = @_; + my $x = Math::BigInt->bzero(); - my $rc = __from_bin($bs); + # The library method requires a prefix. - return $self->bnan() unless defined $rc; + $x->{value} = $CALC->_from_hex('0x' . $chrs); - $rc; - } + # Place the sign. -sub from_oct - { - # create a bigint from a hexadecimal string - my ($self, $os) = @_; + if ($sign eq '-' && ! $CALC->_is_zero($x->{value})) { + $x->{sign} = '-'; + } - my $x = $self->bzero(); - - # strip underscores - $os =~ s/([0-7])_([0-7])/$1$2/g; - $os =~ s/([0-7])_([0-7])/$1$2/g; - - return $x->bnan() if $os !~ /^[\-\+]?0[0-7]+\z/; + return $x; + } - my $sign = '+'; $sign = '-' if $os =~ /^-/; + # CORE::hex() parses as much as it can, and ignores any trailing garbage. + # For backwards compatibility, we return NaN. - $os =~ s/^[+-]//; # strip sign - $x->{value} = $CALC->_from_oct($os); - $x->{sign} = $sign unless $CALC->_is_zero($x->{value}); # no '-0' - $x; - } + return $self->bnan(); +} -sub __from_hex - { - # internal - # convert a (ref to) big hex string to BigInt, return undef for error - my $hs = shift; +sub from_oct { + # Create a bigint from an octal string. - my $x = Math::BigInt->bzero(); - - # strip underscores - $hs =~ s/([0-9a-fA-F])_([0-9a-fA-F])/$1$2/g; - $hs =~ s/([0-9a-fA-F])_([0-9a-fA-F])/$1$2/g; - - return $x->bnan() if $hs !~ /^[\-\+]?0x[0-9A-Fa-f]+$/; + my ($self, $str) = @_; - my $sign = '+'; $sign = '-' if $hs =~ /^-/; + if ($str =~ s/ + ^ + ( [+-]? ) + ( + [0-7]* + ( _ [0-7]+ )* + ) + $ + //x) + { + # Get a "clean" version of the string, i.e., non-emtpy and with no + # underscores or invalid characters. - $hs =~ s/^[+-]//; # strip sign - $x->{value} = $CALC->_from_hex($hs); - $x->{sign} = $sign unless $CALC->_is_zero($x->{value}); # no '-0' - $x; - } + my $sign = $1; + my $chrs = $2; + $chrs =~ tr/_//d; + $chrs = '0' unless CORE::length $chrs; -sub __from_bin - { - # internal - # convert a (ref to) big binary string to BigInt, return undef for error - my $bs = shift; + # Initialize output. - my $x = Math::BigInt->bzero(); + my $x = Math::BigInt->bzero(); - # strip underscores - $bs =~ s/([01])_([01])/$1$2/g; - $bs =~ s/([01])_([01])/$1$2/g; - return $x->bnan() if $bs !~ /^[+-]?0b[01]+$/; + # The library method requires a prefix. - my $sign = '+'; $sign = '-' if $bs =~ /^\-/; - $bs =~ s/^[+-]//; # strip sign + $x->{value} = $CALC->_from_oct('0' . $chrs); - $x->{value} = $CALC->_from_bin($bs); - $x->{sign} = $sign unless $CALC->_is_zero($x->{value}); # no '-0' - $x; - } + # Place the sign. + + if ($sign eq '-' && ! $CALC->_is_zero($x->{value})) { + $x->{sign} = '-'; + } + + return $x; + } + + # CORE::oct() parses as much as it can, and ignores any trailing garbage. + # For backwards compatibility, we return NaN. + + return $self->bnan(); +} + +sub from_bin { + # Create a bigint from a binary string. + + my ($self, $str) = @_; + + if ($str =~ s/ + ^ + ( [+-]? ) + (0?b)? + ( + [01]* + ( _ [01]+ )* + ) + $ + //x) + { + # Get a "clean" version of the string, i.e., non-emtpy and with no + # underscores or invalid characters. + + my $sign = $1; + my $chrs = $3; + $chrs =~ tr/_//d; + $chrs = '0' unless CORE::length $chrs; + + # Initialize output. + + my $x = Math::BigInt->bzero(); + + # The library method requires a prefix. + + $x->{value} = $CALC->_from_bin('0b' . $chrs); + + # Place the sign. + + if ($sign eq '-' && ! $CALC->_is_zero($x->{value})) { + $x->{sign} = '-'; + } + + return $x; + } + + # For consistency with from_hex() and from_oct(), we return NaN when the + # input is invalid. + + return $self->bnan(); +} sub _split { @@ -2849,7 +2998,7 @@ sub _split # invalid input. my $x = shift; - # strip white space at front, also extranous leading zeros + # strip white space at front, also extraneous leading zeros $x =~ s/^\s*([-]?)0*([0-9])/$1$2/g; # will not strip ' .2' $x =~ s/^\s+//; # but this will $x =~ s/\s+$//g; # strip white space at end @@ -2864,9 +3013,9 @@ sub _split # invalid starting char? return if $x !~ /^[+-]?(\.?[0-9]|0b[0-1]|0x[0-9a-fA-F])/; - return __from_hex($x) if $x =~ /^[\-\+]?0x/; # hex string - return __from_bin($x) if $x =~ /^[\-\+]?0b/; # binary string - + return Math::BigInt->from_hex($x) if $x =~ /^[+-]?0x/; # hex string + return Math::BigInt->from_bin($x) if $x =~ /^[+-]?0b/; # binary string + # strip underscores between digits $x =~ s/([0-9])_([0-9])/$1$2/g; $x =~ s/([0-9])_([0-9])/$1$2/g; # do twice for 1_2_3 @@ -3100,7 +3249,7 @@ Math::BigInt - Arbitrary size integer/float math package # will warn if Math::BigInt::GMP cannot be found use Math::BigInt lib => 'GMP'; - # to supress the warning use this: + # to suppress the warning use this: # use Math::BigInt try => 'GMP'; # dies if GMP cannot be loaded: @@ -3136,8 +3285,8 @@ Math::BigInt - Arbitrary size integer/float math package $x->is_one('-'); # if $x is -1 $x->is_odd(); # if $x is odd $x->is_even(); # if $x is even - $x->is_pos(); # if $x >= 0 - $x->is_neg(); # if $x < 0 + $x->is_pos(); # if $x > 0 + $x->is_neg(); # if $x < 0 $x->is_inf($sign); # if $x is +inf, or -inf (sign is default '+') $x->is_int(); # if $x is an integer (not a float) @@ -3165,7 +3314,7 @@ Math::BigInt - Arbitrary size integer/float math package $x->bnot(); # two's complement (bit wise not) $x->binc(); # increment $x by 1 $x->bdec(); # decrement $x by 1 - + $x->badd($y); # addition (add $y to $x) $x->bsub($y); # subtraction (subtract $y from $x) $x->bmul($y); # multiplication (multiply $x by $y) @@ -3175,9 +3324,8 @@ Math::BigInt - Arbitrary size integer/float math package $x->bmuladd($y,$z); # $x = $x * $y + $z $x->bmod($y); # modulus (x % y) - $x->bmodpow($exp,$mod); # modular exponentation (($num**$exp) % $mod)) - $x->bmodinv($mod); # the inverse of $x in the given modulus $mod - + $x->bmodpow($y,$mod); # modular exponentiation (($x ** $y) % $mod) + $x->bmodinv($mod); # modular multiplicative inverse $x->bpow($y); # power of arguments (x ** y) $x->blsft($y); # left shift in base 2 $x->brsft($y); # right shift in base 2 @@ -3185,7 +3333,7 @@ Math::BigInt - Arbitrary size integer/float math package $x->blsft($y,$n); # left shift by $y places in base $n $x->brsft($y,$n); # right shift by $y places in base $n # returns (quo,rem) or quo if in scalar context - + $x->band($y); # bitwise and $x->bior($y); # bitwise inclusive or $x->bxor($y); # bitwise exclusive or @@ -3200,7 +3348,7 @@ Math::BigInt - Arbitrary size integer/float math package $x->blog(); # logarithm of $x to base e (Euler's number) $x->blog($base); # logarithm of $x to base $base (f.i. 2) $x->bexp(); # calculate e ** $x where e is Euler's number - + $x->round($A,$P,$mode); # round to accuracy or precision using mode $mode $x->bround($n); # accuracy: preserve $n digits $x->bfround($n); # $n > 0: round $nth digits, @@ -3212,14 +3360,14 @@ Math::BigInt - Arbitrary size integer/float math package $x->bfloor(); # return integer less or equal than $x $x->bceil(); # return integer greater or equal than $x - + # The following do not modify their arguments: # greatest common divisor (no OO style) my $gcd = Math::BigInt::bgcd(@values); - # lowest common multiplicator (no OO style) - my $lcm = Math::BigInt::blcm(@values); - + # lowest common multiple (no OO style) + my $lcm = Math::BigInt::blcm(@values); + $x->length(); # return number of digits in number ($xl,$f) = $x->length(); # length of number and length of fraction part, # latter is always 0 digits long for BigInts @@ -3230,8 +3378,8 @@ Math::BigInt - Arbitrary size integer/float math package $x->copy(); # make a true copy of $x (unlike $y = $x;) $x->as_int(); # return as BigInt (in BigInt: same as copy()) $x->numify(); # return as scalar (might overflow!) - - # conversation to string (do not modify their argument) + + # conversion to string (do not modify their argument) $x->bstr(); # normalized string (e.g. '3') $x->bsstr(); # norm. string in scientific notation (e.g. '3E0') $x->as_hex(); # as signed hexadecimal string with prefixed 0x @@ -3270,7 +3418,7 @@ Input values to these routines may be any string, that looks like a number and results in an integer, including hexadecimal and binary numbers. Scalars holding numbers may also be passed, but note that non-integer numbers -may already have lost precision due to the conversation to float. Quote +may already have lost precision due to the conversion to float. Quote your input if you want BigInt to see all the digits: $x = Math::BigInt->new(12345678890123456789); # bad @@ -3286,7 +3434,7 @@ are accepted, too. Please note that octal numbers are not recognized by new(), so the following will print "123": perl -MMath::BigInt -le 'print Math::BigInt->new("0123")' - + To convert an octal number, use from_oct(); perl -MMath::BigInt -le 'print Math::BigInt->from_oct("0123")' @@ -3295,8 +3443,8 @@ Currently, Math::BigInt::new() defaults to 0, while Math::BigInt::new('') results in 'NaN'. This might change in the future, so use always the following explicit forms to get a zero or NaN: - $zero = Math::BigInt->bzero(); - $nan = Math::BigInt->bnan(); + $zero = Math::BigInt->bzero(); + $nan = Math::BigInt->bnan(); C<bnorm()> on a BigInt object is now effectively a no-op, since the numbers are always stored in normalized form. If passed a string, creates a BigInt @@ -3365,7 +3513,7 @@ The following values can be set by passing C<config()> a reference to a hash: upgrade downgrade precision accuracy round_mode div_scale Example: - + $new_cfg = Math::BigInt->config( { trap_inf => 1, precision => 5 } ); =head2 accuracy() @@ -3382,7 +3530,7 @@ results have. If you set a global accuracy, then this also applies to new()! Warning! The accuracy I<sticks>, e.g. once you created a number under the influence of C<< CLASS->accuracy($A) >>, all results from math operations with -that number will also be rounded. +that number will also be rounded. In most cases, you should probably round the results explicitly using one of L<round()>, L<bround()> or L<bfround()> or by passing the desired accuracy @@ -3393,15 +3541,15 @@ to the math operation as additional parameter: print scalar $x->copy()->bdiv($y, 2); # print 4300 print scalar $x->copy()->bdiv($y)->bround(2); # print 4300 -Please see the section about L<ACCURACY AND PRECISION> for further details. +Please see the section about L<ACCURACY and PRECISION> for further details. Value must be greater than zero. Pass an undef value to disable it: $x->accuracy(undef); Math::BigInt->accuracy(undef); -Returns the current accuracy. For C<$x->accuracy()> it will return either the -local accuracy, or if not defined, the global. This means the return value +Returns the current accuracy. For C<< $x->accuracy() >> it will return either +the local accuracy, or if not defined, the global. This means the return value represents the accuracy that will be in effect for $x: $y = Math::BigInt->new(1234567); # unrounded @@ -3428,7 +3576,7 @@ Math::BigInt. # This also applies to new()! CLASS->precision(-5); # ditto - $P = CLASS->precision(); # read out global precision + $P = CLASS->precision(); # read out global precision $P = $x->precision(); # read out precision that affects $x Note: You probably want to use L<accuracy()> instead. With L<accuracy> you @@ -3443,15 +3591,15 @@ In Math::BigInt, passing a negative number precision has no effect since no numbers have digits after the dot. In L<Math::BigFloat>, it will round all results to P digits after the dot. -Please see the section about L<ACCURACY AND PRECISION> for further details. +Please see the section about L<ACCURACY and PRECISION> for further details. Pass an undef value to disable it: $x->precision(undef); Math::BigInt->precision(undef); -Returns the current precision. For C<$x->precision()> it will return either the -local precision of $x, or if not defined, the global. This means the return +Returns the current precision. For C<< $x->precision() >> it will return either +the local precision of $x, or if not defined, the global. This means the return value represents the prevision that will be in effect for $x: $y = Math::BigInt->new(1234567); # unrounded @@ -3466,7 +3614,7 @@ Math::BigInt. =head2 brsft() - $x->brsft($y,$n); + $x->brsft($y,$n); Shifts $x right by $y in base $n. Default is base 2, used are usually 10 and 2, but others work, too. @@ -3503,13 +3651,26 @@ See L<Input> for more info on accepted input formats. $x = Math::BigInt->from_oct("0775"); # input is octal +Interpret the input as an octal string and return the corresponding value. A +"0" (zero) prefix is optional. A single underscore character may be placed +right after the prefix, if present, or between any two digits. If the input is +invalid, a NaN is returned. + =head2 from_hex() $x = Math::BigInt->from_hex("0xcafe"); # input is hexadecimal +Interpret input as a hexadecimal string. A "0x" or "x" prefix is optional. A +single underscore character may be placed right after the prefix, if present, +or between any two digits. If the input is invalid, a NaN is returned. + =head2 from_bin() - $x = Math::BigInt->from_oct("0x10011"); # input is binary + $x = Math::BigInt->from_bin("0b10011"); # input is binary + +Interpret the input as a binary string. A "0b" or "b" prefix is optional. A +single underscore character may be placed right after the prefix, if present, +or between any two digits. If the input is invalid, a NaN is returned. =head2 bnan() @@ -3553,7 +3714,6 @@ If used on an object, it will set it to one: =head2 is_one()/is_zero()/is_nan()/is_inf() - $x->is_zero(); # true if arg is +0 $x->is_nan(); # true if arg is NaN $x->is_one(); # true if arg is +1 @@ -3568,7 +3728,7 @@ like: if ($x == 0) =head2 is_pos()/is_neg()/is_positive()/is_negative() - + $x->is_pos(); # true if > 0 $x->is_neg(); # true if < 0 @@ -3605,7 +3765,7 @@ Returns -1, 0, 1 or undef. $x->bacmp($y); -Compares $x with $y while ignoring their. Returns -1, 0, 1 or undef. +Compares $x with $y while ignoring their sign. Returns -1, 0, 1 or undef. =head2 sign() @@ -3648,7 +3808,7 @@ numbers. =head2 bnot() - $x->bnot(); + $x->bnot(); Two's complement (bitwise not). This is equivalent to @@ -3695,19 +3855,28 @@ This method was added in v1.87 of Math::BigInt (June 2007). =head2 bmodinv() - num->bmodinv($mod); # modular inverse + $x->bmodinv($mod); # modular multiplicative inverse + +Returns the multiplicative inverse of C<$x> modulo C<$mod>. If + + $y = $x -> copy() -> bmodinv($mod) + +then C<$y> is the number closest to zero, and with the same sign as C<$mod>, +satisfying + + ($x * $y) % $mod = 1 % $mod -Returns the inverse of C<$num> in the given modulus C<$mod>. 'C<NaN>' is -returned unless C<$num> is relatively prime to C<$mod>, i.e. unless -C<bgcd($num, $mod)==1>. +If C<$x> and C<$y> are non-zero, they must be relative primes, i.e., +C<bgcd($y, $mod)==1>. 'C<NaN>' is returned when no modular multiplicative +inverse exists. =head2 bmodpow() - $num->bmodpow($exp,$mod); # modular exponentation + $num->bmodpow($exp,$mod); # modular exponentiation # ($num**$exp % $mod) Returns the value of C<$num> taken to the power C<$exp> in the modulus -C<$mod> using binary exponentation. C<bmodpow> is far superior to +C<$mod> using binary exponentiation. C<bmodpow> is far superior to writing $num ** $exp % $mod @@ -3867,7 +4036,7 @@ Calculates the N'th root of C<$x>. =head2 round() $x->round($A,$P,$round_mode); - + Round $x to accuracy C<$A> or precision C<$P> using the round mode C<$round_mode>. @@ -3894,7 +4063,7 @@ Examples: =head2 bfloor() - $x->bfloor(); + $x->bfloor(); Set $x to the integer less or equal than $x. This is a no-op in BigInt, but does change $x in BigFloat. @@ -3912,8 +4081,8 @@ does change $x in BigFloat. =head2 blcm() - blcm(@values); # lowest common multiplicator (no OO style) - + blcm(@values); # lowest common multiple (no OO style) + head2 length() $x->length(); @@ -3945,14 +4114,14 @@ Return the signed mantissa of $x as BigInt. =head2 as_int()/as_number() - $x->as_int(); + $x->as_int(); Returns $x as a BigInt (truncated towards zero). In BigInt this is the same as -C<copy()>. +C<copy()>. C<as_number()> is an alias to this method. C<as_number> was introduced in v1.22, while C<as_int()> was only introduced in v1.68. - + =head2 bstr() $x->bstr(); @@ -3989,7 +4158,7 @@ This loses precision, to avoid this use L<as_int()> instead. $x->modify('bpowd'); This method returns 0 if the object can be modified with the given -peration, or 1 if not. +operation, or 1 if not. This is used for instance by L<Math::BigInt::Constant>. @@ -4039,12 +4208,12 @@ the decimal point. For example, 123.45 has a precision of -2. 0 means an integer like 123 (or 120). A precision of 2 means two digits to the left of the decimal point are zero, so 123 with P = 1 becomes 120. Note that numbers with zeros before the decimal point may have different precisions, -because 1200 can have p = 0, 1 or 2 (depending on what the inital value +because 1200 can have p = 0, 1 or 2 (depending on what the initial value was). It could also have p < 0, when the digits after the decimal point are zero. The string output (of floating point numbers) will be padded with zeros: - + Initial value P A Result String ------------------------------------------------------------ 1234.01 -3 1000 1000 @@ -4161,7 +4330,7 @@ versions <= 5.7.2) is like this: =item Accuracy (significant digits) * fround($a) rounds to $a significant digits - * only fdiv() and fsqrt() take A as (optional) paramater + * only fdiv() and fsqrt() take A as (optional) parameter + other operations simply create the same number (fneg etc), or more (fmul) of digits + rounding/truncating is only done when explicitly calling one of fround @@ -4186,7 +4355,7 @@ versions <= 5.7.2) is like this: assumption that 124 has 3 significant digits, while 120/7 will get you '17', not '17.1' since 120 is thought to have 2 significant digits. The rounding after the division then uses the remainder and $y to determine - wether it must round up or down. + whether it must round up or down. ? I have no idea which is the right way. That's why I used a slightly more ? simple scheme and tweaked the few failing testcases to match it. @@ -4239,7 +4408,7 @@ This is how it works now: Math::BigInt->accuracy(2); Math::BigInt::SomeSubClass->accuracy(3); - $x = Math::BigInt::SomeSubClass->new(1234); + $x = Math::BigInt::SomeSubClass->new(1234); $x is now 1230, and not 1200. A subclass might choose to implement this otherwise, e.g. falling back to the parent's A and P. @@ -4301,7 +4470,7 @@ This is how it works now: and P to -2, globally. ?Maybe an extra option that forbids local A & P settings would be in order, - ?so that intermediate rounding does not 'poison' further math? + ?so that intermediate rounding does not 'poison' further math? =item Overriding globals @@ -4414,12 +4583,12 @@ have real numbers as results, the result is NaN. =item exp(), cos(), sin(), atan2() These all might have problems handling infinity right. - + =back =head1 INTERNALS -The actual numbers are stored as unsigned big integers (with seperate sign). +The actual numbers are stored as unsigned big integers (with separate sign). You should neither care about nor depend on the internal representation; it might change without notice. Use B<ONLY> method calls like C<< $x->sign(); >> @@ -4466,7 +4635,7 @@ small numbers (less than about 20 digits) and when converting very large numbers to decimal (for instance for printing, rounding, calculating their length in decimal etc). -So please select carefully what libary you want to use. +So please select carefully what library you want to use. Different low-level libraries use different formats to store the numbers. However, you should B<NOT> depend on the number having a specific format @@ -4506,7 +4675,7 @@ C<$e> and C<$m> will stay always the same, though their real values might change. =head1 EXAMPLES - + use Math::BigInt; sub bint { Math::BigInt->new(shift); } @@ -4654,8 +4823,8 @@ directly. =item * -The private object hash keys like C<$x->{sign}> may not be changed, but -additional keys can be added, like C<$x->{_custom}>. +The private object hash keys like C<< $x->{sign} >> may not be changed, but +additional keys can be added, like C<< $x->{_custom} >>. =item * @@ -4716,7 +4885,7 @@ As a shortcut, you can use the module C<bignum>: use bignum; -Also good for oneliners: +Also good for one-liners: perl -Mbignum -le 'print 2 ** 255' @@ -4793,7 +4962,7 @@ So, the following examples will now work all as expected: print "$x eq 9" if $x eq 3*3; Additionally, the following still works: - + print "$x == 9" if $x == $y; print "$x == 9" if $x == 9; print "$x == 9" if $x == 3*3; @@ -4858,8 +5027,8 @@ The following will probably not do what you expect: It prints both the number of digits in the number and in the fraction part since print calls C<length()> in list context. Use something like: - - print scalar $c->length(),"\n"; # prints 3 + + print scalar $c->length(),"\n"; # prints 3 =item bdiv @@ -4870,7 +5039,7 @@ The following will probably not do what you expect: It prints both quotient and remainder since print calls C<bdiv()> in list context. Also, C<bdiv()> will modify $c, so be careful. You probably want to use - + print $c / 10000,"\n"; print scalar $c->bdiv(10000),"\n"; # or if you want to modify $c @@ -4878,7 +5047,7 @@ instead. The quotient is always the greatest integer less than or equal to the real-valued quotient of the two operands, and the remainder (when it is -nonzero) always has the same sign as the second operand; so, for +non-zero) always has the same sign as the second operand; so, for example, 1 / 4 => ( 0, 1) @@ -4934,8 +5103,8 @@ clearly the reasoning: -inf/-inf = 1, 0 1 * -inf + 0 = -inf inf/-inf = -1, 0 -1 * -inf + 0 = inf -inf/ inf = -1, 0 1 * -inf + 0 = -inf - 8/ 0 = inf, 8 inf * 0 + 8 = 8 - inf/ 0 = inf, inf inf * 0 + inf = inf + 8/ 0 = inf, 8 inf * 0 + 8 = 8 + inf/ 0 = inf, inf inf * 0 + inf = inf 0/ 0 = NaN These cases below violate the "remainder has the sign of the second of the two @@ -4943,8 +5112,8 @@ arguments", since they wouldn't match up otherwise. A / B = C, R so that C * B + R = A ======================================================== - -inf/ 0 = -inf, -inf -inf * 0 + inf = -inf - -8/ 0 = -inf, -8 -inf * 0 + 8 = -8 + -inf/ 0 = -inf, -inf -inf * 0 + inf = -inf + -8/ 0 = -inf, -8 -inf * 0 + 8 = -8 =item Modifying and = @@ -4983,7 +5152,7 @@ modify $x, the last one won't: print bpow($x,$i),"\n"; # modify $x print $x->bpow($i),"\n"; # ditto print $x **= $i,"\n"; # the same - print $x ** $i,"\n"; # leave $x alone + print $x ** $i,"\n"; # leave $x alone The form C<$x **= $y> is faster than C<$x = $x ** $y;>, though. @@ -5033,7 +5202,7 @@ the result should be a Math::BigFloat or the second operant is one. To get a Math::BigFloat you either need to call the operation manually, make sure the operands are already of the proper type or casted to that type via Math::BigFloat->new(): - + $float = Math::BigFloat->new($mbi2) / $mbi; # = 2.5 Beware of simple "casting" the entire expression, this would only convert @@ -5050,7 +5219,7 @@ If in doubt, break the expression into simpler terms, or cast all operands to the desired resulting type. Scalar values are a bit different, since: - + $float = 2 + $mbf; $float = $mbf + 2; |