1package Math::BigFloat; 2 3# 4# Mike grinned. 'Two down, infinity to go' - Mike Nostrus in 'Before and After' 5# 6 7# The following hash values are used internally: 8# 9# sign : "+", "-", "+inf", "-inf", or "NaN" 10# _m : absolute value of mantissa ($LIB thingy) 11# _es : sign of exponent ("+" or "-") 12# _e : absolute value of exponent ($LIB thingy) 13# accuracy : accuracy (scalar) 14# precision : precision (scalar) 15 16use 5.006001; 17use strict; 18use warnings; 19 20use Carp qw< carp croak >; 21use Scalar::Util qw< blessed >; 22use Math::BigInt qw< >; 23 24our $VERSION = '2.003002'; 25$VERSION =~ tr/_//d; 26 27require Exporter; 28our @ISA = qw/Math::BigInt/; 29our @EXPORT_OK = qw/bpi/; 30 31# $_trap_inf/$_trap_nan are internal and should never be accessed from outside 32our ($AUTOLOAD, $accuracy, $precision, $div_scale, $round_mode, $rnd_mode, 33 $upgrade, $downgrade, $_trap_nan, $_trap_inf); 34 35use overload 36 37 # overload key: with_assign 38 39 '+' => sub { $_[0] -> copy() -> badd($_[1]); }, 40 41 '-' => sub { my $c = $_[0] -> copy(); 42 $_[2] ? $c -> bneg() -> badd($_[1]) 43 : $c -> bsub($_[1]); }, 44 45 '*' => sub { $_[0] -> copy() -> bmul($_[1]); }, 46 47 '/' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bdiv($_[0]) 48 : $_[0] -> copy() -> bdiv($_[1]); }, 49 50 '%' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bmod($_[0]) 51 : $_[0] -> copy() -> bmod($_[1]); }, 52 53 '**' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bpow($_[0]) 54 : $_[0] -> copy() -> bpow($_[1]); }, 55 56 '<<' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bblsft($_[0]) 57 : $_[0] -> copy() -> bblsft($_[1]); }, 58 59 '>>' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bbrsft($_[0]) 60 : $_[0] -> copy() -> bbrsft($_[1]); }, 61 62 # overload key: assign 63 64 '+=' => sub { $_[0] -> badd($_[1]); }, 65 66 '-=' => sub { $_[0] -> bsub($_[1]); }, 67 68 '*=' => sub { $_[0] -> bmul($_[1]); }, 69 70 '/=' => sub { scalar $_[0] -> bdiv($_[1]); }, 71 72 '%=' => sub { $_[0] -> bmod($_[1]); }, 73 74 '**=' => sub { $_[0] -> bpow($_[1]); }, 75 76 '<<=' => sub { $_[0] -> bblsft($_[1]); }, 77 78 '>>=' => sub { $_[0] -> bbrsft($_[1]); }, 79 80# 'x=' => sub { }, 81 82# '.=' => sub { }, 83 84 # overload key: num_comparison 85 86 '<' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> blt($_[0]) 87 : $_[0] -> blt($_[1]); }, 88 89 '<=' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> ble($_[0]) 90 : $_[0] -> ble($_[1]); }, 91 92 '>' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bgt($_[0]) 93 : $_[0] -> bgt($_[1]); }, 94 95 '>=' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bge($_[0]) 96 : $_[0] -> bge($_[1]); }, 97 98 '==' => sub { $_[0] -> beq($_[1]); }, 99 100 '!=' => sub { $_[0] -> bne($_[1]); }, 101 102 # overload key: 3way_comparison 103 104 '<=>' => sub { my $cmp = $_[0] -> bcmp($_[1]); 105 defined($cmp) && $_[2] ? -$cmp : $cmp; }, 106 107 'cmp' => sub { $_[2] ? "$_[1]" cmp $_[0] -> bstr() 108 : $_[0] -> bstr() cmp "$_[1]"; }, 109 110 # overload key: str_comparison 111 112# 'lt' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bstrlt($_[0]) 113# : $_[0] -> bstrlt($_[1]); }, 114# 115# 'le' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bstrle($_[0]) 116# : $_[0] -> bstrle($_[1]); }, 117# 118# 'gt' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bstrgt($_[0]) 119# : $_[0] -> bstrgt($_[1]); }, 120# 121# 'ge' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bstrge($_[0]) 122# : $_[0] -> bstrge($_[1]); }, 123# 124# 'eq' => sub { $_[0] -> bstreq($_[1]); }, 125# 126# 'ne' => sub { $_[0] -> bstrne($_[1]); }, 127 128 # overload key: binary 129 130 '&' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> band($_[0]) 131 : $_[0] -> copy() -> band($_[1]); }, 132 133 '&=' => sub { $_[0] -> band($_[1]); }, 134 135 '|' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bior($_[0]) 136 : $_[0] -> copy() -> bior($_[1]); }, 137 138 '|=' => sub { $_[0] -> bior($_[1]); }, 139 140 '^' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bxor($_[0]) 141 : $_[0] -> copy() -> bxor($_[1]); }, 142 143 '^=' => sub { $_[0] -> bxor($_[1]); }, 144 145# '&.' => sub { }, 146 147# '&.=' => sub { }, 148 149# '|.' => sub { }, 150 151# '|.=' => sub { }, 152 153# '^.' => sub { }, 154 155# '^.=' => sub { }, 156 157 # overload key: unary 158 159 'neg' => sub { $_[0] -> copy() -> bneg(); }, 160 161# '!' => sub { }, 162 163 '~' => sub { $_[0] -> copy() -> bnot(); }, 164 165# '~.' => sub { }, 166 167 # overload key: mutators 168 169 '++' => sub { $_[0] -> binc() }, 170 171 '--' => sub { $_[0] -> bdec() }, 172 173 # overload key: func 174 175 'atan2' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> batan2($_[0]) 176 : $_[0] -> copy() -> batan2($_[1]); }, 177 178 'cos' => sub { $_[0] -> copy() -> bcos(); }, 179 180 'sin' => sub { $_[0] -> copy() -> bsin(); }, 181 182 'exp' => sub { $_[0] -> copy() -> bexp($_[1]); }, 183 184 'abs' => sub { $_[0] -> copy() -> babs(); }, 185 186 'log' => sub { $_[0] -> copy() -> blog(); }, 187 188 'sqrt' => sub { $_[0] -> copy() -> bsqrt(); }, 189 190 'int' => sub { $_[0] -> copy() -> bint(); }, 191 192 # overload key: conversion 193 194 'bool' => sub { $_[0] -> is_zero() ? '' : 1; }, 195 196 '""' => sub { $_[0] -> bstr(); }, 197 198 '0+' => sub { $_[0] -> numify(); }, 199 200 '=' => sub { $_[0] -> copy(); }, 201 202 ; 203 204############################################################################## 205# global constants, flags and assorted stuff 206 207# the following are public, but their usage is not recommended. Use the 208# accessor methods instead. 209 210# class constants, use Class->constant_name() to access 211# one of 'even', 'odd', '+inf', '-inf', 'zero', 'trunc' or 'common' 212$round_mode = 'even'; 213$accuracy = undef; 214$precision = undef; 215$div_scale = 40; 216 217$upgrade = undef; 218$downgrade = undef; 219# the package we are using for our private parts, defaults to: 220# Math::BigInt->config('lib') 221my $LIB = 'Math::BigInt::Calc'; 222 223# are NaNs ok? (otherwise it dies when encountering an NaN) set w/ config() 224$_trap_nan = 0; 225# the same for infinity 226$_trap_inf = 0; 227 228# constant for easier life 229my $nan = 'NaN'; 230 231# Has import() been called yet? This variable is needed to make "require" work. 232 233my $IMPORT = 0; 234 235# some digits of accuracy for blog(undef, 10); which we use in blog() for speed 236my $LOG_10 = 237 '2.3025850929940456840179914546843642076011014886287729760333279009675726097'; 238my $LOG_10_A = length($LOG_10)-1; 239# ditto for log(2) 240my $LOG_2 = 241 '0.6931471805599453094172321214581765680755001343602552541206800094933936220'; 242my $LOG_2_A = length($LOG_2)-1; 243my $HALF = '0.5'; # made into an object if nec. 244 245############################################################################## 246# the old code had $rnd_mode, so we need to support it, too 247 248sub TIESCALAR { 249 my ($class) = @_; 250 bless \$round_mode, $class; 251} 252 253sub FETCH { 254 return $round_mode; 255} 256 257sub STORE { 258 $rnd_mode = (ref $_[0]) -> round_mode($_[1]); 259} 260 261BEGIN { 262 *objectify = \&Math::BigInt::objectify; 263 264 # when someone sets $rnd_mode, we catch this and check the value to see 265 # whether it is valid or not. 266 $rnd_mode = 'even'; 267 tie $rnd_mode, 'Math::BigFloat'; 268 269 *as_number = \&as_int; 270} 271 272sub DESTROY { 273 # going through AUTOLOAD for every DESTROY is costly, avoid it by empty sub 274} 275 276sub AUTOLOAD { 277 278 # Make fxxx() work by mapping fxxx() to Math::BigFloat::bxxx(). 279 280 my $name = $AUTOLOAD; 281 $name =~ s/^(.*):://; # strip package name 282 my $class = $1 || __PACKAGE__; 283 284 $class -> import() if $IMPORT == 0; 285 286 # E.g., "fabs" -> "babs", but "is_neg" -> "is_neg" 287 288 my $bname = $name; 289 $bname =~ s/^f/b/; 290 291 # Map, e.g., Math::BigFloat::fabs() to Math::BigFloat::babs() 292 293 if ($bname ne $name && Math::BigFloat -> can($bname)) { 294 no strict 'refs'; 295 return &{"Math::BigFloat::$bname"}(@_); 296 } 297 298 # Map, e.g., Math::BigFloat::babs() to Math::BigInt::babs() 299 300 elsif (Math::BigInt -> can($bname)) { 301 no strict 'refs'; 302 return &{"Math::BigInt::$bname"}(@_); 303 } 304 305 else { 306 croak("Can't call $class->$name(), not a valid method"); 307 } 308} 309 310############################################################################## 311 312# Compare the following function with @ISA above. This inheritance mess needs a 313# clean up. When doing so, also consider the BEGIN block and the AUTOLOAD code. 314# Fixme! 315 316sub isa { 317 my ($self, $class) = @_; 318 return if $class =~ /^Math::BigInt/; # we aren't one of these 319 UNIVERSAL::isa($self, $class); 320} 321 322sub config { 323 # return (later set?) configuration data as hash ref 324 my $class = shift || 'Math::BigFloat'; 325 326 # Getter/accessor. 327 328 if (@_ == 1 && ref($_[0]) ne 'HASH') { 329 my $param = shift; 330 return $class if $param eq 'class'; 331 return $LIB if $param eq 'with'; 332 return $class->SUPER::config($param); 333 } 334 335 # Setter. 336 337 my $cfg = $class->SUPER::config(@_); 338 339 # now we need only to override the ones that are different from our parent 340 $cfg->{class} = $class; 341 $cfg->{with} = $LIB; 342 $cfg; 343} 344 345############################################################################### 346# Constructor methods 347############################################################################### 348 349sub new { 350 # Create a new Math::BigFloat object from a string or another bigfloat 351 # object. 352 # _e: exponent 353 # _m: mantissa 354 # sign => ("+", "-", "+inf", "-inf", or "NaN") 355 356 my $self = shift; 357 my $selfref = ref $self; 358 my $class = $selfref || $self; 359 360 # Make "require" work. 361 362 $class -> import() if $IMPORT == 0; 363 364 # Although this use has been discouraged for more than 10 years, people 365 # apparently still use it, so we still support it. 366 367 return $class -> bzero() unless @_; 368 369 my ($wanted, @r) = @_; 370 371 if (!defined($wanted)) { 372 #if (warnings::enabled("uninitialized")) { 373 # warnings::warn("uninitialized", 374 # "Use of uninitialized value in new()"); 375 #} 376 return $class -> bzero(@r); 377 } 378 379 if (!ref($wanted) && $wanted eq "") { 380 #if (warnings::enabled("numeric")) { 381 # warnings::warn("numeric", 382 # q|Argument "" isn't numeric in new()|); 383 #} 384 #return $class -> bzero(@r); 385 return $class -> bnan(@r); 386 } 387 388 # Initialize a new object. 389 390 $self = bless {}, $class unless $selfref; 391 392 # Math::BigFloat or subclass 393 394 if (defined(blessed($wanted)) && $wanted -> isa(__PACKAGE__)) { 395 396 # Don't copy the accuracy and precision, because a new object should get 397 # them from the global configuration. 398 399 $self -> {sign} = $wanted -> {sign}; 400 $self -> {_m} = $LIB -> _copy($wanted -> {_m}); 401 $self -> {_es} = $wanted -> {_es}; 402 $self -> {_e} = $LIB -> _copy($wanted -> {_e}); 403 $self = $self->round(@r) 404 unless @r >= 2 && !defined($r[0]) && !defined($r[1]); 405 return $self; 406 } 407 408 # Shortcut for Math::BigInt and its subclasses. This should be improved. 409 410 if (defined(blessed($wanted))) { 411 if ($wanted -> isa('Math::BigInt')) { 412 $self->{sign} = $wanted -> {sign}; 413 $self->{_m} = $LIB -> _copy($wanted -> {value}); 414 $self->{_es} = '+'; 415 $self->{_e} = $LIB -> _zero(); 416 return $self -> bnorm(); 417 } 418 419 if ($wanted -> can("as_number")) { 420 $self->{sign} = $wanted -> sign(); 421 $self->{_m} = $wanted -> as_number() -> {value}; 422 $self->{_es} = '+'; 423 $self->{_e} = $LIB -> _zero(); 424 return $self -> bnorm(); 425 } 426 } 427 428 # Shortcut for simple forms like '123' that have no trailing zeros. Trailing 429 # zeros would require a non-zero exponent. 430 431 if ($wanted =~ 432 / ^ 433 \s* # optional leading whitespace 434 ( [+-]? ) # optional sign 435 0* # optional leading zeros 436 ( [1-9] (?: [0-9]* [1-9] )? ) # significand 437 \s* # optional trailing whitespace 438 $ 439 /x) 440 { 441 return $downgrade -> new($1 . $2) if defined $downgrade; 442 $self->{sign} = $1 || '+'; 443 $self->{_m} = $LIB -> _new($2); 444 $self->{_es} = '+'; 445 $self->{_e} = $LIB -> _zero(); 446 $self = $self->round(@r) 447 unless @r >= 2 && !defined $r[0] && !defined $r[1]; 448 return $self; 449 } 450 451 # Handle Infs. 452 453 if ($wanted =~ / ^ 454 \s* 455 ( [+-]? ) 456 inf (?: inity )? 457 \s* 458 \z 459 /ix) 460 { 461 my $sgn = $1 || '+'; 462 return $class -> binf($sgn, @r); 463 } 464 465 # Handle explicit NaNs (not the ones returned due to invalid input). 466 467 if ($wanted =~ / ^ 468 \s* 469 ( [+-]? ) 470 nan 471 \s* 472 \z 473 /ix) 474 { 475 return $class -> bnan(@r); 476 } 477 478 my @parts; 479 480 if ( 481 # Handle hexadecimal numbers. We auto-detect hexadecimal numbers if they 482 # have a "0x", "0X", "x", or "X" prefix, cf. CORE::oct(). 483 484 $wanted =~ /^\s*[+-]?0?[Xx]/ and 485 @parts = $class -> _hex_str_to_flt_lib_parts($wanted) 486 487 or 488 489 # Handle octal numbers. We auto-detect octal numbers if they have a 490 # "0o", "0O", "o", "O" prefix, cf. CORE::oct(). 491 492 $wanted =~ /^\s*[+-]?0?[Oo]/ and 493 @parts = $class -> _oct_str_to_flt_lib_parts($wanted) 494 495 or 496 497 # Handle binary numbers. We auto-detect binary numbers if they have a 498 # "0b", "0B", "b", or "B" prefix, cf. CORE::oct(). 499 500 $wanted =~ /^\s*[+-]?0?[Bb]/ and 501 @parts = $class -> _bin_str_to_flt_lib_parts($wanted) 502 503 or 504 505 # At this point, what is left are decimal numbers that aren't handled 506 # above and octal floating point numbers that don't have any of the 507 # "0o", "0O", "o", or "O" prefixes. First see if it is a decimal number. 508 509 @parts = $class -> _dec_str_to_flt_lib_parts($wanted) 510 or 511 512 # See if it is an octal floating point number. The extra check is 513 # included because _oct_str_to_flt_lib_parts() accepts octal numbers 514 # that don't have a prefix (this is needed to make it work with, e.g., 515 # from_oct() that don't require a prefix). However, Perl requires a 516 # prefix for octal floating point literals. For example, "1p+0" is not 517 # valid, but "01p+0" and "0__1p+0" are. 518 519 $wanted =~ /^\s*[+-]?0_*\d/ and 520 @parts = $class -> _oct_str_to_flt_lib_parts($wanted)) 521 { 522 ($self->{sign}, $self->{_m}, $self->{_es}, $self->{_e}) = @parts; 523 524 $self = $self->round(@r) 525 unless @r >= 2 && !defined($r[0]) && !defined($r[1]); 526 527 return $downgrade -> new($self -> bdstr(), @r) 528 if defined($downgrade) && $self -> is_int(); 529 return $self; 530 } 531 532 # If we get here, the value is neither a valid decimal, binary, octal, or 533 # hexadecimal number. It is not an explicit Inf or a NaN either. 534 535 return $class -> bnan(@r); 536} 537 538sub from_dec { 539 my $self = shift; 540 my $selfref = ref $self; 541 my $class = $selfref || $self; 542 543 # Make "require" work. 544 545 $class -> import() if $IMPORT == 0; 546 547 # Don't modify constant (read-only) objects. 548 549 return $self if $selfref && $self->modify('from_dec'); 550 551 my $str = shift; 552 my @r = @_; 553 554 # If called as a class method, initialize a new object. 555 556 $self = bless {}, $class unless $selfref; 557 558 if (my @parts = $class -> _dec_str_to_flt_lib_parts($str)) { 559 ($self->{sign}, $self->{_m}, $self->{_es}, $self->{_e}) = @parts; 560 561 $self = $self->round(@r) 562 unless @r >= 2 && !defined($r[0]) && !defined($r[1]); 563 564 return $downgrade -> new($self -> bdstr(), @r) 565 if defined($downgrade) && $self -> is_int(); 566 return $self; 567 } 568 569 return $self -> bnan(@r); 570} 571 572sub from_hex { 573 my $self = shift; 574 my $selfref = ref $self; 575 my $class = $selfref || $self; 576 577 # Make "require" work. 578 579 $class -> import() if $IMPORT == 0; 580 581 # Don't modify constant (read-only) objects. 582 583 return $self if $selfref && $self->modify('from_hex'); 584 585 my $str = shift; 586 my @r = @_; 587 588 # If called as a class method, initialize a new object. 589 590 $self = bless {}, $class unless $selfref; 591 592 if (my @parts = $class -> _hex_str_to_flt_lib_parts($str)) { 593 ($self->{sign}, $self->{_m}, $self->{_es}, $self->{_e}) = @parts; 594 595 $self = $self->round(@r) 596 unless @r >= 2 && !defined($r[0]) && !defined($r[1]); 597 598 return $downgrade -> new($self -> bdstr(), @r) 599 if defined($downgrade) && $self -> is_int(); 600 return $self; 601 } 602 603 return $self -> bnan(@r); 604} 605 606sub from_oct { 607 my $self = shift; 608 my $selfref = ref $self; 609 my $class = $selfref || $self; 610 611 # Make "require" work. 612 613 $class -> import() if $IMPORT == 0; 614 615 # Don't modify constant (read-only) objects. 616 617 return $self if $selfref && $self->modify('from_oct'); 618 619 my $str = shift; 620 my @r = @_; 621 622 # If called as a class method, initialize a new object. 623 624 $self = bless {}, $class unless $selfref; 625 626 if (my @parts = $class -> _oct_str_to_flt_lib_parts($str)) { 627 ($self->{sign}, $self->{_m}, $self->{_es}, $self->{_e}) = @parts; 628 629 $self = $self->round(@r) 630 unless @r >= 2 && !defined($r[0]) && !defined($r[1]); 631 632 return $downgrade -> new($self -> bdstr(), @r) 633 if defined($downgrade) && $self -> is_int(); 634 return $self; 635 } 636 637 return $self -> bnan(@r); 638} 639 640sub from_bin { 641 my $self = shift; 642 my $selfref = ref $self; 643 my $class = $selfref || $self; 644 645 # Make "require" work. 646 647 $class -> import() if $IMPORT == 0; 648 649 # Don't modify constant (read-only) objects. 650 651 return $self if $selfref && $self->modify('from_bin'); 652 653 my $str = shift; 654 my @r = @_; 655 656 # If called as a class method, initialize a new object. 657 658 $self = bless {}, $class unless $selfref; 659 660 if (my @parts = $class -> _bin_str_to_flt_lib_parts($str)) { 661 ($self->{sign}, $self->{_m}, $self->{_es}, $self->{_e}) = @parts; 662 663 $self = $self->round(@r) 664 unless @r >= 2 && !defined($r[0]) && !defined($r[1]); 665 666 return $downgrade -> new($self -> bdstr(), @r) 667 if defined($downgrade) && $self -> is_int(); 668 return $self; 669 } 670 671 return $self -> bnan(@r); 672} 673 674sub from_ieee754 { 675 my $self = shift; 676 my $selfref = ref $self; 677 my $class = $selfref || $self; 678 679 # Make "require" work. 680 681 $class -> import() if $IMPORT == 0; 682 683 # Don't modify constant (read-only) objects. 684 685 return $self if $selfref && $self->modify('from_ieee754'); 686 687 my $in = shift; # input string (or raw bytes) 688 my $format = shift; # format ("binary32", "decimal64" etc.) 689 my $enc; # significand encoding (applies only to decimal) 690 my $k; # storage width in bits 691 my $b; # base 692 my @r = @_; # rounding parameters, if any 693 694 if ($format =~ /^binary(\d+)\z/) { 695 $k = $1; 696 $b = 2; 697 } elsif ($format =~ /^decimal(\d+)(dpd|bcd)?\z/) { 698 $k = $1; 699 $b = 10; 700 $enc = $2 || 'dpd'; # default is dencely-packed decimals (DPD) 701 } elsif ($format eq 'half') { 702 $k = 16; 703 $b = 2; 704 } elsif ($format eq 'single') { 705 $k = 32; 706 $b = 2; 707 } elsif ($format eq 'double') { 708 $k = 64; 709 $b = 2; 710 } elsif ($format eq 'quadruple') { 711 $k = 128; 712 $b = 2; 713 } elsif ($format eq 'octuple') { 714 $k = 256; 715 $b = 2; 716 } elsif ($format eq 'sexdecuple') { 717 $k = 512; 718 $b = 2; 719 } 720 721 if ($b == 2) { 722 723 # Get the parameters for this format. 724 725 my $p; # precision (in bits) 726 my $t; # number of bits in significand 727 my $w; # number of bits in exponent 728 729 if ($k == 16) { # binary16 (half-precision) 730 $p = 11; 731 $t = 10; 732 $w = 5; 733 } elsif ($k == 32) { # binary32 (single-precision) 734 $p = 24; 735 $t = 23; 736 $w = 8; 737 } elsif ($k == 64) { # binary64 (double-precision) 738 $p = 53; 739 $t = 52; 740 $w = 11; 741 } else { # binaryN (quadruple-precision and above) 742 if ($k < 128 || $k != 32 * sprintf('%.0f', $k / 32)) { 743 croak "Number of bits must be 16, 32, 64, or >= 128 and", 744 " a multiple of 32"; 745 } 746 $p = $k - sprintf('%.0f', 4 * log($k) / log(2)) + 13; 747 $t = $p - 1; 748 $w = $k - $t - 1; 749 } 750 751 # The maximum exponent, minimum exponent, and exponent bias. 752 753 my $emax = $class -> new(2) -> bpow($w - 1) -> bdec(); 754 my $emin = 1 - $emax; 755 my $bias = $emax; 756 757 # Undefined input. 758 759 unless (defined $in) { 760 carp("Input is undefined"); 761 return $self -> bzero(@r); 762 } 763 764 # Make sure input string is a string of zeros and ones. 765 766 my $len = CORE::length $in; 767 if (8 * $len == $k) { # bytes 768 $in = unpack "B*", $in; 769 } elsif (4 * $len == $k) { # hexadecimal 770 if ($in =~ /([^\da-f])/i) { 771 croak "Illegal hexadecimal digit '$1'"; 772 } 773 $in = unpack "B*", pack "H*", $in; 774 } elsif ($len == $k) { # bits 775 if ($in =~ /([^01])/) { 776 croak "Illegal binary digit '$1'"; 777 } 778 } else { 779 croak "Unknown input -- $in"; 780 } 781 782 # Split bit string into sign, exponent, and mantissa/significand. 783 784 my $sign = substr($in, 0, 1) eq '1' ? '-' : '+'; 785 my $expo = $class -> from_bin(substr($in, 1, $w)); 786 my $mant = $class -> from_bin(substr($in, $w + 1)); 787 788 my $x; 789 790 $expo = $expo -> bsub($bias); # subtract bias 791 792 if ($expo < $emin) { # zero and subnormals 793 if ($mant == 0) { # zero 794 $x = $class -> bzero(); 795 } else { # subnormals 796 # compute (1/$b)**(N) rather than ($b)**(-N) 797 $x = $class -> new("0.5"); # 1/$b 798 $x = $x -> bpow($bias + $t - 1) -> bmul($mant); 799 $x = $x -> bneg() if $sign eq '-'; 800 } 801 } 802 803 elsif ($expo > $emax) { # inf and nan 804 if ($mant == 0) { # inf 805 $x = $class -> binf($sign); 806 } else { # nan 807 $x = $class -> bnan(@r); 808 } 809 } 810 811 else { # normals 812 $mant = $class -> new(2) -> bpow($t) -> badd($mant); 813 if ($expo < $t) { 814 # compute (1/$b)**(N) rather than ($b)**(-N) 815 $x = $class -> new("0.5"); # 1/$b 816 $x = $x -> bpow($t - $expo) -> bmul($mant); 817 } else { 818 $x = $class -> new(2); 819 $x = $x -> bpow($expo - $t) -> bmul($mant); 820 } 821 $x = $x -> bneg() if $sign eq '-'; 822 } 823 824 if ($selfref) { 825 $self -> {sign} = $x -> {sign}; 826 $self -> {_m} = $x -> {_m}; 827 $self -> {_es} = $x -> {_es}; 828 $self -> {_e} = $x -> {_e}; 829 } else { 830 $self = $x; 831 } 832 833 return $downgrade -> new($self -> bdstr(), @r) 834 if defined($downgrade) && $self -> is_int(); 835 return $self -> round(@r); 836 } 837 838 croak("The format '$format' is not yet supported."); 839} 840 841sub bzero { 842 # create/assign '+0' 843 844 # Class::method(...) -> Class->method(...) 845 unless (@_ && (defined(blessed($_[0])) && $_[0] -> isa(__PACKAGE__) || 846 $_[0] =~ /^[a-z]\w*(?:::[a-z]\w*)*$/i)) 847 { 848 #carp "Using ", (caller(0))[3], "() as a function is deprecated;", 849 # " use is as a method instead"; 850 unshift @_, __PACKAGE__; 851 } 852 853 my $self = shift; 854 my $selfref = ref $self; 855 my $class = $selfref || $self; 856 857 # Make "require" work. 858 859 $class -> import() if $IMPORT == 0; 860 861 # Don't modify constant (read-only) objects. 862 863 return $self if $selfref && $self->modify('bzero'); 864 865 # Get the rounding parameters, if any. 866 867 my @r = @_; 868 869 return $downgrade -> bzero(@r) if defined $downgrade; 870 871 # If called as a class method, initialize a new object. 872 873 $self = bless {}, $class unless $selfref; 874 875 $self -> {sign} = '+'; 876 $self -> {_m} = $LIB -> _zero(); 877 $self -> {_es} = '+'; 878 $self -> {_e} = $LIB -> _zero(); 879 880 # If rounding parameters are given as arguments, use them. If no rounding 881 # parameters are given, and if called as a class method initialize the new 882 # instance with the class variables. 883 884 #return $self -> round(@r); # this should work, but doesnt; fixme! 885 886 if (@r) { 887 if (@r >= 2 && defined($r[0]) && defined($r[1])) { 888 carp "can't specify both accuracy and precision"; 889 return $self -> bnan(); 890 } 891 $self->{accuracy} = $r[0]; 892 $self->{precision} = $r[1]; 893 } else { 894 unless($selfref) { 895 $self->{accuracy} = $class -> accuracy(); 896 $self->{precision} = $class -> precision(); 897 } 898 } 899 900 return $self; 901} 902 903sub bone { 904 # Create or assign '+1' (or -1 if given sign '-'). 905 906 # Class::method(...) -> Class->method(...) 907 unless (@_ && (defined(blessed($_[0])) && $_[0] -> isa(__PACKAGE__) || 908 $_[0] =~ /^[a-z]\w*(?:::[a-z]\w*)*$/i)) 909 { 910 #carp "Using ", (caller(0))[3], "() as a function is deprecated;", 911 # " use is as a method instead"; 912 unshift @_, __PACKAGE__; 913 } 914 915 my $self = shift; 916 my $selfref = ref $self; 917 my $class = $selfref || $self; 918 919 # Make "require" work. 920 921 $class -> import() if $IMPORT == 0; 922 923 # Don't modify constant (read-only) objects. 924 925 return $self if $selfref && $self->modify('bone'); 926 927 return $downgrade -> bone(@_) if defined $downgrade; 928 929 # Get the sign. 930 931 my $sign = '+'; # default is to return +1 932 if (defined($_[0]) && $_[0] =~ /^\s*([+-])\s*$/) { 933 $sign = $1; 934 shift; 935 } 936 937 # Get the rounding parameters, if any. 938 939 my @r = @_; 940 941 # If called as a class method, initialize a new object. 942 943 $self = bless {}, $class unless $selfref; 944 945 $self -> {sign} = $sign; 946 $self -> {_m} = $LIB -> _one(); 947 $self -> {_es} = '+'; 948 $self -> {_e} = $LIB -> _zero(); 949 950 # If rounding parameters are given as arguments, use them. If no rounding 951 # parameters are given, and if called as a class method initialize the new 952 # instance with the class variables. 953 954 #return $self -> round(@r); # this should work, but doesnt; fixme! 955 956 if (@r) { 957 if (@r >= 2 && defined($r[0]) && defined($r[1])) { 958 carp "can't specify both accuracy and precision"; 959 return $self -> bnan(); 960 } 961 $self->{accuracy} = $_[0]; 962 $self->{precision} = $_[1]; 963 } else { 964 unless($selfref) { 965 $self->{accuracy} = $class -> accuracy(); 966 $self->{precision} = $class -> precision(); 967 } 968 } 969 970 return $self; 971} 972 973sub binf { 974 # create/assign a '+inf' or '-inf' 975 976 # Class::method(...) -> Class->method(...) 977 unless (@_ && (defined(blessed($_[0])) && $_[0] -> isa(__PACKAGE__) || 978 $_[0] =~ /^[a-z]\w*(?:::[a-z]\w*)*$/i)) 979 { 980 #carp "Using ", (caller(0))[3], "() as a function is deprecated;", 981 # " use is as a method instead"; 982 unshift @_, __PACKAGE__; 983 } 984 985 my $self = shift; 986 my $selfref = ref $self; 987 my $class = $selfref || $self; 988 989 { 990 no strict 'refs'; 991 if (${"${class}::_trap_inf"}) { 992 croak("Tried to create +-inf in $class->binf()"); 993 } 994 } 995 996 # Make "require" work. 997 998 $class -> import() if $IMPORT == 0; 999 1000 # Don't modify constant (read-only) objects. 1001 1002 return $self if $selfref && $self->modify('binf'); 1003 1004 return $downgrade -> binf(@_) if $downgrade; 1005 1006 # Get the sign. 1007 1008 my $sign = '+'; # default is to return positive infinity 1009 if (defined($_[0]) && $_[0] =~ /^\s*([+-])(inf|$)/i) { 1010 $sign = $1; 1011 shift; 1012 } 1013 1014 # Get the rounding parameters, if any. 1015 1016 my @r = @_; 1017 1018 # If called as a class method, initialize a new object. 1019 1020 $self = bless {}, $class unless $selfref; 1021 1022 $self -> {sign} = $sign . 'inf'; 1023 $self -> {_m} = $LIB -> _zero(); 1024 $self -> {_es} = '+'; 1025 $self -> {_e} = $LIB -> _zero(); 1026 1027 # If rounding parameters are given as arguments, use them. If no rounding 1028 # parameters are given, and if called as a class method initialize the new 1029 # instance with the class variables. 1030 1031 #return $self -> round(@r); # this should work, but doesnt; fixme! 1032 1033 if (@r) { 1034 if (@r >= 2 && defined($r[0]) && defined($r[1])) { 1035 carp "can't specify both accuracy and precision"; 1036 return $self -> bnan(); 1037 } 1038 $self->{accuracy} = $r[0]; 1039 $self->{precision} = $r[1]; 1040 } else { 1041 unless($selfref) { 1042 $self->{accuracy} = $class -> accuracy(); 1043 $self->{precision} = $class -> precision(); 1044 } 1045 } 1046 1047 return $self; 1048} 1049 1050sub bnan { 1051 # create/assign a 'NaN' 1052 1053 # Class::method(...) -> Class->method(...) 1054 unless (@_ && (defined(blessed($_[0])) && $_[0] -> isa(__PACKAGE__) || 1055 $_[0] =~ /^[a-z]\w*(?:::[a-z]\w*)*$/i)) 1056 { 1057 #carp "Using ", (caller(0))[3], "() as a function is deprecated;", 1058 # " use is as a method instead"; 1059 unshift @_, __PACKAGE__; 1060 } 1061 1062 my $self = shift; 1063 my $selfref = ref $self; 1064 my $class = $selfref || $self; 1065 1066 { 1067 no strict 'refs'; 1068 if (${"${class}::_trap_nan"}) { 1069 croak("Tried to create NaN in $class->bnan()"); 1070 } 1071 } 1072 1073 # Make "require" work. 1074 1075 $class -> import() if $IMPORT == 0; 1076 1077 # Don't modify constant (read-only) objects. 1078 1079 return $self if $selfref && $self->modify('bnan'); 1080 1081 return $downgrade -> bnan(@_) if defined $downgrade; 1082 1083 # Get the rounding parameters, if any. 1084 1085 my @r = @_; 1086 1087 # If called as a class method, initialize a new object. 1088 1089 $self = bless {}, $class unless $selfref; 1090 1091 $self -> {sign} = $nan; 1092 $self -> {_m} = $LIB -> _zero(); 1093 $self -> {_es} = '+'; 1094 $self -> {_e} = $LIB -> _zero(); 1095 1096 # If rounding parameters are given as arguments, use them. If no rounding 1097 # parameters are given, and if called as a class method initialize the new 1098 # instance with the class variables. 1099 1100 #return $self -> round(@r); # this should work, but doesnt; fixme! 1101 1102 if (@r) { 1103 if (@r >= 2 && defined($r[0]) && defined($r[1])) { 1104 carp "can't specify both accuracy and precision"; 1105 return $self -> bnan(); 1106 } 1107 $self->{accuracy} = $r[0]; 1108 $self->{precision} = $r[1]; 1109 } else { 1110 unless($selfref) { 1111 $self->{accuracy} = $class -> accuracy(); 1112 $self->{precision} = $class -> precision(); 1113 } 1114 } 1115 1116 return $self; 1117} 1118 1119sub bpi { 1120 1121 # Class::method(...) -> Class->method(...) 1122 unless (@_ && (defined(blessed($_[0])) && $_[0] -> isa(__PACKAGE__) || 1123 $_[0] =~ /^[a-z]\w*(?:::[a-z]\w*)*$/i)) 1124 { 1125 #carp "Using ", (caller(0))[3], "() as a function is deprecated;", 1126 # " use is as a method instead"; 1127 unshift @_, __PACKAGE__; 1128 } 1129 1130 # Called as Argument list 1131 # --------- ------------- 1132 # Math::BigFloat->bpi() ("Math::BigFloat") 1133 # Math::BigFloat->bpi(10) ("Math::BigFloat", 10) 1134 # $x->bpi() ($x) 1135 # $x->bpi(10) ($x, 10) 1136 # Math::BigFloat::bpi() () 1137 # Math::BigFloat::bpi(10) (10) 1138 # 1139 # In ambiguous cases, we favour the OO-style, so the following case 1140 # 1141 # $n = Math::BigFloat->new("10"); 1142 # $x = Math::BigFloat->bpi($n); 1143 # 1144 # which gives an argument list with the single element $n, is resolved as 1145 # 1146 # $n->bpi(); 1147 1148 my $self = shift; 1149 my $selfref = ref $self; 1150 my $class = $selfref || $self; 1151 my @r = @_; # rounding paramters 1152 1153 # Make "require" work. 1154 1155 $class -> import() if $IMPORT == 0; 1156 1157 if ($selfref) { # bpi() called as an instance method 1158 return $self if $self -> modify('bpi'); 1159 } else { # bpi() called as a class method 1160 $self = bless {}, $class; # initialize new instance 1161 } 1162 1163 ($self, @r) = $self -> _find_round_parameters(@r); 1164 1165 # The accuracy, i.e., the number of digits. Pi has one digit before the 1166 # dot, so a precision of 4 digits is equivalent to an accuracy of 5 digits. 1167 1168 my $n = defined $r[0] ? $r[0] 1169 : defined $r[1] ? 1 - $r[1] 1170 : $self -> div_scale(); 1171 1172 my $rmode = defined $r[2] ? $r[2] : $self -> round_mode(); 1173 1174 my $pi; 1175 1176 if ($n <= 1000) { 1177 1178 # 75 x 14 = 1050 digits 1179 1180 my $all_digits = <<EOF; 1181314159265358979323846264338327950288419716939937510582097494459230781640628 1182620899862803482534211706798214808651328230664709384460955058223172535940812 1183848111745028410270193852110555964462294895493038196442881097566593344612847 1184564823378678316527120190914564856692346034861045432664821339360726024914127 1185372458700660631558817488152092096282925409171536436789259036001133053054882 1186046652138414695194151160943305727036575959195309218611738193261179310511854 1187807446237996274956735188575272489122793818301194912983367336244065664308602 1188139494639522473719070217986094370277053921717629317675238467481846766940513 1189200056812714526356082778577134275778960917363717872146844090122495343014654 1190958537105079227968925892354201995611212902196086403441815981362977477130996 1191051870721134999999837297804995105973173281609631859502445945534690830264252 1192230825334468503526193118817101000313783875288658753320838142061717766914730 1193359825349042875546873115956286388235378759375195778185778053217122680661300 1194192787661119590921642019893809525720106548586327886593615338182796823030195 1195EOF 1196 1197 # Should we round up? 1198 1199 my $round_up; 1200 1201 # From the string above, we need to extract the number of digits we 1202 # want plus extra characters for the newlines. 1203 1204 my $nchrs = $n + int($n / 75); 1205 1206 # Extract the digits we want. 1207 1208 my $digits = substr($all_digits, 0, $nchrs); 1209 1210 # Find out whether we should round up or down. Rounding is easy, since 1211 # pi is trancendental. With directed rounding, it doesn't matter what 1212 # the following digits are. With rounding to nearest, we only have to 1213 # look at one extra digit. 1214 1215 if ($rmode eq 'trunc') { 1216 $round_up = 0; 1217 } else { 1218 my $next_digit = substr($all_digits, $nchrs, 1); 1219 $round_up = $next_digit lt '5' ? 0 : 1; 1220 } 1221 1222 # Remove the newlines. 1223 1224 $digits =~ tr/0-9//cd; 1225 1226 # Now do the rounding. We could easily make the regex substitution 1227 # handle all cases, but we avoid using the regex engine when it is 1228 # simple to avoid it. 1229 1230 if ($round_up) { 1231 my $last_digit = substr($digits, -1, 1); 1232 if ($last_digit lt '9') { 1233 substr($digits, -1, 1) = ++$last_digit; 1234 } else { 1235 $digits =~ s{([0-8])(9+)$} 1236 { ($1 + 1) . ("0" x CORE::length($2)) }e; 1237 } 1238 } 1239 1240 # Convert to an object. 1241 1242 $pi = bless { 1243 sign => '+', 1244 _m => $LIB -> _new($digits), 1245 _es => '-', 1246 _e => $LIB -> _new($n - 1), 1247 }, $class; 1248 1249 } else { 1250 1251 # For large accuracy, the arctan formulas become very inefficient with 1252 # Math::BigFloat, so use Brent-Salamin (aka AGM or Gauss-Legendre). 1253 1254 # Use a few more digits in the intermediate computations. 1255 $n += 8; 1256 1257 $HALF = $class -> new($HALF) unless ref($HALF); 1258 my ($an, $bn, $tn, $pn) 1259 = ($class -> bone, $HALF -> copy() -> bsqrt($n), 1260 $HALF -> copy() -> bmul($HALF), $class -> bone); 1261 while ($pn < $n) { 1262 my $prev_an = $an -> copy(); 1263 $an = $an -> badd($bn) -> bmul($HALF, $n); 1264 $bn = $bn -> bmul($prev_an) -> bsqrt($n); 1265 $prev_an = $prev_an -> bsub($an); 1266 $tn = $tn -> bsub($pn * $prev_an * $prev_an); 1267 $pn = $pn -> badd($pn); 1268 } 1269 $an = $an -> badd($bn); 1270 $an = $an -> bmul($an, $n) -> bdiv(4 * $tn, $n); 1271 1272 $an = $an -> round(@r); 1273 $pi = $an; 1274 } 1275 1276 if (defined $r[0]) { 1277 $pi -> accuracy($r[0]); 1278 } elsif (defined $r[1]) { 1279 $pi -> precision($r[1]); 1280 } 1281 1282 for my $key (qw/ sign _m _es _e accuracy precision /) { 1283 $self -> {$key} = $pi -> {$key}; 1284 } 1285 1286 return $downgrade -> new($self -> bdstr(), @r) 1287 if defined($downgrade) && $self->is_int(); 1288 return $self; 1289} 1290 1291sub copy { 1292 my ($x, $class); 1293 if (ref($_[0])) { # $y = $x -> copy() 1294 $x = shift; 1295 $class = ref($x); 1296 } else { # $y = Math::BigInt -> copy($y) 1297 $class = shift; 1298 $x = shift; 1299 } 1300 1301 carp "Rounding is not supported for ", (caller(0))[3], "()" if @_; 1302 1303 my $copy = bless {}, $class; 1304 1305 $copy->{sign} = $x->{sign}; 1306 $copy->{_es} = $x->{_es}; 1307 $copy->{_m} = $LIB->_copy($x->{_m}); 1308 $copy->{_e} = $LIB->_copy($x->{_e}); 1309 $copy->{accuracy} = $x->{accuracy} if exists $x->{accuracy}; 1310 $copy->{precision} = $x->{precision} if exists $x->{precision}; 1311 1312 return $copy; 1313} 1314 1315sub as_int { 1316 # return copy as a bigint representation of this Math::BigFloat number 1317 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 1318 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 1319 1320 return $x -> copy() if $x -> isa("Math::BigInt"); 1321 1322 # Disable upgrading and downgrading. 1323 1324 require Math::BigInt; 1325 my $upg = Math::BigInt -> upgrade(); 1326 my $dng = Math::BigInt -> downgrade(); 1327 Math::BigInt -> upgrade(undef); 1328 Math::BigInt -> downgrade(undef); 1329 1330 # Copy the value. 1331 1332 my $y; 1333 if ($x -> is_inf()) { 1334 $y = Math::BigInt -> binf($x->sign()); 1335 } elsif ($x -> is_nan()) { 1336 $y = Math::BigInt -> bnan(); 1337 } else { 1338 $y = $LIB->_copy($x->{_m}); 1339 if ($x->{_es} eq '-') { # < 0 1340 $y = $LIB->_rsft($y, $x->{_e}, 10); 1341 } elsif (! $LIB->_is_zero($x->{_e})) { # > 0 1342 $y = $LIB->_lsft($y, $x->{_e}, 10); 1343 } 1344 $y = Math::BigInt->new($x->{sign} . $LIB->_str($y)); 1345 } 1346 1347 # Copy the remaining instance variables. 1348 1349 ($y->{accuracy}, $y->{precision}) = ($x->{accuracy}, $x->{precision}); 1350 1351 # Restore upgrading and downgrading. 1352 1353 Math::BigInt -> upgrade($upg); 1354 Math::BigInt -> downgrade($dng); 1355 1356 return $y; 1357} 1358 1359sub as_float { 1360 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 1361 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 1362 1363 return $x -> copy() if $x -> isa("Math::BigFloat"); 1364 1365 # Disable upgrading and downgrading. 1366 1367 my $upg = Math::BigFloat -> upgrade(); 1368 my $dng = Math::BigFloat -> downgrade(); 1369 Math::BigFloat -> upgrade(undef); 1370 Math::BigFloat -> downgrade(undef); 1371 1372 # Copy the value. 1373 1374 my $y = Math::BigFloat -> new($x); 1375 1376 # Copy the remaining instance variables. 1377 1378 ($y->{accuracy}, $y->{precision}) = ($x->{accuracy}, $x->{precision}); 1379 1380 # Restore upgrading and downgrading. 1381 1382 Math::BigFloat -> upgrade($upg); 1383 Math::BigFloat -> downgrade($dng); 1384 1385 return $y; 1386} 1387 1388sub as_rat { 1389 # return copy as a Math::BigRat representation of this Math::BigFloat 1390 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 1391 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 1392 1393 return $x -> copy() if $x -> isa("Math::BigRat"); 1394 1395 # Disable upgrading and downgrading. 1396 1397 require Math::BigRat; 1398 my $upg = Math::BigRat -> upgrade(); 1399 my $dng = Math::BigRat -> downgrade(); 1400 Math::BigRat -> upgrade(undef); 1401 Math::BigRat -> downgrade(undef); 1402 1403 # Copy the value. 1404 1405 my $y; 1406 if ($x -> is_inf()) { 1407 $y = Math::BigRat -> binf($x -> sign()); 1408 } elsif ($x -> is_nan()) { 1409 $y = Math::BigRat -> bnan(); 1410 } else { 1411 my @flt_parts = ($x->{sign}, $x->{_m}, $x->{_es}, $x->{_e}); 1412 my @rat_parts = $class -> _flt_lib_parts_to_rat_lib_parts(@flt_parts); 1413 $y = Math::BigRat -> new($rat_parts[0] . $LIB -> _str($rat_parts[1]) 1414 . '/' . $LIB -> _str($rat_parts[2])); 1415 } 1416 1417 # Copy the remaining instance variables. 1418 1419 ($y->{accuracy}, $y->{precision}) = ($x->{accuracy}, $x->{precision}); 1420 1421 # Restore upgrading and downgrading. 1422 1423 Math::BigRat -> upgrade($upg); 1424 Math::BigRat -> downgrade($dng); 1425 1426 return $y; 1427} 1428 1429############################################################################### 1430# Boolean methods 1431############################################################################### 1432 1433sub is_zero { 1434 # return true if arg (BFLOAT or num_str) is zero 1435 my (undef, $x) = ref($_[0]) ? (undef, @_) : objectify(1, @_); 1436 1437 ($x->{sign} eq '+' && $LIB->_is_zero($x->{_m})) ? 1 : 0; 1438} 1439 1440sub is_one { 1441 # return true if arg (BFLOAT or num_str) is +1 or -1 if signis given 1442 my (undef, $x, $sign) = ref($_[0]) ? (undef, @_) : objectify(1, @_); 1443 1444 $sign = '+' if !defined $sign || $sign ne '-'; 1445 1446 ($x->{sign} eq $sign && 1447 $LIB->_is_zero($x->{_e}) && 1448 $LIB->_is_one($x->{_m})) ? 1 : 0; 1449} 1450 1451sub is_odd { 1452 # return true if arg (BFLOAT or num_str) is odd or false if even 1453 my (undef, $x) = ref($_[0]) ? (undef, @_) : objectify(1, @_); 1454 1455 (($x->{sign} =~ /^[+-]$/) && # NaN & +-inf aren't 1456 ($LIB->_is_zero($x->{_e})) && 1457 ($LIB->_is_odd($x->{_m}))) ? 1 : 0; 1458} 1459 1460sub is_even { 1461 # return true if arg (BINT or num_str) is even or false if odd 1462 my (undef, $x) = ref($_[0]) ? (undef, @_) : objectify(1, @_); 1463 1464 (($x->{sign} =~ /^[+-]$/) && # NaN & +-inf aren't 1465 ($x->{_es} eq '+') && # 123.45 isn't 1466 ($LIB->_is_even($x->{_m}))) ? 1 : 0; # but 1200 is 1467} 1468 1469sub is_int { 1470 # return true if arg (BFLOAT or num_str) is an integer 1471 my (undef, $x) = ref($_[0]) ? (undef, @_) : objectify(1, @_); 1472 1473 (($x->{sign} =~ /^[+-]$/) && # NaN and +-inf aren't 1474 ($x->{_es} eq '+')) ? 1 : 0; # 1e-1 => no integer 1475} 1476 1477############################################################################### 1478# Comparison methods 1479############################################################################### 1480 1481sub bcmp { 1482 # Compares 2 values. Returns one of undef, <0, =0, >0. (suitable for sort) 1483 1484 # set up parameters 1485 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1]) 1486 ? (ref($_[0]), @_) 1487 : objectify(2, @_); 1488 1489 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 1490 1491 # Handle all 'nan' cases. 1492 1493 return if ($x->{sign} eq $nan) || ($y->{sign} eq $nan); 1494 1495 # Handle all '+inf' and '-inf' cases. 1496 1497 return 0 if ($x->{sign} eq '+inf' && $y->{sign} eq '+inf' || 1498 $x->{sign} eq '-inf' && $y->{sign} eq '-inf'); 1499 return +1 if $x->{sign} eq '+inf'; # x = +inf and y < +inf 1500 return -1 if $x->{sign} eq '-inf'; # x = -inf and y > -inf 1501 return -1 if $y->{sign} eq '+inf'; # x < +inf and y = +inf 1502 return +1 if $y->{sign} eq '-inf'; # x > -inf and y = -inf 1503 1504 # Handle all cases with opposite signs. 1505 1506 return +1 if $x->{sign} eq '+' && $y->{sign} eq '-'; # also does 0 <=> -y 1507 return -1 if $x->{sign} eq '-' && $y->{sign} eq '+'; # also does -x <=> 0 1508 1509 # Handle all remaining zero cases. 1510 1511 my $xz = $x->is_zero(); 1512 my $yz = $y->is_zero(); 1513 return 0 if $xz && $yz; # 0 <=> 0 1514 return -1 if $xz && $y->{sign} eq '+'; # 0 <=> +y 1515 return +1 if $yz && $x->{sign} eq '+'; # +x <=> 0 1516 1517 # Both arguments are now finite, non-zero numbers with the same sign. 1518 1519 my $cmp; 1520 1521 # The next step is to compare the exponents, but since each mantissa is an 1522 # integer of arbitrary value, the exponents must be normalized by the length 1523 # of the mantissas before we can compare them. 1524 1525 my $mxl = $LIB->_len($x->{_m}); 1526 my $myl = $LIB->_len($y->{_m}); 1527 1528 # If the mantissas have the same length, there is no point in normalizing 1529 # the exponents by the length of the mantissas, so treat that as a special 1530 # case. 1531 1532 if ($mxl == $myl) { 1533 1534 # First handle the two cases where the exponents have different signs. 1535 1536 if ($x->{_es} eq '+' && $y->{_es} eq '-') { 1537 $cmp = +1; 1538 } elsif ($x->{_es} eq '-' && $y->{_es} eq '+') { 1539 $cmp = -1; 1540 } 1541 1542 # Then handle the case where the exponents have the same sign. 1543 1544 else { 1545 $cmp = $LIB->_acmp($x->{_e}, $y->{_e}); 1546 $cmp = -$cmp if $x->{_es} eq '-'; 1547 } 1548 1549 # Adjust for the sign, which is the same for x and y, and bail out if 1550 # we're done. 1551 1552 $cmp = -$cmp if $x->{sign} eq '-'; # 124 > 123, but -124 < -123 1553 return $cmp if $cmp; 1554 1555 } 1556 1557 # We must normalize each exponent by the length of the corresponding 1558 # mantissa. Life is a lot easier if we first make both exponents 1559 # non-negative. We do this by adding the same positive value to both 1560 # exponent. This is safe, because when comparing the exponents, only the 1561 # relative difference is important. 1562 1563 my $ex; 1564 my $ey; 1565 1566 if ($x->{_es} eq '+') { 1567 1568 # If the exponent of x is >= 0 and the exponent of y is >= 0, there is 1569 # no need to do anything special. 1570 1571 if ($y->{_es} eq '+') { 1572 $ex = $LIB->_copy($x->{_e}); 1573 $ey = $LIB->_copy($y->{_e}); 1574 } 1575 1576 # If the exponent of x is >= 0 and the exponent of y is < 0, add the 1577 # absolute value of the exponent of y to both. 1578 1579 else { 1580 $ex = $LIB->_copy($x->{_e}); 1581 $ex = $LIB->_add($ex, $y->{_e}); # ex + |ey| 1582 $ey = $LIB->_zero(); # -ex + |ey| = 0 1583 } 1584 1585 } else { 1586 1587 # If the exponent of x is < 0 and the exponent of y is >= 0, add the 1588 # absolute value of the exponent of x to both. 1589 1590 if ($y->{_es} eq '+') { 1591 $ex = $LIB->_zero(); # -ex + |ex| = 0 1592 $ey = $LIB->_copy($y->{_e}); 1593 $ey = $LIB->_add($ey, $x->{_e}); # ey + |ex| 1594 } 1595 1596 # If the exponent of x is < 0 and the exponent of y is < 0, add the 1597 # absolute values of both exponents to both exponents. 1598 1599 else { 1600 $ex = $LIB->_copy($y->{_e}); # -ex + |ey| + |ex| = |ey| 1601 $ey = $LIB->_copy($x->{_e}); # -ey + |ex| + |ey| = |ex| 1602 } 1603 1604 } 1605 1606 # Now we can normalize the exponents by adding lengths of the mantissas. 1607 1608 $ex = $LIB->_add($ex, $LIB->_new($mxl)); 1609 $ey = $LIB->_add($ey, $LIB->_new($myl)); 1610 1611 # We're done if the exponents are different. 1612 1613 $cmp = $LIB->_acmp($ex, $ey); 1614 $cmp = -$cmp if $x->{sign} eq '-'; # 124 > 123, but -124 < -123 1615 return $cmp if $cmp; 1616 1617 # Compare the mantissas, but first normalize them by padding the shorter 1618 # mantissa with zeros (shift left) until it has the same length as the 1619 # longer mantissa. 1620 1621 my $mx = $x->{_m}; 1622 my $my = $y->{_m}; 1623 1624 if ($mxl > $myl) { 1625 $my = $LIB->_lsft($LIB->_copy($my), $LIB->_new($mxl - $myl), 10); 1626 } elsif ($mxl < $myl) { 1627 $mx = $LIB->_lsft($LIB->_copy($mx), $LIB->_new($myl - $mxl), 10); 1628 } 1629 1630 $cmp = $LIB->_acmp($mx, $my); 1631 $cmp = -$cmp if $x->{sign} eq '-'; # 124 > 123, but -124 < -123 1632 return $cmp; 1633 1634} 1635 1636sub bacmp { 1637 # Compares 2 values, ignoring their signs. 1638 # Returns one of undef, <0, =0, >0. (suitable for sort) 1639 1640 # set up parameters 1641 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1]) 1642 ? (ref($_[0]), @_) 1643 : objectify(2, @_); 1644 1645 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 1646 1647 # handle +-inf and NaN's 1648 if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/) { 1649 return if (($x->{sign} eq $nan) || ($y->{sign} eq $nan)); 1650 return 0 if ($x->is_inf() && $y->is_inf()); 1651 return 1 if ($x->is_inf() && !$y->is_inf()); 1652 return -1; 1653 } 1654 1655 # shortcut 1656 my $xz = $x->is_zero(); 1657 my $yz = $y->is_zero(); 1658 return 0 if $xz && $yz; # 0 <=> 0 1659 return -1 if $xz && !$yz; # 0 <=> +y 1660 return 1 if $yz && !$xz; # +x <=> 0 1661 1662 # adjust so that exponents are equal 1663 my $lxm = $LIB->_len($x->{_m}); 1664 my $lym = $LIB->_len($y->{_m}); 1665 my ($xes, $yes) = (1, 1); 1666 $xes = -1 if $x->{_es} ne '+'; 1667 $yes = -1 if $y->{_es} ne '+'; 1668 # the numify somewhat limits our length, but makes it much faster 1669 my $lx = $lxm + $xes * $LIB->_num($x->{_e}); 1670 my $ly = $lym + $yes * $LIB->_num($y->{_e}); 1671 my $l = $lx - $ly; 1672 return $l <=> 0 if $l != 0; 1673 1674 # lengths (corrected by exponent) are equal 1675 # so make mantissa equal-length by padding with zero (shift left) 1676 my $diff = $lxm - $lym; 1677 my $xm = $x->{_m}; # not yet copy it 1678 my $ym = $y->{_m}; 1679 if ($diff > 0) { 1680 $ym = $LIB->_copy($y->{_m}); 1681 $ym = $LIB->_lsft($ym, $LIB->_new($diff), 10); 1682 } elsif ($diff < 0) { 1683 $xm = $LIB->_copy($x->{_m}); 1684 $xm = $LIB->_lsft($xm, $LIB->_new(-$diff), 10); 1685 } 1686 $LIB->_acmp($xm, $ym); 1687} 1688 1689############################################################################### 1690# Arithmetic methods 1691############################################################################### 1692 1693sub bneg { 1694 # (BINT or num_str) return BINT 1695 # negate number or make a negated number from string 1696 my (undef, $x, @r) = ref($_[0]) ? (undef, @_) : objectify(1, @_); 1697 1698 return $x if $x->modify('bneg'); 1699 1700 return $x -> bnan(@r) if $x -> is_nan(); 1701 1702 # For +0 do not negate (to have always normalized +0). 1703 $x->{sign} =~ tr/+-/-+/ 1704 unless $x->{sign} eq '+' && $LIB->_is_zero($x->{_m}); 1705 1706 return $downgrade -> new($x -> bdstr(), @r) if defined($downgrade) 1707 && ($x -> is_int() || $x -> is_inf() || $x -> is_nan()); 1708 return $x -> round(@r); 1709} 1710 1711sub bnorm { 1712 # bnorm() can't support rounding, because bround() and bfround() call 1713 # bnorm(), which would recurse indefinitely. 1714 1715 # adjust m and e so that m is smallest possible 1716 my (undef, $x, @r) = ref($_[0]) ? (undef, @_) : objectify(1, @_); 1717 1718 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 1719 1720 # inf, nan etc 1721 if ($x->{sign} !~ /^[+-]$/) { 1722 return $downgrade -> new($x) if defined $downgrade; 1723 return $x; 1724 } 1725 1726 my $zeros = $LIB->_zeros($x->{_m}); # correct for trailing zeros 1727 if ($zeros != 0) { 1728 my $z = $LIB->_new($zeros); 1729 $x->{_m} = $LIB->_rsft($x->{_m}, $z, 10); 1730 if ($x->{_es} eq '-') { 1731 if ($LIB->_acmp($x->{_e}, $z) >= 0) { 1732 $x->{_e} = $LIB->_sub($x->{_e}, $z); 1733 $x->{_es} = '+' if $LIB->_is_zero($x->{_e}); 1734 } else { 1735 $x->{_e} = $LIB->_sub($LIB->_copy($z), $x->{_e}); 1736 $x->{_es} = '+'; 1737 } 1738 } else { 1739 $x->{_e} = $LIB->_add($x->{_e}, $z); 1740 } 1741 } else { 1742 # $x can only be 0Ey if there are no trailing zeros ('0' has 0 trailing 1743 # zeros). So, for something like 0Ey, set y to 0, and -0 => +0 1744 if ($LIB->_is_zero($x->{_m})) { 1745 $x->{sign} = '+'; 1746 $x->{_es} = '+'; 1747 $x->{_e} = $LIB->_zero(); 1748 } 1749 } 1750 1751 return $downgrade -> new($x) 1752 if defined($downgrade) && $x->is_int(); 1753 return $x; 1754} 1755 1756sub binc { 1757 # increment arg by one 1758 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 1759 1760 return $x if $x->modify('binc'); 1761 1762 # Inf and NaN 1763 1764 return $x -> bnan(@r) if $x -> is_nan(); 1765 return $x -> binf($x->{sign}, @r) if $x -> is_inf(); 1766 1767 # Non-integer 1768 1769 if ($x->{_es} eq '-') { 1770 return $x->badd($class->bone(), @r); 1771 } 1772 1773 # If the exponent is non-zero, convert the internal representation, so that, 1774 # e.g., 12e+3 becomes 12000e+0 and we can easily increment the mantissa. 1775 1776 if (!$LIB->_is_zero($x->{_e})) { 1777 $x->{_m} = $LIB->_lsft($x->{_m}, $x->{_e}, 10); # 1e2 => 100 1778 $x->{_e} = $LIB->_zero(); # normalize 1779 $x->{_es} = '+'; 1780 # we know that the last digit of $x will be '1' or '9', depending on the 1781 # sign 1782 } 1783 1784 # now $x->{_e} == 0 1785 if ($x->{sign} eq '+') { 1786 $x->{_m} = $LIB->_inc($x->{_m}); 1787 return $x->bnorm()->bround(@r); 1788 } elsif ($x->{sign} eq '-') { 1789 $x->{_m} = $LIB->_dec($x->{_m}); 1790 $x->{sign} = '+' if $LIB->_is_zero($x->{_m}); # -1 +1 => -0 => +0 1791 return $x->bnorm()->bround(@r); 1792 } 1793 1794 return $downgrade -> new($x -> bdstr(), @r) 1795 if defined($downgrade) && $x -> is_int(); 1796 return $x; 1797} 1798 1799sub bdec { 1800 # decrement arg by one 1801 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 1802 1803 return $x if $x->modify('bdec'); 1804 1805 # Inf and NaN 1806 1807 return $x -> bnan(@r) if $x -> is_nan(); 1808 return $x -> binf($x->{sign}, @r) if $x -> is_inf(); 1809 1810 # Non-integer 1811 1812 if ($x->{_es} eq '-') { 1813 return $x->badd($class->bone('-'), @r); 1814 } 1815 1816 # If the exponent is non-zero, convert the internal representation, so that, 1817 # e.g., 12e+3 becomes 12000e+0 and we can easily increment the mantissa. 1818 1819 if (!$LIB->_is_zero($x->{_e})) { 1820 $x->{_m} = $LIB->_lsft($x->{_m}, $x->{_e}, 10); # 1e2 => 100 1821 $x->{_e} = $LIB->_zero(); # normalize 1822 $x->{_es} = '+'; 1823 } 1824 1825 # now $x->{_e} == 0 1826 my $zero = $x->is_zero(); 1827 if (($x->{sign} eq '-') || $zero) { # x <= 0 1828 $x->{_m} = $LIB->_inc($x->{_m}); 1829 $x->{sign} = '-' if $zero; # 0 => 1 => -1 1830 $x->{sign} = '+' if $LIB->_is_zero($x->{_m}); # -1 +1 => -0 => +0 1831 return $x->bnorm()->round(@r); 1832 } 1833 elsif ($x->{sign} eq '+') { # x > 0 1834 $x->{_m} = $LIB->_dec($x->{_m}); 1835 return $x->bnorm()->round(@r); 1836 } 1837 1838 return $downgrade -> new($x -> bdstr(), @r) 1839 if defined($downgrade) && $x -> is_int(); 1840 return $x -> round(@r); 1841} 1842 1843sub badd { 1844 # set up parameters 1845 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1]) 1846 ? (ref($_[0]), @_) 1847 : objectify(2, @_); 1848 1849 return $x if $x->modify('badd'); 1850 1851 # inf and NaN handling 1852 if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/) { 1853 1854 # $x is NaN and/or $y is NaN 1855 if ($x->{sign} eq $nan || $y->{sign} eq $nan) { 1856 $x = $x->bnan(); 1857 } 1858 1859 # $x is Inf and $y is Inf 1860 elsif ($x->{sign} =~ /^[+-]inf$/ && $y->{sign} =~ /^[+-]inf$/) { 1861 # +Inf + +Inf or -Inf + -Inf => same, rest is NaN 1862 $x = $x->bnan() if $x->{sign} ne $y->{sign}; 1863 } 1864 1865 # +-inf + something => +-inf; something +-inf => +-inf 1866 elsif ($y->{sign} =~ /^[+-]inf$/) { 1867 $x->{sign} = $y->{sign}; 1868 } 1869 1870 return $downgrade -> new($x -> bdstr(), @r) if defined $downgrade; 1871 return $x -> round(@r); 1872 } 1873 1874 return $upgrade->badd($x, $y, @r) if defined $upgrade; 1875 1876 $r[3] = $y; # no push! 1877 1878 # for speed: no add for $x + 0 1879 if ($y->is_zero()) { 1880 $x = $x->round(@r); 1881 } 1882 1883 # for speed: no add for 0 + $y 1884 elsif ($x->is_zero()) { 1885 # make copy, clobbering up x (modify in place!) 1886 $x->{_e} = $LIB->_copy($y->{_e}); 1887 $x->{_es} = $y->{_es}; 1888 $x->{_m} = $LIB->_copy($y->{_m}); 1889 $x->{sign} = $y->{sign} || $nan; 1890 $x = $x->round(@r); 1891 } 1892 1893 # both $x and $y are non-zero 1894 else { 1895 1896 # take lower of the two e's and adapt m1 to it to match m2 1897 my $e = $y->{_e}; 1898 $e = $LIB->_zero() if !defined $e; # if no BFLOAT? 1899 $e = $LIB->_copy($e); # make copy (didn't do it yet) 1900 1901 my $es; 1902 1903 ($e, $es) = $LIB -> _ssub($e, $y->{_es} || '+', $x->{_e}, $x->{_es}); 1904 1905 my $add = $LIB->_copy($y->{_m}); 1906 1907 if ($es eq '-') { # < 0 1908 $x->{_m} = $LIB->_lsft($x->{_m}, $e, 10); 1909 ($x->{_e}, $x->{_es}) = $LIB -> _sadd($x->{_e}, $x->{_es}, $e, $es); 1910 } elsif (!$LIB->_is_zero($e)) { # > 0 1911 $add = $LIB->_lsft($add, $e, 10); 1912 } 1913 1914 # else: both e are the same, so just leave them 1915 1916 if ($x->{sign} eq $y->{sign}) { 1917 $x->{_m} = $LIB->_add($x->{_m}, $add); 1918 } else { 1919 ($x->{_m}, $x->{sign}) = 1920 $LIB -> _sadd($x->{_m}, $x->{sign}, $add, $y->{sign}); 1921 } 1922 1923 # delete trailing zeros, then round 1924 $x = $x->bnorm()->round(@r); 1925 } 1926 1927 return $downgrade -> new($x -> bdstr(), @r) 1928 if defined($downgrade) && $x -> is_int(); 1929 return $x; # rounding already done above 1930} 1931 1932sub bsub { 1933 # set up parameters 1934 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1]) 1935 ? (ref($_[0]), @_) 1936 : objectify(2, @_); 1937 1938 return $x if $x -> modify('bsub'); 1939 1940 if ($y -> is_zero()) { 1941 $x = $x -> round(@r); 1942 } else { 1943 1944 # To correctly handle the special case $x -> bsub($x), we note the sign 1945 # of $x, then flip the sign of $y, and if the sign of $x changed too, 1946 # then we know that $x and $y are the same object. 1947 1948 my $xsign = $x -> {sign}; 1949 $y -> {sign} =~ tr/+-/-+/; # does nothing for NaN 1950 if ($xsign ne $x -> {sign}) { 1951 # special case of $x -> bsub($x) results in 0 1952 if ($xsign =~ /^[+-]$/) { 1953 $x = $x -> bzero(@r); 1954 } else { 1955 $x = $x -> bnan(); # NaN, -inf, +inf 1956 } 1957 return $downgrade -> new($x -> bdstr(), @r) if defined $downgrade; 1958 return $x -> round(@r); 1959 } 1960 $x = $x -> badd($y, @r); # badd does not leave internal zeros 1961 $y -> {sign} =~ tr/+-/-+/; # reset $y (does nothing for NaN) 1962 } 1963 1964 return $downgrade -> new($x -> bdstr(), @r) 1965 if defined($downgrade) && ($x->is_int() || $x->is_inf() || $x->is_nan()); 1966 $x; # already rounded by badd() or no rounding 1967} 1968 1969sub bmul { 1970 # multiply two numbers 1971 1972 # set up parameters 1973 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1]) 1974 ? (ref($_[0]), @_) 1975 : objectify(2, @_); 1976 1977 return $x if $x->modify('bmul'); 1978 1979 return $x->bnan(@r) if ($x->{sign} eq $nan) || ($y->{sign} eq $nan); 1980 1981 # inf handling 1982 if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/)) { 1983 return $x->bnan(@r) if $x->is_zero() || $y->is_zero(); 1984 # result will always be +-inf: 1985 # +inf * +/+inf => +inf, -inf * -/-inf => +inf 1986 # +inf * -/-inf => -inf, -inf * +/+inf => -inf 1987 return $x->binf(@r) if ($x->{sign} =~ /^\+/ && $y->{sign} =~ /^\+/); 1988 return $x->binf(@r) if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/); 1989 return $x->binf('-', @r); 1990 } 1991 1992 return $upgrade->bmul($x, $y, @r) if defined $upgrade; 1993 1994 # aEb * cEd = (a*c)E(b+d) 1995 $x->{_m} = $LIB->_mul($x->{_m}, $y->{_m}); 1996 ($x->{_e}, $x->{_es}) 1997 = $LIB -> _sadd($x->{_e}, $x->{_es}, $y->{_e}, $y->{_es}); 1998 1999 $r[3] = $y; # no push! 2000 2001 # adjust sign: 2002 $x->{sign} = $x->{sign} ne $y->{sign} ? '-' : '+'; 2003 $x = $x->bnorm->round(@r); 2004 2005 return $downgrade -> new($x -> bdstr(), @r) 2006 if defined($downgrade) && ($x->is_int() || $x->is_inf() || $x->is_nan()); 2007 return $x; 2008} 2009 2010sub bmuladd { 2011 # multiply two numbers and add the third to the result 2012 2013 # set up parameters 2014 my ($class, $x, $y, $z, @r) 2015 = ref($_[0]) && ref($_[0]) eq ref($_[1]) && ref($_[1]) eq ref($_[2]) 2016 ? (ref($_[0]), @_) 2017 : objectify(3, @_); 2018 2019 return $x if $x->modify('bmuladd'); 2020 2021 return $x->bnan(@r) if (($x->{sign} eq $nan) || 2022 ($y->{sign} eq $nan) || 2023 ($z->{sign} eq $nan)); 2024 2025 # inf handling 2026 if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/)) { 2027 return $x->bnan(@r) if $x->is_zero() || $y->is_zero(); 2028 # result will always be +-inf: 2029 # +inf * +/+inf => +inf, -inf * -/-inf => +inf 2030 # +inf * -/-inf => -inf, -inf * +/+inf => -inf 2031 return $x->binf(@r) if ($x->{sign} =~ /^\+/ && $y->{sign} =~ /^\+/); 2032 return $x->binf(@r) if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/); 2033 return $x->binf('-', @r); 2034 } 2035 2036 # aEb * cEd = (a*c)E(b+d) 2037 $x->{_m} = $LIB->_mul($x->{_m}, $y->{_m}); 2038 ($x->{_e}, $x->{_es}) 2039 = $LIB -> _sadd($x->{_e}, $x->{_es}, $y->{_e}, $y->{_es}); 2040 2041 $r[3] = $y; # no push! 2042 2043 # adjust sign: 2044 $x->{sign} = $x->{sign} ne $y->{sign} ? '-' : '+'; 2045 2046 # z=inf handling (z=NaN handled above) 2047 if ($z->{sign} =~ /^[+-]inf$/) { 2048 $x->{sign} = $z->{sign}; 2049 return $downgrade -> new($x -> bdstr(), @r) if defined $downgrade; 2050 return $x -> round(@r); 2051 } 2052 2053 # take lower of the two e's and adapt m1 to it to match m2 2054 my $e = $z->{_e}; 2055 $e = $LIB->_zero() if !defined $e; # if no BFLOAT? 2056 $e = $LIB->_copy($e); # make copy (didn't do it yet) 2057 2058 my $es; 2059 2060 ($e, $es) = $LIB -> _ssub($e, $z->{_es} || '+', $x->{_e}, $x->{_es}); 2061 2062 my $add = $LIB->_copy($z->{_m}); 2063 2064 if ($es eq '-') # < 0 2065 { 2066 $x->{_m} = $LIB->_lsft($x->{_m}, $e, 10); 2067 ($x->{_e}, $x->{_es}) = $LIB -> _sadd($x->{_e}, $x->{_es}, $e, $es); 2068 } elsif (!$LIB->_is_zero($e)) # > 0 2069 { 2070 $add = $LIB->_lsft($add, $e, 10); 2071 } 2072 # else: both e are the same, so just leave them 2073 2074 if ($x->{sign} eq $z->{sign}) { 2075 # add 2076 $x->{_m} = $LIB->_add($x->{_m}, $add); 2077 } else { 2078 ($x->{_m}, $x->{sign}) = 2079 $LIB -> _sadd($x->{_m}, $x->{sign}, $add, $z->{sign}); 2080 } 2081 2082 # delete trailing zeros, then round 2083 $x = $x->bnorm()->round(@r); 2084 2085 return $downgrade -> new($x -> bdstr(), @r) 2086 if defined($downgrade) && ($x->is_int() || $x->is_inf() || $x->is_nan()); 2087 return $x; 2088} 2089 2090sub bdiv { 2091 # (dividend: BFLOAT or num_str, divisor: BFLOAT or num_str) return 2092 # (BFLOAT, BFLOAT) (quo, rem) or BFLOAT (only quo) 2093 2094 # set up parameters 2095 my ($class, $x, $y, @r) = (ref($_[0]), @_); 2096 # objectify is costly, so avoid it 2097 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) { 2098 ($class, $x, $y, @r) = objectify(2, @_); 2099 } 2100 2101 return $x if $x->modify('bdiv'); 2102 2103 my $wantarray = wantarray; # call only once 2104 2105 # At least one argument is NaN. This is handled the same way as in 2106 # Math::BigInt -> bdiv(). 2107 2108 if ($x -> is_nan() || $y -> is_nan()) { 2109 return $wantarray ? ($x -> bnan(@r), $class -> bnan(@r)) 2110 : $x -> bnan(@r); 2111 } 2112 2113 # Divide by zero and modulo zero. This is handled the same way as in 2114 # Math::BigInt -> bdiv(). See the comment in the code for Math::BigInt -> 2115 # bdiv() for further details. 2116 2117 if ($y -> is_zero()) { 2118 my ($quo, $rem); 2119 if ($wantarray) { 2120 $rem = $x -> copy() -> round(@r); 2121 $rem = $downgrade -> new($rem, @r) 2122 if defined($downgrade) && $rem -> is_int(); 2123 } 2124 if ($x -> is_zero()) { 2125 $quo = $x -> bnan(@r); 2126 } else { 2127 $quo = $x -> binf($x -> {sign}, @r); 2128 } 2129 return $wantarray ? ($quo, $rem) : $quo; 2130 } 2131 2132 # Numerator (dividend) is +/-inf. This is handled the same way as in 2133 # Math::BigInt -> bdiv(). See the comment in the code for Math::BigInt -> 2134 # bdiv() for further details. 2135 2136 if ($x -> is_inf()) { 2137 my ($quo, $rem); 2138 $rem = $class -> bnan(@r) if $wantarray; 2139 if ($y -> is_inf()) { 2140 $quo = $x -> bnan(@r); 2141 } else { 2142 my $sign = $x -> bcmp(0) == $y -> bcmp(0) ? '+' : '-'; 2143 $quo = $x -> binf($sign, @r); 2144 } 2145 return $wantarray ? ($quo, $rem) : $quo; 2146 } 2147 2148 # Denominator (divisor) is +/-inf. This is handled the same way as in 2149 # Math::BigInt -> bdiv(), with one exception: In scalar context, 2150 # Math::BigFloat does true division (although rounded), not floored division 2151 # (F-division), so a finite number divided by +/-inf is always zero. See the 2152 # comment in the code for Math::BigInt -> bdiv() for further details. 2153 2154 if ($y -> is_inf()) { 2155 my ($quo, $rem); 2156 if ($wantarray) { 2157 if ($x -> is_zero() || $x -> bcmp(0) == $y -> bcmp(0)) { 2158 $rem = $x -> copy() -> round(@r); 2159 $rem = $downgrade -> new($rem, @r) 2160 if defined($downgrade) && $rem -> is_int(); 2161 $quo = $x -> bzero(@r); 2162 } else { 2163 $rem = $class -> binf($y -> {sign}, @r); 2164 $quo = $x -> bone('-', @r); 2165 } 2166 return ($quo, $rem); 2167 } else { 2168 if ($y -> is_inf()) { 2169 if ($x -> is_nan() || $x -> is_inf()) { 2170 return $x -> bnan(@r); 2171 } else { 2172 return $x -> bzero(@r); 2173 } 2174 } 2175 } 2176 } 2177 2178 # At this point, both the numerator and denominator are finite numbers, and 2179 # the denominator (divisor) is non-zero. 2180 2181 # x == 0? 2182 if ($x->is_zero()) { 2183 my ($quo, $rem); 2184 $quo = $x->round(@r); 2185 $quo = $downgrade -> new($quo, @r) 2186 if defined($downgrade) && $quo -> is_int(); 2187 if ($wantarray) { 2188 $rem = $class -> bzero(@r); 2189 return $quo, $rem; 2190 } 2191 return $quo; 2192 } 2193 2194 # Division might return a value that we can not represent exactly, so 2195 # upgrade, if upgrading is enabled. 2196 2197 return $upgrade -> bdiv($x, $y, @r) 2198 if defined($upgrade) && !wantarray && !$LIB -> _is_one($y -> {_m}); 2199 2200 # we need to limit the accuracy to protect against overflow 2201 my $fallback = 0; 2202 my (@params, $scale); 2203 ($x, @params) = $x->_find_round_parameters($r[0], $r[1], $r[2], $y); 2204 2205 return $x -> round(@r) if $x->is_nan(); # error in _find_round_parameters? 2206 2207 # no rounding at all, so must use fallback 2208 if (scalar @params == 0) { 2209 # simulate old behaviour 2210 $params[0] = $class->div_scale(); # and round to it as accuracy 2211 $scale = $params[0]+4; # at least four more for proper round 2212 $params[2] = $r[2]; # round mode by caller or undef 2213 $fallback = 1; # to clear a/p afterwards 2214 } else { 2215 # the 4 below is empirical, and there might be cases where it is not 2216 # enough... 2217 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 2218 } 2219 2220 my $rem; 2221 $rem = $class -> bzero() if wantarray; 2222 2223 $y = $class->new($y) unless $y->isa('Math::BigFloat'); 2224 2225 my $lx = $LIB -> _len($x->{_m}); 2226 my $ly = $LIB -> _len($y->{_m}); 2227 $scale = $lx if $lx > $scale; 2228 $scale = $ly if $ly > $scale; 2229 my $diff = $ly - $lx; 2230 $scale += $diff if $diff > 0; # if lx << ly, but not if ly << lx! 2231 2232 # check that $y is not 1 nor -1 and cache the result: 2233 my $y_not_one = !($LIB->_is_zero($y->{_e}) && $LIB->_is_one($y->{_m})); 2234 2235 # flipping the sign of $y will also flip the sign of $x for the special 2236 # case of $x->bsub($x); so we can catch it below: 2237 my $xsign = $x->{sign}; 2238 $y->{sign} =~ tr/+-/-+/; 2239 2240 if ($xsign ne $x->{sign}) { 2241 # special case of $x /= $x results in 1 2242 $x = $x->bone(); # "fixes" also sign of $y, since $x is $y 2243 } else { 2244 # correct $y's sign again 2245 $y->{sign} =~ tr/+-/-+/; 2246 # continue with normal div code: 2247 2248 # make copy of $x in case of list context for later remainder 2249 # calculation 2250 if (wantarray && $y_not_one) { 2251 $rem = $x->copy(); 2252 } 2253 2254 $x->{sign} = $x->{sign} ne $y->sign() ? '-' : '+'; 2255 2256 # check for / +-1 (+/- 1E0) 2257 if ($y_not_one) { 2258 # promote Math::BigInt and its subclasses (except when already a 2259 # Math::BigFloat) 2260 $y = $class->new($y) unless $y->isa('Math::BigFloat'); 2261 2262 # calculate the result to $scale digits and then round it 2263 # a * 10 ** b / c * 10 ** d => a/c * 10 ** (b-d) 2264 $x->{_m} = $LIB->_lsft($x->{_m}, $LIB->_new($scale), 10); 2265 $x->{_m} = $LIB->_div($x->{_m}, $y->{_m}); # a/c 2266 2267 # correct exponent of $x 2268 ($x->{_e}, $x->{_es}) 2269 = $LIB -> _ssub($x->{_e}, $x->{_es}, $y->{_e}, $y->{_es}); 2270 # correct for 10**scale 2271 ($x->{_e}, $x->{_es}) 2272 = $LIB -> _ssub($x->{_e}, $x->{_es}, $LIB->_new($scale), '+'); 2273 $x = $x->bnorm(); # remove trailing 0's 2274 } 2275 } # end else $x != $y 2276 2277 # shortcut to not run through _find_round_parameters again 2278 if (defined $params[0]) { 2279 $x->{accuracy} = undef; # clear before round 2280 $x = $x->bround($params[0], $params[2]); # then round accordingly 2281 } else { 2282 $x->{precision} = undef; # clear before round 2283 $x = $x->bfround($params[1], $params[2]); # then round accordingly 2284 } 2285 if ($fallback) { 2286 # clear a/p after round, since user did not request it 2287 $x->{accuracy} = undef; 2288 $x->{precision} = undef; 2289 } 2290 2291 if (wantarray) { 2292 if ($y_not_one) { 2293 $x = $x -> bfloor(); 2294 $rem = $rem->bmod($y, @params); # copy already done 2295 } 2296 if ($fallback) { 2297 # clear a/p after round, since user did not request it 2298 $rem->{accuracy} = undef; 2299 $rem->{precision} = undef; 2300 } 2301 $x = $downgrade -> new($x -> bdstr(), @r) 2302 if defined($downgrade) && $x -> is_int(); 2303 $rem = $downgrade -> new($rem -> bdstr(), @r) 2304 if defined($downgrade) && $rem -> is_int(); 2305 return ($x, $rem); 2306 } 2307 2308 $x = $downgrade -> new($x, @r) 2309 if defined($downgrade) && $x -> is_int(); 2310 $x; # rounding already done above 2311} 2312 2313sub bmod { 2314 # (dividend: BFLOAT or num_str, divisor: BFLOAT or num_str) return remainder 2315 2316 # set up parameters 2317 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1]) 2318 ? (ref($_[0]), @_) 2319 : objectify(2, @_); 2320 2321 return $x if $x->modify('bmod'); 2322 2323 # At least one argument is NaN. This is handled the same way as in 2324 # Math::BigInt -> bmod(). 2325 2326 return $x -> bnan(@r) if $x -> is_nan() || $y -> is_nan(); 2327 2328 # Modulo zero. This is handled the same way as in Math::BigInt -> bmod(). 2329 2330 if ($y -> is_zero()) { 2331 return $x -> round(@r); 2332 } 2333 2334 # Numerator (dividend) is +/-inf. This is handled the same way as in 2335 # Math::BigInt -> bmod(). 2336 2337 if ($x -> is_inf()) { 2338 return $x -> bnan(@r); 2339 } 2340 2341 # Denominator (divisor) is +/-inf. This is handled the same way as in 2342 # Math::BigInt -> bmod(). 2343 2344 if ($y -> is_inf()) { 2345 if ($x -> is_zero() || $x -> bcmp(0) == $y -> bcmp(0)) { 2346 return $x -> round(@r); 2347 } else { 2348 return $x -> binf($y -> sign(), @r); 2349 } 2350 } 2351 2352 return $x->bzero(@r) if $x->is_zero() 2353 || ($x->is_int() && 2354 # check that $y == +1 or $y == -1: 2355 ($LIB->_is_zero($y->{_e}) && $LIB->_is_one($y->{_m}))); 2356 2357 my $cmp = $x->bacmp($y); # equal or $x < $y? 2358 if ($cmp == 0) { # $x == $y => result 0 2359 return $x -> bzero(@r); 2360 } 2361 2362 # only $y of the operands negative? 2363 my $neg = $x->{sign} ne $y->{sign} ? 1 : 0; 2364 2365 $x->{sign} = $y->{sign}; # calc sign first 2366 if ($cmp < 0 && $neg == 0) { # $x < $y => result $x 2367 return $x -> round(@r); 2368 } 2369 2370 my $ym = $LIB->_copy($y->{_m}); 2371 2372 # 2e1 => 20 2373 $ym = $LIB->_lsft($ym, $y->{_e}, 10) 2374 if $y->{_es} eq '+' && !$LIB->_is_zero($y->{_e}); 2375 2376 # if $y has digits after dot 2377 my $shifty = 0; # correct _e of $x by this 2378 if ($y->{_es} eq '-') # has digits after dot 2379 { 2380 # 123 % 2.5 => 1230 % 25 => 5 => 0.5 2381 $shifty = $LIB->_num($y->{_e}); # no more digits after dot 2382 # 123 => 1230, $y->{_m} is already 25 2383 $x->{_m} = $LIB->_lsft($x->{_m}, $y->{_e}, 10); 2384 } 2385 # $ym is now mantissa of $y based on exponent 0 2386 2387 my $shiftx = 0; # correct _e of $x by this 2388 if ($x->{_es} eq '-') # has digits after dot 2389 { 2390 # 123.4 % 20 => 1234 % 200 2391 $shiftx = $LIB->_num($x->{_e}); # no more digits after dot 2392 $ym = $LIB->_lsft($ym, $x->{_e}, 10); # 123 => 1230 2393 } 2394 # 123e1 % 20 => 1230 % 20 2395 if ($x->{_es} eq '+' && !$LIB->_is_zero($x->{_e})) { 2396 $x->{_m} = $LIB->_lsft($x->{_m}, $x->{_e}, 10); # es => '+' here 2397 } 2398 2399 $x->{_e} = $LIB->_new($shiftx); 2400 $x->{_es} = '+'; 2401 $x->{_es} = '-' if $shiftx != 0 || $shifty != 0; 2402 $x->{_e} = $LIB->_add($x->{_e}, $LIB->_new($shifty)) if $shifty != 0; 2403 2404 # now mantissas are equalized, exponent of $x is adjusted, so calc result 2405 2406 $x->{_m} = $LIB->_mod($x->{_m}, $ym); 2407 2408 $x->{sign} = '+' if $LIB->_is_zero($x->{_m}); # fix sign for -0 2409 $x = $x->bnorm(); 2410 2411 # if one of them negative => correct in place 2412 if ($neg != 0 && ! $x -> is_zero()) { 2413 my $r = $y - $x; 2414 $x->{_m} = $r->{_m}; 2415 $x->{_e} = $r->{_e}; 2416 $x->{_es} = $r->{_es}; 2417 $x->{sign} = '+' if $LIB->_is_zero($x->{_m}); # fix sign for -0 2418 $x = $x->bnorm(); 2419 } 2420 2421 $x = $x->round($r[0], $r[1], $r[2], $y); 2422 return $downgrade -> new($x -> bdstr(), @r) 2423 if defined($downgrade) && ($x->is_int() || $x->is_inf() || $x->is_nan()); 2424 return $x; 2425} 2426 2427sub bmodpow { 2428 # takes a very large number to a very large exponent in a given very 2429 # large modulus, quickly, thanks to binary exponentiation. Supports 2430 # negative exponents. 2431 my ($class, $num, $exp, $mod, @r) 2432 = ref($_[0]) && ref($_[0]) eq ref($_[1]) && ref($_[1]) eq ref($_[2]) 2433 ? (ref($_[0]), @_) 2434 : objectify(3, @_); 2435 2436 return $num if $num->modify('bmodpow'); 2437 2438 return $num -> bnan(@r) 2439 if $mod->is_nan() || $exp->is_nan() || $mod->is_nan(); 2440 2441 # check modulus for valid values 2442 return $num->bnan(@r) if $mod->{sign} ne '+' || $mod->is_zero(); 2443 2444 # check exponent for valid values 2445 if ($exp->{sign} =~ /\w/) { 2446 # i.e., if it's NaN, +inf, or -inf... 2447 return $num->bnan(@r); 2448 } 2449 2450 $num = $num->bmodinv($mod, @r) if $exp->{sign} eq '-'; 2451 2452 # check num for valid values (also NaN if there was no inverse but $exp < 0) 2453 return $num->bnan(@r) if $num->{sign} !~ /^[+-]$/; 2454 2455 # $mod is positive, sign on $exp is ignored, result also positive 2456 2457 # XXX TODO: speed it up when all three numbers are integers 2458 $num = $num->bpow($exp)->bmod($mod); 2459 2460 return $downgrade -> new($num -> bdstr(), @r) if defined($downgrade) 2461 && ($num->is_int() || $num->is_inf() || $num->is_nan()); 2462 return $num -> round(@r); 2463} 2464 2465sub bpow { 2466 # (BFLOAT or num_str, BFLOAT or num_str) return BFLOAT 2467 # compute power of two numbers, second arg is used as integer 2468 # modifies first argument 2469 2470 # set up parameters 2471 my ($class, $x, $y, $a, $p, $r) = (ref($_[0]), @_); 2472 # objectify is costly, so avoid it 2473 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) { 2474 ($class, $x, $y, $a, $p, $r) = objectify(2, @_); 2475 } 2476 2477 return $x if $x -> modify('bpow'); 2478 2479 # $x and/or $y is a NaN 2480 return $x -> bnan() if $x -> is_nan() || $y -> is_nan(); 2481 2482 # $x and/or $y is a +/-Inf 2483 if ($x -> is_inf("-")) { 2484 return $x -> bzero() if $y -> is_negative(); 2485 return $x -> bnan() if $y -> is_zero(); 2486 return $x if $y -> is_odd(); 2487 return $x -> bneg(); 2488 } elsif ($x -> is_inf("+")) { 2489 return $x -> bzero() if $y -> is_negative(); 2490 return $x -> bnan() if $y -> is_zero(); 2491 return $x; 2492 } elsif ($y -> is_inf("-")) { 2493 return $x -> bnan() if $x -> is_one("-"); 2494 return $x -> binf("+") if $x > -1 && $x < 1; 2495 return $x -> bone() if $x -> is_one("+"); 2496 return $x -> bzero(); 2497 } elsif ($y -> is_inf("+")) { 2498 return $x -> bnan() if $x -> is_one("-"); 2499 return $x -> bzero() if $x > -1 && $x < 1; 2500 return $x -> bone() if $x -> is_one("+"); 2501 return $x -> binf("+"); 2502 } 2503 2504 if ($x -> is_zero()) { 2505 return $x -> bone() if $y -> is_zero(); 2506 return $x -> binf() if $y -> is_negative(); 2507 return $x; 2508 } 2509 2510 # We don't support complex numbers, so upgrade or return NaN. 2511 2512 if ($x -> is_negative() && !$y -> is_int()) { 2513 return $upgrade -> bpow($x, $y, $a, $p, $r) if defined $upgrade; 2514 return $x -> bnan(); 2515 } 2516 2517 if ($x -> is_one("+") || $y -> is_one()) { 2518 return $x; 2519 } 2520 2521 if ($x -> is_one("-")) { 2522 return $x if $y -> is_odd(); 2523 return $x -> bneg(); 2524 } 2525 2526 return $x -> _pow($y, $a, $p, $r) if !$y -> is_int(); 2527 2528 my $y1 = $y -> as_int()->{value}; # make MBI part 2529 2530 my $new_sign = '+'; 2531 $new_sign = $LIB -> _is_odd($y1) ? '-' : '+' if $x->{sign} ne '+'; 2532 2533 # calculate $x->{_m} ** $y and $x->{_e} * $y separately (faster) 2534 $x->{_m} = $LIB -> _pow($x->{_m}, $y1); 2535 $x->{_e} = $LIB -> _mul($x->{_e}, $y1); 2536 2537 $x->{sign} = $new_sign; 2538 $x = $x -> bnorm(); 2539 2540 # x ** (-y) = 1 / (x ** y) 2541 2542 if ($y->{sign} eq '-') { 2543 # modify $x in place! 2544 my $z = $x -> copy(); 2545 $x = $x -> bone(); 2546 # round in one go (might ignore y's A!) 2547 return scalar $x -> bdiv($z, $a, $p, $r); 2548 } 2549 2550 $x = $x -> round($a, $p, $r, $y); 2551 2552 return $downgrade -> new($x) 2553 if defined($downgrade) && ($x->is_int() || $x->is_inf() || $x->is_nan()); 2554 return $x; 2555} 2556 2557sub binv { 2558 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 2559 2560 return $x if $x->modify('binv'); 2561 2562 my $inv = $class -> bdiv($class -> bone(), $x, @r); 2563 2564 return $downgrade -> new($inv, @r) if defined($downgrade) 2565 && ($inv -> is_int() || $inv -> is_inf() || $inv -> is_nan()); 2566 2567 for my $key (qw/ sign _m _es _e /) { 2568 $x -> {$key} = $inv -> {$key}; 2569 } 2570 2571 $x; 2572} 2573 2574sub blog { 2575 # Return the logarithm of the operand. If a second operand is defined, that 2576 # value is used as the base, otherwise the base is assumed to be Euler's 2577 # constant. 2578 2579 my ($class, $x, $base, @r); 2580 2581 # Only objectify the base if it is defined, since an undefined base, as in 2582 # $x->blog() or $x->blog(undef) signals that the base is Euler's number = 2583 # 2.718281828... 2584 2585 if (!ref($_[0]) && $_[0] =~ /^[A-Za-z]|::/) { 2586 # E.g., Math::BigFloat->blog(256, 2) 2587 ($class, $x, $base, @r) = 2588 defined $_[2] ? objectify(2, @_) : objectify(1, @_); 2589 } else { 2590 # E.g., $x->blog(2) or the deprecated Math::BigFloat::blog(256, 2) 2591 ($class, $x, $base, @r) = 2592 defined $_[1] ? objectify(2, @_) : objectify(1, @_); 2593 } 2594 2595 return $x if $x->modify('blog'); 2596 2597 # Handle all exception cases and all trivial cases. I have used Wolfram 2598 # Alpha (http://www.wolframalpha.com) as the reference for these cases. 2599 2600 return $x -> bnan(@r) if $x -> is_nan(); 2601 2602 if (defined $base) { 2603 $base = $class -> new($base) 2604 unless defined(blessed($base)) && $base -> isa(__PACKAGE__); 2605 if ($base -> is_nan() || $base -> is_one()) { 2606 return $x -> bnan(@r); 2607 } elsif ($base -> is_inf() || $base -> is_zero()) { 2608 return $x -> bnan(@r) if $x -> is_inf() || $x -> is_zero(); 2609 return $x -> bzero(@r); 2610 } elsif ($base -> is_negative()) { # -inf < base < 0 2611 return $x -> bzero(@r) if $x -> is_one(); # x = 1 2612 return $x -> bone('+', @r) if $x == $base; # x = base 2613 # we can't handle these cases, so upgrade, if we can 2614 return $upgrade -> blog($x, $base, @r) if defined $upgrade; 2615 return $x -> bnan(@r); 2616 } 2617 return $x -> bone(@r) if $x == $base; # 0 < base && 0 < x < inf 2618 } 2619 2620 if ($x -> is_inf()) { # x = +/-inf 2621 my $sign = defined($base) && $base < 1 ? '-' : '+'; 2622 return $x -> binf($sign, @r); 2623 } elsif ($x -> is_neg()) { # -inf < x < 0 2624 return $upgrade -> blog($x, $base, @r) if defined $upgrade; 2625 return $x -> bnan(@r); 2626 } elsif ($x -> is_one()) { # x = 1 2627 return $x -> bzero(@r); 2628 } elsif ($x -> is_zero()) { # x = 0 2629 my $sign = defined($base) && $base < 1 ? '+' : '-'; 2630 return $x -> binf($sign, @r); 2631 } 2632 2633 # we need to limit the accuracy to protect against overflow 2634 my $fallback = 0; 2635 my ($scale, @params); 2636 ($x, @params) = $x->_find_round_parameters(@r); 2637 2638 # no rounding at all, so must use fallback 2639 if (scalar @params == 0) { 2640 # simulate old behaviour 2641 $params[0] = $class->div_scale(); # and round to it as accuracy 2642 $params[1] = undef; # P = undef 2643 $scale = $params[0]+4; # at least four more for proper round 2644 $params[2] = $r[2]; # round mode by caller or undef 2645 $fallback = 1; # to clear a/p afterwards 2646 } else { 2647 # the 4 below is empirical, and there might be cases where it is not 2648 # enough... 2649 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 2650 } 2651 2652 # When user set globals, they would interfere with our calculation, so 2653 # disable them and later re-enable them. 2654 2655 my $ab = $class -> accuracy(); 2656 my $pb = $class -> precision(); 2657 $class -> accuracy(undef); 2658 $class -> precision(undef); 2659 2660 # Disabling upgrading and downgrading is no longer necessary to avoid an 2661 # infinite recursion, but it avoids unnecessary upgrading and downgrading in 2662 # the intermediate computations. 2663 2664 my $upg = $class -> upgrade(); 2665 my $dng = $class -> downgrade(); 2666 $class -> upgrade(undef); 2667 $class -> downgrade(undef); 2668 2669 # We also need to disable any set A or P on $x (_find_round_parameters took 2670 # them already into account), since these would interfere, too. 2671 2672 $x->{accuracy} = undef; 2673 $x->{precision} = undef; 2674 2675 my $done = 0; 2676 2677 # If both $x and $base are integers, try to calculate an integer result 2678 # first. This is very fast, and if the exact result was found, we are done. 2679 2680 if (defined($base) && $base -> is_int() && $x -> is_int()) { 2681 my $x_lib = $LIB -> _new($x -> bdstr()); 2682 my $b_lib = $LIB -> _new($base -> bdstr()); 2683 ($x_lib, my $exact) = $LIB -> _log_int($x_lib, $b_lib); 2684 if ($exact) { 2685 $x->{_m} = $x_lib; 2686 $x->{_e} = $LIB -> _zero(); 2687 $x = $x -> bnorm(); 2688 $done = 1; 2689 } 2690 } 2691 2692 # If the integer result was not accurate, compute the natural logarithm 2693 # log($x) (using reduction by 10 and possibly also by 2), and if a 2694 # different base was requested, convert the result with log($x)/log($base). 2695 2696 unless ($done) { 2697 $x = $x -> _log_10($scale); 2698 if (defined $base) { 2699 # log_b(x) = ln(x) / ln(b), so compute ln(b) 2700 my $base_log_e = $base -> copy() -> _log_10($scale); 2701 $x = $x -> bdiv($base_log_e, $scale); 2702 } 2703 } 2704 2705 # shortcut to not run through _find_round_parameters again 2706 2707 if (defined $params[0]) { 2708 $x = $x -> bround($params[0], $params[2]); # then round accordingly 2709 } else { 2710 $x = $x -> bfround($params[1], $params[2]); # then round accordingly 2711 } 2712 if ($fallback) { 2713 # clear a/p after round, since user did not request it 2714 $x->{accuracy} = undef; 2715 $x->{precision} = undef; 2716 } 2717 2718 # Restore globals. We need to do it like this, because setting one 2719 # undefines the other. 2720 2721 if (defined $ab) { 2722 $class -> accuracy($ab); 2723 } else { 2724 $class -> precision($pb); 2725 } 2726 2727 $class -> upgrade($upg); 2728 $class -> downgrade($dng); 2729 2730 return $downgrade -> new($x -> bdstr(), @r) 2731 if defined($downgrade) && $x -> is_int(); 2732 return $x; 2733} 2734 2735sub bexp { 2736 # Calculate e ** X (Euler's number to the power of X) 2737 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 2738 2739 return $x if $x -> modify('bexp'); 2740 2741 return $x -> bnan(@r) if $x -> is_nan(); 2742 return $x -> binf(@r) if $x->{sign} eq '+inf'; 2743 return $x -> bzero(@r) if $x->{sign} eq '-inf'; 2744 2745 # Get the rounding parameters, if any. 2746 2747 my $fallback = 0; 2748 my ($scale, @params); 2749 ($x, @params) = $x -> _find_round_parameters(@r); 2750 2751 # Error in _find_round_parameters? 2752 2753 return $x -> bnan(@r) if $x->{sign} eq 'NaN'; 2754 2755 return $x -> bone(@r) if $x -> is_zero(); 2756 2757 # If no rounding parameters are give, use fallback. 2758 2759 if (!@params) { 2760 $params[0] = $class -> div_scale(); # fallback accuracy 2761 $params[1] = undef; # no precision 2762 $params[2] = $r[2]; # rounding mode 2763 $scale = $params[0]; 2764 $fallback = 1; # to clear a/p afterwards 2765 } else { 2766 if (defined($params[0])) { 2767 $scale = $params[0]; 2768 } else { 2769 # We perform the computations below using accuracy only, not 2770 # precision, so when precision is given, we need to "convert" this 2771 # to accuracy. To do that, we need to know, at least approximately, 2772 # how many digits there will be in the final result. 2773 # 2774 # log10(exp($x)) = log(exp($x)) / log(10) = $x / log(10) 2775 2776 #$scale = 1 + int(log($ms) / log(10) + $es) - $params[1]; 2777 my $ndig = $x -> numify() / log(10); 2778 $scale = 1 + int($ndig) - $params[1]; 2779 } 2780 } 2781 2782 # Add extra digits to reduce the consequence of round-off errors in the 2783 # intermediate computations. 2784 2785 $scale += 4; 2786 2787 if (!$x -> isa('Math::BigFloat')) { 2788 $x = Math::BigFloat -> new($x); 2789 $class = ref($x); 2790 } 2791 2792 # When user set globals, they would interfere with our calculation, so 2793 # disable them and later re-enable them. 2794 2795 my $ab = $class -> accuracy(); 2796 my $pb = $class -> precision(); 2797 $class -> accuracy(undef); 2798 $class -> precision(undef); 2799 2800 # Disabling upgrading and downgrading is no longer necessary to avoid an 2801 # infinite recursion, but it avoids unnecessary upgrading and downgrading in 2802 # the intermediate computations. 2803 2804 my $upg = $class -> upgrade(); 2805 my $dng = $class -> downgrade(); 2806 $class -> upgrade(undef); 2807 $class -> downgrade(undef); 2808 2809 # We also need to disable any set A or P on $x (_find_round_parameters took 2810 # them already into account), since these would interfere, too. 2811 2812 $x->{accuracy} = undef; 2813 $x->{precision} = undef; 2814 2815 my $x_orig = $x -> copy(); 2816 2817 # We use the following Taylor series: 2818 2819 # x x^2 x^3 x^4 2820 # e = 1 + --- + --- + --- + --- ... 2821 # 1! 2! 3! 4! 2822 2823 # The difference for each term is X and N, which would result in: 2824 # 2 copy, 2 mul, 2 add, 1 inc, 1 div operations per term 2825 2826 # But it is faster to compute exp(1) and then raising it to the 2827 # given power, esp. if $x is really big and an integer because: 2828 2829 # * The numerator is always 1, making the computation faster 2830 # * the series converges faster in the case of x == 1 2831 # * We can also easily check when we have reached our limit: when the 2832 # term to be added is smaller than "1E$scale", we can stop - f.i. 2833 # scale == 5, and we have 1/40320, then we stop since 1/40320 < 1E-5. 2834 # * we can compute the *exact* result by simulating bigrat math: 2835 2836 # 1 1 gcd(3, 4) = 1 1*24 + 1*6 5 2837 # - + - = ---------- = -- 2838 # 6 24 6*24 24 2839 2840 # We do not compute the gcd() here, but simple do: 2841 # 1 1 1*24 + 1*6 30 2842 # - + - = --------- = -- 2843 # 6 24 6*24 144 2844 2845 # In general: 2846 # a c a*d + c*b and note that c is always 1 and d = (b*f) 2847 # - + - = --------- 2848 # b d b*d 2849 2850 # This leads to: which can be reduced by b to: 2851 # a 1 a*b*f + b a*f + 1 2852 # - + - = --------- = ------- 2853 # b b*f b*b*f b*f 2854 2855 # The first terms in the series are: 2856 2857 # 1 1 1 1 1 1 1 1 13700 2858 # -- + -- + -- + -- + -- + --- + --- + ---- = ----- 2859 # 1 1 2 6 24 120 720 5040 5040 2860 2861 # Note that we cannot simply reduce 13700/5040 to 685/252, but must keep 2862 # the numerator and the denominator! 2863 2864 if ($scale <= 75) { 2865 # set $x directly from a cached string form 2866 $x->{_m} = $LIB->_new("2718281828459045235360287471352662497757" . 2867 "2470936999595749669676277240766303535476"); 2868 $x->{sign} = '+'; 2869 $x->{_es} = '-'; 2870 $x->{_e} = $LIB->_new(79); 2871 } else { 2872 # compute A and B so that e = A / B. 2873 2874 # After some terms we end up with this, so we use it as a starting 2875 # point: 2876 my $A = $LIB->_new("9093339520860578540197197" . 2877 "0164779391644753259799242"); 2878 my $F = $LIB->_new(42); 2879 my $step = 42; 2880 2881 # Compute number of steps needed to get $A and $B sufficiently large. 2882 2883 my $steps = _len_to_steps($scale - 4); 2884 # print STDERR "# Doing $steps steps for ", $scale-4, " digits\n"; 2885 2886 while ($step++ <= $steps) { 2887 # calculate $a * $f + 1 2888 $A = $LIB -> _mul($A, $F); 2889 $A = $LIB -> _inc($A); 2890 # increment f 2891 $F = $LIB -> _inc($F); 2892 } 2893 2894 # Compute $B as factorial of $steps (this is faster than doing it 2895 # manually) 2896 my $B = $LIB->_fac($LIB->_new($steps)); 2897 2898 # print "A ", $LIB->_str($A), "\nB ", $LIB->_str($B), "\n"; 2899 2900 # compute A/B with $scale digits in the result (truncate, not round) 2901 $A = $LIB->_lsft($A, $LIB->_new($scale), 10); 2902 $A = $LIB->_div($A, $B); 2903 2904 $x->{_m} = $A; 2905 $x->{sign} = '+'; 2906 $x->{_es} = '-'; 2907 $x->{_e} = $LIB->_new($scale); 2908 } 2909 2910 # Now $x contains now an estimate of e, with some additional digits. 2911 2912 if ($x_orig -> is_one()) { 2913 2914 # else just round the already computed result 2915 2916 $x->{accuracy} = undef; 2917 $x->{precision} = undef; 2918 2919 # shortcut to not run through _find_round_parameters again 2920 2921 if (defined $params[0]) { 2922 $x = $x -> bround($params[0], $params[2]); # then round accordingly 2923 } else { 2924 $x = $x -> bfround($params[1], $params[2]); # then round accordingly 2925 } 2926 2927 } else { 2928 2929 # Use the fact exp(x) = exp(x/n)**n. In our case, n = 2**i for some 2930 # integer i. We use this to compute exp(y) where y = x / (2**i) and 2931 # 1 <= |y| < 2. 2932 # 2933 # The code below is similar to the code found in to_ieee754(). 2934 2935 # We need to find the base 2 exponent. First make an estimate of the 2936 # base 2 exponent, before adjusting it below. We could skip this 2937 # estimation and go straight to the while-loops below, but the loops 2938 # are slow, especially when the final exponent is far from zero and 2939 # even more so if the number of digits is large. This initial 2940 # estimation speeds up the computation dramatically. 2941 # 2942 # log2($m * 10**$e) = log10($m + 10**$e) * log(10)/log(2) 2943 # = (log10($m) + $e) * log(10)/log(2) 2944 # = (log($m)/log(10) + $e) * log(10)/log(2) 2945 2946 my ($m, $e) = $x_orig -> nparts(); 2947 my $ms = $m -> numify(); 2948 my $es = $e -> numify(); 2949 2950 # We start off by initializing the exponent to zero and the mantissa to 2951 # the input value. Then we increase the mantissa and decrease the 2952 # exponent, or vice versa, until the mantissa is in the desired range 2953 # or we hit one of the limits for the exponent. 2954 2955 my $mant = $x_orig -> copy() -> babs(); 2956 my $expo; 2957 2958 my $one = $class -> bone(); 2959 my $two = $class -> new("2"); 2960 my $half = $class -> new("0.5"); 2961 2962 my $expo_est = (log(abs($ms))/log(10) + $es) * log(10)/log(2); 2963 $expo_est = int($expo_est); 2964 2965 # Don't multiply by a number raised to a negative exponent. This will 2966 # cause a division, whose result is truncated to some fixed number of 2967 # digits. Instead, multiply by the inverse number raised to a positive 2968 # exponent. 2969 2970 $expo = $class -> new($expo_est); 2971 if ($expo_est > 0) { 2972 $mant = $mant -> bmul($half -> copy() -> bpow($expo)); 2973 } elsif ($expo_est < 0) { 2974 my $expo_abs = $expo -> copy() -> bneg(); 2975 $mant = $mant -> bmul($two -> copy() -> bpow($expo_abs)); 2976 } 2977 2978 # Final adjustment of the estimate above. 2979 2980 while ($mant -> bcmp($two) >= 0) { # $mant <= $two 2981 $mant = $mant -> bmul($half); 2982 $expo = $expo -> binc(); 2983 } 2984 2985 while ($mant -> bcmp($one) < 0) { # $mant > $one 2986 $mant = $mant -> bmul($two); 2987 $expo = $expo -> bdec(); 2988 } 2989 2990 # Because of the upscaling, we need some additional digits. 2991 2992 my $rescale = int($scale + abs($expo) * log(2) / log(10) + 1); 2993 $rescale = 4 if $rescale < 4; 2994 2995 $x = $x -> bpow($mant, $rescale); 2996 my $pow2 = $two -> bpow($expo, $rescale); 2997 $pow2 -> bneg() if $x_orig -> is_negative(); 2998 2999 # The bpow() below fails with the GMP and GMPz libraries if abs($pow2) 3000 # >= 2**30 = 1073741824. With the Pari library, it fails already when 3001 # abs($pow) >= 2**13 = 8192. With the Calc library, it is rediculously 3002 # slow when abs($pow2) is large. Fixme? 3003 3004 croak "cannot compute bexp(); input value is too large" 3005 if $pow2 -> copy() -> babs() -> bcmp("1073741824") >= 0; 3006 3007 $x = $x -> bpow($pow2, $rescale); 3008 3009 # Rounding parameters given as arguments currently don't override 3010 # instance variables, so accuracy (which is set in the computations 3011 # above) must be undefined before rounding. Fixme. 3012 3013 $x->{accuracy} = undef; 3014 $x -> round(@params); 3015 } 3016 3017 if ($fallback) { 3018 # clear a/p after round, since user did not request it 3019 $x->{accuracy} = undef; 3020 $x->{precision} = undef; 3021 } 3022 3023 # Restore globals. We need to do it like this, because setting one 3024 # undefines the other. 3025 3026 if (defined $ab) { 3027 $class -> accuracy($ab); 3028 } else { 3029 $class -> precision($pb); 3030 } 3031 3032 $class -> upgrade($upg); 3033 $class -> downgrade($dng); 3034 3035 # If downgrading, remember to preserve the relevant instance parameters. 3036 # There should be a more elegant way to do this. Fixme. 3037 3038 if ($downgrade && $x -> is_int()) { 3039 @r = ($x->{accuracy}, $x->{_r}); 3040 my $tmp = $downgrade -> new($x, @r); 3041 %$x = %$tmp; 3042 return bless $x, $downgrade; 3043 } 3044 3045 $x; 3046} 3047 3048sub bilog2 { 3049 croak "Method ", (caller(0))[3], "() not implemented yet"; 3050} 3051 3052sub bilog10 { 3053 croak "Method ", (caller(0))[3], "() not implemented yet"; 3054} 3055 3056sub bclog2 { 3057 croak "Method ", (caller(0))[3], "() not implemented yet"; 3058} 3059 3060sub bclog10 { 3061 croak "Method ", (caller(0))[3], "() not implemented yet"; 3062} 3063 3064sub bnok { 3065 # Calculate n over k (binomial coefficient or "choose" function) as integer. 3066 # set up parameters 3067 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1]) 3068 ? (ref($_[0]), @_) 3069 : objectify(2, @_); 3070 3071 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 3072 3073 return $x if $x->modify('bnok'); 3074 3075 return $x->bnan() if $x->is_nan() || $y->is_nan(); 3076 return $x->bnan() if (($x->is_finite() && !$x->is_int()) || 3077 ($y->is_finite() && !$y->is_int())); 3078 3079 my $xint = Math::BigInt -> new($x -> bsstr()); 3080 my $yint = Math::BigInt -> new($y -> bsstr()); 3081 $xint = $xint -> bnok($yint); 3082 3083 return $xint if defined $downgrade; 3084 3085 my $xflt = Math::BigFloat -> new($xint); 3086 3087 $x->{_m} = $xflt->{_m}; 3088 $x->{_e} = $xflt->{_e}; 3089 $x->{_es} = $xflt->{_es}; 3090 $x->{sign} = $xflt->{sign}; 3091 3092 return $x; 3093} 3094 3095sub bsin { 3096 # Calculate a sinus of x. 3097 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 3098 3099 # First we apply range reduction to x. This is because if x is large, the 3100 # Taylor series converges slowly and requires higher accuracy in the 3101 # intermediate computation. The Taylor series is: 3102 # 3103 # x^3 x^5 x^7 x^9 3104 # sin(x) = x - --- + --- - --- + --- ... 3105 # 3! 5! 7! 9! 3106 3107 return $x if $x -> modify('bsin'); 3108 3109 return $x -> bzero(@r) if $x -> is_zero(); 3110 return $x -> bnan(@r) if $x -> is_nan() || $x -> is_inf(); 3111 3112 # Get the rounding parameters, if any. 3113 3114 my $fallback = 0; 3115 my ($scale, @params); 3116 ($x, @params) = $x -> _find_round_parameters(@r); 3117 3118 # Error in _find_round_parameters? 3119 3120 return $x -> bnan(@r) if $x -> is_nan(); 3121 3122 # If no rounding parameters are given, use fallback. 3123 3124 if (!@params) { 3125 $params[0] = $class -> div_scale(); # fallback accuracy 3126 $params[1] = undef; # no precision 3127 $params[2] = $r[2]; # rounding mode 3128 $scale = $params[0]; 3129 $fallback = 1; # to clear a/p afterwards 3130 } else { 3131 if (defined($params[0])) { 3132 $scale = $params[0]; 3133 } else { 3134 # We perform the computations below using accuracy only, not 3135 # precision, so when precision is given, we need to "convert" this 3136 # to accuracy. 3137 $scale = 1 - $params[1]; 3138 } 3139 } 3140 3141 # Add more digits to the scale if the magnitude of $x is large. 3142 3143 my ($m, $e) = $x -> nparts(); 3144 $scale += $e if $x >= 10; 3145 $scale = 4 if $scale < 4; 3146 3147 # When user set globals, they would interfere with our calculation, so 3148 # disable them and later re-enable them 3149 3150 my $ab = $class -> accuracy(); 3151 my $pb = $class -> precision(); 3152 $class -> accuracy(undef); 3153 $class -> precision(undef); 3154 3155 # Disabling upgrading and downgrading is no longer necessary to avoid an 3156 # infinite recursion, but it avoids unnecessary upgrading and downgrading in 3157 # the intermediate computations. 3158 3159 my $upg = $class -> upgrade(); 3160 my $dng = $class -> downgrade(); 3161 $class -> upgrade(undef); 3162 $class -> downgrade(undef); 3163 3164 # We also need to disable any set A or P on $x (_find_round_parameters took 3165 # them already into account), since these would interfere, too. 3166 3167 $x->{accuracy} = undef; 3168 $x->{precision} = undef; 3169 3170 my $sin_prev; # the previous approximation of sin(x) 3171 my $sin; # the current approximation of sin(x) 3172 3173 while (1) { 3174 3175 # Compute constants to the current scale. 3176 3177 my $pi = $class -> bpi($scale); # 3178 my $twopi = $pi -> copy() -> bmul("2"); # 2 3179 my $halfpi = $pi -> copy() -> bmul("0.5"); # /2 3180 3181 # Use the fact that sin(-x) = -sin(x) to reduce the range to the 3182 # interval to [0,∞). 3183 3184 my $xsgn = $x < 0 ? -1 : 1; 3185 my $x = $x -> copy() -> babs(); 3186 3187 # Use the fact that sin(2x) = sin(x) to reduce the range to the 3188 # interval to [0, 2). 3189 3190 $x = $x -> bmod($twopi, $scale); 3191 3192 # Use the fact that sin(x+) = -sin(x) to reduce the range to the 3193 # interval to [0,). 3194 3195 if ($x -> bcmp($pi) > 0) { 3196 $xsgn = -$xsgn; 3197 $x = $x -> bsub($pi); 3198 } 3199 3200 # Use the fact that sin(-x) = sin(x) to reduce the range to the 3201 # interval [0,/2). 3202 3203 if ($x -> bcmp($halfpi) > 0) { 3204 $x = $x -> bsub($pi) -> bneg(); # - x 3205 } 3206 3207 my $tol = $class -> new("1E-". ($scale-1)); 3208 3209 my $xsq = $x -> copy() -> bmul($x, $scale) -> bneg(); 3210 my $term = $x -> copy(); 3211 my $fac = $class -> bone(); 3212 my $n = $class -> bone(); 3213 3214 $sin = $x -> copy(); # initialize sin(x) to the first term 3215 3216 while (1) { 3217 $n -> binc(); 3218 $fac = $n -> copy(); 3219 $n -> binc(); 3220 $fac -> bmul($n); 3221 3222 $term -> bmul($xsq, $scale) -> bdiv($fac, $scale); 3223 3224 $sin -> badd($term, $scale); 3225 last if $term -> copy() -> babs() -> bcmp($tol) < 0; 3226 } 3227 3228 $sin -> bneg() if $xsgn < 0; 3229 3230 # Rounding parameters given as arguments currently don't override 3231 # instance variables, so accuracy (which is set in the computations 3232 # above) must be undefined before rounding. Fixme. 3233 3234 $sin->{accuracy} = undef; 3235 $sin -> round(@params); 3236 3237 # Compare the current approximation of sin(x) with the previous one, 3238 # and if they are identical, we're done. 3239 3240 if (defined $sin_prev) { 3241 last if $sin -> bcmp($sin_prev) == 0; 3242 } 3243 3244 # If the current approximation of sin(x) is different from the previous 3245 # approximation, double the scale (accuracy) and retry. 3246 3247 $sin_prev = $sin; 3248 $scale *= 2; 3249 } 3250 3251 # Assign the result to the invocand. 3252 3253 %$x = %$sin; 3254 3255 if ($fallback) { 3256 # clear a/p after round, since user did not request it 3257 $x->{accuracy} = undef; 3258 $x->{precision} = undef; 3259 } 3260 3261 # Restore globals. We need to do it like this, because setting one 3262 # undefines the other. 3263 3264 if (defined $ab) { 3265 $class -> accuracy($ab); 3266 } else { 3267 $class -> precision($pb); 3268 } 3269 3270 $class -> upgrade($upg); 3271 $class -> downgrade($dng); 3272 3273 # If downgrading, remember to preserve the relevant instance parameters. 3274 # There should be a more elegant way to do this. Fixme. 3275 3276 if ($downgrade && $x -> is_int()) { 3277 @r = ($x->{accuracy}, $x->{_r}); 3278 my $tmp = $downgrade -> new($x, @r); 3279 %$x = %$tmp; 3280 return bless $x, $downgrade; 3281 } 3282 3283 $x; 3284} 3285 3286sub bcos { 3287 # Calculate a cosinus of x. 3288 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 3289 3290 # Taylor: x^2 x^4 x^6 x^8 3291 # cos = 1 - --- + --- - --- + --- ... 3292 # 2! 4! 6! 8! 3293 3294 # we need to limit the accuracy to protect against overflow 3295 my $fallback = 0; 3296 my ($scale, @params); 3297 ($x, @params) = $x->_find_round_parameters(@r); 3298 3299 # constant object or error in _find_round_parameters? 3300 return $x if $x->modify('bcos') || $x->is_nan(); 3301 return $x->bnan() if $x->is_inf(); 3302 return $x->bone(@r) if $x->is_zero(); 3303 3304 # no rounding at all, so must use fallback 3305 if (scalar @params == 0) { 3306 # simulate old behaviour 3307 $params[0] = $class->div_scale(); # and round to it as accuracy 3308 $params[1] = undef; # disable P 3309 $scale = $params[0]+4; # at least four more for proper round 3310 $params[2] = $r[2]; # round mode by caller or undef 3311 $fallback = 1; # to clear a/p afterwards 3312 } else { 3313 # the 4 below is empirical, and there might be cases where it is not 3314 # enough... 3315 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 3316 } 3317 3318 # When user set globals, they would interfere with our calculation, so 3319 # disable them and later re-enable them. 3320 3321 my $ab = $class -> accuracy(); 3322 my $pb = $class -> precision(); 3323 $class -> accuracy(undef); 3324 $class -> precision(undef); 3325 3326 # Disabling upgrading and downgrading is no longer necessary to avoid an 3327 # infinite recursion, but it avoids unnecessary upgrading and downgrading in 3328 # the intermediate computations. 3329 3330 my $upg = $class -> upgrade(); 3331 my $dng = $class -> downgrade(); 3332 $class -> upgrade(undef); 3333 $class -> downgrade(undef); 3334 3335 # We also need to disable any set A or P on $x (_find_round_parameters took 3336 # them already into account), since these would interfere, too. 3337 3338 $x->{accuracy} = undef; 3339 $x->{precision} = undef; 3340 3341 my $over = $x * $x; # X ^ 2 3342 my $x2 = $over->copy(); # X ^ 2; difference between terms 3343 my $sign = 1; # start with -= 3344 my $below = $class->new(2); 3345 my $factorial = $class->new(3); 3346 $x = $x->bone(); 3347 $x->{accuracy} = undef; 3348 $x->{precision} = undef; 3349 3350 my $limit = $class->new("1E-". ($scale-1)); 3351 #my $steps = 0; 3352 while (3 < 5) { 3353 # we calculate the next term, and add it to the last 3354 # when the next term is below our limit, it won't affect the outcome 3355 # anymore, so we stop: 3356 my $next = $over->copy()->bdiv($below, $scale); 3357 last if $next->bacmp($limit) <= 0; 3358 3359 if ($sign == 0) { 3360 $x = $x->badd($next); 3361 } else { 3362 $x = $x->bsub($next); 3363 } 3364 $sign = 1-$sign; # alternate 3365 # calculate things for the next term 3366 $over = $over->bmul($x2); # $x*$x 3367 $below = $below->bmul($factorial); # n*(n+1) 3368 $factorial = $factorial -> binc(); 3369 $below = $below->bmul($factorial); # n*(n+1) 3370 $factorial = $factorial -> binc(); 3371 } 3372 3373 # shortcut to not run through _find_round_parameters again 3374 if (defined $params[0]) { 3375 $x = $x->bround($params[0], $params[2]); # then round accordingly 3376 } else { 3377 $x = $x->bfround($params[1], $params[2]); # then round accordingly 3378 } 3379 if ($fallback) { 3380 # clear a/p after round, since user did not request it 3381 $x->{accuracy} = undef; 3382 $x->{precision} = undef; 3383 } 3384 3385 # Restore globals. We need to do it like this, because setting one 3386 # undefines the other. 3387 3388 if (defined $ab) { 3389 $class -> accuracy($ab); 3390 } else { 3391 $class -> precision($pb); 3392 } 3393 3394 $class -> upgrade($upg); 3395 $class -> downgrade($dng); 3396 3397 return $downgrade -> new($x -> bdstr(), @r) 3398 if defined($downgrade) && $x -> is_int(); 3399 $x; 3400} 3401 3402sub batan { 3403 # Calculate a arcus tangens of x. 3404 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 3405 3406 # taylor: x^3 x^5 x^7 x^9 3407 # atan = x - --- + --- - --- + --- ... 3408 # 3 5 7 9 3409 3410 return $x if $x->modify('batan'); 3411 3412 return $x -> bnan(@r) if $x->is_nan(); 3413 3414 # We need to limit the accuracy to protect against overflow. 3415 3416 my $fallback = 0; 3417 my ($scale, @params); 3418 ($x, @params) = $x->_find_round_parameters(@r); 3419 3420 # Error in _find_round_parameters? 3421 3422 return $x -> bnan(@r) if $x->is_nan(); 3423 3424 if ($x->{sign} =~ /^[+-]inf\z/) { 3425 # +inf result is PI/2 3426 # -inf result is -PI/2 3427 # calculate PI/2 3428 my $pi = $class->bpi(@r); 3429 # modify $x in place 3430 $x->{_m} = $pi->{_m}; 3431 $x->{_e} = $pi->{_e}; 3432 $x->{_es} = $pi->{_es}; 3433 # -y => -PI/2, +y => PI/2 3434 $x->{sign} = substr($x->{sign}, 0, 1); # "+inf" => "+" 3435 $x -> {_m} = $LIB->_div($x->{_m}, $LIB->_new(2)); 3436 return $x; 3437 } 3438 3439 return $x->bzero(@r) if $x->is_zero(); 3440 3441 # no rounding at all, so must use fallback 3442 if (scalar @params == 0) { 3443 # simulate old behaviour 3444 $params[0] = $class->div_scale(); # and round to it as accuracy 3445 $params[1] = undef; # disable P 3446 $scale = $params[0]+4; # at least four more for proper round 3447 $params[2] = $r[2]; # round mode by caller or undef 3448 $fallback = 1; # to clear a/p afterwards 3449 } else { 3450 # the 4 below is empirical, and there might be cases where it is not 3451 # enough... 3452 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 3453 } 3454 3455 # 1 or -1 => PI/4 3456 # inlined is_one() && is_one('-') 3457 if ($LIB->_is_one($x->{_m}) && $LIB->_is_zero($x->{_e})) { 3458 my $pi = $class->bpi($scale - 3); 3459 # modify $x in place 3460 $x->{_m} = $pi->{_m}; 3461 $x->{_e} = $pi->{_e}; 3462 $x->{_es} = $pi->{_es}; 3463 # leave the sign of $x alone (+1 => +PI/4, -1 => -PI/4) 3464 $x->{_m} = $LIB->_div($x->{_m}, $LIB->_new(4)); 3465 return $x; 3466 } 3467 3468 # This series is only valid if -1 < x < 1, so for other x we need to 3469 # calculate PI/2 - atan(1/x): 3470 my $pi = undef; 3471 if ($x->bacmp($x->copy()->bone) >= 0) { 3472 # calculate PI/2 3473 $pi = $class->bpi($scale - 3); 3474 $pi->{_m} = $LIB->_div($pi->{_m}, $LIB->_new(2)); 3475 # calculate 1/$x: 3476 my $x_copy = $x->copy(); 3477 # modify $x in place 3478 $x = $x->bone(); 3479 $x = $x->bdiv($x_copy, $scale); 3480 } 3481 3482 my $fmul = 1; 3483 foreach (0 .. int($scale / 20)) { 3484 $fmul *= 2; 3485 $x = $x->bdiv($x->copy()->bmul($x)->binc()->bsqrt($scale + 4)->binc(), 3486 $scale + 4); 3487 } 3488 3489 # When user set globals, they would interfere with our calculation, so 3490 # disable them and later re-enable them. 3491 3492 my $ab = $class -> accuracy(); 3493 my $pb = $class -> precision(); 3494 $class -> accuracy(undef); 3495 $class -> precision(undef); 3496 3497 # Disabling upgrading and downgrading is no longer necessary to avoid an 3498 # infinite recursion, but it avoids unnecessary upgrading and downgrading in 3499 # the intermediate computations. 3500 3501 my $upg = $class -> upgrade(); 3502 my $dng = $class -> downgrade(); 3503 $class -> upgrade(undef); 3504 $class -> downgrade(undef); 3505 3506 # We also need to disable any set A or P on $x (_find_round_parameters took 3507 # them already into account), since these would interfere, too. 3508 3509 $x->{accuracy} = undef; 3510 $x->{precision} = undef; 3511 3512 my $over = $x * $x; # X ^ 2 3513 my $x2 = $over->copy(); # X ^ 2; difference between terms 3514 $over = $over->bmul($x); # X ^ 3 as starting value 3515 my $sign = 1; # start with -= 3516 my $below = $class->new(3); 3517 my $two = $class->new(2); 3518 $x->{accuracy} = undef; 3519 $x->{precision} = undef; 3520 3521 my $limit = $class->new("1E-". ($scale-1)); 3522 #my $steps = 0; 3523 while (1) { 3524 # We calculate the next term, and add it to the last. When the next 3525 # term is below our limit, it won't affect the outcome anymore, so we 3526 # stop: 3527 my $next = $over->copy()->bdiv($below, $scale); 3528 last if $next->bacmp($limit) <= 0; 3529 3530 if ($sign == 0) { 3531 $x = $x->badd($next); 3532 } else { 3533 $x = $x->bsub($next); 3534 } 3535 $sign = 1-$sign; # alternatex 3536 # calculate things for the next term 3537 $over = $over->bmul($x2); # $x*$x 3538 $below = $below->badd($two); # n += 2 3539 } 3540 $x = $x->bmul($fmul); 3541 3542 if (defined $pi) { 3543 my $x_copy = $x->copy(); 3544 # modify $x in place 3545 $x->{_m} = $pi->{_m}; 3546 $x->{_e} = $pi->{_e}; 3547 $x->{_es} = $pi->{_es}; 3548 # PI/2 - $x 3549 $x = $x->bsub($x_copy); 3550 } 3551 3552 # Shortcut to not run through _find_round_parameters again. 3553 if (defined $params[0]) { 3554 $x = $x->bround($params[0], $params[2]); # then round accordingly 3555 } else { 3556 $x = $x->bfround($params[1], $params[2]); # then round accordingly 3557 } 3558 if ($fallback) { 3559 # Clear a/p after round, since user did not request it. 3560 $x->{accuracy} = undef; 3561 $x->{precision} = undef; 3562 } 3563 3564 # Restore globals. We need to do it like this, because setting one 3565 # undefines the other. 3566 3567 if (defined $ab) { 3568 $class -> accuracy($ab); 3569 } else { 3570 $class -> precision($pb); 3571 } 3572 3573 $class -> upgrade($upg); 3574 $class -> downgrade($dng); 3575 3576 return $downgrade -> new($x -> bdstr(), @r) 3577 if defined($downgrade) && ($x -> is_int() || $x -> is_inf()); 3578 $x; 3579} 3580 3581sub batan2 { 3582 # $y -> batan2($x) returns the arcus tangens of $y / $x. 3583 3584 # Set up parameters. 3585 my ($class, $y, $x, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1]) 3586 ? (ref($_[0]), @_) 3587 : objectify(2, @_); 3588 3589 # Quick exit if $y is read-only. 3590 return $y if $y -> modify('batan2'); 3591 3592 # Handle all NaN cases. 3593 return $y -> bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan; 3594 3595 # We need to limit the accuracy to protect against overflow. 3596 my $fallback = 0; 3597 my ($scale, @params); 3598 ($y, @params) = $y -> _find_round_parameters(@r); 3599 3600 # Error in _find_round_parameters? 3601 return $y if $y->is_nan(); 3602 3603 # No rounding at all, so must use fallback. 3604 if (scalar @params == 0) { 3605 # Simulate old behaviour 3606 $params[0] = $class -> div_scale(); # and round to it as accuracy 3607 $params[1] = undef; # disable P 3608 $scale = $params[0] + 4; # at least four more for proper round 3609 $params[2] = $r[2]; # round mode by caller or undef 3610 $fallback = 1; # to clear a/p afterwards 3611 } else { 3612 # The 4 below is empirical, and there might be cases where it is not 3613 # enough ... 3614 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 3615 } 3616 3617 if ($x -> is_inf("+")) { # x = inf 3618 if ($y -> is_inf("+")) { # y = inf 3619 $y = $y -> bpi($scale) -> bmul("0.25"); # pi/4 3620 } elsif ($y -> is_inf("-")) { # y = -inf 3621 $y = $y -> bpi($scale) -> bmul("-0.25"); # -pi/4 3622 } else { # -inf < y < inf 3623 return $y -> bzero(@r); # 0 3624 } 3625 } elsif ($x -> is_inf("-")) { # x = -inf 3626 if ($y -> is_inf("+")) { # y = inf 3627 $y = $y -> bpi($scale) -> bmul("0.75"); # 3/4 pi 3628 } elsif ($y -> is_inf("-")) { # y = -inf 3629 $y = $y -> bpi($scale) -> bmul("-0.75"); # -3/4 pi 3630 } elsif ($y >= 0) { # y >= 0 3631 $y = $y -> bpi($scale); # pi 3632 } else { # y < 0 3633 $y = $y -> bpi($scale) -> bneg(); # -pi 3634 } 3635 } elsif ($x > 0) { # 0 < x < inf 3636 if ($y -> is_inf("+")) { # y = inf 3637 $y = $y -> bpi($scale) -> bmul("0.5"); # pi/2 3638 } elsif ($y -> is_inf("-")) { # y = -inf 3639 $y = $y -> bpi($scale) -> bmul("-0.5"); # -pi/2 3640 } else { # -inf < y < inf 3641 $y = $y -> bdiv($x, $scale) -> batan($scale); # atan(y/x) 3642 } 3643 } elsif ($x < 0) { # -inf < x < 0 3644 my $pi = $class -> bpi($scale); 3645 if ($y >= 0) { # y >= 0 3646 $y = $y -> bdiv($x, $scale) -> batan() # atan(y/x) + pi 3647 -> badd($pi); 3648 } else { # y < 0 3649 $y = $y -> bdiv($x, $scale) -> batan() # atan(y/x) - pi 3650 -> bsub($pi); 3651 } 3652 } else { # x = 0 3653 if ($y > 0) { # y > 0 3654 $y = $y -> bpi($scale) -> bmul("0.5"); # pi/2 3655 } elsif ($y < 0) { # y < 0 3656 $y = $y -> bpi($scale) -> bmul("-0.5"); # -pi/2 3657 } else { # y = 0 3658 return $y -> bzero(@r); # 0 3659 } 3660 } 3661 3662 $y = $y -> round(@r); 3663 3664 if ($fallback) { 3665 $y->{accuracy} = undef; 3666 $y->{precision} = undef; 3667 } 3668 3669 return $y; 3670} 3671 3672sub bsqrt { 3673 # calculate square root 3674 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 3675 3676 return $x if $x->modify('bsqrt'); 3677 3678 # Handle trivial cases. 3679 3680 return $x -> bnan(@r) if $x->is_nan(); 3681 return $x -> binf("+", @r) if $x->{sign} eq '+inf'; 3682 return $x -> round(@r) if $x->is_zero() || $x->is_one(); 3683 3684 # We don't support complex numbers. 3685 3686 if ($x -> is_neg()) { 3687 return $upgrade -> bsqrt($x, @r) if defined($upgrade); 3688 return $x -> bnan(@r); 3689 } 3690 3691 # we need to limit the accuracy to protect against overflow 3692 my $fallback = 0; 3693 my (@params, $scale); 3694 ($x, @params) = $x->_find_round_parameters(@r); 3695 3696 # error in _find_round_parameters? 3697 return $x -> bnan(@r) if $x->is_nan(); 3698 3699 # no rounding at all, so must use fallback 3700 if (scalar @params == 0) { 3701 # simulate old behaviour 3702 $params[0] = $class->div_scale(); # and round to it as accuracy 3703 $scale = $params[0]+4; # at least four more for proper round 3704 $params[2] = $r[2]; # round mode by caller or undef 3705 $fallback = 1; # to clear a/p afterwards 3706 } else { 3707 # the 4 below is empirical, and there might be cases where it is not 3708 # enough... 3709 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 3710 } 3711 3712 # Shift the significand left or right to get the desired number of digits, 3713 # which is 2*$scale with possibly one extra digit to ensure that the 3714 # exponent is an even number. 3715 3716 my $l = $LIB -> _len($x->{_m}); 3717 my $n = 2 * $scale - $l; # how much should we shift? 3718 $n++ if ($l % 2 xor $LIB -> _is_odd($x->{_e})); 3719 my ($na, $ns) = $n < 0 ? (abs($n), "-") : ($n, "+"); 3720 $na = $LIB -> _new($na); 3721 3722 $x->{_m} = $ns eq "+" ? $LIB -> _lsft($x->{_m}, $na, 10) 3723 : $LIB -> _rsft($x->{_m}, $na, 10); 3724 3725 $x->{_m} = $LIB -> _sqrt($x->{_m}); 3726 3727 # Adjust the exponent by the amount that we shifted the significand. The 3728 # square root of the exponent is simply half of it: sqrt(10^(2*a)) = 10^a. 3729 3730 ($x->{_e}, $x->{_es}) = $LIB -> _ssub($x->{_e}, $x->{_es}, $na, $ns); 3731 $x->{_e} = $LIB -> _div($x->{_e}, $LIB -> _new("2")); 3732 3733 # Normalize to get rid of any trailing zeros in the significand. 3734 3735 $x -> bnorm(); 3736 3737 # shortcut to not run through _find_round_parameters again 3738 if (defined $params[0]) { 3739 $x = $x->bround($params[0], $params[2]); # then round accordingly 3740 } else { 3741 $x = $x->bfround($params[1], $params[2]); # then round accordingly 3742 } 3743 3744 if ($fallback) { 3745 # clear a/p after round, since user did not request it 3746 $x->{accuracy} = undef; 3747 $x->{precision} = undef; 3748 } 3749 3750 return $downgrade -> new($x, @r) 3751 if defined($downgrade) && $x -> is_int(); 3752 $x; 3753} 3754 3755sub broot { 3756 # calculate $y'th root of $x 3757 3758 # set up parameters 3759 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1]) 3760 ? (ref($_[0]), @_) 3761 : objectify(2, @_); 3762 3763 return $x if $x->modify('broot'); 3764 3765 # Handle trivial cases. 3766 3767 return $x -> bnan(@r) if $x->is_nan() || $y->is_nan(); 3768 3769 if ($x -> is_neg()) { 3770 # -27 ** (1/3) = -3 3771 return $x -> broot($y -> copy() -> bneg(), @r) -> bneg() 3772 if $x -> is_int() && $y -> is_int() && $y -> is_neg(); 3773 return $upgrade -> broot($x, $y, @r) if defined $upgrade; 3774 return $x -> bnan(@r); 3775 } 3776 3777 # NaN handling: $x ** 1/0, x or y NaN, or y inf/-inf or y == 0 3778 return $x->bnan() if $x->{sign} !~ /^\+/ || $y->is_zero() || 3779 $y->{sign} !~ /^\+$/; 3780 3781 return $x if $x->is_zero() || $x->is_one() || $x->is_inf() || $y->is_one(); 3782 3783 # we need to limit the accuracy to protect against overflow 3784 my $fallback = 0; 3785 my (@params, $scale); 3786 ($x, @params) = $x->_find_round_parameters(@r); 3787 3788 return $x if $x->is_nan(); # error in _find_round_parameters? 3789 3790 # no rounding at all, so must use fallback 3791 if (scalar @params == 0) { 3792 # simulate old behaviour 3793 $params[0] = $class->div_scale(); # and round to it as accuracy 3794 $scale = $params[0]+4; # at least four more for proper round 3795 $params[2] = $r[2]; # round mode by caller or undef 3796 $fallback = 1; # to clear a/p afterwards 3797 } else { 3798 # the 4 below is empirical, and there might be cases where it is not 3799 # enough... 3800 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 3801 } 3802 3803 # When user set globals, they would interfere with our calculation, so 3804 # disable them and later re-enable them. 3805 3806 my $ab = $class -> accuracy(); 3807 my $pb = $class -> precision(); 3808 $class -> accuracy(undef); 3809 $class -> precision(undef); 3810 3811 # Disabling upgrading and downgrading is no longer necessary to avoid an 3812 # infinite recursion, but it avoids unnecessary upgrading and downgrading in 3813 # the intermediate computations. 3814 3815 my $upg = $class -> upgrade(); 3816 my $dng = $class -> downgrade(); 3817 $class -> upgrade(undef); 3818 $class -> downgrade(undef); 3819 3820 # We also need to disable any set A or P on $x (_find_round_parameters took 3821 # them already into account), since these would interfere, too. 3822 3823 $x->{accuracy} = undef; 3824 $x->{precision} = undef; 3825 3826 # remember sign and make $x positive, since -4 ** (1/2) => -2 3827 my $sign = 0; 3828 $sign = 1 if $x->{sign} eq '-'; 3829 $x->{sign} = '+'; 3830 3831 my $is_two = 0; 3832 if ($y->isa('Math::BigFloat')) { 3833 $is_two = $y->{sign} eq '+' && $LIB->_is_two($y->{_m}) 3834 && $LIB->_is_zero($y->{_e}); 3835 } else { 3836 $is_two = $y == 2; 3837 } 3838 3839 # normal square root if $y == 2: 3840 if ($is_two) { 3841 $x = $x->bsqrt($scale+4); 3842 } elsif ($y->is_one('-')) { 3843 # $x ** -1 => 1/$x 3844 my $u = $class->bone()->bdiv($x, $scale); 3845 # copy private parts over 3846 $x->{_m} = $u->{_m}; 3847 $x->{_e} = $u->{_e}; 3848 $x->{_es} = $u->{_es}; 3849 } else { 3850 # calculate the broot() as integer result first, and if it fits, return 3851 # it rightaway (but only if $x and $y are integer): 3852 3853 my $done = 0; # not yet 3854 if ($y->is_int() && $x->is_int()) { 3855 my $i = $LIB->_copy($x->{_m}); 3856 $i = $LIB->_lsft($i, $x->{_e}, 10) unless $LIB->_is_zero($x->{_e}); 3857 my $int = Math::BigInt->bzero(); 3858 $int->{value} = $i; 3859 $int = $int->broot($y->as_number()); 3860 # if ($exact) 3861 if ($int->copy()->bpow($y) == $x) { 3862 # found result, return it 3863 $x->{_m} = $int->{value}; 3864 $x->{_e} = $LIB->_zero(); 3865 $x->{_es} = '+'; 3866 $x = $x->bnorm(); 3867 $done = 1; 3868 } 3869 } 3870 if ($done == 0) { 3871 my $u = $class->bone()->bdiv($y, $scale+4); 3872 $u->{accuracy} = undef; 3873 $u->{precision} = undef; 3874 $x = $x->bpow($u, $scale+4); # el cheapo 3875 } 3876 } 3877 $x = $x->bneg() if $sign == 1; 3878 3879 # shortcut to not run through _find_round_parameters again 3880 if (defined $params[0]) { 3881 $x = $x->bround($params[0], $params[2]); # then round accordingly 3882 } else { 3883 $x = $x->bfround($params[1], $params[2]); # then round accordingly 3884 } 3885 if ($fallback) { 3886 # clear a/p after round, since user did not request it 3887 $x->{accuracy} = undef; 3888 $x->{precision} = undef; 3889 } 3890 3891 # Restore globals. We need to do it like this, because setting one 3892 # undefines the other. 3893 3894 if (defined $ab) { 3895 $class -> accuracy($ab); 3896 } else { 3897 $class -> precision($pb); 3898 } 3899 3900 $class -> upgrade($upg); 3901 $class -> downgrade($dng); 3902 3903 return $downgrade -> new($x -> bdstr(), @r) 3904 if defined($downgrade) && ($x -> is_int() || $x -> is_inf()); 3905 $x; 3906} 3907 3908sub bfac { 3909 # (BFLOAT or num_str, BFLOAT or num_str) return BFLOAT 3910 # compute factorial number, modifies first argument 3911 3912 # set up parameters 3913 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 3914 3915 # inf => inf 3916 return $x if $x->modify('bfac'); 3917 3918 return $x -> bnan(@r) if $x->is_nan() || $x->is_inf("-"); 3919 return $x -> binf("+", @r) if $x->is_inf("+"); 3920 return $x -> bone(@r) if $x->is_zero() || $x->is_one(); 3921 3922 if ($x -> is_neg() || !$x -> is_int()) { 3923 return $upgrade -> bfac($x, @r) if defined($upgrade); 3924 return $x -> bnan(@r); 3925 } 3926 3927 if (! $LIB->_is_zero($x->{_e})) { 3928 $x->{_m} = $LIB->_lsft($x->{_m}, $x->{_e}, 10); # change 12e1 to 120e0 3929 $x->{_e} = $LIB->_zero(); # normalize 3930 $x->{_es} = '+'; 3931 } 3932 $x->{_m} = $LIB->_fac($x->{_m}); # calculate factorial 3933 3934 $x = $x->bnorm()->round(@r); # norm again and round result 3935 3936 return $downgrade -> new($x -> bdstr(), @r) if defined($downgrade) 3937 && ($x -> is_int() || $x -> is_inf()); 3938 $x; 3939} 3940 3941sub bdfac { 3942 # compute double factorial 3943 3944 # set up parameters 3945 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 3946 3947 return $x if $x->modify('bdfac'); 3948 3949 return $x -> bnan(@r) if $x->is_nan() || $x->is_inf("-"); 3950 return $x -> binf("+", @r) if $x->is_inf("+"); 3951 3952 if ($x <= -2 || !$x -> is_int()) { 3953 return $upgrade -> bdfac($x, @r) if defined($upgrade); 3954 return $x -> bnan(@r); 3955 } 3956 3957 return $x->bone() if $x <= 1; 3958 3959 croak("bdfac() requires a newer version of the $LIB library.") 3960 unless $LIB->can('_dfac'); 3961 3962 if (! $LIB->_is_zero($x->{_e})) { 3963 $x->{_m} = $LIB->_lsft($x->{_m}, $x->{_e}, 10); # change 12e1 to 120e0 3964 $x->{_e} = $LIB->_zero(); # normalize 3965 $x->{_es} = '+'; 3966 } 3967 $x->{_m} = $LIB->_dfac($x->{_m}); # calculate factorial 3968 3969 $x = $x->bnorm()->round(@r); # norm again and round result 3970 3971 return $downgrade -> new($x -> bdstr(), @r) 3972 if defined($downgrade) && $x -> is_int(); 3973 return $x; 3974} 3975 3976sub btfac { 3977 # compute triple factorial 3978 3979 # set up parameters 3980 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 3981 3982 return $x if $x->modify('btfac'); 3983 3984 return $x -> bnan(@r) if $x->is_nan() || $x->is_inf("-"); 3985 return $x -> binf("+", @r) if $x->is_inf("+"); 3986 3987 if ($x <= -3 || !$x -> is_int()) { 3988 return $upgrade -> btfac($x, @r) if defined($upgrade); 3989 return $x -> bnan(@r); 3990 } 3991 3992 my $k = $class -> new("3"); 3993 return $x->bnan(@r) if $x <= -$k; 3994 3995 my $one = $class -> bone(); 3996 return $x->bone(@r) if $x <= $one; 3997 3998 my $f = $x -> copy(); 3999 while ($f -> bsub($k) > $one) { 4000 $x = $x -> bmul($f); 4001 } 4002 4003 $x = $x->round(@r); 4004 4005 return $downgrade -> new($x -> bdstr(), @r) 4006 if defined($downgrade) && $x -> is_int(); 4007 return $x; 4008} 4009 4010sub bmfac { 4011 my ($class, $x, $k, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1]) 4012 ? (ref($_[0]), @_) 4013 : objectify(2, @_); 4014 4015 return $x if $x->modify('bmfac'); 4016 4017 return $x -> bnan(@r) if $x->is_nan() || $x->is_inf("-") || !$k->is_pos(); 4018 return $x -> binf("+", @r) if $x->is_inf("+"); 4019 4020 if ($x <= -$k || !$x -> is_int() || 4021 ($k -> is_finite() && !$k -> is_int())) 4022 { 4023 return $upgrade -> bmfac($x, $k, @r) if defined($upgrade); 4024 return $x -> bnan(@r); 4025 } 4026 4027 my $one = $class -> bone(); 4028 return $x->bone(@r) if $x <= $one; 4029 4030 my $f = $x -> copy(); 4031 while ($f -> bsub($k) > $one) { 4032 $x = $x -> bmul($f); 4033 } 4034 4035 $x = $x->round(@r); 4036 4037 return $downgrade -> new($x -> bdstr(), @r) 4038 if defined($downgrade) && $x -> is_int(); 4039 return $x; 4040} 4041 4042sub blsft { 4043 # shift left by $y in base $b, i.e., multiply by $b ** $y 4044 4045 # set up parameters 4046 my ($class, $x, $y, $b, @r) 4047 = ref($_[0]) && ref($_[0]) eq ref($_[1]) && ref($_[1]) eq ref($_[2]) 4048 ? (ref($_[0]), @_) 4049 : objectify(2, @_); 4050 4051 return $x if $x -> modify('blsft'); 4052 4053 return $x -> bnan(@r) if $x -> is_nan() || $y -> is_nan(); 4054 4055 $b = 2 if !defined $b; 4056 $b = $class -> new($b) 4057 unless defined(blessed($b)) && $b -> isa(__PACKAGE__); 4058 return $x -> bnan(@r) if $b -> is_nan(); 4059 4060 # There needs to be more checking for special cases here. Fixme! 4061 4062 # shift by a negative amount? 4063 return $x -> brsft($y -> copy() -> babs(), $b) if $y -> {sign} =~ /^-/; 4064 4065 $x = $x -> bmul($b -> bpow($y), $r[0], $r[1], $r[2], $y); 4066 4067 return $downgrade -> new($x -> bdstr(), @r) if defined($downgrade) 4068 && ($x -> is_int() || $x -> is_inf() || $x -> is_nan()); 4069 return $x; 4070} 4071 4072sub brsft { 4073 # shift right by $y in base $b, i.e., divide by $b ** $y 4074 4075 # set up parameters 4076 my ($class, $x, $y, $b, @r) 4077 = ref($_[0]) && ref($_[0]) eq ref($_[1]) && ref($_[1]) eq ref($_[2]) 4078 ? (ref($_[0]), @_) 4079 : objectify(2, @_); 4080 4081 return $x if $x -> modify('brsft'); 4082 4083 return $x -> bnan(@r) if $x -> is_nan() || $y -> is_nan(); 4084 4085 # There needs to be more checking for special cases here. Fixme! 4086 4087 $b = 2 if !defined $b; 4088 $b = $class -> new($b) 4089 unless defined(blessed($b)) && $b -> isa(__PACKAGE__); 4090 return $x -> bnan(@r) if $b -> is_nan(); 4091 4092 # shift by a negative amount? 4093 return $x -> blsft($y -> copy() -> babs(), $b) if $y -> {sign} =~ /^-/; 4094 4095 # call bdiv() 4096 $x = $x -> bdiv($b -> bpow($y), $r[0], $r[1], $r[2], $y); 4097 4098 return $downgrade -> new($x -> bdstr(), @r) if defined($downgrade) 4099 && ($x -> is_int() || $x -> is_inf() || $x -> is_nan()); 4100 return $x; 4101} 4102 4103############################################################################### 4104# Bitwise methods 4105############################################################################### 4106 4107# Bitwise left shift. 4108 4109sub bblsft { 4110 # We don't call objectify(), because the bitwise methods should not 4111 # upgrade/downgrade, even when upgrading/downgrading is enabled. 4112 4113 my ($class, $x, $y, @r) = ref($_[0]) ? (ref($_[0]), @_) : @_; 4114 4115 my $xint = Math::BigInt -> bblsft($x, $y, @r); 4116 4117 # Temporarily disable downgrading. 4118 4119 my $dng = $class -> downgrade(); 4120 $class -> downgrade(undef); 4121 4122 # convert to our class without downgrading. 4123 4124 my $xflt = $class -> new($xint); 4125 4126 # Reset downgrading. 4127 4128 $class -> downgrade($dng); 4129 4130 # If we are called as a class method, the first operand might not be an 4131 # object of this class, so check. 4132 4133 if (defined(blessed($x)) && $x -> isa(__PACKAGE__)) { 4134 $x -> {sign} = $xflt -> {sign}; 4135 $x -> {_m} = $xflt -> {_m}; 4136 $x -> {_es} = $xflt -> {_es}; 4137 $x -> {_e} = $xflt -> {_e}; 4138 } else { 4139 $x = $xflt; 4140 } 4141 4142 # Now we might downgrade. 4143 4144 return $downgrade -> new($x) if defined($downgrade); 4145 $x -> round(@r); 4146} 4147 4148# Bitwise right shift. 4149 4150sub bbrsft { 4151 # We don't call objectify(), because the bitwise methods should not 4152 # upgrade/downgrade, even when upgrading/downgrading is enabled. 4153 4154 my ($class, $x, $y, @r) = ref($_[0]) ? (ref($_[0]), @_) : @_; 4155 4156 my $xint = Math::BigInt -> bbrsft($x, $y, @r); 4157 4158 # Temporarily disable downgrading. 4159 4160 my $dng = $class -> downgrade(); 4161 $class -> downgrade(undef); 4162 4163 # Convert to our class without downgrading. 4164 4165 my $xflt = $class -> new($xint); 4166 4167 # Reset downgrading. 4168 4169 $class -> downgrade($dng); 4170 4171 # If we are called as a class method, the first operand might not be an 4172 # object of this class, so check. 4173 4174 if (defined(blessed($x)) && $x -> isa(__PACKAGE__)) { 4175 $x -> {sign} = $xflt -> {sign}; 4176 $x -> {_m} = $xflt -> {_m}; 4177 $x -> {_es} = $xflt -> {_es}; 4178 $x -> {_e} = $xflt -> {_e}; 4179 } else { 4180 $x = $xflt; 4181 } 4182 4183 # Now we might downgrade. 4184 4185 return $downgrade -> new($x) if defined($downgrade); 4186 $x -> round(@r); 4187} 4188 4189sub band { 4190 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1]) 4191 ? (ref($_[0]), @_) 4192 : objectify(2, @_); 4193 4194 return if $x -> modify('band'); 4195 4196 return $x -> bnan(@r) if $x -> is_nan() || $y -> is_nan(); 4197 4198 my $xint = $x -> as_int(); # to Math::BigInt 4199 my $yint = $y -> as_int(); # to Math::BigInt 4200 4201 $xint = $xint -> band($yint); 4202 4203 return $xint -> round(@r) if defined $downgrade; 4204 4205 my $xflt = $class -> new($xint); # back to Math::BigFloat 4206 $x -> {sign} = $xflt -> {sign}; 4207 $x -> {_m} = $xflt -> {_m}; 4208 $x -> {_es} = $xflt -> {_es}; 4209 $x -> {_e} = $xflt -> {_e}; 4210 4211 return $x -> round(@r); 4212} 4213 4214sub bior { 4215 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1]) 4216 ? (ref($_[0]), @_) 4217 : objectify(2, @_); 4218 4219 return if $x -> modify('bior'); 4220 4221 return $x -> bnan(@r) if $x -> is_nan() || $y -> is_nan(); 4222 4223 my $xint = $x -> as_int(); # to Math::BigInt 4224 my $yint = $y -> as_int(); # to Math::BigInt 4225 4226 $xint = $xint -> bior($yint); 4227 4228 return $xint -> round(@r) if defined $downgrade; 4229 4230 my $xflt = $class -> new($xint); # back to Math::BigFloat 4231 $x -> {sign} = $xflt -> {sign}; 4232 $x -> {_m} = $xflt -> {_m}; 4233 $x -> {_es} = $xflt -> {_es}; 4234 $x -> {_e} = $xflt -> {_e}; 4235 4236 return $x -> round(@r); 4237} 4238 4239sub bxor { 4240 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1]) 4241 ? (ref($_[0]), @_) 4242 : objectify(2, @_); 4243 4244 return if $x -> modify('bxor'); 4245 4246 return $x -> bnan(@r) if $x -> is_nan() || $y -> is_nan(); 4247 4248 my $xint = $x -> as_int(); # to Math::BigInt 4249 my $yint = $y -> as_int(); # to Math::BigInt 4250 4251 $xint = $xint -> bxor($yint); 4252 4253 return $xint -> round(@r) if defined $downgrade; 4254 4255 my $xflt = $class -> new($xint); # back to Math::BigFloat 4256 $x -> {sign} = $xflt -> {sign}; 4257 $x -> {_m} = $xflt -> {_m}; 4258 $x -> {_es} = $xflt -> {_es}; 4259 $x -> {_e} = $xflt -> {_e}; 4260 4261 return $x -> round(@r); 4262} 4263 4264sub bnot { 4265 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4266 4267 return if $x -> modify('bnot'); 4268 4269 return $x -> bnan(@r) if $x -> is_nan(); 4270 4271 my $xint = $x -> as_int(); # to Math::BigInt 4272 $xint = $xint -> bnot(); 4273 4274 return $xint -> round(@r) if defined $downgrade; 4275 4276 my $xflt = $class -> new($xint); # back to Math::BigFloat 4277 $x -> {sign} = $xflt -> {sign}; 4278 $x -> {_m} = $xflt -> {_m}; 4279 $x -> {_es} = $xflt -> {_es}; 4280 $x -> {_e} = $xflt -> {_e}; 4281 4282 return $x -> round(@r); 4283} 4284 4285############################################################################### 4286# Rounding methods 4287############################################################################### 4288 4289sub bround { 4290 # accuracy: preserve $N digits, and overwrite the rest with 0's 4291 4292 my ($class, $x, @a) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4293 4294 if (($a[0] || 0) < 0) { 4295 croak('bround() needs positive accuracy'); 4296 } 4297 4298 return $x if $x->modify('bround'); 4299 4300 my ($scale, $mode) = $x->_scale_a(@a); 4301 if (!defined $scale) { # no-op 4302 return $downgrade -> new($x) if defined($downgrade) 4303 && ($x->is_int() || $x->is_inf() || $x->is_nan()); 4304 return $x; 4305 } 4306 4307 # Scale is now either $x->{accuracy}, $accuracy, or the input argument. Test 4308 # whether $x already has lower accuracy, do nothing in this case but do 4309 # round if the accuracy is the same, since a math operation might want to 4310 # round a number with A=5 to 5 digits afterwards again 4311 4312 if (defined $x->{accuracy} && $x->{accuracy} < $scale) { 4313 return $downgrade -> new($x) if defined($downgrade) 4314 && ($x->is_int() || $x->is_inf() || $x->is_nan()); 4315 return $x; 4316 } 4317 4318 # scale < 0 makes no sense 4319 # scale == 0 => keep all digits 4320 # never round a +-inf, NaN 4321 4322 if ($scale <= 0 || $x->{sign} !~ /^[+-]$/) { 4323 return $downgrade -> new($x) if defined($downgrade) 4324 && ($x->is_int() || $x->is_inf() || $x->is_nan()); 4325 return $x; 4326 } 4327 4328 # 1: never round a 0 4329 # 2: if we should keep more digits than the mantissa has, do nothing 4330 if ($x->is_zero() || $LIB->_len($x->{_m}) <= $scale) { 4331 $x->{accuracy} = $scale if !defined $x->{accuracy} || $x->{accuracy} > $scale; 4332 return $downgrade -> new($x) if defined($downgrade) 4333 && ($x->is_int() || $x->is_inf() || $x->is_nan()); 4334 return $x; 4335 } 4336 4337 # pass sign to bround for '+inf' and '-inf' rounding modes 4338 my $m = bless { sign => $x->{sign}, value => $x->{_m} }, 'Math::BigInt'; 4339 4340 $m = $m->bround($scale, $mode); # round mantissa 4341 $x->{_m} = $m->{value}; # get our mantissa back 4342 $x->{accuracy} = $scale; # remember rounding 4343 $x->{precision} = undef; # and clear P 4344 4345 # bnorm() downgrades if necessary, so no need to check whether to downgrade. 4346 $x->bnorm(); # del trailing zeros gen. by bround() 4347} 4348 4349sub bfround { 4350 # precision: round to the $Nth digit left (+$n) or right (-$n) from the '.' 4351 # $n == 0 means round to integer 4352 # expects and returns normalized numbers! 4353 4354 my ($class, $x, @p) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4355 4356 return $x if $x->modify('bfround'); # no-op 4357 4358 my ($scale, $mode) = $x->_scale_p(@p); 4359 if (!defined $scale) { 4360 return $downgrade -> new($x) if defined($downgrade) 4361 && ($x->is_int() || $x->is_inf() || $x->is_nan()); 4362 return $x; 4363 } 4364 4365 # never round a 0, +-inf, NaN 4366 4367 if ($x->is_zero()) { 4368 $x->{precision} = $scale if !defined $x->{precision} || $x->{precision} < $scale; # -3 < -2 4369 return $downgrade -> new($x) if defined($downgrade) 4370 && ($x->is_int() || $x->is_inf() || $x->is_nan()); 4371 return $x; 4372 } 4373 4374 if ($x->{sign} !~ /^[+-]$/) { 4375 return $downgrade -> new($x) if defined($downgrade) 4376 && ($x->is_int() || $x->is_inf() || $x->is_nan()); 4377 return $x; 4378 } 4379 4380 # don't round if x already has lower precision 4381 if (defined $x->{precision} && $x->{precision} < 0 && $scale < $x->{precision}) { 4382 return $downgrade -> new($x) if defined($downgrade) 4383 && ($x->is_int() || $x->is_inf() || $x->is_nan()); 4384 return $x; 4385 } 4386 4387 $x->{precision} = $scale; # remember round in any case 4388 $x->{accuracy} = undef; # and clear A 4389 if ($scale < 0) { 4390 # round right from the '.' 4391 4392 if ($x->{_es} eq '+') { # e >= 0 => nothing to round 4393 return $downgrade -> new($x) if defined($downgrade) 4394 && ($x->is_int() || $x->is_inf() || $x->is_nan()); 4395 return $x; 4396 } 4397 4398 $scale = -$scale; # positive for simplicity 4399 my $len = $LIB->_len($x->{_m}); # length of mantissa 4400 4401 # the following poses a restriction on _e, but if _e is bigger than a 4402 # scalar, you got other problems (memory etc) anyway 4403 my $dad = -(0+ ($x->{_es}.$LIB->_num($x->{_e}))); # digits after dot 4404 my $zad = 0; # zeros after dot 4405 $zad = $dad - $len if (-$dad < -$len); # for 0.00..00xxx style 4406 4407 # print "scale $scale dad $dad zad $zad len $len\n"; 4408 # number bsstr len zad dad 4409 # 0.123 123e-3 3 0 3 4410 # 0.0123 123e-4 3 1 4 4411 # 0.001 1e-3 1 2 3 4412 # 1.23 123e-2 3 0 2 4413 # 1.2345 12345e-4 5 0 4 4414 4415 # do not round after/right of the $dad 4416 4417 if ($scale > $dad) { # 0.123, scale >= 3 => exit 4418 return $downgrade -> new($x) if defined($downgrade) 4419 && ($x->is_int() || $x->is_inf() || $x->is_nan()); 4420 return $x; 4421 } 4422 4423 # round to zero if rounding inside the $zad, but not for last zero like: 4424 # 0.0065, scale -2, round last '0' with following '65' (scale == zad 4425 # case) 4426 if ($scale < $zad) { 4427 return $downgrade -> new($x) if defined($downgrade) 4428 && ($x->is_int() || $x->is_inf() || $x->is_nan()); 4429 return $x->bzero(); 4430 } 4431 4432 if ($scale == $zad) { # for 0.006, scale -3 and trunc 4433 $scale = -$len; 4434 } else { 4435 # adjust round-point to be inside mantissa 4436 if ($zad != 0) { 4437 $scale = $scale-$zad; 4438 } else { 4439 my $dbd = $len - $dad; 4440 $dbd = 0 if $dbd < 0; # digits before dot 4441 $scale = $dbd+$scale; 4442 } 4443 } 4444 } else { 4445 # round left from the '.' 4446 4447 # 123 => 100 means length(123) = 3 - $scale (2) => 1 4448 4449 my $dbt = $LIB->_len($x->{_m}); 4450 # digits before dot 4451 my $dbd = $dbt + ($x->{_es} . $LIB->_num($x->{_e})); 4452 # should be the same, so treat it as this 4453 $scale = 1 if $scale == 0; 4454 # shortcut if already integer 4455 if ($scale == 1 && $dbt <= $dbd) { 4456 return $downgrade -> new($x) if defined($downgrade) 4457 && ($x->is_int() || $x->is_inf() || $x->is_nan()); 4458 return $x; 4459 } 4460 # maximum digits before dot 4461 ++$dbd; 4462 4463 if ($scale > $dbd) { 4464 # not enough digits before dot, so round to zero 4465 return $downgrade -> new($x) if defined($downgrade); 4466 return $x->bzero; 4467 } elsif ($scale == $dbd) { 4468 # maximum 4469 $scale = -$dbt; 4470 } else { 4471 $scale = $dbd - $scale; 4472 } 4473 } 4474 4475 # pass sign to bround for rounding modes '+inf' and '-inf' 4476 my $m = bless { sign => $x->{sign}, value => $x->{_m} }, 'Math::BigInt'; 4477 $m = $m->bround($scale, $mode); 4478 $x->{_m} = $m->{value}; # get our mantissa back 4479 4480 # bnorm() downgrades if necessary, so no need to check whether to downgrade. 4481 $x->bnorm(); 4482} 4483 4484sub bfloor { 4485 # round towards minus infinity 4486 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4487 4488 return $x if $x->modify('bfloor'); 4489 4490 return $x -> bnan(@r) if $x -> is_nan(); 4491 4492 if ($x->{sign} =~ /^[+-]$/) { 4493 # if $x has digits after dot, remove them 4494 if ($x->{_es} eq '-') { 4495 $x->{_m} = $LIB->_rsft($x->{_m}, $x->{_e}, 10); 4496 $x->{_e} = $LIB->_zero(); 4497 $x->{_es} = '+'; 4498 # increment if negative 4499 $x->{_m} = $LIB->_inc($x->{_m}) if $x->{sign} eq '-'; 4500 } 4501 $x = $x->round(@r); 4502 } 4503 return $downgrade -> new($x -> bdstr(), @r) if defined($downgrade); 4504 return $x; 4505} 4506 4507sub bceil { 4508 # round towards plus infinity 4509 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4510 4511 return $x if $x->modify('bceil'); 4512 4513 return $x -> bnan(@r) if $x -> is_nan(); 4514 4515 # if $x has digits after dot, remove them 4516 if ($x->{sign} =~ /^[+-]$/) { 4517 if ($x->{_es} eq '-') { 4518 $x->{_m} = $LIB->_rsft($x->{_m}, $x->{_e}, 10); 4519 $x->{_e} = $LIB->_zero(); 4520 $x->{_es} = '+'; 4521 if ($x->{sign} eq '+') { 4522 $x->{_m} = $LIB->_inc($x->{_m}); # increment if positive 4523 } else { 4524 $x->{sign} = '+' if $LIB->_is_zero($x->{_m}); # avoid -0 4525 } 4526 } 4527 $x = $x->round(@r); 4528 } 4529 4530 return $downgrade -> new($x -> bdstr(), @r) if defined($downgrade); 4531 return $x; 4532} 4533 4534sub bint { 4535 # round towards zero 4536 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4537 4538 return $x if $x->modify('bint'); 4539 4540 return $x -> bnan(@r) if $x -> is_nan(); 4541 4542 if ($x->{sign} =~ /^[+-]$/) { 4543 # if $x has digits after the decimal point 4544 if ($x->{_es} eq '-') { 4545 $x->{_m} = $LIB->_rsft($x->{_m}, $x->{_e}, 10); # remove frac part 4546 $x->{_e} = $LIB->_zero(); # truncate/normalize 4547 $x->{_es} = '+'; # abs e 4548 $x->{sign} = '+' if $LIB->_is_zero($x->{_m}); # avoid -0 4549 } 4550 $x = $x->round(@r); 4551 } 4552 4553 return $downgrade -> new($x -> bdstr(), @r) if defined($downgrade); 4554 return $x; 4555} 4556 4557############################################################################### 4558# Other mathematical methods 4559############################################################################### 4560 4561sub bgcd { 4562 # (BINT or num_str, BINT or num_str) return BINT 4563 # does not modify arguments, but returns new object 4564 4565 # Class::method(...) -> Class->method(...) 4566 unless (@_ && (defined(blessed($_[0])) && $_[0] -> isa(__PACKAGE__) || 4567 $_[0] =~ /^[a-z]\w*(?:::[a-z]\w*)*$/i)) 4568 { 4569 #carp "Using ", (caller(0))[3], "() as a function is deprecated;", 4570 # " use is as a method instead"; 4571 unshift @_, __PACKAGE__; 4572 } 4573 4574 my ($class, @args) = objectify(0, @_); 4575 4576 my $x = shift @args; 4577 $x = defined(blessed($x)) && $x -> isa(__PACKAGE__) ? $x -> copy() 4578 : $class -> new($x); 4579 return $class->bnan() unless $x -> is_int(); 4580 4581 while (@args) { 4582 my $y = shift @args; 4583 $y = $class->new($y) 4584 unless defined(blessed($y)) && $y -> isa(__PACKAGE__); 4585 return $class->bnan() unless $y -> is_int(); 4586 4587 # greatest common divisor 4588 while (! $y->is_zero()) { 4589 ($x, $y) = ($y->copy(), $x->copy()->bmod($y)); 4590 } 4591 4592 last if $x -> is_one(); 4593 } 4594 $x = $x -> babs(); 4595 4596 return $downgrade -> new($x) 4597 if defined $downgrade && $x->is_int(); 4598 return $x; 4599} 4600 4601sub blcm { 4602 # (BFLOAT or num_str, BFLOAT or num_str) return BFLOAT 4603 # does not modify arguments, but returns new object 4604 # Least Common Multiple 4605 4606 # Class::method(...) -> Class->method(...) 4607 unless (@_ && (defined(blessed($_[0])) && $_[0] -> isa(__PACKAGE__) || 4608 $_[0] =~ /^[a-z]\w*(?:::[a-z]\w*)*$/i)) 4609 { 4610 #carp "Using ", (caller(0))[3], "() as a function is deprecated;", 4611 # " use is as a method instead"; 4612 unshift @_, __PACKAGE__; 4613 } 4614 4615 my ($class, @args) = objectify(0, @_); 4616 4617 my $x = shift @args; 4618 $x = defined(blessed($x)) && $x -> isa(__PACKAGE__) ? $x -> copy() 4619 : $class -> new($x); 4620 return $class->bnan() if $x->{sign} !~ /^[+-]$/; # x NaN? 4621 4622 while (@args) { 4623 my $y = shift @args; 4624 $y = $class -> new($y) 4625 unless defined(blessed($y)) && $y -> isa(__PACKAGE__); 4626 return $x->bnan() unless $y -> is_int(); 4627 my $gcd = $x -> bgcd($y); 4628 $x = $x -> bdiv($gcd) -> bmul($y); 4629 } 4630 4631 $x = $x -> babs(); 4632 4633 return $downgrade -> new($x) 4634 if defined $downgrade && $x->is_int(); 4635 return $x; 4636} 4637 4638############################################################################### 4639# Object property methods 4640############################################################################### 4641 4642sub length { 4643 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4644 4645 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 4646 4647 return 1 if $LIB->_is_zero($x->{_m}); 4648 4649 my $len = $LIB->_len($x->{_m}); 4650 $len += $LIB->_num($x->{_e}) if $x->{_es} eq '+'; 4651 if (wantarray()) { 4652 my $t = 0; 4653 $t = $LIB->_num($x->{_e}) if $x->{_es} eq '-'; 4654 return ($len, $t); 4655 } 4656 $len; 4657} 4658 4659sub mantissa { 4660 # return a copy of the mantissa 4661 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4662 4663 # The following line causes a lot of noise in the test suits for 4664 # the Math-BigRat and bignum distributions. Fixme! 4665 #carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 4666 4667 return $x -> bnan(@r) if $x -> is_nan(); 4668 4669 if ($x->{sign} !~ /^[+-]$/) { 4670 my $s = $x->{sign}; 4671 $s =~ s/^\+//; 4672 return Math::BigInt->new($s, undef, undef); # -inf, +inf => +inf 4673 } 4674 my $m = Math::BigInt->new($LIB->_str($x->{_m}), undef, undef); 4675 $m = $m->bneg() if $x->{sign} eq '-'; 4676 $m; 4677} 4678 4679sub exponent { 4680 # return a copy of the exponent 4681 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4682 4683 # The following line causes a lot of noise in the test suits for 4684 # the Math-BigRat and bignum distributions. Fixme! 4685 #carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 4686 4687 return $x -> bnan(@r) if $x -> is_nan(); 4688 4689 if ($x->{sign} !~ /^[+-]$/) { 4690 my $s = $x->{sign}; 4691 $s =~ s/^[+-]//; 4692 return Math::BigInt->new($s, undef, undef); # -inf, +inf => +inf 4693 } 4694 Math::BigInt->new($x->{_es} . $LIB->_str($x->{_e}), undef, undef); 4695} 4696 4697sub parts { 4698 # return a copy of both the exponent and the mantissa 4699 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4700 4701 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 4702 4703 if ($x->{sign} !~ /^[+-]$/) { 4704 my $s = $x->{sign}; 4705 $s =~ s/^\+//; 4706 my $se = $s; 4707 $se =~ s/^-//; 4708 # +inf => inf and -inf, +inf => inf 4709 return ($class->new($s), $class->new($se)); 4710 } 4711 my $m = Math::BigInt->bzero(); 4712 $m->{value} = $LIB->_copy($x->{_m}); 4713 $m = $m->bneg() if $x->{sign} eq '-'; 4714 ($m, Math::BigInt->new($x->{_es} . $LIB->_num($x->{_e}))); 4715} 4716 4717# Parts used for scientific notation with significand/mantissa and exponent as 4718# integers. E.g., "12345.6789" is returned as "123456789" (mantissa) and "-4" 4719# (exponent). 4720 4721sub sparts { 4722 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4723 4724 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 4725 4726 # Not-a-number. 4727 4728 if ($x -> is_nan()) { 4729 my $mant = $class -> bnan(); # mantissa 4730 return $mant unless wantarray; # scalar context 4731 my $expo = $class -> bnan(); # exponent 4732 return ($mant, $expo); # list context 4733 } 4734 4735 # Infinity. 4736 4737 if ($x -> is_inf()) { 4738 my $mant = $class -> binf($x->{sign}); # mantissa 4739 return $mant unless wantarray; # scalar context 4740 my $expo = $class -> binf('+'); # exponent 4741 return ($mant, $expo); # list context 4742 } 4743 4744 # Finite number. 4745 4746 my $mant = $class -> new($x); 4747 $mant->{_es} = '+'; 4748 $mant->{_e} = $LIB->_zero(); 4749 $mant = $downgrade -> new($mant) if defined $downgrade; 4750 return $mant unless wantarray; 4751 4752 my $expo = $class -> new($x -> {_es} . $LIB->_str($x -> {_e})); 4753 $expo = $downgrade -> new($expo) if defined $downgrade; 4754 return ($mant, $expo); 4755} 4756 4757# Parts used for normalized notation with significand/mantissa as either 0 or a 4758# number in the semi-open interval [1,10). E.g., "12345.6789" is returned as 4759# "1.23456789" and "4". 4760 4761sub nparts { 4762 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4763 4764 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 4765 4766 # Not-a-number and Infinity. 4767 4768 return $x -> sparts() if $x -> is_nan() || $x -> is_inf(); 4769 4770 # Finite number. 4771 4772 my ($mant, $expo) = $x -> sparts(); 4773 4774 if ($mant -> bcmp(0)) { 4775 my ($ndigtot, $ndigfrac) = $mant -> length(); 4776 my $expo10adj = $ndigtot - $ndigfrac - 1; 4777 4778 if ($expo10adj > 0) { # if mantissa is not an integer 4779 $mant = $mant -> brsft($expo10adj, 10); 4780 return $mant unless wantarray; 4781 $expo = $expo -> badd($expo10adj); 4782 return ($mant, $expo); 4783 } 4784 } 4785 4786 return $mant unless wantarray; 4787 return ($mant, $expo); 4788} 4789 4790# Parts used for engineering notation with significand/mantissa as either 0 or a 4791# number in the semi-open interval [1,1000) and the exponent is a multiple of 3. 4792# E.g., "12345.6789" is returned as "12.3456789" and "3". 4793 4794sub eparts { 4795 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4796 4797 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 4798 4799 # Not-a-number and Infinity. 4800 4801 return $x -> sparts() if $x -> is_nan() || $x -> is_inf(); 4802 4803 # Finite number. 4804 4805 my ($mant, $expo) = $x -> nparts(); 4806 4807 my $c = $expo -> copy() -> bmod(3); 4808 $mant = $mant -> blsft($c, 10); 4809 return $mant unless wantarray; 4810 4811 $expo = $expo -> bsub($c); 4812 return ($mant, $expo); 4813} 4814 4815# Parts used for decimal notation, e.g., "12345.6789" is returned as "12345" 4816# (integer part) and "0.6789" (fraction part). 4817 4818sub dparts { 4819 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4820 4821 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 4822 4823 # Not-a-number. 4824 4825 if ($x -> is_nan()) { 4826 my $int = $class -> bnan(); 4827 return $int unless wantarray; 4828 my $frc = $class -> bzero(); # or NaN? 4829 return ($int, $frc); 4830 } 4831 4832 # Infinity. 4833 4834 if ($x -> is_inf()) { 4835 my $int = $class -> binf($x->{sign}); 4836 return $int unless wantarray; 4837 my $frc = $class -> bzero(); 4838 return ($int, $frc); 4839 } 4840 4841 # Finite number. 4842 4843 my $int = $x -> copy(); 4844 my $frc; 4845 4846 # If the input is an integer. 4847 4848 if ($int->{_es} eq '+') { 4849 $frc = $class -> bzero(); 4850 } 4851 4852 # If the input has a fraction part 4853 4854 else { 4855 $int->{_m} = $LIB -> _rsft($int->{_m}, $int->{_e}, 10); 4856 $int->{_e} = $LIB -> _zero(); 4857 $int->{_es} = '+'; 4858 $int->{sign} = '+' if $LIB->_is_zero($int->{_m}); # avoid -0 4859 return $int unless wantarray; 4860 $frc = $x -> copy() -> bsub($int); 4861 return ($int, $frc); 4862 } 4863 4864 $int = $downgrade -> new($int) if defined $downgrade; 4865 return $int unless wantarray; 4866 return $int, $frc; 4867} 4868 4869# Fractional parts with the numerator and denominator as integers. E.g., 4870# "123.4375" is returned as "1975" and "16". 4871 4872sub fparts { 4873 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4874 4875 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 4876 4877 # NaN => NaN/NaN 4878 4879 if ($x -> is_nan()) { 4880 return $class -> bnan() unless wantarray; 4881 return $class -> bnan(), $class -> bnan(); 4882 } 4883 4884 # ±Inf => ±Inf/1 4885 4886 if ($x -> is_inf()) { 4887 my $numer = $class -> binf($x->{sign}); 4888 return $numer unless wantarray; 4889 my $denom = $class -> bone(); 4890 return $numer, $denom; 4891 } 4892 4893 # Finite number. 4894 4895 # If we get here, we know that the output is an integer. 4896 4897 $class = $downgrade if defined $downgrade; 4898 4899 my @flt_parts = ($x->{sign}, $x->{_m}, $x->{_es}, $x->{_e}); 4900 my @rat_parts = $class -> _flt_lib_parts_to_rat_lib_parts(@flt_parts); 4901 my $num = $class -> new($LIB -> _str($rat_parts[1])); 4902 my $den = $class -> new($LIB -> _str($rat_parts[2])); 4903 $num = $num -> bneg() if $rat_parts[0] eq "-"; 4904 return $num unless wantarray; 4905 return $num, $den; 4906} 4907 4908# Given "123.4375", returns "1975", since "123.4375" is "1975/16". 4909 4910sub numerator { 4911 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4912 4913 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 4914 4915 return $class -> bnan() if $x -> is_nan(); 4916 return $class -> binf($x -> sign()) if $x -> is_inf(); 4917 return $class -> bzero() if $x -> is_zero(); 4918 4919 # If we get here, we know that the output is an integer. 4920 4921 $class = $downgrade if defined $downgrade; 4922 4923 if ($x -> {_es} eq '-') { # exponent < 0 4924 my $numer_lib = $LIB -> _copy($x -> {_m}); 4925 my $denom_lib = $LIB -> _1ex($x -> {_e}); 4926 my $gcd_lib = $LIB -> _gcd($LIB -> _copy($numer_lib), $denom_lib); 4927 $numer_lib = $LIB -> _div($numer_lib, $gcd_lib); 4928 return $class -> new($x -> {sign} . $LIB -> _str($numer_lib)); 4929 } 4930 4931 elsif (! $LIB -> _is_zero($x -> {_e})) { # exponent > 0 4932 my $numer_lib = $LIB -> _copy($x -> {_m}); 4933 $numer_lib = $LIB -> _lsft($numer_lib, $x -> {_e}, 10); 4934 return $class -> new($x -> {sign} . $LIB -> _str($numer_lib)); 4935 } 4936 4937 else { # exponent = 0 4938 return $class -> new($x -> {sign} . $LIB -> _str($x -> {_m})); 4939 } 4940} 4941 4942# Given "123.4375", returns "16", since "123.4375" is "1975/16". 4943 4944sub denominator { 4945 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4946 4947 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 4948 4949 return $class -> bnan() if $x -> is_nan(); 4950 4951 # If we get here, we know that the output is an integer. 4952 4953 $class = $downgrade if defined $downgrade; 4954 4955 if ($x -> {_es} eq '-') { # exponent < 0 4956 my $numer_lib = $LIB -> _copy($x -> {_m}); 4957 my $denom_lib = $LIB -> _1ex($x -> {_e}); 4958 my $gcd_lib = $LIB -> _gcd($LIB -> _copy($numer_lib), $denom_lib); 4959 $denom_lib = $LIB -> _div($denom_lib, $gcd_lib); 4960 return $class -> new($LIB -> _str($denom_lib)); 4961 } 4962 4963 else { # exponent >= 0 4964 return $class -> bone(); 4965 } 4966} 4967 4968############################################################################### 4969# String conversion methods 4970############################################################################### 4971 4972sub bstr { 4973 # (ref to BFLOAT or num_str) return num_str 4974 # Convert number from internal format to (non-scientific) string format. 4975 # internal format is always normalized (no leading zeros, "-0" => "+0") 4976 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 4977 4978 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 4979 4980 # Inf and NaN 4981 4982 if ($x->{sign} ne '+' && $x->{sign} ne '-') { 4983 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN 4984 return 'inf'; # +inf 4985 } 4986 4987 # Finite number 4988 4989 my $es = '0'; 4990 my $len = 1; 4991 my $cad = 0; 4992 my $dot = '.'; 4993 4994 # $x is zero? 4995 my $not_zero = !($x->{sign} eq '+' && $LIB->_is_zero($x->{_m})); 4996 if ($not_zero) { 4997 $es = $LIB->_str($x->{_m}); 4998 $len = CORE::length($es); 4999 my $e = $LIB->_num($x->{_e}); 5000 $e = -$e if $x->{_es} eq '-'; 5001 if ($e < 0) { 5002 $dot = ''; 5003 # if _e is bigger than a scalar, the following will blow your memory 5004 if ($e <= -$len) { 5005 my $r = abs($e) - $len; 5006 $es = '0.'. ('0' x $r) . $es; 5007 $cad = -($len+$r); 5008 } else { 5009 substr($es, $e, 0) = '.'; 5010 $cad = $LIB->_num($x->{_e}); 5011 $cad = -$cad if $x->{_es} eq '-'; 5012 } 5013 } elsif ($e > 0) { 5014 # expand with zeros 5015 $es .= '0' x $e; 5016 $len += $e; 5017 $cad = 0; 5018 } 5019 } # if not zero 5020 5021 $es = '-'.$es if $x->{sign} eq '-'; 5022 # if set accuracy or precision, pad with zeros on the right side 5023 if ((defined $x->{accuracy}) && ($not_zero)) { 5024 # 123400 => 6, 0.1234 => 4, 0.001234 => 4 5025 my $zeros = $x->{accuracy} - $cad; # cad == 0 => 12340 5026 $zeros = $x->{accuracy} - $len if $cad != $len; 5027 $es .= $dot.'0' x $zeros if $zeros > 0; 5028 } elsif ((($x->{precision} || 0) < 0)) { 5029 # 123400 => 6, 0.1234 => 4, 0.001234 => 6 5030 my $zeros = -$x->{precision} + $cad; 5031 $es .= $dot.'0' x $zeros if $zeros > 0; 5032 } 5033 $es; 5034} 5035 5036# Decimal notation, e.g., "12345.6789" (no exponent). 5037 5038sub bdstr { 5039 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 5040 5041 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 5042 5043 # Inf and NaN 5044 5045 if ($x->{sign} ne '+' && $x->{sign} ne '-') { 5046 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN 5047 return 'inf'; # +inf 5048 } 5049 5050 # Upgrade? 5051 5052 return $upgrade -> bdstr($x, @r) 5053 if defined($upgrade) && !$x -> isa(__PACKAGE__); 5054 5055 # Finite number 5056 5057 my $mant = $LIB->_str($x->{_m}); 5058 my $esgn = $x->{_es}; 5059 my $eabs = $LIB -> _num($x->{_e}); 5060 5061 my $uintmax = ~0; 5062 5063 my $str = $mant; 5064 if ($esgn eq '+') { 5065 5066 croak("The absolute value of the exponent is too large") 5067 if $eabs > $uintmax; 5068 5069 $str .= "0" x $eabs; 5070 5071 } else { 5072 my $mlen = CORE::length($mant); 5073 my $c = $mlen - $eabs; 5074 5075 my $intmax = ($uintmax - 1) / 2; 5076 croak("The absolute value of the exponent is too large") 5077 if (1 - $c) > $intmax; 5078 5079 $str = "0" x (1 - $c) . $str if $c <= 0; 5080 substr($str, -$eabs, 0) = '.'; 5081 } 5082 5083 return $x->{sign} eq '-' ? '-' . $str : $str; 5084} 5085 5086# Scientific notation with significand/mantissa and exponent as integers, e.g., 5087# "12345.6789" is written as "123456789e-4". 5088 5089sub bsstr { 5090 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 5091 5092 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 5093 5094 # Inf and NaN 5095 5096 if ($x->{sign} ne '+' && $x->{sign} ne '-') { 5097 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN 5098 return 'inf'; # +inf 5099 } 5100 5101 # Upgrade? 5102 5103 return $upgrade -> bsstr($x, @r) 5104 if defined($upgrade) && !$x -> isa(__PACKAGE__); 5105 5106 # Finite number 5107 5108 ($x->{sign} eq '-' ? '-' : '') . $LIB->_str($x->{_m}) 5109 . 'e' . $x->{_es} . $LIB->_str($x->{_e}); 5110} 5111 5112# Normalized notation, e.g., "12345.6789" is written as "1.23456789e+4". 5113 5114sub bnstr { 5115 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 5116 5117 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 5118 5119 # Inf and NaN 5120 5121 if ($x->{sign} ne '+' && $x->{sign} ne '-') { 5122 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN 5123 return 'inf'; # +inf 5124 } 5125 5126 # Upgrade? 5127 5128 return $upgrade -> bnstr($x, @r) 5129 if defined($upgrade) && !$x -> isa(__PACKAGE__); 5130 5131 # Finite number 5132 5133 my $str = $x->{sign} eq '-' ? '-' : ''; 5134 5135 # Get the mantissa and the length of the mantissa. 5136 5137 my $mant = $LIB->_str($x->{_m}); 5138 my $mantlen = CORE::length($mant); 5139 5140 if ($mantlen == 1) { 5141 5142 # Not decimal point when the mantissa has length one, i.e., return the 5143 # number 2 as the string "2", not "2.". 5144 5145 $str .= $mant . 'e' . $x->{_es} . $LIB->_str($x->{_e}); 5146 5147 } else { 5148 5149 # Compute new exponent where the original exponent is adjusted by the 5150 # length of the mantissa minus one (because the decimal point is after 5151 # one digit). 5152 5153 my ($eabs, $esgn) = $LIB -> _sadd($LIB -> _copy($x->{_e}), $x->{_es}, 5154 $LIB -> _new($mantlen - 1), "+"); 5155 substr $mant, 1, 0, "."; 5156 $str .= $mant . 'e' . $esgn . $LIB->_str($eabs); 5157 5158 } 5159 5160 return $str; 5161} 5162 5163# Engineering notation, e.g., "12345.6789" is written as "12.3456789e+3". 5164 5165sub bestr { 5166 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 5167 5168 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 5169 5170 # Inf and NaN 5171 5172 if ($x->{sign} ne '+' && $x->{sign} ne '-') { 5173 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN 5174 return 'inf'; # +inf 5175 } 5176 5177 # Upgrade? 5178 5179 return $upgrade -> bestr($x, @r) 5180 if defined($upgrade) && !$x -> isa(__PACKAGE__); 5181 5182 # Finite number 5183 5184 my $str = $x->{sign} eq '-' ? '-' : ''; 5185 5186 # Get the mantissa, the length of the mantissa, and adjust the exponent by 5187 # the length of the mantissa minus 1 (because the dot is after one digit). 5188 5189 my $mant = $LIB->_str($x->{_m}); 5190 my $mantlen = CORE::length($mant); 5191 my ($eabs, $esgn) = $LIB -> _sadd($LIB -> _copy($x->{_e}), $x->{_es}, 5192 $LIB -> _new($mantlen - 1), "+"); 5193 5194 my $dotpos = 1; 5195 my $mod = $LIB -> _mod($LIB -> _copy($eabs), $LIB -> _new("3")); 5196 unless ($LIB -> _is_zero($mod)) { 5197 if ($esgn eq '+') { 5198 $eabs = $LIB -> _sub($eabs, $mod); 5199 $dotpos += $LIB -> _num($mod); 5200 } else { 5201 my $delta = $LIB -> _sub($LIB -> _new("3"), $mod); 5202 $eabs = $LIB -> _add($eabs, $delta); 5203 $dotpos += $LIB -> _num($delta); 5204 } 5205 } 5206 5207 if ($dotpos < $mantlen) { 5208 substr $mant, $dotpos, 0, "."; 5209 } elsif ($dotpos > $mantlen) { 5210 $mant .= "0" x ($dotpos - $mantlen); 5211 } 5212 5213 $str .= $mant . 'e' . $esgn . $LIB->_str($eabs); 5214 5215 return $str; 5216} 5217 5218# Fractional notation, e.g., "123.4375" is written as "1975/16". 5219 5220sub bfstr { 5221 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_); 5222 5223 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 5224 5225 # Inf and NaN 5226 5227 if ($x->{sign} ne '+' && $x->{sign} ne '-') { 5228 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN 5229 return 'inf'; # +inf 5230 } 5231 5232 # Upgrade? 5233 5234 return $upgrade -> bfstr($x, @r) 5235 if defined($upgrade) && !$x -> isa(__PACKAGE__); 5236 5237 # Finite number 5238 5239 my $str = $x->{sign} eq '-' ? '-' : ''; 5240 5241 if ($x->{_es} eq '+') { 5242 $str .= $LIB -> _str($x->{_m}) . ("0" x $LIB -> _num($x->{_e})); 5243 } else { 5244 my @flt_parts = ($x->{sign}, $x->{_m}, $x->{_es}, $x->{_e}); 5245 my @rat_parts = $class -> _flt_lib_parts_to_rat_lib_parts(@flt_parts); 5246 $str = $LIB -> _str($rat_parts[1]) . "/" . $LIB -> _str($rat_parts[2]); 5247 $str = "-" . $str if $rat_parts[0] eq "-"; 5248 } 5249 5250 return $str; 5251} 5252 5253sub to_hex { 5254 # return number as hexadecimal string (only for integers defined) 5255 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_); 5256 5257 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 5258 5259 # Inf and NaN 5260 5261 if ($x->{sign} ne '+' && $x->{sign} ne '-') { 5262 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN 5263 return 'inf'; # +inf 5264 } 5265 5266 # Upgrade? 5267 5268 return $upgrade -> to_hex($x, @r) 5269 if defined($upgrade) && !$x -> isa(__PACKAGE__); 5270 5271 # Finite number 5272 5273 return '0' if $x->is_zero(); 5274 5275 return $nan if $x->{_es} ne '+'; # how to do 1e-1 in hex? 5276 5277 my $z = $LIB->_copy($x->{_m}); 5278 if (! $LIB->_is_zero($x->{_e})) { # > 0 5279 $z = $LIB->_lsft($z, $x->{_e}, 10); 5280 } 5281 my $str = $LIB->_to_hex($z); 5282 return $x->{sign} eq '-' ? "-$str" : $str; 5283} 5284 5285sub to_oct { 5286 # return number as octal digit string (only for integers defined) 5287 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_); 5288 5289 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 5290 5291 # Inf and NaN 5292 5293 if ($x->{sign} ne '+' && $x->{sign} ne '-') { 5294 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN 5295 return 'inf'; # +inf 5296 } 5297 5298 # Upgrade? 5299 5300 return $upgrade -> to_oct($x, @r) 5301 if defined($upgrade) && !$x -> isa(__PACKAGE__); 5302 5303 # Finite number 5304 5305 return '0' if $x->is_zero(); 5306 5307 return $nan if $x->{_es} ne '+'; # how to do 1e-1 in octal? 5308 5309 my $z = $LIB->_copy($x->{_m}); 5310 if (! $LIB->_is_zero($x->{_e})) { # > 0 5311 $z = $LIB->_lsft($z, $x->{_e}, 10); 5312 } 5313 my $str = $LIB->_to_oct($z); 5314 return $x->{sign} eq '-' ? "-$str" : $str; 5315} 5316 5317sub to_bin { 5318 # return number as binary digit string (only for integers defined) 5319 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_); 5320 5321 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 5322 5323 # Inf and NaN 5324 5325 if ($x->{sign} ne '+' && $x->{sign} ne '-') { 5326 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN 5327 return 'inf'; # +inf 5328 } 5329 5330 # Upgrade? 5331 5332 return $upgrade -> to_bin($x, @r) 5333 if defined($upgrade) && !$x -> isa(__PACKAGE__); 5334 5335 # Finite number 5336 5337 return '0' if $x->is_zero(); 5338 5339 return $nan if $x->{_es} ne '+'; # how to do 1e-1 in binary? 5340 5341 my $z = $LIB->_copy($x->{_m}); 5342 if (! $LIB->_is_zero($x->{_e})) { # > 0 5343 $z = $LIB->_lsft($z, $x->{_e}, 10); 5344 } 5345 my $str = $LIB->_to_bin($z); 5346 return $x->{sign} eq '-' ? "-$str" : $str; 5347} 5348 5349sub to_ieee754 { 5350 my ($class, $x, $format, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_); 5351 5352 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 5353 5354 my $enc; # significand encoding (applies only to decimal) 5355 my $k; # storage width in bits 5356 my $b; # base 5357 5358 if ($format =~ /^binary(\d+)\z/) { 5359 $k = $1; 5360 $b = 2; 5361 } elsif ($format =~ /^decimal(\d+)(dpd|bcd)?\z/) { 5362 $k = $1; 5363 $b = 10; 5364 $enc = $2 || 'dpd'; # default is dencely-packed decimals (DPD) 5365 } elsif ($format eq 'half') { 5366 $k = 16; 5367 $b = 2; 5368 } elsif ($format eq 'single') { 5369 $k = 32; 5370 $b = 2; 5371 } elsif ($format eq 'double') { 5372 $k = 64; 5373 $b = 2; 5374 } elsif ($format eq 'quadruple') { 5375 $k = 128; 5376 $b = 2; 5377 } elsif ($format eq 'octuple') { 5378 $k = 256; 5379 $b = 2; 5380 } elsif ($format eq 'sexdecuple') { 5381 $k = 512; 5382 $b = 2; 5383 } 5384 5385 if ($b == 2) { 5386 5387 # Get the parameters for this format. 5388 5389 my $p; # precision (in bits) 5390 my $t; # number of bits in significand 5391 my $w; # number of bits in exponent 5392 5393 if ($k == 16) { # binary16 (half-precision) 5394 $p = 11; 5395 $t = 10; 5396 $w = 5; 5397 } elsif ($k == 32) { # binary32 (single-precision) 5398 $p = 24; 5399 $t = 23; 5400 $w = 8; 5401 } elsif ($k == 64) { # binary64 (double-precision) 5402 $p = 53; 5403 $t = 52; 5404 $w = 11; 5405 } else { # binaryN (quadruple-precition and above) 5406 if ($k < 128 || $k != 32 * sprintf('%.0f', $k / 32)) { 5407 croak "Number of bits must be 16, 32, 64, or >= 128 and", 5408 " a multiple of 32"; 5409 } 5410 $p = $k - sprintf('%.0f', 4 * log($k) / log(2)) + 13; 5411 $t = $p - 1; 5412 $w = $k - $t - 1; 5413 } 5414 5415 # The maximum exponent, minimum exponent, and exponent bias. 5416 5417 my $emax = $class -> new(2) -> bpow($w - 1) -> bdec(); 5418 my $emin = 1 - $emax; 5419 my $bias = $emax; 5420 5421 # Get numerical sign, exponent, and mantissa/significand for bit 5422 # string. 5423 5424 my $sign = 0; 5425 my $expo; 5426 my $mant; 5427 5428 if ($x -> is_nan()) { # nan 5429 $sign = 1; 5430 $expo = $emax -> copy() -> binc(); 5431 $mant = $class -> new(2) -> bpow($t - 1); 5432 } elsif ($x -> is_inf()) { # inf 5433 $sign = 1 if $x -> is_neg(); 5434 $expo = $emax -> copy() -> binc(); 5435 $mant = $class -> bzero(); 5436 } elsif ($x -> is_zero()) { # zero 5437 $expo = $emin -> copy() -> bdec(); 5438 $mant = $class -> bzero(); 5439 } else { # normal and subnormal 5440 5441 $sign = 1 if $x -> is_neg(); 5442 5443 # Now we need to compute the mantissa and exponent in base $b. 5444 5445 my $binv = $class -> new("0.5"); 5446 my $b = $class -> new(2); 5447 my $one = $class -> bone(); 5448 5449 # We start off by initializing the exponent to zero and the 5450 # mantissa to the input value. Then we increase the mantissa and 5451 # decrease the exponent, or vice versa, until the mantissa is in 5452 # the desired range or we hit one of the limits for the exponent. 5453 5454 $mant = $x -> copy() -> babs(); 5455 5456 # We need to find the base 2 exponent. First make an estimate of 5457 # the base 2 exponent, before adjusting it below. We could skip 5458 # this estimation and go straight to the while-loops below, but the 5459 # loops are slow, especially when the final exponent is far from 5460 # zero and even more so if the number of digits is large. This 5461 # initial estimation speeds up the computation dramatically. 5462 # 5463 # log2($m * 10**$e) = log10($m + 10**$e) * log(10)/log(2) 5464 # = (log10($m) + $e) * log(10)/log(2) 5465 # = (log($m)/log(10) + $e) * log(10)/log(2) 5466 5467 my ($m, $e) = $x -> nparts(); 5468 my $ms = $m -> numify(); 5469 my $es = $e -> numify(); 5470 5471 my $expo_est = (log(abs($ms))/log(10) + $es) * log(10)/log(2); 5472 $expo_est = int($expo_est); 5473 5474 # Limit the exponent. 5475 5476 if ($expo_est > $emax) { 5477 $expo_est = $emax; 5478 } elsif ($expo_est < $emin) { 5479 $expo_est = $emin; 5480 } 5481 5482 # Don't multiply by a number raised to a negative exponent. This 5483 # will cause a division, whose result is truncated to some fixed 5484 # number of digits. Instead, multiply by the inverse number raised 5485 # to a positive exponent. 5486 5487 $expo = $class -> new($expo_est); 5488 if ($expo_est > 0) { 5489 $mant = $mant -> bmul($binv -> copy() -> bpow($expo)); 5490 } elsif ($expo_est < 0) { 5491 my $expo_abs = $expo -> copy() -> bneg(); 5492 $mant = $mant -> bmul($b -> copy() -> bpow($expo_abs)); 5493 } 5494 5495 # Final adjustment of the estimate above. 5496 5497 while ($mant >= $b && $expo <= $emax) { 5498 $mant = $mant -> bmul($binv); 5499 $expo = $expo -> binc(); 5500 } 5501 5502 while ($mant < $one && $expo >= $emin) { 5503 $mant = $mant -> bmul($b); 5504 $expo = $expo -> bdec(); 5505 } 5506 5507 # This is when the magnitude is larger than what can be represented 5508 # in this format. Encode as infinity. 5509 5510 if ($expo > $emax) { 5511 $mant = $class -> bzero(); 5512 $expo = $emax -> copy() -> binc(); 5513 } 5514 5515 # This is when the magnitude is so small that the number is encoded 5516 # as a subnormal number. 5517 # 5518 # If the magnitude is smaller than that of the smallest subnormal 5519 # number, and rounded downwards, it is encoded as zero. This works 5520 # transparently and does not need to be treated as a special case. 5521 # 5522 # If the number is between the largest subnormal number and the 5523 # smallest normal number, and the value is rounded upwards, the 5524 # value must be encoded as a normal number. This must be treated as 5525 # a special case. 5526 5527 elsif ($expo < $emin) { 5528 5529 # Scale up the mantissa (significand), and round to integer. 5530 5531 my $const = $class -> new($b) -> bpow($t - 1); 5532 $mant = $mant -> bmul($const); 5533 $mant = $mant -> bfround(0); 5534 5535 # If the mantissa overflowed, encode as the smallest normal 5536 # number. 5537 5538 if ($mant == $const -> bmul($b)) { 5539 $mant = $mant -> bzero(); 5540 $expo = $expo -> binc(); 5541 } 5542 } 5543 5544 # This is when the magnitude is within the range of what can be 5545 # encoded as a normal number. 5546 5547 else { 5548 5549 # Remove implicit leading bit, scale up the mantissa 5550 # (significand) to an integer, and round. 5551 5552 $mant = $mant -> bdec(); 5553 my $const = $class -> new($b) -> bpow($t); 5554 $mant = $mant -> bmul($const) -> bfround(0); 5555 5556 # If the mantissa overflowed, encode as the next larger value. 5557 # This works correctly also when the next larger value is 5558 # infinity. 5559 5560 if ($mant == $const) { 5561 $mant = $mant -> bzero(); 5562 $expo = $expo -> binc(); 5563 } 5564 } 5565 } 5566 5567 $expo = $expo -> badd($bias); # add bias 5568 5569 my $signbit = "$sign"; 5570 5571 my $mantbits = $mant -> to_bin(); 5572 $mantbits = ("0" x ($t - CORE::length($mantbits))) . $mantbits; 5573 5574 my $expobits = $expo -> to_bin(); 5575 $expobits = ("0" x ($w - CORE::length($expobits))) . $expobits; 5576 5577 my $bin = $signbit . $expobits . $mantbits; 5578 return pack "B*", $bin; 5579 } 5580 5581 croak("The format '$format' is not yet supported."); 5582} 5583 5584sub as_hex { 5585 # return number as hexadecimal string (only for integers defined) 5586 5587 my (undef, $x, @r) = ref($_[0]) ? (undef, @_) : objectify(1, @_); 5588 5589 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 5590 5591 return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, nan etc 5592 return '0x0' if $x->is_zero(); 5593 5594 return $nan if $x->{_es} ne '+'; # how to do 1e-1 in hex? 5595 5596 my $z = $LIB->_copy($x->{_m}); 5597 if (! $LIB->_is_zero($x->{_e})) { # > 0 5598 $z = $LIB->_lsft($z, $x->{_e}, 10); 5599 } 5600 my $str = $LIB->_as_hex($z); 5601 return $x->{sign} eq '-' ? "-$str" : $str; 5602} 5603 5604sub as_oct { 5605 # return number as octal digit string (only for integers defined) 5606 5607 my (undef, $x, @r) = ref($_[0]) ? (undef, @_) : objectify(1, @_); 5608 5609 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 5610 5611 return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, nan etc 5612 return '00' if $x->is_zero(); 5613 5614 return $nan if $x->{_es} ne '+'; # how to do 1e-1 in octal? 5615 5616 my $z = $LIB->_copy($x->{_m}); 5617 if (! $LIB->_is_zero($x->{_e})) { # > 0 5618 $z = $LIB->_lsft($z, $x->{_e}, 10); 5619 } 5620 my $str = $LIB->_as_oct($z); 5621 return $x->{sign} eq '-' ? "-$str" : $str; 5622} 5623 5624sub as_bin { 5625 # return number as binary digit string (only for integers defined) 5626 5627 my (undef, $x, @r) = ref($_[0]) ? (undef, @_) : objectify(1, @_); 5628 5629 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 5630 5631 return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, nan etc 5632 return '0b0' if $x->is_zero(); 5633 5634 return $nan if $x->{_es} ne '+'; # how to do 1e-1 in binary? 5635 5636 my $z = $LIB->_copy($x->{_m}); 5637 if (! $LIB->_is_zero($x->{_e})) { # > 0 5638 $z = $LIB->_lsft($z, $x->{_e}, 10); 5639 } 5640 my $str = $LIB->_as_bin($z); 5641 return $x->{sign} eq '-' ? "-$str" : $str; 5642} 5643 5644sub numify { 5645 # Make a Perl scalar number from a Math::BigFloat object. 5646 5647 my (undef, $x, @r) = ref($_[0]) ? (undef, @_) : objectify(1, @_); 5648 5649 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r; 5650 5651 if ($x -> is_nan()) { 5652 require Math::Complex; 5653 my $inf = $Math::Complex::Inf; 5654 return $inf - $inf; 5655 } 5656 5657 if ($x -> is_inf()) { 5658 require Math::Complex; 5659 my $inf = $Math::Complex::Inf; 5660 return $x -> is_negative() ? -$inf : $inf; 5661 } 5662 5663 # Create a string and let Perl's atoi()/atof() handle the rest. 5664 5665 return 0 + $x -> bnstr(); 5666} 5667 5668############################################################################### 5669# Private methods and functions. 5670############################################################################### 5671 5672sub import { 5673 my $class = shift; 5674 $IMPORT++; # remember we did import() 5675 my @a; # unrecognized arguments 5676 5677 my @import = (); 5678 5679 while (@_) { 5680 my $param = shift; 5681 5682 # Enable overloading of constants. 5683 5684 if ($param eq ':constant') { 5685 overload::constant 5686 5687 integer => sub { 5688 $class -> new(shift); 5689 }, 5690 5691 float => sub { 5692 $class -> new(shift); 5693 }, 5694 5695 binary => sub { 5696 # E.g., a literal 0377 shall result in an object whose value 5697 # is decimal 255, but new("0377") returns decimal 377. 5698 return $class -> from_oct($_[0]) if $_[0] =~ /^0_*[0-7]/; 5699 $class -> new(shift); 5700 }; 5701 next; 5702 } 5703 5704 # Upgrading. 5705 5706 if ($param eq 'upgrade') { 5707 $class -> upgrade(shift); 5708 next; 5709 } 5710 5711 # Downgrading. 5712 5713 if ($param eq 'downgrade') { 5714 $class -> downgrade(shift); 5715 next; 5716 } 5717 5718 # Accuracy. 5719 5720 if ($param eq 'accuracy') { 5721 $class -> accuracy(shift); 5722 next; 5723 } 5724 5725 # Precision. 5726 5727 if ($param eq 'precision') { 5728 $class -> precision(shift); 5729 next; 5730 } 5731 5732 # Rounding mode. 5733 5734 if ($param eq 'round_mode') { 5735 $class -> round_mode(shift); 5736 next; 5737 } 5738 5739 # Fall-back accuracy. 5740 5741 if ($param eq 'div_scale') { 5742 $class -> div_scale(shift); 5743 next; 5744 } 5745 5746 # Backend library. 5747 5748 if ($param =~ /^(lib|try|only)\z/) { 5749 push @import, $param; 5750 push @import, shift() if @_; 5751 next; 5752 } 5753 5754 if ($param eq 'with') { 5755 # alternative class for our private parts() 5756 # XXX: no longer supported 5757 # $LIB = shift() || 'Calc'; 5758 # carp "'with' is no longer supported, use 'lib', 'try', or 'only'"; 5759 shift; 5760 next; 5761 } 5762 5763 # Unrecognized parameter. 5764 5765 push @a, $param; 5766 } 5767 5768 Math::BigInt -> import(@import); 5769 5770 # find out which library was actually loaded 5771 $LIB = Math::BigInt -> config('lib'); 5772 5773 $class -> SUPER::import(@a); # for subclasses 5774 $class -> export_to_level(1, $class, @a) if @a; # need this, too 5775} 5776 5777sub _len_to_steps { 5778 # Given D (digits in decimal), compute N so that N! (N factorial) is 5779 # at least D digits long. D should be at least 50. 5780 my $d = shift; 5781 5782 # two constants for the Ramanujan estimate of ln(N!) 5783 my $lg2 = log(2 * 3.14159265) / 2; 5784 my $lg10 = log(10); 5785 5786 # D = 50 => N => 42, so L = 40 and R = 50 5787 my $l = 40; 5788 my $r = $d; 5789 5790 # Otherwise this does not work under -Mbignum and we do not yet have "no 5791 # bignum;" :( 5792 $l = $l->numify if ref($l); 5793 $r = $r->numify if ref($r); 5794 $lg2 = $lg2->numify if ref($lg2); 5795 $lg10 = $lg10->numify if ref($lg10); 5796 5797 # binary search for the right value (could this be written as the reverse of 5798 # lg(n!)?) 5799 while ($r - $l > 1) { 5800 my $n = int(($r - $l) / 2) + $l; 5801 my $ramanujan 5802 = int(($n * log($n) - $n + log($n * (1 + 4*$n*(1+2*$n))) / 6 + $lg2) 5803 / $lg10); 5804 $ramanujan > $d ? $r = $n : $l = $n; 5805 } 5806 $l; 5807} 5808 5809sub _log { 5810 # internal log function to calculate ln() based on Taylor series. 5811 # Modifies $x in place. 5812 my ($x, $scale) = @_; 5813 my $class = ref $x; 5814 5815 # in case of $x == 1, result is 0 5816 return $x -> bzero() if $x -> is_one(); 5817 5818 # XXX TODO: rewrite this in a similar manner to bexp() 5819 5820 # http://www.efunda.com/math/taylor_series/logarithmic.cfm?search_string=log 5821 5822 # u = x-1, v = x+1 5823 # _ _ 5824 # Taylor: | u 1 u^3 1 u^5 | 5825 # ln (x) = 2 | --- + - * --- + - * --- + ... | x > 0 5826 # |_ v 3 v^3 5 v^5 _| 5827 5828 # This takes much more steps to calculate the result and is thus not used 5829 # u = x-1 5830 # _ _ 5831 # Taylor: | u 1 u^2 1 u^3 | 5832 # ln (x) = 2 | --- + - * --- + - * --- + ... | x > 1/2 5833 # |_ x 2 x^2 3 x^3 _| 5834 5835 # scale used in intermediate computations 5836 my $scaleup = $scale + 4; 5837 5838 my ($v, $u, $numer, $denom, $factor, $f); 5839 5840 $v = $x -> copy(); 5841 $v = $v -> binc(); # v = x+1 5842 $x = $x -> bdec(); 5843 $u = $x -> copy(); # u = x-1; x = x-1 5844 5845 $x = $x -> bdiv($v, $scaleup); # first term: u/v 5846 5847 $numer = $u -> copy(); # numerator 5848 $denom = $v -> copy(); # denominator 5849 5850 $u = $u -> bmul($u); # u^2 5851 $v = $v -> bmul($v); # v^2 5852 5853 $numer = $numer -> bmul($u); # u^3 5854 $denom = $denom -> bmul($v); # v^3 5855 5856 $factor = $class -> new(3); 5857 $f = $class -> new(2); 5858 5859 while (1) { 5860 my $next = $numer -> copy() -> bround($scaleup) 5861 -> bdiv($denom -> copy() -> bmul($factor) -> bround($scaleup), $scaleup); 5862 5863 $next->{accuracy} = undef; 5864 $next->{precision} = undef; 5865 my $x_prev = $x -> copy(); 5866 $x = $x -> badd($next); 5867 5868 last if $x -> bacmp($x_prev) == 0; 5869 5870 # calculate things for the next term 5871 $numer = $numer -> bmul($u); 5872 $denom = $denom -> bmul($v); 5873 $factor = $factor -> badd($f); 5874 } 5875 5876 $x = $x -> bmul($f); # $x *= 2 5877 $x = $x -> bround($scale); 5878} 5879 5880sub _log_10 { 5881 # Internal log function based on reducing input to the range of 0.1 .. 9.99 5882 # and then "correcting" the result to the proper one. Modifies $x in place. 5883 my ($x, $scale) = @_; 5884 my $class = ref $x; 5885 5886 # Taking blog() from numbers greater than 10 takes a *very long* time, so we 5887 # break the computation down into parts based on the observation that: 5888 # blog(X*Y) = blog(X) + blog(Y) 5889 # We set Y here to multiples of 10 so that $x becomes below 1 - the smaller 5890 # $x is the faster it gets. Since 2*$x takes about 10 times as 5891 # long, we make it faster by about a factor of 100 by dividing $x by 10. 5892 5893 # The same observation is valid for numbers smaller than 0.1, e.g. computing 5894 # log(1) is fastest, and the further away we get from 1, the longer it 5895 # takes. So we also 'break' this down by multiplying $x with 10 and subtract 5896 # the log(10) afterwards to get the correct result. 5897 5898 # To get $x even closer to 1, we also divide by 2 and then use log(2) to 5899 # correct for this. For instance if $x is 2.4, we use the formula: 5900 # blog(2.4 * 2) == blog(1.2) + blog(2) 5901 # and thus calculate only blog(1.2) and blog(2), which is faster in total 5902 # than calculating blog(2.4). 5903 5904 # In addition, the values for blog(2) and blog(10) are cached. 5905 5906 # Calculate the number of digits before the dot, i.e., 1 + floor(log10(x)): 5907 # x = 123 => dbd = 3 5908 # x = 1.23 => dbd = 1 5909 # x = 0.0123 => dbd = -1 5910 # x = 0.000123 => dbd = -3 5911 # etc. 5912 5913 my $dbd = $LIB->_num($x->{_e}); 5914 $dbd = -$dbd if $x->{_es} eq '-'; 5915 $dbd += $LIB->_len($x->{_m}); 5916 5917 # more than one digit (e.g. at least 10), but *not* exactly 10 to avoid 5918 # infinite recursion 5919 5920 my $calc = 1; # do some calculation? 5921 5922 # No upgrading or downgrading in the intermediate computations. 5923 5924 my $upg = $class -> upgrade(); 5925 my $dng = $class -> downgrade(); 5926 $class -> upgrade(undef); 5927 $class -> downgrade(undef); 5928 5929 # disable the shortcut for 10, since we need log(10) and this would recurse 5930 # infinitely deep 5931 if ($x->{_es} eq '+' && # $x == 10 5932 ($LIB->_is_one($x->{_e}) && 5933 $LIB->_is_one($x->{_m}))) 5934 { 5935 $dbd = 0; # disable shortcut 5936 # we can use the cached value in these cases 5937 if ($scale <= $LOG_10_A) { 5938 $x = $x->bzero(); 5939 $x = $x->badd($LOG_10); # modify $x in place 5940 $calc = 0; # no need to calc, but round 5941 } 5942 # if we can't use the shortcut, we continue normally 5943 } else { 5944 # disable the shortcut for 2, since we maybe have it cached 5945 if (($LIB->_is_zero($x->{_e}) && # $x == 2 5946 $LIB->_is_two($x->{_m}))) 5947 { 5948 $dbd = 0; # disable shortcut 5949 # we can use the cached value in these cases 5950 if ($scale <= $LOG_2_A) { 5951 $x = $x->bzero(); 5952 $x = $x->badd($LOG_2); # modify $x in place 5953 $calc = 0; # no need to calc, but round 5954 } 5955 # if we can't use the shortcut, we continue normally 5956 } 5957 } 5958 5959 # if $x = 0.1, we know the result must be 0-log(10) 5960 if ($calc != 0 && 5961 ($x->{_es} eq '-' && # $x == 0.1 5962 ($LIB->_is_one($x->{_e}) && 5963 $LIB->_is_one($x->{_m})))) 5964 { 5965 $dbd = 0; # disable shortcut 5966 # we can use the cached value in these cases 5967 if ($scale <= $LOG_10_A) { 5968 $x = $x->bzero(); 5969 $x = $x->bsub($LOG_10); 5970 $calc = 0; # no need to calc, but round 5971 } 5972 } 5973 5974 return $x if $calc == 0; # already have the result 5975 5976 # default: these correction factors are undef and thus not used 5977 my $l_10; # value of ln(10) to A of $scale 5978 my $l_2; # value of ln(2) to A of $scale 5979 5980 my $two = $class->new(2); 5981 5982 # $x == 2 => 1, $x == 13 => 2, $x == 0.1 => 0, $x == 0.01 => -1 5983 # so don't do this shortcut for 1 or 0 5984 if (($dbd > 1) || ($dbd < 0)) { 5985 # convert our cached value to an object if not already (avoid doing this 5986 # at import() time, since not everybody needs this) 5987 $LOG_10 = $class->new($LOG_10, undef, undef) unless ref $LOG_10; 5988 5989 # got more than one digit before the dot, or more than one zero after 5990 # the dot, so do: 5991 # log(123) == log(1.23) + log(10) * 2 5992 # log(0.0123) == log(1.23) - log(10) * 2 5993 5994 if ($scale <= $LOG_10_A) { 5995 # use cached value 5996 $l_10 = $LOG_10->copy(); # copy for mul 5997 } else { 5998 # else: slower, compute and cache result 5999 6000 # shorten the time to calculate log(10) based on the following: 6001 # log(1.25 * 8) = log(1.25) + log(8) 6002 # = log(1.25) + log(2) + log(2) + log(2) 6003 6004 # first get $l_2 (and possible compute and cache log(2)) 6005 $LOG_2 = $class->new($LOG_2, undef, undef) unless ref $LOG_2; 6006 if ($scale <= $LOG_2_A) { 6007 # use cached value 6008 $l_2 = $LOG_2->copy(); # copy() for the mul below 6009 } else { 6010 # else: slower, compute and cache result 6011 $l_2 = $two->copy(); 6012 $l_2 = $l_2->_log($scale); # scale+4, actually 6013 $LOG_2 = $l_2->copy(); # cache the result for later 6014 # the copy() is for mul below 6015 $LOG_2_A = $scale; 6016 } 6017 6018 # now calculate log(1.25): 6019 $l_10 = $class->new('1.25'); 6020 $l_10 = $l_10->_log($scale); # scale+4, actually 6021 6022 # log(1.25) + log(2) + log(2) + log(2): 6023 $l_10 = $l_10->badd($l_2); 6024 $l_10 = $l_10->badd($l_2); 6025 $l_10 = $l_10->badd($l_2); 6026 $LOG_10 = $l_10->copy(); # cache the result for later 6027 # the copy() is for mul below 6028 $LOG_10_A = $scale; 6029 } 6030 $dbd-- if ($dbd > 1); # 20 => dbd=2, so make it dbd=1 6031 $l_10 = $l_10->bmul($class->new($dbd)); # log(10) * (digits_before_dot-1) 6032 my $dbd_sign = '+'; 6033 if ($dbd < 0) { 6034 $dbd = -$dbd; 6035 $dbd_sign = '-'; 6036 } 6037 ($x->{_e}, $x->{_es}) = 6038 $LIB -> _ssub($x->{_e}, $x->{_es}, $LIB->_new($dbd), $dbd_sign); 6039 } 6040 6041 # Now: 0.1 <= $x < 10 (and possible correction in l_10) 6042 6043 ### Since $x in the range 0.5 .. 1.5 is MUCH faster, we do a repeated div 6044 ### or mul by 2 (maximum times 3, since x < 10 and x > 0.1) 6045 6046 $HALF = $class->new($HALF) unless ref($HALF); 6047 6048 my $twos = 0; # default: none (0 times) 6049 while ($x->bacmp($HALF) <= 0) { # X <= 0.5 6050 $twos--; 6051 $x = $x->bmul($two); 6052 } 6053 while ($x->bacmp($two) >= 0) { # X >= 2 6054 $twos++; 6055 $x = $x->bdiv($two, $scale+4); # keep all digits 6056 } 6057 $x = $x->bround($scale+4); 6058 # $twos > 0 => did mul 2, < 0 => did div 2 (but we never did both) 6059 # So calculate correction factor based on ln(2): 6060 if ($twos != 0) { 6061 $LOG_2 = $class->new($LOG_2, undef, undef) unless ref $LOG_2; 6062 if ($scale <= $LOG_2_A) { 6063 # use cached value 6064 $l_2 = $LOG_2->copy(); # copy() for the mul below 6065 } else { 6066 # else: slower, compute and cache result 6067 $l_2 = $two->copy(); 6068 $l_2 = $l_2->_log($scale); # scale+4, actually 6069 $LOG_2 = $l_2->copy(); # cache the result for later 6070 # the copy() is for mul below 6071 $LOG_2_A = $scale; 6072 } 6073 $l_2 = $l_2->bmul($twos); # * -2 => subtract, * 2 => add 6074 } else { 6075 undef $l_2; 6076 } 6077 6078 $x = $x->_log($scale); # need to do the "normal" way 6079 $x = $x->badd($l_10) if defined $l_10; # correct it by ln(10) 6080 $x = $x->badd($l_2) if defined $l_2; # and maybe by ln(2) 6081 6082 # Restore globals 6083 6084 $class -> upgrade($upg); 6085 $class -> downgrade($dng); 6086 6087 # all done, $x contains now the result 6088 $x; 6089} 6090 6091sub _pow { 6092 # Calculate a power where $y is a non-integer, like 2 ** 0.3 6093 my ($x, $y, @r) = @_; 6094 my $class = ref($x); 6095 6096 # if $y == 0.5, it is sqrt($x) 6097 $HALF = $class->new($HALF) unless ref($HALF); 6098 return $x->bsqrt(@r, $y) if $y->bcmp($HALF) == 0; 6099 6100 # Using: 6101 # a ** x == e ** (x * ln a) 6102 6103 # u = y * ln x 6104 # _ _ 6105 # Taylor: | u u^2 u^3 | 6106 # x ** y = 1 + | --- + --- + ----- + ... | 6107 # |_ 1 1*2 1*2*3 _| 6108 6109 # we need to limit the accuracy to protect against overflow 6110 my $fallback = 0; 6111 my ($scale, @params); 6112 ($x, @params) = $x->_find_round_parameters(@r); 6113 6114 return $x if $x->is_nan(); # error in _find_round_parameters? 6115 6116 # no rounding at all, so must use fallback 6117 if (scalar @params == 0) { 6118 # simulate old behaviour 6119 $params[0] = $class->div_scale(); # and round to it as accuracy 6120 $params[1] = undef; # disable P 6121 $scale = $params[0]+4; # at least four more for proper round 6122 $params[2] = $r[2]; # round mode by caller or undef 6123 $fallback = 1; # to clear a/p afterwards 6124 } else { 6125 # the 4 below is empirical, and there might be cases where it is not 6126 # enough... 6127 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 6128 } 6129 6130 # When user set globals, they would interfere with our calculation, so 6131 # disable them and later re-enable them. 6132 6133 my $ab = $class -> accuracy(); 6134 my $pb = $class -> precision(); 6135 $class -> accuracy(undef); 6136 $class -> precision(undef); 6137 6138 # Disabling upgrading and downgrading is no longer necessary to avoid an 6139 # infinite recursion, but it avoids unnecessary upgrading and downgrading in 6140 # the intermediate computations. 6141 6142 my $upg = $class -> upgrade(); 6143 my $dng = $class -> downgrade(); 6144 $class -> upgrade(undef); 6145 $class -> downgrade(undef); 6146 6147 # We also need to disable any set A or P on $x (_find_round_parameters took 6148 # them already into account), since these would interfere, too. 6149 6150 $x->{accuracy} = undef; 6151 $x->{precision} = undef; 6152 6153 my ($limit, $v, $u, $below, $factor, $next, $over); 6154 6155 $u = $x->copy()->blog(undef, $scale)->bmul($y); 6156 my $do_invert = ($u->{sign} eq '-'); 6157 $u = $u->bneg() if $do_invert; 6158 $v = $class->bone(); # 1 6159 $factor = $class->new(2); # 2 6160 $x = $x->bone(); # first term: 1 6161 6162 $below = $v->copy(); 6163 $over = $u->copy(); 6164 6165 $limit = $class->new("1E-". ($scale-1)); 6166 while (3 < 5) { 6167 # we calculate the next term, and add it to the last 6168 # when the next term is below our limit, it won't affect the outcome 6169 # anymore, so we stop: 6170 $next = $over->copy()->bdiv($below, $scale); 6171 last if $next->bacmp($limit) <= 0; 6172 $x = $x->badd($next); 6173 # calculate things for the next term 6174 $over *= $u; 6175 $below *= $factor; 6176 $factor = $factor->binc(); 6177 6178 last if $x->{sign} !~ /^[-+]$/; 6179 } 6180 6181 if ($do_invert) { 6182 my $x_copy = $x->copy(); 6183 $x = $x->bone->bdiv($x_copy, $scale); 6184 } 6185 6186 # shortcut to not run through _find_round_parameters again 6187 if (defined $params[0]) { 6188 $x = $x->bround($params[0], $params[2]); # then round accordingly 6189 } else { 6190 $x = $x->bfround($params[1], $params[2]); # then round accordingly 6191 } 6192 if ($fallback) { 6193 # clear a/p after round, since user did not request it 6194 $x->{accuracy} = undef; 6195 $x->{precision} = undef; 6196 } 6197 6198 # Restore globals. We need to do it like this, because setting one 6199 # undefines the other. 6200 6201 if (defined $ab) { 6202 $class -> accuracy($ab); 6203 } else { 6204 $class -> precision($pb); 6205 } 6206 6207 $class -> upgrade($upg); 6208 $class -> downgrade($dng); 6209 6210 $x; 6211} 6212 6213# These functions are only provided for backwards compabibility so that old 6214# version of Math::BigRat etc. don't complain about missing them. 6215 6216sub _e_add { 6217 my ($x, $y, $xs, $ys) = @_; 6218 return $LIB -> _sadd($x, $xs, $y, $ys); 6219} 6220 6221sub _e_sub { 6222 my ($x, $y, $xs, $ys) = @_; 6223 return $LIB -> _ssub($x, $xs, $y, $ys); 6224} 6225 62261; 6227 6228__END__ 6229 6230=pod 6231 6232=head1 NAME 6233 6234Math::BigFloat - arbitrary size floating point math package 6235 6236=head1 SYNOPSIS 6237 6238 use Math::BigFloat; 6239 6240 # Configuration methods (may be used as class methods and instance methods) 6241 6242 Math::BigFloat->accuracy(); # get class accuracy 6243 Math::BigFloat->accuracy($n); # set class accuracy 6244 Math::BigFloat->precision(); # get class precision 6245 Math::BigFloat->precision($n); # set class precision 6246 Math::BigFloat->round_mode(); # get class rounding mode 6247 Math::BigFloat->round_mode($m); # set global round mode, must be one of 6248 # 'even', 'odd', '+inf', '-inf', 'zero', 6249 # 'trunc', or 'common' 6250 Math::BigFloat->config("lib"); # name of backend math library 6251 6252 # Constructor methods (when the class methods below are used as instance 6253 # methods, the value is assigned the invocand) 6254 6255 $x = Math::BigFloat->new($str); # defaults to 0 6256 $x = Math::BigFloat->new('0x123'); # from hexadecimal 6257 $x = Math::BigFloat->new('0o377'); # from octal 6258 $x = Math::BigFloat->new('0b101'); # from binary 6259 $x = Math::BigFloat->from_hex('0xc.afep+3'); # from hex 6260 $x = Math::BigFloat->from_hex('cafe'); # ditto 6261 $x = Math::BigFloat->from_oct('1.3267p-4'); # from octal 6262 $x = Math::BigFloat->from_oct('01.3267p-4'); # ditto 6263 $x = Math::BigFloat->from_oct('0o1.3267p-4'); # ditto 6264 $x = Math::BigFloat->from_oct('0377'); # ditto 6265 $x = Math::BigFloat->from_bin('0b1.1001p-4'); # from binary 6266 $x = Math::BigFloat->from_bin('0101'); # ditto 6267 $x = Math::BigFloat->from_ieee754($b, "binary64"); # from IEEE-754 bytes 6268 $x = Math::BigFloat->bzero(); # create a +0 6269 $x = Math::BigFloat->bone(); # create a +1 6270 $x = Math::BigFloat->bone('-'); # create a -1 6271 $x = Math::BigFloat->binf(); # create a +inf 6272 $x = Math::BigFloat->binf('-'); # create a -inf 6273 $x = Math::BigFloat->bnan(); # create a Not-A-Number 6274 $x = Math::BigFloat->bpi(); # returns pi 6275 6276 $y = $x->copy(); # make a copy (unlike $y = $x) 6277 $y = $x->as_int(); # return as BigInt 6278 $y = $x->as_float(); # return as a Math::BigFloat 6279 $y = $x->as_rat(); # return as a Math::BigRat 6280 6281 # Boolean methods (these don't modify the invocand) 6282 6283 $x->is_zero(); # if $x is 0 6284 $x->is_one(); # if $x is +1 6285 $x->is_one("+"); # ditto 6286 $x->is_one("-"); # if $x is -1 6287 $x->is_inf(); # if $x is +inf or -inf 6288 $x->is_inf("+"); # if $x is +inf 6289 $x->is_inf("-"); # if $x is -inf 6290 $x->is_nan(); # if $x is NaN 6291 6292 $x->is_positive(); # if $x > 0 6293 $x->is_pos(); # ditto 6294 $x->is_negative(); # if $x < 0 6295 $x->is_neg(); # ditto 6296 6297 $x->is_odd(); # if $x is odd 6298 $x->is_even(); # if $x is even 6299 $x->is_int(); # if $x is an integer 6300 6301 # Comparison methods 6302 6303 $x->bcmp($y); # compare numbers (undef, < 0, == 0, > 0) 6304 $x->bacmp($y); # compare absolutely (undef, < 0, == 0, > 0) 6305 $x->beq($y); # true if and only if $x == $y 6306 $x->bne($y); # true if and only if $x != $y 6307 $x->blt($y); # true if and only if $x < $y 6308 $x->ble($y); # true if and only if $x <= $y 6309 $x->bgt($y); # true if and only if $x > $y 6310 $x->bge($y); # true if and only if $x >= $y 6311 6312 # Arithmetic methods 6313 6314 $x->bneg(); # negation 6315 $x->babs(); # absolute value 6316 $x->bsgn(); # sign function (-1, 0, 1, or NaN) 6317 $x->bnorm(); # normalize (no-op) 6318 $x->binc(); # increment $x by 1 6319 $x->bdec(); # decrement $x by 1 6320 $x->badd($y); # addition (add $y to $x) 6321 $x->bsub($y); # subtraction (subtract $y from $x) 6322 $x->bmul($y); # multiplication (multiply $x by $y) 6323 $x->bmuladd($y,$z); # $x = $x * $y + $z 6324 $x->bdiv($y); # division (floored), set $x to quotient 6325 # return (quo,rem) or quo if scalar 6326 $x->btdiv($y); # division (truncated), set $x to quotient 6327 # return (quo,rem) or quo if scalar 6328 $x->bmod($y); # modulus (x % y) 6329 $x->btmod($y); # modulus (truncated) 6330 $x->bmodinv($mod); # modular multiplicative inverse 6331 $x->bmodpow($y,$mod); # modular exponentiation (($x ** $y) % $mod) 6332 $x->bpow($y); # power of arguments (x ** y) 6333 $x->blog(); # logarithm of $x to base e (Euler's number) 6334 $x->blog($base); # logarithm of $x to base $base (e.g., base 2) 6335 $x->bexp(); # calculate e ** $x where e is Euler's number 6336 $x->bnok($y); # x over y (binomial coefficient n over k) 6337 $x->bsin(); # sine 6338 $x->bcos(); # cosine 6339 $x->batan(); # inverse tangent 6340 $x->batan2($y); # two-argument inverse tangent 6341 $x->bsqrt(); # calculate square root 6342 $x->broot($y); # $y'th root of $x (e.g. $y == 3 => cubic root) 6343 $x->bfac(); # factorial of $x (1*2*3*4*..$x) 6344 6345 $x->blsft($n); # left shift $n places in base 2 6346 $x->blsft($n,$b); # left shift $n places in base $b 6347 # returns (quo,rem) or quo (scalar context) 6348 $x->brsft($n); # right shift $n places in base 2 6349 $x->brsft($n,$b); # right shift $n places in base $b 6350 # returns (quo,rem) or quo (scalar context) 6351 6352 # Bitwise methods 6353 6354 $x->bblsft($y); # bitwise left shift 6355 $x->bbrsft($y); # bitwise right shift 6356 $x->band($y); # bitwise and 6357 $x->bior($y); # bitwise inclusive or 6358 $x->bxor($y); # bitwise exclusive or 6359 $x->bnot(); # bitwise not (two's complement) 6360 6361 # Rounding methods 6362 $x->round($A,$P,$mode); # round to accuracy or precision using 6363 # rounding mode $mode 6364 $x->bround($n); # accuracy: preserve $n digits 6365 $x->bfround($n); # $n > 0: round to $nth digit left of dec. point 6366 # $n < 0: round to $nth digit right of dec. point 6367 $x->bfloor(); # round towards minus infinity 6368 $x->bceil(); # round towards plus infinity 6369 $x->bint(); # round towards zero 6370 6371 # Other mathematical methods 6372 6373 $x->bgcd($y); # greatest common divisor 6374 $x->blcm($y); # least common multiple 6375 6376 # Object property methods (do not modify the invocand) 6377 6378 $x->sign(); # the sign, either +, - or NaN 6379 $x->digit($n); # the nth digit, counting from the right 6380 $x->digit(-$n); # the nth digit, counting from the left 6381 $x->length(); # return number of digits in number 6382 ($xl,$f) = $x->length(); # length of number and length of fraction 6383 # part, latter is always 0 digits long 6384 # for Math::BigInt objects 6385 $x->mantissa(); # return (signed) mantissa as BigInt 6386 $x->exponent(); # return exponent as BigInt 6387 $x->parts(); # return (mantissa,exponent) as BigInt 6388 $x->sparts(); # mantissa and exponent (as integers) 6389 $x->nparts(); # mantissa and exponent (normalised) 6390 $x->eparts(); # mantissa and exponent (engineering notation) 6391 $x->dparts(); # integer and fraction part 6392 $x->fparts(); # numerator and denominator 6393 $x->numerator(); # numerator 6394 $x->denominator(); # denominator 6395 6396 # Conversion methods (do not modify the invocand) 6397 6398 $x->bstr(); # decimal notation, possibly zero padded 6399 $x->bsstr(); # string in scientific notation with integers 6400 $x->bnstr(); # string in normalized notation 6401 $x->bestr(); # string in engineering notation 6402 $x->bdstr(); # string in decimal notation 6403 $x->bfstr(); # string in fractional notation 6404 6405 $x->as_hex(); # as signed hexadecimal string with prefixed 0x 6406 $x->as_bin(); # as signed binary string with prefixed 0b 6407 $x->as_oct(); # as signed octal string with prefixed 0 6408 $x->to_ieee754($format); # to bytes encoded according to IEEE 754-2008 6409 6410 # Other conversion methods 6411 6412 $x->numify(); # return as scalar (might overflow or underflow) 6413 6414=head1 DESCRIPTION 6415 6416Math::BigFloat provides support for arbitrary precision floating point. 6417Overloading is also provided for Perl operators. 6418 6419All operators (including basic math operations) are overloaded if you 6420declare your big floating point numbers as 6421 6422 $x = Math::BigFloat -> new('12_3.456_789_123_456_789E-2'); 6423 6424Operations with overloaded operators preserve the arguments, which is 6425exactly what you expect. 6426 6427=head2 Input 6428 6429Input values to these routines may be any scalar number or string that looks 6430like a number. Anything that is accepted by Perl as a literal numeric constant 6431should be accepted by this module. 6432 6433=over 6434 6435=item * 6436 6437Leading and trailing whitespace is ignored. 6438 6439=item * 6440 6441Leading zeros are ignored, except for floating point numbers with a binary 6442exponent, in which case the number is interpreted as an octal floating point 6443number. For example, "01.4p+0" gives 1.5, "00.4p+0" gives 0.5, but "0.4p+0" 6444gives a NaN. And while "0377" gives 255, "0377p0" gives 255. 6445 6446=item * 6447 6448If the string has a "0x" or "0X" prefix, it is interpreted as a hexadecimal 6449number. 6450 6451=item * 6452 6453If the string has a "0o" or "0O" prefix, it is interpreted as an octal number. A 6454floating point literal with a "0" prefix is also interpreted as an octal number. 6455 6456=item * 6457 6458If the string has a "0b" or "0B" prefix, it is interpreted as a binary number. 6459 6460=item * 6461 6462Underline characters are allowed in the same way as they are allowed in literal 6463numerical constants. 6464 6465=item * 6466 6467If the string can not be interpreted, NaN is returned. 6468 6469=item * 6470 6471For hexadecimal, octal, and binary floating point numbers, the exponent must be 6472separated from the significand (mantissa) by the letter "p" or "P", not "e" or 6473"E" as with decimal numbers. 6474 6475=back 6476 6477Some examples of valid string input 6478 6479 Input string Resulting value 6480 6481 123 123 6482 1.23e2 123 6483 12300e-2 123 6484 6485 67_538_754 67538754 6486 -4_5_6.7_8_9e+0_1_0 -4567890000000 6487 6488 0x13a 314 6489 0x13ap0 314 6490 0x1.3ap+8 314 6491 0x0.00013ap+24 314 6492 0x13a000p-12 314 6493 6494 0o472 314 6495 0o1.164p+8 314 6496 0o0.0001164p+20 314 6497 0o1164000p-10 314 6498 6499 0472 472 Note! 6500 01.164p+8 314 6501 00.0001164p+20 314 6502 01164000p-10 314 6503 6504 0b100111010 314 6505 0b1.0011101p+8 314 6506 0b0.00010011101p+12 314 6507 0b100111010000p-3 314 6508 6509 0x1.921fb5p+1 3.14159262180328369140625e+0 6510 0o1.2677025p1 2.71828174591064453125 6511 01.2677025p1 2.71828174591064453125 6512 0b1.1001p-4 9.765625e-2 6513 6514=head2 Output 6515 6516Output values are usually Math::BigFloat objects. 6517 6518Boolean operators C<is_zero()>, C<is_one()>, C<is_inf()>, etc. return true or 6519false. 6520 6521Comparison operators C<bcmp()> and C<bacmp()>) return -1, 0, 1, or 6522undef. 6523 6524=head1 METHODS 6525 6526Math::BigFloat supports all methods that Math::BigInt supports, except it 6527calculates non-integer results when possible. Please see L<Math::BigInt> for a 6528full description of each method. Below are just the most important differences: 6529 6530=head2 Configuration methods 6531 6532=over 6533 6534=item accuracy() 6535 6536 $x->accuracy(5); # local for $x 6537 CLASS->accuracy(5); # global for all members of CLASS 6538 # Note: This also applies to new()! 6539 6540 $A = $x->accuracy(); # read out accuracy that affects $x 6541 $A = CLASS->accuracy(); # read out global accuracy 6542 6543Set or get the global or local accuracy, aka how many significant digits the 6544results have. If you set a global accuracy, then this also applies to new()! 6545 6546Warning! The accuracy I<sticks>, e.g. once you created a number under the 6547influence of C<< CLASS->accuracy($A) >>, all results from math operations with 6548that number will also be rounded. 6549 6550In most cases, you should probably round the results explicitly using one of 6551L<Math::BigInt/round()>, L<Math::BigInt/bround()> or L<Math::BigInt/bfround()> 6552or by passing the desired accuracy to the math operation as additional 6553parameter: 6554 6555 my $x = Math::BigInt->new(30000); 6556 my $y = Math::BigInt->new(7); 6557 print scalar $x->copy()->bdiv($y, 2); # print 4300 6558 print scalar $x->copy()->bdiv($y)->bround(2); # print 4300 6559 6560=item precision() 6561 6562 $x->precision(-2); # local for $x, round at the second 6563 # digit right of the dot 6564 $x->precision(2); # ditto, round at the second digit 6565 # left of the dot 6566 6567 CLASS->precision(5); # Global for all members of CLASS 6568 # This also applies to new()! 6569 CLASS->precision(-5); # ditto 6570 6571 $P = CLASS->precision(); # read out global precision 6572 $P = $x->precision(); # read out precision that affects $x 6573 6574Note: You probably want to use L</accuracy()> instead. With L</accuracy()> you 6575set the number of digits each result should have, with L</precision()> you 6576set the place where to round! 6577 6578=back 6579 6580=head2 Constructor methods 6581 6582=over 6583 6584=item from_hex() 6585 6586 $x -> from_hex("0x1.921fb54442d18p+1"); 6587 $x = Math::BigFloat -> from_hex("0x1.921fb54442d18p+1"); 6588 6589Interpret input as a hexadecimal string.A prefix ("0x", "x", ignoring case) is 6590optional. A single underscore character ("_") may be placed between any two 6591digits. If the input is invalid, a NaN is returned. The exponent is in base 2 6592using decimal digits. 6593 6594If called as an instance method, the value is assigned to the invocand. 6595 6596=item from_oct() 6597 6598 $x -> from_oct("1.3267p-4"); 6599 $x = Math::BigFloat -> from_oct("1.3267p-4"); 6600 6601Interpret input as an octal string. A single underscore character ("_") may be 6602placed between any two digits. If the input is invalid, a NaN is returned. The 6603exponent is in base 2 using decimal digits. 6604 6605If called as an instance method, the value is assigned to the invocand. 6606 6607=item from_bin() 6608 6609 $x -> from_bin("0b1.1001p-4"); 6610 $x = Math::BigFloat -> from_bin("0b1.1001p-4"); 6611 6612Interpret input as a hexadecimal string. A prefix ("0b" or "b", ignoring case) 6613is optional. A single underscore character ("_") may be placed between any two 6614digits. If the input is invalid, a NaN is returned. The exponent is in base 2 6615using decimal digits. 6616 6617If called as an instance method, the value is assigned to the invocand. 6618 6619=item from_ieee754() 6620 6621Interpret the input as a value encoded as described in IEEE754-2008. The input 6622can be given as a byte string, hex string or binary string. The input is 6623assumed to be in big-endian byte-order. 6624 6625 # both $dbl and $mbf are 3.141592... 6626 $bytes = "\x40\x09\x21\xfb\x54\x44\x2d\x18"; 6627 $dbl = unpack "d>", $bytes; 6628 $mbf = Math::BigFloat -> from_ieee754($bytes, "binary64"); 6629 6630=item bpi() 6631 6632 print Math::BigFloat->bpi(100), "\n"; 6633 6634Calculate PI to N digits (including the 3 before the dot). The result is 6635rounded according to the current rounding mode, which defaults to "even". 6636 6637This method was added in v1.87 of Math::BigInt (June 2007). 6638 6639=back 6640 6641=head2 Arithmetic methods 6642 6643=over 6644 6645=item bmuladd() 6646 6647 $x->bmuladd($y,$z); 6648 6649Multiply $x by $y, and then add $z to the result. 6650 6651This method was added in v1.87 of Math::BigInt (June 2007). 6652 6653=item binv() 6654 6655 $x->binv(); 6656 6657Invert the value of $x, i.e., compute 1/$x. 6658 6659=item bdiv() 6660 6661 $q = $x->bdiv($y); 6662 ($q, $r) = $x->bdiv($y); 6663 6664In scalar context, divides $x by $y and returns the result to the given or 6665default accuracy/precision. In list context, does floored division 6666(F-division), returning an integer $q and a remainder $r so that $x = $q * $y + 6667$r. The remainer (modulo) is equal to what is returned by C<< $x->bmod($y) >>. 6668 6669=item bmod() 6670 6671 $x->bmod($y); 6672 6673Returns $x modulo $y. When $x is finite, and $y is finite and non-zero, the 6674result is identical to the remainder after floored division (F-division). If, 6675in addition, both $x and $y are integers, the result is identical to the result 6676from Perl's % operator. 6677 6678=item bexp() 6679 6680 $x->bexp($accuracy); # calculate e ** X 6681 6682Calculates the expression C<e ** $x> where C<e> is Euler's number. 6683 6684This method was added in v1.82 of Math::BigInt (April 2007). 6685 6686=item bnok() 6687 6688 $x->bnok($y); # x over y (binomial coefficient n over k) 6689 6690Calculates the binomial coefficient n over k, also called the "choose" 6691function. The result is equivalent to: 6692 6693 ( n ) n! 6694 | - | = ------- 6695 ( k ) k!(n-k)! 6696 6697This method was added in v1.84 of Math::BigInt (April 2007). 6698 6699=item bsin() 6700 6701 my $x = Math::BigFloat->new(1); 6702 print $x->bsin(100), "\n"; 6703 6704Calculate the sinus of $x, modifying $x in place. 6705 6706This method was added in v1.87 of Math::BigInt (June 2007). 6707 6708=item bcos() 6709 6710 my $x = Math::BigFloat->new(1); 6711 print $x->bcos(100), "\n"; 6712 6713Calculate the cosinus of $x, modifying $x in place. 6714 6715This method was added in v1.87 of Math::BigInt (June 2007). 6716 6717=item batan() 6718 6719 my $x = Math::BigFloat->new(1); 6720 print $x->batan(100), "\n"; 6721 6722Calculate the arcus tanges of $x, modifying $x in place. See also L</batan2()>. 6723 6724This method was added in v1.87 of Math::BigInt (June 2007). 6725 6726=item batan2() 6727 6728 my $y = Math::BigFloat->new(2); 6729 my $x = Math::BigFloat->new(3); 6730 print $y->batan2($x), "\n"; 6731 6732Calculate the arcus tanges of C<$y> divided by C<$x>, modifying $y in place. 6733See also L</batan()>. 6734 6735This method was added in v1.87 of Math::BigInt (June 2007). 6736 6737=item as_float() 6738 6739This method is called when Math::BigFloat encounters an object it doesn't know 6740how to handle. For instance, assume $x is a Math::BigFloat, or subclass 6741thereof, and $y is defined, but not a Math::BigFloat, or subclass thereof. If 6742you do 6743 6744 $x -> badd($y); 6745 6746$y needs to be converted into an object that $x can deal with. This is done by 6747first checking if $y is something that $x might be upgraded to. If that is the 6748case, no further attempts are made. The next is to see if $y supports the 6749method C<as_float()>. The method C<as_float()> is expected to return either an 6750object that has the same class as $x, a subclass thereof, or a string that 6751C<ref($x)-E<gt>new()> can parse to create an object. 6752 6753In Math::BigFloat, C<as_float()> has the same effect as C<copy()>. 6754 6755=item to_ieee754() 6756 6757Encodes the invocand as a byte string in the given format as specified in IEEE 6758754-2008. Note that the encoded value is the nearest possible representation of 6759the value. This value might not be exactly the same as the value in the 6760invocand. 6761 6762 # $x = 3.1415926535897932385 6763 $x = Math::BigFloat -> bpi(30); 6764 6765 $b = $x -> to_ieee754("binary64"); # encode as 8 bytes 6766 $h = unpack "H*", $b; # "400921fb54442d18" 6767 6768 # 3.141592653589793115997963... 6769 $y = Math::BigFloat -> from_ieee754($h, "binary64"); 6770 6771All binary formats in IEEE 754-2008 are accepted. For convenience, som aliases 6772are recognized: "half" for "binary16", "single" for "binary32", "double" for 6773"binary64", "quadruple" for "binary128", "octuple" for "binary256", and 6774"sexdecuple" for "binary512". 6775 6776See also L<https://en.wikipedia.org/wiki/IEEE_754>. 6777 6778=back 6779 6780=head2 ACCURACY AND PRECISION 6781 6782See also: L<Rounding|/Rounding>. 6783 6784Math::BigFloat supports both precision (rounding to a certain place before or 6785after the dot) and accuracy (rounding to a certain number of digits). For a 6786full documentation, examples and tips on these topics please see the large 6787section about rounding in L<Math::BigInt>. 6788 6789Since things like C<sqrt(2)> or C<1 / 3> must presented with a limited 6790accuracy lest a operation consumes all resources, each operation produces 6791no more than the requested number of digits. 6792 6793If there is no global precision or accuracy set, B<and> the operation in 6794question was not called with a requested precision or accuracy, B<and> the 6795input $x has no accuracy or precision set, then a fallback parameter will 6796be used. For historical reasons, it is called C<div_scale> and can be accessed 6797via: 6798 6799 $d = Math::BigFloat->div_scale(); # query 6800 Math::BigFloat->div_scale($n); # set to $n digits 6801 6802The default value for C<div_scale> is 40. 6803 6804In case the result of one operation has more digits than specified, 6805it is rounded. The rounding mode taken is either the default mode, or the one 6806supplied to the operation after the I<scale>: 6807 6808 $x = Math::BigFloat->new(2); 6809 Math::BigFloat->accuracy(5); # 5 digits max 6810 $y = $x->copy()->bdiv(3); # gives 0.66667 6811 $y = $x->copy()->bdiv(3,6); # gives 0.666667 6812 $y = $x->copy()->bdiv(3,6,undef,'odd'); # gives 0.666667 6813 Math::BigFloat->round_mode('zero'); 6814 $y = $x->copy()->bdiv(3,6); # will also give 0.666667 6815 6816Note that C<< Math::BigFloat->accuracy() >> and 6817C<< Math::BigFloat->precision() >> set the global variables, and thus B<any> 6818newly created number will be subject to the global rounding B<immediately>. This 6819means that in the examples above, the C<3> as argument to C<bdiv()> will also 6820get an accuracy of B<5>. 6821 6822It is less confusing to either calculate the result fully, and afterwards 6823round it explicitly, or use the additional parameters to the math 6824functions like so: 6825 6826 use Math::BigFloat; 6827 $x = Math::BigFloat->new(2); 6828 $y = $x->copy()->bdiv(3); 6829 print $y->bround(5),"\n"; # gives 0.66667 6830 6831 or 6832 6833 use Math::BigFloat; 6834 $x = Math::BigFloat->new(2); 6835 $y = $x->copy()->bdiv(3,5); # gives 0.66667 6836 print "$y\n"; 6837 6838=head2 Rounding 6839 6840=over 6841 6842=item bfround ( +$scale ) 6843 6844Rounds to the $scale'th place left from the '.', counting from the dot. 6845The first digit is numbered 1. 6846 6847=item bfround ( -$scale ) 6848 6849Rounds to the $scale'th place right from the '.', counting from the dot. 6850 6851=item bfround ( 0 ) 6852 6853Rounds to an integer. 6854 6855=item bround ( +$scale ) 6856 6857Preserves accuracy to $scale digits from the left (aka significant digits) and 6858pads the rest with zeros. If the number is between 1 and -1, the significant 6859digits count from the first non-zero after the '.' 6860 6861=item bround ( -$scale ) and bround ( 0 ) 6862 6863These are effectively no-ops. 6864 6865=back 6866 6867All rounding functions take as a second parameter a rounding mode from one of 6868the following: 'even', 'odd', '+inf', '-inf', 'zero', 'trunc' or 'common'. 6869 6870The default rounding mode is 'even'. By using 6871C<< Math::BigFloat->round_mode($round_mode); >> you can get and set the default 6872mode for subsequent rounding. The usage of C<$Math::BigFloat::$round_mode> is 6873no longer supported. 6874The second parameter to the round functions then overrides the default 6875temporarily. 6876 6877The C<as_number()> function returns a BigInt from a Math::BigFloat. It uses 6878'trunc' as rounding mode to make it equivalent to: 6879 6880 $x = 2.5; 6881 $y = int($x) + 2; 6882 6883You can override this by passing the desired rounding mode as parameter to 6884C<as_number()>: 6885 6886 $x = Math::BigFloat->new(2.5); 6887 $y = $x->as_number('odd'); # $y = 3 6888 6889=head1 NUMERIC LITERALS 6890 6891After C<use Math::BigFloat ':constant'> all numeric literals in the given scope 6892are converted to C<Math::BigFloat> objects. This conversion happens at compile 6893time. 6894 6895For example, 6896 6897 perl -MMath::BigFloat=:constant -le 'print 2e-150' 6898 6899prints the exact value of C<2e-150>. Note that without conversion of constants 6900the expression C<2e-150> is calculated using Perl scalars, which leads to an 6901inaccuracte result. 6902 6903Note that strings are not affected, so that 6904 6905 use Math::BigFloat qw/:constant/; 6906 6907 $y = "1234567890123456789012345678901234567890" 6908 + "123456789123456789"; 6909 6910does not give you what you expect. You need an explicit Math::BigFloat->new() 6911around at least one of the operands. You should also quote large constants to 6912prevent loss of precision: 6913 6914 use Math::BigFloat; 6915 6916 $x = Math::BigFloat->new("1234567889123456789123456789123456789"); 6917 6918Without the quotes Perl converts the large number to a floating point constant 6919at compile time, and then converts the result to a Math::BigFloat object at 6920runtime, which results in an inaccurate result. 6921 6922=head2 Hexadecimal, octal, and binary floating point literals 6923 6924Perl (and this module) accepts hexadecimal, octal, and binary floating point 6925literals, but use them with care with Perl versions before v5.32.0, because some 6926versions of Perl silently give the wrong result. Below are some examples of 6927different ways to write the number decimal 314. 6928 6929Hexadecimal floating point literals: 6930 6931 0x1.3ap+8 0X1.3AP+8 6932 0x1.3ap8 0X1.3AP8 6933 0x13a0p-4 0X13A0P-4 6934 6935Octal floating point literals (with "0" prefix): 6936 6937 01.164p+8 01.164P+8 6938 01.164p8 01.164P8 6939 011640p-4 011640P-4 6940 6941Octal floating point literals (with "0o" prefix) (requires v5.34.0): 6942 6943 0o1.164p+8 0O1.164P+8 6944 0o1.164p8 0O1.164P8 6945 0o11640p-4 0O11640P-4 6946 6947Binary floating point literals: 6948 6949 0b1.0011101p+8 0B1.0011101P+8 6950 0b1.0011101p8 0B1.0011101P8 6951 0b10011101000p-2 0B10011101000P-2 6952 6953=head2 Math library 6954 6955Math with the numbers is done (by default) by a module called 6956Math::BigInt::Calc. This is equivalent to saying: 6957 6958 use Math::BigFloat lib => "Calc"; 6959 6960You can change this by using: 6961 6962 use Math::BigFloat lib => "GMP"; 6963 6964B<Note>: General purpose packages should not be explicit about the library to 6965use; let the script author decide which is best. 6966 6967Note: The keyword 'lib' will warn when the requested library could not be 6968loaded. To suppress the warning use 'try' instead: 6969 6970 use Math::BigFloat try => "GMP"; 6971 6972If your script works with huge numbers and Calc is too slow for them, you can 6973also for the loading of one of these libraries and if none of them can be used, 6974the code will die: 6975 6976 use Math::BigFloat only => "GMP,Pari"; 6977 6978The following would first try to find Math::BigInt::Foo, then Math::BigInt::Bar, 6979and when this also fails, revert to Math::BigInt::Calc: 6980 6981 use Math::BigFloat lib => "Foo,Math::BigInt::Bar"; 6982 6983See the respective low-level library documentation for further details. 6984 6985See L<Math::BigInt> for more details about using a different low-level library. 6986 6987=head1 EXPORTS 6988 6989C<Math::BigFloat> exports nothing by default, but can export the C<bpi()> 6990method: 6991 6992 use Math::BigFloat qw/bpi/; 6993 6994 print bpi(10), "\n"; 6995 6996=over 6997 6998=item stringify, bstr() 6999 7000Both stringify and bstr() now drop the leading '+'. The old code would return 7001'+1.23', the new returns '1.23'. See the documentation in L<Math::BigInt> for 7002reasoning and details. 7003 7004=item brsft() 7005 7006The following will probably not print what you expect: 7007 7008 my $c = Math::BigFloat->new('3.14159'); 7009 print $c->brsft(3,10),"\n"; # prints 0.00314153.1415 7010 7011It prints both quotient and remainder, since print calls C<brsft()> in list 7012context. Also, C<< $c->brsft() >> will modify $c, so be careful. 7013You probably want to use 7014 7015 print scalar $c->copy()->brsft(3,10),"\n"; 7016 # or if you really want to modify $c 7017 print scalar $c->brsft(3,10),"\n"; 7018 7019instead. 7020 7021=item Modifying and = 7022 7023Beware of: 7024 7025 $x = Math::BigFloat->new(5); 7026 $y = $x; 7027 7028It will not do what you think, e.g. making a copy of $x. Instead it just makes 7029a second reference to the B<same> object and stores it in $y. Thus anything 7030that modifies $x will modify $y (except overloaded math operators), and vice 7031versa. See L<Math::BigInt> for details and how to avoid that. 7032 7033=item precision() vs. accuracy() 7034 7035A common pitfall is to use L</precision()> when you want to round a result to 7036a certain number of digits: 7037 7038 use Math::BigFloat; 7039 7040 Math::BigFloat->precision(4); # does not do what you 7041 # think it does 7042 my $x = Math::BigFloat->new(12345); # rounds $x to "12000"! 7043 print "$x\n"; # print "12000" 7044 my $y = Math::BigFloat->new(3); # rounds $y to "0"! 7045 print "$y\n"; # print "0" 7046 $z = $x / $y; # 12000 / 0 => NaN! 7047 print "$z\n"; 7048 print $z->precision(),"\n"; # 4 7049 7050Replacing L</precision()> with L</accuracy()> is probably not what you want, 7051either: 7052 7053 use Math::BigFloat; 7054 7055 Math::BigFloat->accuracy(4); # enables global rounding: 7056 my $x = Math::BigFloat->new(123456); # rounded immediately 7057 # to "12350" 7058 print "$x\n"; # print "123500" 7059 my $y = Math::BigFloat->new(3); # rounded to "3 7060 print "$y\n"; # print "3" 7061 print $z = $x->copy()->bdiv($y),"\n"; # 41170 7062 print $z->accuracy(),"\n"; # 4 7063 7064What you want to use instead is: 7065 7066 use Math::BigFloat; 7067 7068 my $x = Math::BigFloat->new(123456); # no rounding 7069 print "$x\n"; # print "123456" 7070 my $y = Math::BigFloat->new(3); # no rounding 7071 print "$y\n"; # print "3" 7072 print $z = $x->copy()->bdiv($y,4),"\n"; # 41150 7073 print $z->accuracy(),"\n"; # undef 7074 7075In addition to computing what you expected, the last example also does B<not> 7076"taint" the result with an accuracy or precision setting, which would 7077influence any further operation. 7078 7079=back 7080 7081=head1 BUGS 7082 7083Please report any bugs or feature requests to 7084C<bug-math-bigint at rt.cpan.org>, or through the web interface at 7085L<https://rt.cpan.org/Ticket/Create.html?Queue=Math-BigInt> (requires login). 7086We will be notified, and then you'll automatically be notified of progress on 7087your bug as I make changes. 7088 7089=head1 SUPPORT 7090 7091You can find documentation for this module with the perldoc command. 7092 7093 perldoc Math::BigFloat 7094 7095You can also look for information at: 7096 7097=over 4 7098 7099=item * GitHub 7100 7101L<https://github.com/pjacklam/p5-Math-BigInt> 7102 7103=item * RT: CPAN's request tracker 7104 7105L<https://rt.cpan.org/Dist/Display.html?Name=Math-BigInt> 7106 7107=item * MetaCPAN 7108 7109L<https://metacpan.org/release/Math-BigInt> 7110 7111=item * CPAN Testers Matrix 7112 7113L<http://matrix.cpantesters.org/?dist=Math-BigInt> 7114 7115=back 7116 7117=head1 LICENSE 7118 7119This program is free software; you may redistribute it and/or modify it under 7120the same terms as Perl itself. 7121 7122=head1 SEE ALSO 7123 7124L<Math::BigInt> and L<Math::BigRat> as well as the backend libraries 7125L<Math::BigInt::FastCalc>, L<Math::BigInt::GMP>, and L<Math::BigInt::Pari>, 7126L<Math::BigInt::GMPz>, and L<Math::BigInt::BitVect>. 7127 7128The pragmas L<bigint>, L<bigfloat>, and L<bigrat> might also be of interest. In 7129addition there is the L<bignum> pragma which does upgrading and downgrading. 7130 7131=head1 AUTHORS 7132 7133=over 4 7134 7135=item * 7136 7137Mark Biggar, overloaded interface by Ilya Zakharevich, 1996-2001. 7138 7139=item * 7140 7141Completely rewritten by Tels L<http://bloodgate.com> in 2001-2008. 7142 7143=item * 7144 7145Florian Ragwitz E<lt>flora@cpan.orgE<gt>, 2010. 7146 7147=item * 7148 7149Peter John Acklam E<lt>pjacklam@gmail.comE<gt>, 2011-. 7150 7151=back 7152 7153=cut 7154