diff options
Diffstat (limited to 'cpan/Math-BigInt/lib/Math/BigFloat.pm')
-rw-r--r-- | cpan/Math-BigInt/lib/Math/BigFloat.pm | 259 |
1 files changed, 161 insertions, 98 deletions
diff --git a/cpan/Math-BigInt/lib/Math/BigFloat.pm b/cpan/Math-BigInt/lib/Math/BigFloat.pm index f1d7a1a0a0..5dcc919e1a 100644 --- a/cpan/Math-BigInt/lib/Math/BigFloat.pm +++ b/cpan/Math-BigInt/lib/Math/BigFloat.pm @@ -19,7 +19,7 @@ use warnings; use Carp qw< carp croak >; use Math::BigInt (); -our $VERSION = '1.999818'; +our $VERSION = '1.999823'; require Exporter; our @ISA = qw/Math::BigInt/; @@ -417,17 +417,18 @@ sub new { return $self; } - # Handle hexadecimal numbers. We auto-detect hexadecimal numbers if they - # have a "0x" or "0X" prefix. + # Handle hexadecimal numbers. Just like CORE::oct(), we accept octal numbers with + # prefix "0x", "0X", "x", or "X". - if ($wanted =~ /^\s*[+-]?0[Xx]/) { + if ($wanted =~ /^\s*[+-]?0?[Xx]/) { $self = $class -> from_hex($wanted); $self->round(@r) unless @r >= 2 && !defined $r[0] && !defined $r[1]; return $self; } - # Handle octal numbers. We auto-detect octal numbers if they have a "0" - # prefix and a binary exponent. + # Handle octal numbers. Just like CORE::oct(), we accept octal numbers with + # prefix "0o", "0O", "o", or "O". If the prefix is just "0", the number must + # have a binary exponent, or else the number is interpreted as decimal. if ($wanted =~ / ^ @@ -436,23 +437,28 @@ sub new { # sign [+-]? - # prefix - 0 - - # significand using the octal digits 0..7 - [0-7]+ (?: _ [0-7]+ )* (?: - \. - (?: [0-7]+ (?: _ [0-7]+ )* )? - )? - - # exponent (power of 2) using decimal digits - [Pp] - [+-]? - \d+ (?: _ \d+ )* - - \s* - $ + # prefix + 0? [Oo] + | + + # prefix + 0 + + # significand using the octal digits 0..7 + [0-7]+ (?: _ [0-7]+ )* + (?: + \. + (?: [0-7]+ (?: _ [0-7]+ )* )? + )? + + # exponent (power of 2) using decimal digits + [Pp] + [+-]? + \d+ (?: _ \d+ )* + \s* + $ + ) /x) { $self = $class -> from_oct($wanted); @@ -460,10 +466,10 @@ sub new { return $self; } - # Handle binary numbers. We auto-detect binary numbers if they have a "0b" - # or "0B" prefix. + # Handle binary numbers. Just like CORE::oct(), we accept octal numbers with + # prefix "0b", "0B", "b", or "B". - if ($wanted =~ /^\s*[+-]?0[Bb]/) { + if ($wanted =~ /^\s*[+-]?0?[Bb]/) { $self = $class -> from_bin($wanted); $self->round(@r) unless @r >= 2 && !defined $r[0] && !defined $r[1]; return $self; @@ -571,8 +577,8 @@ sub from_hex { # sign ( [+-]? ) - # optional "hex marker" - (?: 0? x )? + # optional hexadecimal prefix + (?: 0? [Xx] )? # significand using the hex digits 0..9 and a..f ( @@ -662,6 +668,9 @@ sub from_oct { # sign ( [+-]? ) + # optional octal prefix + (?: 0? [Oo] )? + # significand using the octal digits 0..7 ( [0-7]+ (?: _ [0-7]+ )* @@ -750,8 +759,8 @@ sub from_bin { # sign ( [+-]? ) - # optional "bin marker" - (?: 0? b )? + # optional binary prefix + (?: 0? [Bb] )? # significand using the binary digits 0 and 1 ( @@ -2794,7 +2803,7 @@ sub bsin { # constant object or error in _find_round_parameters? return $x if $x->modify('bsin') || $x->is_nan(); - + return $x->bnan() if $x->is_inf(); return $x->bzero(@r) if $x->is_zero(); # no rounding at all, so must use fallback @@ -2884,7 +2893,7 @@ sub bcos { # constant object or error in _find_round_parameters? return $x if $x->modify('bcos') || $x->is_nan(); - + return $x->bnan() if $x->is_inf(); return $x->bone(@r) if $x->is_zero(); # no rounding at all, so must use fallback @@ -3519,11 +3528,12 @@ sub bdfac { ($class, $x, @r) = objectify(1, @_) if !ref($x); # inf => inf - return $x if $x->modify('bfac') || $x->{sign} eq '+inf'; + return $x if $x->modify('bdfac') || $x->{sign} eq '+inf'; - return $x->bnan() - if (($x->{sign} ne '+') || # inf, NaN, <0 etc => NaN - ($x->{_es} ne '+')); # digits after dot? + return $x->bnan() if ($x->is_nan() || + $x->{_es} ne '+'); # digits after dot? + return $x->bnan() if $x <= -2; + return $x->bone() if $x <= 1; croak("bdfac() requires a newer version of the $LIB library.") unless $LIB->can('_dfac'); @@ -3537,6 +3547,55 @@ sub bdfac { $x->bnorm()->round(@r); # norm again and round result } +sub btfac { + # compute triple factorial + + # set up parameters + my ($class, $x, @r) = (ref($_[0]), @_); + # objectify is costly, so avoid it + ($class, $x, @r) = objectify(1, @_) if !ref($x); + + # inf => inf + return $x if $x->modify('btfac') || $x->{sign} eq '+inf'; + + return $x->bnan() if ($x->is_nan() || + $x->{_es} ne '+'); # digits after dot? + + my $k = $class -> new("3"); + return $x->bnan() if $x <= -$k; + + my $one = $class -> bone(); + return $x->bone() if $x <= $one; + + my $f = $x -> copy(); + while ($f -> bsub($k) > $one) { + $x -> bmul($f); + } + $x->round(@r); +} + +sub bmfac { + my ($class, $x, $k, @r) = objectify(2, @_); + + # inf => inf + return $x if $x->modify('bmfac') || $x->{sign} eq '+inf'; + + return $x->bnan() if ($x->is_nan() || $k->is_nan() || + $k < 1 || $x <= -$k || + $x->{_es} ne '+' || $k->{_es} ne '+'); + + return $x->bnan() if $x <= -$k; + + my $one = $class -> bone(); + return $x->bone() if $x <= $one; + + my $f = $x -> copy(); + while ($f -> bsub($k) > $one) { + $x -> bmul($f); + } + $x->round(@r); +} + sub blsft { # shift left by $y (multiply by $b ** $y) @@ -4042,7 +4101,7 @@ sub sparts { # Finite number. - my $mant = $class -> bzero(); + my $mant = $self -> copy() -> bzero(); $mant -> {sign} = $self -> {sign}; $mant -> {_m} = $LIB->_copy($self -> {_m}); return $mant unless wantarray; @@ -4605,13 +4664,13 @@ sub numify { if ($x -> is_nan()) { require Math::Complex; - my $inf = Math::Complex::Inf(); + my $inf = $Math::Complex::Inf; return $inf - $inf; } if ($x -> is_inf()) { require Math::Complex; - my $inf = Math::Complex::Inf(); + my $inf = $Math::Complex::Inf; return $x -> is_negative() ? -$inf : $inf; } @@ -4625,66 +4684,60 @@ sub numify { sub import { my $class = shift; - my $l = scalar @_; + $IMPORT++; # remember we did import() + my @a; # unrecognized arguments my $lib = ''; - my @a; my $lib_kind = 'try'; - $IMPORT=1; - for (my $i = 0; $i < $l ; $i++) { + + for (my $i = 0; $i <= $#_ ; $i++) { + croak "Error in import(): argument with index $i is undefined" + unless defined($_[$i]); + if ($_[$i] eq ':constant') { # This causes overlord er load to step in. 'binary' and 'integer' # are handled by BigInt. overload::constant float => sub { $class->new(shift); }; - } elsif ($_[$i] eq 'upgrade') { + } + + elsif ($_[$i] eq 'upgrade') { # this causes upgrading - $upgrade = $_[$i+1]; # or undef to disable + $upgrade = $_[$i+1]; # or undef to disable $i++; - } elsif ($_[$i] eq 'downgrade') { + } + + elsif ($_[$i] eq 'downgrade') { # this causes downgrading - $downgrade = $_[$i+1]; # or undef to disable + $downgrade = $_[$i+1]; # or undef to disable $i++; - } elsif ($_[$i] =~ /^(lib|try|only)\z/) { + } + + elsif ($_[$i] =~ /^(lib|try|only)\z/) { # alternative library - $lib = $_[$i+1] || ''; # default Calc - $lib_kind = $1; # lib, try or only + $lib = $_[$i+1] || ''; + $lib_kind = $1; # "lib", "try", or "only" $i++; - } elsif ($_[$i] eq 'with') { + } + + elsif ($_[$i] eq 'with') { # alternative class for our private parts() # XXX: no longer supported - # $LIB = $_[$i+1] || 'Math::BigInt'; + # $LIB = $_[$i+1] || 'Calc'; + # carp "'with' is no longer supported, use 'lib', 'try', or 'only'"; $i++; - } else { + } + + else { push @a, $_[$i]; } } - $lib =~ tr/a-zA-Z0-9,://cd; # restrict to sane characters - # let use Math::BigInt lib => 'GMP'; use Math::BigFloat; still work - my $mbilib = eval { Math::BigInt->config('lib') }; - if ((defined $mbilib) && ($LIB eq 'Math::BigInt::Calc')) { - # $LIB already loaded - Math::BigInt->import($lib_kind, "$lib, $mbilib", 'objectify'); - } else { - # $LIB not loaded, or with ne "Math::BigInt::Calc" - $lib .= ",$mbilib" if defined $mbilib; - $lib =~ s/^,//; # don't leave empty - - # replacement library can handle lib statement, but also could ignore it + my @import = ('objectify'); + push @import, $lib_kind, $lib if $lib ne ''; + Math::BigInt -> import(@import); - # Perl < 5.6.0 dies with "out of memory!" when eval() and ':constant' is - # used in the same script, or eval inside import(). So we require MBI: - require Math::BigInt; - Math::BigInt->import($lib_kind => $lib, 'objectify'); - } - if ($@) { - croak("Couldn't load $lib: $! $@"); - } # find out which one was actually loaded $LIB = Math::BigInt->config('lib'); - # register us with MBI to get notified of future lib changes - Math::BigInt::_register_callback($class, sub { $LIB = $_[0]; }); - $class->export_to_level(1, $class, @a); # export wanted functions } @@ -5169,10 +5222,13 @@ Math::BigFloat - Arbitrary size floating point math package $x = Math::BigFloat->new($str); # defaults to 0 $x = Math::BigFloat->new('0x123'); # from hexadecimal + $x = Math::BigFloat->new('0o377'); # from octal $x = Math::BigFloat->new('0b101'); # from binary $x = Math::BigFloat->from_hex('0xc.afep+3'); # from hex $x = Math::BigFloat->from_hex('cafe'); # ditto $x = Math::BigFloat->from_oct('1.3267p-4'); # from octal + $x = Math::BigFloat->from_oct('01.3267p-4'); # ditto + $x = Math::BigFloat->from_oct('0o1.3267p-4'); # ditto $x = Math::BigFloat->from_oct('0377'); # ditto $x = Math::BigFloat->from_bin('0b1.1001p-4'); # from binary $x = Math::BigFloat->from_bin('0101'); # ditto @@ -5340,7 +5396,10 @@ Leading and trailing whitespace is ignored. =item * -Leading and trailing zeros are ignored. +Leading zeros are ignored, except for floating point numbers with a binary +exponent, in which case the number is interpreted as an octal floating point +number. For example, "01.4p+0" gives 1.5, "00.4p+0" gives 0.5, but "0.4p+0" +gives a NaN. And while "0377" gives 255, "0377p0" gives 255. =item * @@ -5348,28 +5407,27 @@ If the string has a "0x" prefix, it is interpreted as a hexadecimal number. =item * -If the string has a "0b" prefix, it is interpreted as a binary number. +If the string has a "0o" prefix, it is interpreted as an octal number. =item * -For hexadecimal and binary numbers, the exponent must be separated from the -significand (mantissa) by the letter "p" or "P", not "e" or "E" as with decimal -numbers. +If the string has a "0b" prefix, it is interpreted as a binary number. =item * -One underline is allowed between any two digits, including hexadecimal and -binary digits. +One underline is allowed between any two digits. =item * If the string can not be interpreted, NaN is returned. -=back +=item * -Octal numbers are typically prefixed by "0", but since leading zeros are -stripped, these methods can not automatically recognize octal numbers, so use -the constructor from_oct() to interpret octal strings. +For hexadecimal, octal, and binary numbers, the exponent must be separated from +the significand (mantissa) by the letter "p" or "P", not "e" or "E" as with +decimal numbers. + +=back Some examples of valid string input @@ -5378,10 +5436,16 @@ Some examples of valid string input 1.23e2 123 12300e-2 123 0xcafe 51966 + 0XCAFE 51966 + 0o1337 735 + 0O1337 735 0b1101 13 + 0B1101 13 67_538_754 67538754 -4_5_6.7_8_9e+0_1_0 -4567890000000 0x1.921fb5p+1 3.14159262180328369140625e+0 + 0o1.2677025p1 2.71828174591064453125 + 01.2677025p1 2.71828174591064453125 0b1.1001p-4 9.765625e-2 =head2 Output @@ -5944,8 +6008,7 @@ influence any further operation. Please report any bugs or feature requests to C<bug-math-bigint at rt.cpan.org>, or through the web interface at -L<https://rt.cpan.org/Ticket/Create.html?Queue=Math-BigInt> -(requires login). +L<https://rt.cpan.org/Ticket/Create.html?Queue=Math-BigInt> (requires login). We will be notified, and then you'll automatically be notified of progress on your bug as I make changes. @@ -5959,17 +6022,13 @@ You can also look for information at: =over 4 -=item * RT: CPAN's request tracker - -L<https://rt.cpan.org/Public/Dist/Display.html?Name=Math-BigInt> +=item * GitHub -=item * AnnoCPAN: Annotated CPAN documentation +L<https://github.com/pjacklam/p5-Math-BigInt> -L<http://annocpan.org/dist/Math-BigInt> - -=item * CPAN Ratings +=item * RT: CPAN's request tracker -L<https://cpanratings.perl.org/dist/Math-BigInt> +L<https://rt.cpan.org/Dist/Display.html?Name=Math-BigInt> =item * MetaCPAN @@ -5979,6 +6038,10 @@ L<https://metacpan.org/release/Math-BigInt> L<http://matrix.cpantesters.org/?dist=Math-BigInt> +=item * CPAN Ratings + +L<https://cpanratings.perl.org/dist/Math-BigInt> + =item * The Bignum mailing list =over 4 @@ -6006,7 +6069,7 @@ the same terms as Perl itself. =head1 SEE ALSO -L<Math::BigFloat> and L<Math::BigInt> as well as the backends +L<Math::BigInt> and L<Math::BigInt> as well as the backends L<Math::BigInt::FastCalc>, L<Math::BigInt::GMP>, and L<Math::BigInt::Pari>. The pragmas L<bignum>, L<bigint> and L<bigrat> also might be of interest @@ -6030,7 +6093,7 @@ Florian Ragwitz E<lt>flora@cpan.orgE<gt>, 2010. =item * -Peter John Acklam E<lt>pjacklam@online.noE<gt>, 2011-. +Peter John Acklam E<lt>pjacklam@gmail.comE<gt>, 2011-. =back |