[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 package 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 internally used: 8 # _e : exponent (ref to $CALC object) 9 # _m : mantissa (ref to $CALC object) 10 # _es : sign of _e 11 # sign : +,-,+inf,-inf, or "NaN" if not a number 12 # _a : accuracy 13 # _p : precision 14 15 $VERSION = '1.59'; 16 require 5.006; 17 18 require Exporter; 19 @ISA = qw/Math::BigInt/; 20 @EXPORT_OK = qw/bpi/; 21 22 use strict; 23 # $_trap_inf/$_trap_nan are internal and should never be accessed from outside 24 use vars qw/$AUTOLOAD $accuracy $precision $div_scale $round_mode $rnd_mode 25 $upgrade $downgrade $_trap_nan $_trap_inf/; 26 my $class = "Math::BigFloat"; 27 28 use overload 29 '<=>' => sub { my $rc = $_[2] ? 30 ref($_[0])->bcmp($_[1],$_[0]) : 31 ref($_[0])->bcmp($_[0],$_[1]); 32 $rc = 1 unless defined $rc; 33 $rc <=> 0; 34 }, 35 # we need '>=' to get things like "1 >= NaN" right: 36 '>=' => sub { my $rc = $_[2] ? 37 ref($_[0])->bcmp($_[1],$_[0]) : 38 ref($_[0])->bcmp($_[0],$_[1]); 39 # if there was a NaN involved, return false 40 return '' unless defined $rc; 41 $rc >= 0; 42 }, 43 'int' => sub { $_[0]->as_number() }, # 'trunc' to bigint 44 ; 45 46 ############################################################################## 47 # global constants, flags and assorted stuff 48 49 # the following are public, but their usage is not recommended. Use the 50 # accessor methods instead. 51 52 # class constants, use Class->constant_name() to access 53 # one of 'even', 'odd', '+inf', '-inf', 'zero', 'trunc' or 'common' 54 $round_mode = 'even'; 55 $accuracy = undef; 56 $precision = undef; 57 $div_scale = 40; 58 59 $upgrade = undef; 60 $downgrade = undef; 61 # the package we are using for our private parts, defaults to: 62 # Math::BigInt->config()->{lib} 63 my $MBI = 'Math::BigInt::FastCalc'; 64 65 # are NaNs ok? (otherwise it dies when encountering an NaN) set w/ config() 66 $_trap_nan = 0; 67 # the same for infinity 68 $_trap_inf = 0; 69 70 # constant for easier life 71 my $nan = 'NaN'; 72 73 my $IMPORT = 0; # was import() called yet? used to make require work 74 75 # some digits of accuracy for blog(undef,10); which we use in blog() for speed 76 my $LOG_10 = 77 '2.3025850929940456840179914546843642076011014886287729760333279009675726097'; 78 my $LOG_10_A = length($LOG_10)-1; 79 # ditto for log(2) 80 my $LOG_2 = 81 '0.6931471805599453094172321214581765680755001343602552541206800094933936220'; 82 my $LOG_2_A = length($LOG_2)-1; 83 my $HALF = '0.5'; # made into an object if nec. 84 85 ############################################################################## 86 # the old code had $rnd_mode, so we need to support it, too 87 88 sub TIESCALAR { my ($class) = @_; bless \$round_mode, $class; } 89 sub FETCH { return $round_mode; } 90 sub STORE { $rnd_mode = $_[0]->round_mode($_[1]); } 91 92 BEGIN 93 { 94 # when someone sets $rnd_mode, we catch this and check the value to see 95 # whether it is valid or not. 96 $rnd_mode = 'even'; tie $rnd_mode, 'Math::BigFloat'; 97 98 # we need both of them in this package: 99 *as_int = \&as_number; 100 } 101 102 ############################################################################## 103 104 { 105 # valid method aliases for AUTOLOAD 106 my %methods = map { $_ => 1 } 107 qw / fadd fsub fmul fdiv fround ffround fsqrt fmod fstr fsstr fpow fnorm 108 fint facmp fcmp fzero fnan finf finc fdec ffac fneg 109 fceil ffloor frsft flsft fone flog froot fexp 110 /; 111 # valid methods that can be handed up (for AUTOLOAD) 112 my %hand_ups = map { $_ => 1 } 113 qw / is_nan is_inf is_negative is_positive is_pos is_neg 114 accuracy precision div_scale round_mode fabs fnot 115 objectify upgrade downgrade 116 bone binf bnan bzero 117 bsub 118 /; 119 120 sub _method_alias { exists $methods{$_[0]||''}; } 121 sub _method_hand_up { exists $hand_ups{$_[0]||''}; } 122 } 123 124 ############################################################################## 125 # constructors 126 127 sub new 128 { 129 # create a new BigFloat object from a string or another bigfloat object. 130 # _e: exponent 131 # _m: mantissa 132 # sign => sign (+/-), or "NaN" 133 134 my ($class,$wanted,@r) = @_; 135 136 # avoid numify-calls by not using || on $wanted! 137 return $class->bzero() if !defined $wanted; # default to 0 138 return $wanted->copy() if UNIVERSAL::isa($wanted,'Math::BigFloat'); 139 140 $class->import() if $IMPORT == 0; # make require work 141 142 my $self = {}; bless $self, $class; 143 # shortcut for bigints and its subclasses 144 if ((ref($wanted)) && UNIVERSAL::can( $wanted, "as_number")) 145 { 146 $self->{_m} = $wanted->as_number()->{value}; # get us a bigint copy 147 $self->{_e} = $MBI->_zero(); 148 $self->{_es} = '+'; 149 $self->{sign} = $wanted->sign(); 150 return $self->bnorm(); 151 } 152 # else: got a string or something maskerading as number (with overload) 153 154 # handle '+inf', '-inf' first 155 if ($wanted =~ /^[+-]?inf\z/) 156 { 157 return $downgrade->new($wanted) if $downgrade; 158 159 $self->{sign} = $wanted; # set a default sign for bstr() 160 return $self->binf($wanted); 161 } 162 163 # shortcut for simple forms like '12' that neither have trailing nor leading 164 # zeros 165 if ($wanted =~ /^([+-]?)([1-9][0-9]*[1-9])$/) 166 { 167 $self->{_e} = $MBI->_zero(); 168 $self->{_es} = '+'; 169 $self->{sign} = $1 || '+'; 170 $self->{_m} = $MBI->_new($2); 171 return $self->round(@r) if !$downgrade; 172 } 173 174 my ($mis,$miv,$mfv,$es,$ev) = Math::BigInt::_split($wanted); 175 if (!ref $mis) 176 { 177 if ($_trap_nan) 178 { 179 require Carp; 180 Carp::croak ("$wanted is not a number initialized to $class"); 181 } 182 183 return $downgrade->bnan() if $downgrade; 184 185 $self->{_e} = $MBI->_zero(); 186 $self->{_es} = '+'; 187 $self->{_m} = $MBI->_zero(); 188 $self->{sign} = $nan; 189 } 190 else 191 { 192 # make integer from mantissa by adjusting exp, then convert to int 193 $self->{_e} = $MBI->_new($$ev); # exponent 194 $self->{_es} = $$es || '+'; 195 my $mantissa = "$$miv$$mfv"; # create mant. 196 $mantissa =~ s/^0+(\d)/$1/; # strip leading zeros 197 $self->{_m} = $MBI->_new($mantissa); # create mant. 198 199 # 3.123E0 = 3123E-3, and 3.123E-2 => 3123E-5 200 if (CORE::length($$mfv) != 0) 201 { 202 my $len = $MBI->_new( CORE::length($$mfv)); 203 ($self->{_e}, $self->{_es}) = 204 _e_sub ($self->{_e}, $len, $self->{_es}, '+'); 205 } 206 # we can only have trailing zeros on the mantissa if $$mfv eq '' 207 else 208 { 209 # Use a regexp to count the trailing zeros in $$miv instead of _zeros() 210 # because that is faster, especially when _m is not stored in base 10. 211 my $zeros = 0; $zeros = CORE::length($1) if $$miv =~ /[1-9](0*)$/; 212 if ($zeros != 0) 213 { 214 my $z = $MBI->_new($zeros); 215 # turn '120e2' into '12e3' 216 $MBI->_rsft ( $self->{_m}, $z, 10); 217 ($self->{_e}, $self->{_es}) = 218 _e_add ( $self->{_e}, $z, $self->{_es}, '+'); 219 } 220 } 221 $self->{sign} = $$mis; 222 223 # for something like 0Ey, set y to 1, and -0 => +0 224 # Check $$miv for being '0' and $$mfv eq '', because otherwise _m could not 225 # have become 0. That's faster than to call $MBI->_is_zero(). 226 $self->{sign} = '+', $self->{_e} = $MBI->_one() 227 if $$miv eq '0' and $$mfv eq ''; 228 229 return $self->round(@r) if !$downgrade; 230 } 231 # if downgrade, inf, NaN or integers go down 232 233 if ($downgrade && $self->{_es} eq '+') 234 { 235 if ($MBI->_is_zero( $self->{_e} )) 236 { 237 return $downgrade->new($$mis . $MBI->_str( $self->{_m} )); 238 } 239 return $downgrade->new($self->bsstr()); 240 } 241 $self->bnorm()->round(@r); # first normalize, then round 242 } 243 244 sub copy 245 { 246 # if two arguments, the first one is the class to "swallow" subclasses 247 if (@_ > 1) 248 { 249 my $self = bless { 250 sign => $_[1]->{sign}, 251 _es => $_[1]->{_es}, 252 _m => $MBI->_copy($_[1]->{_m}), 253 _e => $MBI->_copy($_[1]->{_e}), 254 }, $_[0] if @_ > 1; 255 256 $self->{_a} = $_[1]->{_a} if defined $_[1]->{_a}; 257 $self->{_p} = $_[1]->{_p} if defined $_[1]->{_p}; 258 return $self; 259 } 260 261 my $self = bless { 262 sign => $_[0]->{sign}, 263 _es => $_[0]->{_es}, 264 _m => $MBI->_copy($_[0]->{_m}), 265 _e => $MBI->_copy($_[0]->{_e}), 266 }, ref($_[0]); 267 268 $self->{_a} = $_[0]->{_a} if defined $_[0]->{_a}; 269 $self->{_p} = $_[0]->{_p} if defined $_[0]->{_p}; 270 $self; 271 } 272 273 sub _bnan 274 { 275 # used by parent class bone() to initialize number to NaN 276 my $self = shift; 277 278 if ($_trap_nan) 279 { 280 require Carp; 281 my $class = ref($self); 282 Carp::croak ("Tried to set $self to NaN in $class\::_bnan()"); 283 } 284 285 $IMPORT=1; # call our import only once 286 $self->{_m} = $MBI->_zero(); 287 $self->{_e} = $MBI->_zero(); 288 $self->{_es} = '+'; 289 } 290 291 sub _binf 292 { 293 # used by parent class bone() to initialize number to +-inf 294 my $self = shift; 295 296 if ($_trap_inf) 297 { 298 require Carp; 299 my $class = ref($self); 300 Carp::croak ("Tried to set $self to +-inf in $class\::_binf()"); 301 } 302 303 $IMPORT=1; # call our import only once 304 $self->{_m} = $MBI->_zero(); 305 $self->{_e} = $MBI->_zero(); 306 $self->{_es} = '+'; 307 } 308 309 sub _bone 310 { 311 # used by parent class bone() to initialize number to 1 312 my $self = shift; 313 $IMPORT=1; # call our import only once 314 $self->{_m} = $MBI->_one(); 315 $self->{_e} = $MBI->_zero(); 316 $self->{_es} = '+'; 317 } 318 319 sub _bzero 320 { 321 # used by parent class bone() to initialize number to 0 322 my $self = shift; 323 $IMPORT=1; # call our import only once 324 $self->{_m} = $MBI->_zero(); 325 $self->{_e} = $MBI->_one(); 326 $self->{_es} = '+'; 327 } 328 329 sub isa 330 { 331 my ($self,$class) = @_; 332 return if $class =~ /^Math::BigInt/; # we aren't one of these 333 UNIVERSAL::isa($self,$class); 334 } 335 336 sub config 337 { 338 # return (later set?) configuration data as hash ref 339 my $class = shift || 'Math::BigFloat'; 340 341 if (@_ == 1 && ref($_[0]) ne 'HASH') 342 { 343 my $cfg = $class->SUPER::config(); 344 return $cfg->{$_[0]}; 345 } 346 347 my $cfg = $class->SUPER::config(@_); 348 349 # now we need only to override the ones that are different from our parent 350 $cfg->{class} = $class; 351 $cfg->{with} = $MBI; 352 $cfg; 353 } 354 355 ############################################################################## 356 # string conversation 357 358 sub bstr 359 { 360 # (ref to BFLOAT or num_str ) return num_str 361 # Convert number from internal format to (non-scientific) string format. 362 # internal format is always normalized (no leading zeros, "-0" => "+0") 363 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_); 364 365 if ($x->{sign} !~ /^[+-]$/) 366 { 367 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN 368 return 'inf'; # +inf 369 } 370 371 my $es = '0'; my $len = 1; my $cad = 0; my $dot = '.'; 372 373 # $x is zero? 374 my $not_zero = !($x->{sign} eq '+' && $MBI->_is_zero($x->{_m})); 375 if ($not_zero) 376 { 377 $es = $MBI->_str($x->{_m}); 378 $len = CORE::length($es); 379 my $e = $MBI->_num($x->{_e}); 380 $e = -$e if $x->{_es} eq '-'; 381 if ($e < 0) 382 { 383 $dot = ''; 384 # if _e is bigger than a scalar, the following will blow your memory 385 if ($e <= -$len) 386 { 387 my $r = abs($e) - $len; 388 $es = '0.'. ('0' x $r) . $es; $cad = -($len+$r); 389 } 390 else 391 { 392 substr($es,$e,0) = '.'; $cad = $MBI->_num($x->{_e}); 393 $cad = -$cad if $x->{_es} eq '-'; 394 } 395 } 396 elsif ($e > 0) 397 { 398 # expand with zeros 399 $es .= '0' x $e; $len += $e; $cad = 0; 400 } 401 } # if not zero 402 403 $es = '-'.$es if $x->{sign} eq '-'; 404 # if set accuracy or precision, pad with zeros on the right side 405 if ((defined $x->{_a}) && ($not_zero)) 406 { 407 # 123400 => 6, 0.1234 => 4, 0.001234 => 4 408 my $zeros = $x->{_a} - $cad; # cad == 0 => 12340 409 $zeros = $x->{_a} - $len if $cad != $len; 410 $es .= $dot.'0' x $zeros if $zeros > 0; 411 } 412 elsif ((($x->{_p} || 0) < 0)) 413 { 414 # 123400 => 6, 0.1234 => 4, 0.001234 => 6 415 my $zeros = -$x->{_p} + $cad; 416 $es .= $dot.'0' x $zeros if $zeros > 0; 417 } 418 $es; 419 } 420 421 sub bsstr 422 { 423 # (ref to BFLOAT or num_str ) return num_str 424 # Convert number from internal format to scientific string format. 425 # internal format is always normalized (no leading zeros, "-0E0" => "+0E0") 426 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_); 427 428 if ($x->{sign} !~ /^[+-]$/) 429 { 430 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN 431 return 'inf'; # +inf 432 } 433 my $sep = 'e'.$x->{_es}; 434 my $sign = $x->{sign}; $sign = '' if $sign eq '+'; 435 $sign . $MBI->_str($x->{_m}) . $sep . $MBI->_str($x->{_e}); 436 } 437 438 sub numify 439 { 440 # Make a number from a BigFloat object 441 # simple return a string and let Perl's atoi()/atof() handle the rest 442 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_); 443 $x->bsstr(); 444 } 445 446 ############################################################################## 447 # public stuff (usually prefixed with "b") 448 449 sub bneg 450 { 451 # (BINT or num_str) return BINT 452 # negate number or make a negated number from string 453 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_); 454 455 return $x if $x->modify('bneg'); 456 457 # for +0 dont negate (to have always normalized +0). Does nothing for 'NaN' 458 $x->{sign} =~ tr/+-/-+/ unless ($x->{sign} eq '+' && $MBI->_is_zero($x->{_m})); 459 $x; 460 } 461 462 # tels 2001-08-04 463 # XXX TODO this must be overwritten and return NaN for non-integer values 464 # band(), bior(), bxor(), too 465 #sub bnot 466 # { 467 # $class->SUPER::bnot($class,@_); 468 # } 469 470 sub bcmp 471 { 472 # Compares 2 values. Returns one of undef, <0, =0, >0. (suitable for sort) 473 474 # set up parameters 475 my ($self,$x,$y) = (ref($_[0]),@_); 476 # objectify is costly, so avoid it 477 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) 478 { 479 ($self,$x,$y) = objectify(2,@_); 480 } 481 482 return $upgrade->bcmp($x,$y) if defined $upgrade && 483 ((!$x->isa($self)) || (!$y->isa($self))); 484 485 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/)) 486 { 487 # handle +-inf and NaN 488 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan)); 489 return 0 if ($x->{sign} eq $y->{sign}) && ($x->{sign} =~ /^[+-]inf$/); 490 return +1 if $x->{sign} eq '+inf'; 491 return -1 if $x->{sign} eq '-inf'; 492 return -1 if $y->{sign} eq '+inf'; 493 return +1; 494 } 495 496 # check sign for speed first 497 return 1 if $x->{sign} eq '+' && $y->{sign} eq '-'; # does also 0 <=> -y 498 return -1 if $x->{sign} eq '-' && $y->{sign} eq '+'; # does also -x <=> 0 499 500 # shortcut 501 my $xz = $x->is_zero(); 502 my $yz = $y->is_zero(); 503 return 0 if $xz && $yz; # 0 <=> 0 504 return -1 if $xz && $y->{sign} eq '+'; # 0 <=> +y 505 return 1 if $yz && $x->{sign} eq '+'; # +x <=> 0 506 507 # adjust so that exponents are equal 508 my $lxm = $MBI->_len($x->{_m}); 509 my $lym = $MBI->_len($y->{_m}); 510 # the numify somewhat limits our length, but makes it much faster 511 my ($xes,$yes) = (1,1); 512 $xes = -1 if $x->{_es} ne '+'; 513 $yes = -1 if $y->{_es} ne '+'; 514 my $lx = $lxm + $xes * $MBI->_num($x->{_e}); 515 my $ly = $lym + $yes * $MBI->_num($y->{_e}); 516 my $l = $lx - $ly; $l = -$l if $x->{sign} eq '-'; 517 return $l <=> 0 if $l != 0; 518 519 # lengths (corrected by exponent) are equal 520 # so make mantissa equal length by padding with zero (shift left) 521 my $diff = $lxm - $lym; 522 my $xm = $x->{_m}; # not yet copy it 523 my $ym = $y->{_m}; 524 if ($diff > 0) 525 { 526 $ym = $MBI->_copy($y->{_m}); 527 $ym = $MBI->_lsft($ym, $MBI->_new($diff), 10); 528 } 529 elsif ($diff < 0) 530 { 531 $xm = $MBI->_copy($x->{_m}); 532 $xm = $MBI->_lsft($xm, $MBI->_new(-$diff), 10); 533 } 534 my $rc = $MBI->_acmp($xm,$ym); 535 $rc = -$rc if $x->{sign} eq '-'; # -124 < -123 536 $rc <=> 0; 537 } 538 539 sub bacmp 540 { 541 # Compares 2 values, ignoring their signs. 542 # Returns one of undef, <0, =0, >0. (suitable for sort) 543 544 # set up parameters 545 my ($self,$x,$y) = (ref($_[0]),@_); 546 # objectify is costly, so avoid it 547 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) 548 { 549 ($self,$x,$y) = objectify(2,@_); 550 } 551 552 return $upgrade->bacmp($x,$y) if defined $upgrade && 553 ((!$x->isa($self)) || (!$y->isa($self))); 554 555 # handle +-inf and NaN's 556 if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/) 557 { 558 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan)); 559 return 0 if ($x->is_inf() && $y->is_inf()); 560 return 1 if ($x->is_inf() && !$y->is_inf()); 561 return -1; 562 } 563 564 # shortcut 565 my $xz = $x->is_zero(); 566 my $yz = $y->is_zero(); 567 return 0 if $xz && $yz; # 0 <=> 0 568 return -1 if $xz && !$yz; # 0 <=> +y 569 return 1 if $yz && !$xz; # +x <=> 0 570 571 # adjust so that exponents are equal 572 my $lxm = $MBI->_len($x->{_m}); 573 my $lym = $MBI->_len($y->{_m}); 574 my ($xes,$yes) = (1,1); 575 $xes = -1 if $x->{_es} ne '+'; 576 $yes = -1 if $y->{_es} ne '+'; 577 # the numify somewhat limits our length, but makes it much faster 578 my $lx = $lxm + $xes * $MBI->_num($x->{_e}); 579 my $ly = $lym + $yes * $MBI->_num($y->{_e}); 580 my $l = $lx - $ly; 581 return $l <=> 0 if $l != 0; 582 583 # lengths (corrected by exponent) are equal 584 # so make mantissa equal-length by padding with zero (shift left) 585 my $diff = $lxm - $lym; 586 my $xm = $x->{_m}; # not yet copy it 587 my $ym = $y->{_m}; 588 if ($diff > 0) 589 { 590 $ym = $MBI->_copy($y->{_m}); 591 $ym = $MBI->_lsft($ym, $MBI->_new($diff), 10); 592 } 593 elsif ($diff < 0) 594 { 595 $xm = $MBI->_copy($x->{_m}); 596 $xm = $MBI->_lsft($xm, $MBI->_new(-$diff), 10); 597 } 598 $MBI->_acmp($xm,$ym); 599 } 600 601 sub badd 602 { 603 # add second arg (BFLOAT or string) to first (BFLOAT) (modifies first) 604 # return result as BFLOAT 605 606 # set up parameters 607 my ($self,$x,$y,@r) = (ref($_[0]),@_); 608 # objectify is costly, so avoid it 609 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) 610 { 611 ($self,$x,$y,@r) = objectify(2,@_); 612 } 613 614 return $x if $x->modify('badd'); 615 616 # inf and NaN handling 617 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/)) 618 { 619 # NaN first 620 return $x->bnan() if (($x->{sign} eq $nan) || ($y->{sign} eq $nan)); 621 # inf handling 622 if (($x->{sign} =~ /^[+-]inf$/) && ($y->{sign} =~ /^[+-]inf$/)) 623 { 624 # +inf++inf or -inf+-inf => same, rest is NaN 625 return $x if $x->{sign} eq $y->{sign}; 626 return $x->bnan(); 627 } 628 # +-inf + something => +inf; something +-inf => +-inf 629 $x->{sign} = $y->{sign}, return $x if $y->{sign} =~ /^[+-]inf$/; 630 return $x; 631 } 632 633 return $upgrade->badd($x,$y,@r) if defined $upgrade && 634 ((!$x->isa($self)) || (!$y->isa($self))); 635 636 $r[3] = $y; # no push! 637 638 # speed: no add for 0+y or x+0 639 return $x->bround(@r) if $y->is_zero(); # x+0 640 if ($x->is_zero()) # 0+y 641 { 642 # make copy, clobbering up x (modify in place!) 643 $x->{_e} = $MBI->_copy($y->{_e}); 644 $x->{_es} = $y->{_es}; 645 $x->{_m} = $MBI->_copy($y->{_m}); 646 $x->{sign} = $y->{sign} || $nan; 647 return $x->round(@r); 648 } 649 650 # take lower of the two e's and adapt m1 to it to match m2 651 my $e = $y->{_e}; 652 $e = $MBI->_zero() if !defined $e; # if no BFLOAT? 653 $e = $MBI->_copy($e); # make copy (didn't do it yet) 654 655 my $es; 656 657 ($e,$es) = _e_sub($e, $x->{_e}, $y->{_es} || '+', $x->{_es}); 658 659 my $add = $MBI->_copy($y->{_m}); 660 661 if ($es eq '-') # < 0 662 { 663 $MBI->_lsft( $x->{_m}, $e, 10); 664 ($x->{_e},$x->{_es}) = _e_add($x->{_e}, $e, $x->{_es}, $es); 665 } 666 elsif (!$MBI->_is_zero($e)) # > 0 667 { 668 $MBI->_lsft($add, $e, 10); 669 } 670 # else: both e are the same, so just leave them 671 672 if ($x->{sign} eq $y->{sign}) 673 { 674 # add 675 $x->{_m} = $MBI->_add($x->{_m}, $add); 676 } 677 else 678 { 679 ($x->{_m}, $x->{sign}) = 680 _e_add($x->{_m}, $add, $x->{sign}, $y->{sign}); 681 } 682 683 # delete trailing zeros, then round 684 $x->bnorm()->round(@r); 685 } 686 687 # sub bsub is inherited from Math::BigInt! 688 689 sub binc 690 { 691 # increment arg by one 692 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_); 693 694 return $x if $x->modify('binc'); 695 696 if ($x->{_es} eq '-') 697 { 698 return $x->badd($self->bone(),@r); # digits after dot 699 } 700 701 if (!$MBI->_is_zero($x->{_e})) # _e == 0 for NaN, inf, -inf 702 { 703 # 1e2 => 100, so after the shift below _m has a '0' as last digit 704 $x->{_m} = $MBI->_lsft($x->{_m}, $x->{_e},10); # 1e2 => 100 705 $x->{_e} = $MBI->_zero(); # normalize 706 $x->{_es} = '+'; 707 # we know that the last digit of $x will be '1' or '9', depending on the 708 # sign 709 } 710 # now $x->{_e} == 0 711 if ($x->{sign} eq '+') 712 { 713 $MBI->_inc($x->{_m}); 714 return $x->bnorm()->bround(@r); 715 } 716 elsif ($x->{sign} eq '-') 717 { 718 $MBI->_dec($x->{_m}); 719 $x->{sign} = '+' if $MBI->_is_zero($x->{_m}); # -1 +1 => -0 => +0 720 return $x->bnorm()->bround(@r); 721 } 722 # inf, nan handling etc 723 $x->badd($self->bone(),@r); # badd() does round 724 } 725 726 sub bdec 727 { 728 # decrement arg by one 729 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_); 730 731 return $x if $x->modify('bdec'); 732 733 if ($x->{_es} eq '-') 734 { 735 return $x->badd($self->bone('-'),@r); # digits after dot 736 } 737 738 if (!$MBI->_is_zero($x->{_e})) 739 { 740 $x->{_m} = $MBI->_lsft($x->{_m}, $x->{_e},10); # 1e2 => 100 741 $x->{_e} = $MBI->_zero(); # normalize 742 $x->{_es} = '+'; 743 } 744 # now $x->{_e} == 0 745 my $zero = $x->is_zero(); 746 # <= 0 747 if (($x->{sign} eq '-') || $zero) 748 { 749 $MBI->_inc($x->{_m}); 750 $x->{sign} = '-' if $zero; # 0 => 1 => -1 751 $x->{sign} = '+' if $MBI->_is_zero($x->{_m}); # -1 +1 => -0 => +0 752 return $x->bnorm()->round(@r); 753 } 754 # > 0 755 elsif ($x->{sign} eq '+') 756 { 757 $MBI->_dec($x->{_m}); 758 return $x->bnorm()->round(@r); 759 } 760 # inf, nan handling etc 761 $x->badd($self->bone('-'),@r); # does round 762 } 763 764 sub DEBUG () { 0; } 765 766 sub blog 767 { 768 my ($self,$x,$base,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_); 769 770 return $x if $x->modify('blog'); 771 772 # $base > 0, $base != 1; if $base == undef default to $base == e 773 # $x >= 0 774 775 # we need to limit the accuracy to protect against overflow 776 my $fallback = 0; 777 my ($scale,@params); 778 ($x,@params) = $x->_find_round_parameters($a,$p,$r); 779 780 # also takes care of the "error in _find_round_parameters?" case 781 return $x->bnan() if $x->{sign} ne '+' || $x->is_zero(); 782 783 # no rounding at all, so must use fallback 784 if (scalar @params == 0) 785 { 786 # simulate old behaviour 787 $params[0] = $self->div_scale(); # and round to it as accuracy 788 $params[1] = undef; # P = undef 789 $scale = $params[0]+4; # at least four more for proper round 790 $params[2] = $r; # round mode by caller or undef 791 $fallback = 1; # to clear a/p afterwards 792 } 793 else 794 { 795 # the 4 below is empirical, and there might be cases where it is not 796 # enough... 797 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 798 } 799 800 return $x->bzero(@params) if $x->is_one(); 801 # base not defined => base == Euler's number e 802 if (defined $base) 803 { 804 # make object, since we don't feed it through objectify() to still get the 805 # case of $base == undef 806 $base = $self->new($base) unless ref($base); 807 # $base > 0; $base != 1 808 return $x->bnan() if $base->is_zero() || $base->is_one() || 809 $base->{sign} ne '+'; 810 # if $x == $base, we know the result must be 1.0 811 if ($x->bcmp($base) == 0) 812 { 813 $x->bone('+',@params); 814 if ($fallback) 815 { 816 # clear a/p after round, since user did not request it 817 delete $x->{_a}; delete $x->{_p}; 818 } 819 return $x; 820 } 821 } 822 823 # when user set globals, they would interfere with our calculation, so 824 # disable them and later re-enable them 825 no strict 'refs'; 826 my $abr = "$self\::accuracy"; my $ab = $$abr; $$abr = undef; 827 my $pbr = "$self\::precision"; my $pb = $$pbr; $$pbr = undef; 828 # we also need to disable any set A or P on $x (_find_round_parameters took 829 # them already into account), since these would interfere, too 830 delete $x->{_a}; delete $x->{_p}; 831 # need to disable $upgrade in BigInt, to avoid deep recursion 832 local $Math::BigInt::upgrade = undef; 833 local $Math::BigFloat::downgrade = undef; 834 835 # upgrade $x if $x is not a BigFloat (handle BigInt input) 836 # XXX TODO: rebless! 837 if (!$x->isa('Math::BigFloat')) 838 { 839 $x = Math::BigFloat->new($x); 840 $self = ref($x); 841 } 842 843 my $done = 0; 844 845 # If the base is defined and an integer, try to calculate integer result 846 # first. This is very fast, and in case the real result was found, we can 847 # stop right here. 848 if (defined $base && $base->is_int() && $x->is_int()) 849 { 850 my $i = $MBI->_copy( $x->{_m} ); 851 $MBI->_lsft( $i, $x->{_e}, 10 ) unless $MBI->_is_zero($x->{_e}); 852 my $int = Math::BigInt->bzero(); 853 $int->{value} = $i; 854 $int->blog($base->as_number()); 855 # if ($exact) 856 if ($base->as_number()->bpow($int) == $x) 857 { 858 # found result, return it 859 $x->{_m} = $int->{value}; 860 $x->{_e} = $MBI->_zero(); 861 $x->{_es} = '+'; 862 $x->bnorm(); 863 $done = 1; 864 } 865 } 866 867 if ($done == 0) 868 { 869 # base is undef, so base should be e (Euler's number), so first calculate the 870 # log to base e (using reduction by 10 (and probably 2)): 871 $self->_log_10($x,$scale); 872 873 # and if a different base was requested, convert it 874 if (defined $base) 875 { 876 $base = Math::BigFloat->new($base) unless $base->isa('Math::BigFloat'); 877 # not ln, but some other base (don't modify $base) 878 $x->bdiv( $base->copy()->blog(undef,$scale), $scale ); 879 } 880 } 881 882 # shortcut to not run through _find_round_parameters again 883 if (defined $params[0]) 884 { 885 $x->bround($params[0],$params[2]); # then round accordingly 886 } 887 else 888 { 889 $x->bfround($params[1],$params[2]); # then round accordingly 890 } 891 if ($fallback) 892 { 893 # clear a/p after round, since user did not request it 894 delete $x->{_a}; delete $x->{_p}; 895 } 896 # restore globals 897 $$abr = $ab; $$pbr = $pb; 898 899 $x; 900 } 901 902 sub _len_to_steps 903 { 904 # Given D (digits in decimal), compute N so that N! (N factorial) is 905 # at least D digits long. D should be at least 50. 906 my $d = shift; 907 908 # two constants for the Ramanujan estimate of ln(N!) 909 my $lg2 = log(2 * 3.14159265) / 2; 910 my $lg10 = log(10); 911 912 # D = 50 => N => 42, so L = 40 and R = 50 913 my $l = 40; my $r = $d; 914 915 # Otherwise this does not work under -Mbignum and we do not yet have "no bignum;" :( 916 $l = $l->numify if ref($l); 917 $r = $r->numify if ref($r); 918 $lg2 = $lg2->numify if ref($lg2); 919 $lg10 = $lg10->numify if ref($lg10); 920 921 # binary search for the right value (could this be written as the reverse of lg(n!)?) 922 while ($r - $l > 1) 923 { 924 my $n = int(($r - $l) / 2) + $l; 925 my $ramanujan = 926 int(($n * log($n) - $n + log( $n * (1 + 4*$n*(1+2*$n)) ) / 6 + $lg2) / $lg10); 927 $ramanujan > $d ? $r = $n : $l = $n; 928 } 929 $l; 930 } 931 932 sub bnok 933 { 934 # Calculate n over k (binomial coefficient or "choose" function) as integer. 935 # set up parameters 936 my ($self,$x,$y,@r) = (ref($_[0]),@_); 937 938 # objectify is costly, so avoid it 939 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) 940 { 941 ($self,$x,$y,@r) = objectify(2,@_); 942 } 943 944 return $x if $x->modify('bnok'); 945 946 return $x->bnan() if $x->is_nan() || $y->is_nan(); 947 return $x->binf() if $x->is_inf(); 948 949 my $u = $x->as_int(); 950 $u->bnok($y->as_int()); 951 952 $x->{_m} = $u->{value}; 953 $x->{_e} = $MBI->_zero(); 954 $x->{_es} = '+'; 955 $x->{sign} = '+'; 956 $x->bnorm(@r); 957 } 958 959 sub bexp 960 { 961 # Calculate e ** X (Euler's number to the power of X) 962 my ($self,$x,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_); 963 964 return $x if $x->modify('bexp'); 965 966 return $x->binf() if $x->{sign} eq '+inf'; 967 return $x->bzero() if $x->{sign} eq '-inf'; 968 969 # we need to limit the accuracy to protect against overflow 970 my $fallback = 0; 971 my ($scale,@params); 972 ($x,@params) = $x->_find_round_parameters($a,$p,$r); 973 974 # also takes care of the "error in _find_round_parameters?" case 975 return $x if $x->{sign} eq 'NaN'; 976 977 # no rounding at all, so must use fallback 978 if (scalar @params == 0) 979 { 980 # simulate old behaviour 981 $params[0] = $self->div_scale(); # and round to it as accuracy 982 $params[1] = undef; # P = undef 983 $scale = $params[0]+4; # at least four more for proper round 984 $params[2] = $r; # round mode by caller or undef 985 $fallback = 1; # to clear a/p afterwards 986 } 987 else 988 { 989 # the 4 below is empirical, and there might be cases where it's not enough... 990 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 991 } 992 993 return $x->bone(@params) if $x->is_zero(); 994 995 if (!$x->isa('Math::BigFloat')) 996 { 997 $x = Math::BigFloat->new($x); 998 $self = ref($x); 999 } 1000 1001 # when user set globals, they would interfere with our calculation, so 1002 # disable them and later re-enable them 1003 no strict 'refs'; 1004 my $abr = "$self\::accuracy"; my $ab = $$abr; $$abr = undef; 1005 my $pbr = "$self\::precision"; my $pb = $$pbr; $$pbr = undef; 1006 # we also need to disable any set A or P on $x (_find_round_parameters took 1007 # them already into account), since these would interfere, too 1008 delete $x->{_a}; delete $x->{_p}; 1009 # need to disable $upgrade in BigInt, to avoid deep recursion 1010 local $Math::BigInt::upgrade = undef; 1011 local $Math::BigFloat::downgrade = undef; 1012 1013 my $x_org = $x->copy(); 1014 1015 # We use the following Taylor series: 1016 1017 # x x^2 x^3 x^4 1018 # e = 1 + --- + --- + --- + --- ... 1019 # 1! 2! 3! 4! 1020 1021 # The difference for each term is X and N, which would result in: 1022 # 2 copy, 2 mul, 2 add, 1 inc, 1 div operations per term 1023 1024 # But it is faster to compute exp(1) and then raising it to the 1025 # given power, esp. if $x is really big and an integer because: 1026 1027 # * The numerator is always 1, making the computation faster 1028 # * the series converges faster in the case of x == 1 1029 # * We can also easily check when we have reached our limit: when the 1030 # term to be added is smaller than "1E$scale", we can stop - f.i. 1031 # scale == 5, and we have 1/40320, then we stop since 1/40320 < 1E-5. 1032 # * we can compute the *exact* result by simulating bigrat math: 1033 1034 # 1 1 gcd(3,4) = 1 1*24 + 1*6 5 1035 # - + - = ---------- = -- 1036 # 6 24 6*24 24 1037 1038 # We do not compute the gcd() here, but simple do: 1039 # 1 1 1*24 + 1*6 30 1040 # - + - = --------- = -- 1041 # 6 24 6*24 144 1042 1043 # In general: 1044 # a c a*d + c*b and note that c is always 1 and d = (b*f) 1045 # - + - = --------- 1046 # b d b*d 1047 1048 # This leads to: which can be reduced by b to: 1049 # a 1 a*b*f + b a*f + 1 1050 # - + - = --------- = ------- 1051 # b b*f b*b*f b*f 1052 1053 # The first terms in the series are: 1054 1055 # 1 1 1 1 1 1 1 1 13700 1056 # -- + -- + -- + -- + -- + --- + --- + ---- = ----- 1057 # 1 1 2 6 24 120 720 5040 5040 1058 1059 # Note that we cannot simple reduce 13700/5040 to 685/252, but must keep A and B! 1060 1061 if ($scale <= 75) 1062 { 1063 # set $x directly from a cached string form 1064 $x->{_m} = $MBI->_new( 1065 "27182818284590452353602874713526624977572470936999595749669676277240766303535476"); 1066 $x->{sign} = '+'; 1067 $x->{_es} = '-'; 1068 $x->{_e} = $MBI->_new(79); 1069 } 1070 else 1071 { 1072 # compute A and B so that e = A / B. 1073 1074 # After some terms we end up with this, so we use it as a starting point: 1075 my $A = $MBI->_new("90933395208605785401971970164779391644753259799242"); 1076 my $F = $MBI->_new(42); my $step = 42; 1077 1078 # Compute how many steps we need to take to get $A and $B sufficiently big 1079 my $steps = _len_to_steps($scale - 4); 1080 # print STDERR "# Doing $steps steps for ", $scale-4, " digits\n"; 1081 while ($step++ <= $steps) 1082 { 1083 # calculate $a * $f + 1 1084 $A = $MBI->_mul($A, $F); 1085 $A = $MBI->_inc($A); 1086 # increment f 1087 $F = $MBI->_inc($F); 1088 } 1089 # compute $B as factorial of $steps (this is faster than doing it manually) 1090 my $B = $MBI->_fac($MBI->_new($steps)); 1091 1092 # print "A ", $MBI->_str($A), "\nB ", $MBI->_str($B), "\n"; 1093 1094 # compute A/B with $scale digits in the result (truncate, not round) 1095 $A = $MBI->_lsft( $A, $MBI->_new($scale), 10); 1096 $A = $MBI->_div( $A, $B ); 1097 1098 $x->{_m} = $A; 1099 $x->{sign} = '+'; 1100 $x->{_es} = '-'; 1101 $x->{_e} = $MBI->_new($scale); 1102 } 1103 1104 # $x contains now an estimate of e, with some surplus digits, so we can round 1105 if (!$x_org->is_one()) 1106 { 1107 # raise $x to the wanted power and round it in one step: 1108 $x->bpow($x_org, @params); 1109 } 1110 else 1111 { 1112 # else just round the already computed result 1113 delete $x->{_a}; delete $x->{_p}; 1114 # shortcut to not run through _find_round_parameters again 1115 if (defined $params[0]) 1116 { 1117 $x->bround($params[0],$params[2]); # then round accordingly 1118 } 1119 else 1120 { 1121 $x->bfround($params[1],$params[2]); # then round accordingly 1122 } 1123 } 1124 if ($fallback) 1125 { 1126 # clear a/p after round, since user did not request it 1127 delete $x->{_a}; delete $x->{_p}; 1128 } 1129 # restore globals 1130 $$abr = $ab; $$pbr = $pb; 1131 1132 $x; # return modified $x 1133 } 1134 1135 sub _log 1136 { 1137 # internal log function to calculate ln() based on Taylor series. 1138 # Modifies $x in place. 1139 my ($self,$x,$scale) = @_; 1140 1141 # in case of $x == 1, result is 0 1142 return $x->bzero() if $x->is_one(); 1143 1144 # XXX TODO: rewrite this in a similiar manner to bexp() 1145 1146 # http://www.efunda.com/math/taylor_series/logarithmic.cfm?search_string=log 1147 1148 # u = x-1, v = x+1 1149 # _ _ 1150 # Taylor: | u 1 u^3 1 u^5 | 1151 # ln (x) = 2 | --- + - * --- + - * --- + ... | x > 0 1152 # |_ v 3 v^3 5 v^5 _| 1153 1154 # This takes much more steps to calculate the result and is thus not used 1155 # u = x-1 1156 # _ _ 1157 # Taylor: | u 1 u^2 1 u^3 | 1158 # ln (x) = 2 | --- + - * --- + - * --- + ... | x > 1/2 1159 # |_ x 2 x^2 3 x^3 _| 1160 1161 my ($limit,$v,$u,$below,$factor,$two,$next,$over,$f); 1162 1163 $v = $x->copy(); $v->binc(); # v = x+1 1164 $x->bdec(); $u = $x->copy(); # u = x-1; x = x-1 1165 $x->bdiv($v,$scale); # first term: u/v 1166 $below = $v->copy(); 1167 $over = $u->copy(); 1168 $u *= $u; $v *= $v; # u^2, v^2 1169 $below->bmul($v); # u^3, v^3 1170 $over->bmul($u); 1171 $factor = $self->new(3); $f = $self->new(2); 1172 1173 my $steps = 0 if DEBUG; 1174 $limit = $self->new("1E-". ($scale-1)); 1175 while (3 < 5) 1176 { 1177 # we calculate the next term, and add it to the last 1178 # when the next term is below our limit, it won't affect the outcome 1179 # anymore, so we stop 1180 1181 # calculating the next term simple from over/below will result in quite 1182 # a time hog if the input has many digits, since over and below will 1183 # accumulate more and more digits, and the result will also have many 1184 # digits, but in the end it is rounded to $scale digits anyway. So if we 1185 # round $over and $below first, we save a lot of time for the division 1186 # (not with log(1.2345), but try log (123**123) to see what I mean. This 1187 # can introduce a rounding error if the division result would be f.i. 1188 # 0.1234500000001 and we round it to 5 digits it would become 0.12346, but 1189 # if we truncated $over and $below we might get 0.12345. Does this matter 1190 # for the end result? So we give $over and $below 4 more digits to be 1191 # on the safe side (unscientific error handling as usual... :+D 1192 1193 $next = $over->copy->bround($scale+4)->bdiv( 1194 $below->copy->bmul($factor)->bround($scale+4), 1195 $scale); 1196 1197 ## old version: 1198 ## $next = $over->copy()->bdiv($below->copy()->bmul($factor),$scale); 1199 1200 last if $next->bacmp($limit) <= 0; 1201 1202 delete $next->{_a}; delete $next->{_p}; 1203 $x->badd($next); 1204 # calculate things for the next term 1205 $over *= $u; $below *= $v; $factor->badd($f); 1206 if (DEBUG) 1207 { 1208 $steps++; print "step $steps = $x\n" if $steps % 10 == 0; 1209 } 1210 } 1211 print "took $steps steps\n" if DEBUG; 1212 $x->bmul($f); # $x *= 2 1213 } 1214 1215 sub _log_10 1216 { 1217 # Internal log function based on reducing input to the range of 0.1 .. 9.99 1218 # and then "correcting" the result to the proper one. Modifies $x in place. 1219 my ($self,$x,$scale) = @_; 1220 1221 # Taking blog() from numbers greater than 10 takes a *very long* time, so we 1222 # break the computation down into parts based on the observation that: 1223 # blog(X*Y) = blog(X) + blog(Y) 1224 # We set Y here to multiples of 10 so that $x becomes below 1 - the smaller 1225 # $x is the faster it gets. Since 2*$x takes about 10 times as 1226 # long, we make it faster by about a factor of 100 by dividing $x by 10. 1227 1228 # The same observation is valid for numbers smaller than 0.1, e.g. computing 1229 # log(1) is fastest, and the further away we get from 1, the longer it takes. 1230 # So we also 'break' this down by multiplying $x with 10 and subtract the 1231 # log(10) afterwards to get the correct result. 1232 1233 # To get $x even closer to 1, we also divide by 2 and then use log(2) to 1234 # correct for this. For instance if $x is 2.4, we use the formula: 1235 # blog(2.4 * 2) == blog (1.2) + blog(2) 1236 # and thus calculate only blog(1.2) and blog(2), which is faster in total 1237 # than calculating blog(2.4). 1238 1239 # In addition, the values for blog(2) and blog(10) are cached. 1240 1241 # Calculate nr of digits before dot: 1242 my $dbd = $MBI->_num($x->{_e}); 1243 $dbd = -$dbd if $x->{_es} eq '-'; 1244 $dbd += $MBI->_len($x->{_m}); 1245 1246 # more than one digit (e.g. at least 10), but *not* exactly 10 to avoid 1247 # infinite recursion 1248 1249 my $calc = 1; # do some calculation? 1250 1251 # disable the shortcut for 10, since we need log(10) and this would recurse 1252 # infinitely deep 1253 if ($x->{_es} eq '+' && $MBI->_is_one($x->{_e}) && $MBI->_is_one($x->{_m})) 1254 { 1255 $dbd = 0; # disable shortcut 1256 # we can use the cached value in these cases 1257 if ($scale <= $LOG_10_A) 1258 { 1259 $x->bzero(); $x->badd($LOG_10); # modify $x in place 1260 $calc = 0; # no need to calc, but round 1261 } 1262 # if we can't use the shortcut, we continue normally 1263 } 1264 else 1265 { 1266 # disable the shortcut for 2, since we maybe have it cached 1267 if (($MBI->_is_zero($x->{_e}) && $MBI->_is_two($x->{_m}))) 1268 { 1269 $dbd = 0; # disable shortcut 1270 # we can use the cached value in these cases 1271 if ($scale <= $LOG_2_A) 1272 { 1273 $x->bzero(); $x->badd($LOG_2); # modify $x in place 1274 $calc = 0; # no need to calc, but round 1275 } 1276 # if we can't use the shortcut, we continue normally 1277 } 1278 } 1279 1280 # if $x = 0.1, we know the result must be 0-log(10) 1281 if ($calc != 0 && $x->{_es} eq '-' && $MBI->_is_one($x->{_e}) && 1282 $MBI->_is_one($x->{_m})) 1283 { 1284 $dbd = 0; # disable shortcut 1285 # we can use the cached value in these cases 1286 if ($scale <= $LOG_10_A) 1287 { 1288 $x->bzero(); $x->bsub($LOG_10); 1289 $calc = 0; # no need to calc, but round 1290 } 1291 } 1292 1293 return if $calc == 0; # already have the result 1294 1295 # default: these correction factors are undef and thus not used 1296 my $l_10; # value of ln(10) to A of $scale 1297 my $l_2; # value of ln(2) to A of $scale 1298 1299 my $two = $self->new(2); 1300 1301 # $x == 2 => 1, $x == 13 => 2, $x == 0.1 => 0, $x == 0.01 => -1 1302 # so don't do this shortcut for 1 or 0 1303 if (($dbd > 1) || ($dbd < 0)) 1304 { 1305 # convert our cached value to an object if not already (avoid doing this 1306 # at import() time, since not everybody needs this) 1307 $LOG_10 = $self->new($LOG_10,undef,undef) unless ref $LOG_10; 1308 1309 #print "x = $x, dbd = $dbd, calc = $calc\n"; 1310 # got more than one digit before the dot, or more than one zero after the 1311 # dot, so do: 1312 # log(123) == log(1.23) + log(10) * 2 1313 # log(0.0123) == log(1.23) - log(10) * 2 1314 1315 if ($scale <= $LOG_10_A) 1316 { 1317 # use cached value 1318 $l_10 = $LOG_10->copy(); # copy for mul 1319 } 1320 else 1321 { 1322 # else: slower, compute and cache result 1323 # also disable downgrade for this code path 1324 local $Math::BigFloat::downgrade = undef; 1325 1326 # shorten the time to calculate log(10) based on the following: 1327 # log(1.25 * 8) = log(1.25) + log(8) 1328 # = log(1.25) + log(2) + log(2) + log(2) 1329 1330 # first get $l_2 (and possible compute and cache log(2)) 1331 $LOG_2 = $self->new($LOG_2,undef,undef) unless ref $LOG_2; 1332 if ($scale <= $LOG_2_A) 1333 { 1334 # use cached value 1335 $l_2 = $LOG_2->copy(); # copy() for the mul below 1336 } 1337 else 1338 { 1339 # else: slower, compute and cache result 1340 $l_2 = $two->copy(); $self->_log($l_2, $scale); # scale+4, actually 1341 $LOG_2 = $l_2->copy(); # cache the result for later 1342 # the copy() is for mul below 1343 $LOG_2_A = $scale; 1344 } 1345 1346 # now calculate log(1.25): 1347 $l_10 = $self->new('1.25'); $self->_log($l_10, $scale); # scale+4, actually 1348 1349 # log(1.25) + log(2) + log(2) + log(2): 1350 $l_10->badd($l_2); 1351 $l_10->badd($l_2); 1352 $l_10->badd($l_2); 1353 $LOG_10 = $l_10->copy(); # cache the result for later 1354 # the copy() is for mul below 1355 $LOG_10_A = $scale; 1356 } 1357 $dbd-- if ($dbd > 1); # 20 => dbd=2, so make it dbd=1 1358 $l_10->bmul( $self->new($dbd)); # log(10) * (digits_before_dot-1) 1359 my $dbd_sign = '+'; 1360 if ($dbd < 0) 1361 { 1362 $dbd = -$dbd; 1363 $dbd_sign = '-'; 1364 } 1365 ($x->{_e}, $x->{_es}) = 1366 _e_sub( $x->{_e}, $MBI->_new($dbd), $x->{_es}, $dbd_sign); # 123 => 1.23 1367 1368 } 1369 1370 # Now: 0.1 <= $x < 10 (and possible correction in l_10) 1371 1372 ### Since $x in the range 0.5 .. 1.5 is MUCH faster, we do a repeated div 1373 ### or mul by 2 (maximum times 3, since x < 10 and x > 0.1) 1374 1375 $HALF = $self->new($HALF) unless ref($HALF); 1376 1377 my $twos = 0; # default: none (0 times) 1378 while ($x->bacmp($HALF) <= 0) # X <= 0.5 1379 { 1380 $twos--; $x->bmul($two); 1381 } 1382 while ($x->bacmp($two) >= 0) # X >= 2 1383 { 1384 $twos++; $x->bdiv($two,$scale+4); # keep all digits 1385 } 1386 # $twos > 0 => did mul 2, < 0 => did div 2 (but we never did both) 1387 # So calculate correction factor based on ln(2): 1388 if ($twos != 0) 1389 { 1390 $LOG_2 = $self->new($LOG_2,undef,undef) unless ref $LOG_2; 1391 if ($scale <= $LOG_2_A) 1392 { 1393 # use cached value 1394 $l_2 = $LOG_2->copy(); # copy() for the mul below 1395 } 1396 else 1397 { 1398 # else: slower, compute and cache result 1399 # also disable downgrade for this code path 1400 local $Math::BigFloat::downgrade = undef; 1401 $l_2 = $two->copy(); $self->_log($l_2, $scale); # scale+4, actually 1402 $LOG_2 = $l_2->copy(); # cache the result for later 1403 # the copy() is for mul below 1404 $LOG_2_A = $scale; 1405 } 1406 $l_2->bmul($twos); # * -2 => subtract, * 2 => add 1407 } 1408 1409 $self->_log($x,$scale); # need to do the "normal" way 1410 $x->badd($l_10) if defined $l_10; # correct it by ln(10) 1411 $x->badd($l_2) if defined $l_2; # and maybe by ln(2) 1412 1413 # all done, $x contains now the result 1414 $x; 1415 } 1416 1417 sub blcm 1418 { 1419 # (BFLOAT or num_str, BFLOAT or num_str) return BFLOAT 1420 # does not modify arguments, but returns new object 1421 # Lowest Common Multiplicator 1422 1423 my ($self,@arg) = objectify(0,@_); 1424 my $x = $self->new(shift @arg); 1425 while (@arg) { $x = Math::BigInt::__lcm($x,shift @arg); } 1426 $x; 1427 } 1428 1429 sub bgcd 1430 { 1431 # (BINT or num_str, BINT or num_str) return BINT 1432 # does not modify arguments, but returns new object 1433 1434 my $y = shift; 1435 $y = __PACKAGE__->new($y) if !ref($y); 1436 my $self = ref($y); 1437 my $x = $y->copy()->babs(); # keep arguments 1438 1439 return $x->bnan() if $x->{sign} !~ /^[+-]$/ # x NaN? 1440 || !$x->is_int(); # only for integers now 1441 1442 while (@_) 1443 { 1444 my $t = shift; $t = $self->new($t) if !ref($t); 1445 $y = $t->copy()->babs(); 1446 1447 return $x->bnan() if $y->{sign} !~ /^[+-]$/ # y NaN? 1448 || !$y->is_int(); # only for integers now 1449 1450 # greatest common divisor 1451 while (! $y->is_zero()) 1452 { 1453 ($x,$y) = ($y->copy(), $x->copy()->bmod($y)); 1454 } 1455 1456 last if $x->is_one(); 1457 } 1458 $x; 1459 } 1460 1461 ############################################################################## 1462 1463 sub _e_add 1464 { 1465 # Internal helper sub to take two positive integers and their signs and 1466 # then add them. Input ($CALC,$CALC,('+'|'-'),('+'|'-')), 1467 # output ($CALC,('+'|'-')) 1468 my ($x,$y,$xs,$ys) = @_; 1469 1470 # if the signs are equal we can add them (-5 + -3 => -(5 + 3) => -8) 1471 if ($xs eq $ys) 1472 { 1473 $x = $MBI->_add ($x, $y ); # a+b 1474 # the sign follows $xs 1475 return ($x, $xs); 1476 } 1477 1478 my $a = $MBI->_acmp($x,$y); 1479 if ($a > 0) 1480 { 1481 $x = $MBI->_sub ($x , $y); # abs sub 1482 } 1483 elsif ($a == 0) 1484 { 1485 $x = $MBI->_zero(); # result is 0 1486 $xs = '+'; 1487 } 1488 else # a < 0 1489 { 1490 $x = $MBI->_sub ( $y, $x, 1 ); # abs sub 1491 $xs = $ys; 1492 } 1493 ($x,$xs); 1494 } 1495 1496 sub _e_sub 1497 { 1498 # Internal helper sub to take two positive integers and their signs and 1499 # then subtract them. Input ($CALC,$CALC,('+'|'-'),('+'|'-')), 1500 # output ($CALC,('+'|'-')) 1501 my ($x,$y,$xs,$ys) = @_; 1502 1503 # flip sign 1504 $ys =~ tr/+-/-+/; 1505 _e_add($x,$y,$xs,$ys); # call add (does subtract now) 1506 } 1507 1508 ############################################################################### 1509 # is_foo methods (is_negative, is_positive are inherited from BigInt) 1510 1511 sub is_int 1512 { 1513 # return true if arg (BFLOAT or num_str) is an integer 1514 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_); 1515 1516 (($x->{sign} =~ /^[+-]$/) && # NaN and +-inf aren't 1517 ($x->{_es} eq '+')) ? 1 : 0; # 1e-1 => no integer 1518 } 1519 1520 sub is_zero 1521 { 1522 # return true if arg (BFLOAT or num_str) is zero 1523 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_); 1524 1525 ($x->{sign} eq '+' && $MBI->_is_zero($x->{_m})) ? 1 : 0; 1526 } 1527 1528 sub is_one 1529 { 1530 # return true if arg (BFLOAT or num_str) is +1 or -1 if signis given 1531 my ($self,$x,$sign) = ref($_[0]) ? (undef,@_) : objectify(1,@_); 1532 1533 $sign = '+' if !defined $sign || $sign ne '-'; 1534 1535 ($x->{sign} eq $sign && 1536 $MBI->_is_zero($x->{_e}) && 1537 $MBI->_is_one($x->{_m}) ) ? 1 : 0; 1538 } 1539 1540 sub is_odd 1541 { 1542 # return true if arg (BFLOAT or num_str) is odd or false if even 1543 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_); 1544 1545 (($x->{sign} =~ /^[+-]$/) && # NaN & +-inf aren't 1546 ($MBI->_is_zero($x->{_e})) && 1547 ($MBI->_is_odd($x->{_m}))) ? 1 : 0; 1548 } 1549 1550 sub is_even 1551 { 1552 # return true if arg (BINT or num_str) is even or false if odd 1553 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_); 1554 1555 (($x->{sign} =~ /^[+-]$/) && # NaN & +-inf aren't 1556 ($x->{_es} eq '+') && # 123.45 isn't 1557 ($MBI->_is_even($x->{_m}))) ? 1 : 0; # but 1200 is 1558 } 1559 1560 sub bmul 1561 { 1562 # multiply two numbers 1563 1564 # set up parameters 1565 my ($self,$x,$y,@r) = (ref($_[0]),@_); 1566 # objectify is costly, so avoid it 1567 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) 1568 { 1569 ($self,$x,$y,@r) = objectify(2,@_); 1570 } 1571 1572 return $x if $x->modify('bmul'); 1573 1574 return $x->bnan() if (($x->{sign} eq $nan) || ($y->{sign} eq $nan)); 1575 1576 # inf handling 1577 if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/)) 1578 { 1579 return $x->bnan() if $x->is_zero() || $y->is_zero(); 1580 # result will always be +-inf: 1581 # +inf * +/+inf => +inf, -inf * -/-inf => +inf 1582 # +inf * -/-inf => -inf, -inf * +/+inf => -inf 1583 return $x->binf() if ($x->{sign} =~ /^\+/ && $y->{sign} =~ /^\+/); 1584 return $x->binf() if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/); 1585 return $x->binf('-'); 1586 } 1587 1588 return $upgrade->bmul($x,$y,@r) if defined $upgrade && 1589 ((!$x->isa($self)) || (!$y->isa($self))); 1590 1591 # aEb * cEd = (a*c)E(b+d) 1592 $MBI->_mul($x->{_m},$y->{_m}); 1593 ($x->{_e}, $x->{_es}) = _e_add($x->{_e}, $y->{_e}, $x->{_es}, $y->{_es}); 1594 1595 $r[3] = $y; # no push! 1596 1597 # adjust sign: 1598 $x->{sign} = $x->{sign} ne $y->{sign} ? '-' : '+'; 1599 $x->bnorm->round(@r); 1600 } 1601 1602 sub bmuladd 1603 { 1604 # multiply two numbers and add the third to the result 1605 1606 # set up parameters 1607 my ($self,$x,$y,$z,@r) = (ref($_[0]),@_); 1608 # objectify is costly, so avoid it 1609 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) 1610 { 1611 ($self,$x,$y,$z,@r) = objectify(3,@_); 1612 } 1613 1614 return $x if $x->modify('bmuladd'); 1615 1616 return $x->bnan() if (($x->{sign} eq $nan) || 1617 ($y->{sign} eq $nan) || 1618 ($z->{sign} eq $nan)); 1619 1620 # inf handling 1621 if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/)) 1622 { 1623 return $x->bnan() if $x->is_zero() || $y->is_zero(); 1624 # result will always be +-inf: 1625 # +inf * +/+inf => +inf, -inf * -/-inf => +inf 1626 # +inf * -/-inf => -inf, -inf * +/+inf => -inf 1627 return $x->binf() if ($x->{sign} =~ /^\+/ && $y->{sign} =~ /^\+/); 1628 return $x->binf() if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/); 1629 return $x->binf('-'); 1630 } 1631 1632 return $upgrade->bmul($x,$y,@r) if defined $upgrade && 1633 ((!$x->isa($self)) || (!$y->isa($self))); 1634 1635 # aEb * cEd = (a*c)E(b+d) 1636 $MBI->_mul($x->{_m},$y->{_m}); 1637 ($x->{_e}, $x->{_es}) = _e_add($x->{_e}, $y->{_e}, $x->{_es}, $y->{_es}); 1638 1639 $r[3] = $y; # no push! 1640 1641 # adjust sign: 1642 $x->{sign} = $x->{sign} ne $y->{sign} ? '-' : '+'; 1643 1644 # z=inf handling (z=NaN handled above) 1645 $x->{sign} = $z->{sign}, return $x if $z->{sign} =~ /^[+-]inf$/; 1646 1647 # take lower of the two e's and adapt m1 to it to match m2 1648 my $e = $z->{_e}; 1649 $e = $MBI->_zero() if !defined $e; # if no BFLOAT? 1650 $e = $MBI->_copy($e); # make copy (didn't do it yet) 1651 1652 my $es; 1653 1654 ($e,$es) = _e_sub($e, $x->{_e}, $z->{_es} || '+', $x->{_es}); 1655 1656 my $add = $MBI->_copy($z->{_m}); 1657 1658 if ($es eq '-') # < 0 1659 { 1660 $MBI->_lsft( $x->{_m}, $e, 10); 1661 ($x->{_e},$x->{_es}) = _e_add($x->{_e}, $e, $x->{_es}, $es); 1662 } 1663 elsif (!$MBI->_is_zero($e)) # > 0 1664 { 1665 $MBI->_lsft($add, $e, 10); 1666 } 1667 # else: both e are the same, so just leave them 1668 1669 if ($x->{sign} eq $z->{sign}) 1670 { 1671 # add 1672 $x->{_m} = $MBI->_add($x->{_m}, $add); 1673 } 1674 else 1675 { 1676 ($x->{_m}, $x->{sign}) = 1677 _e_add($x->{_m}, $add, $x->{sign}, $z->{sign}); 1678 } 1679 1680 # delete trailing zeros, then round 1681 $x->bnorm()->round(@r); 1682 } 1683 1684 sub bdiv 1685 { 1686 # (dividend: BFLOAT or num_str, divisor: BFLOAT or num_str) return 1687 # (BFLOAT,BFLOAT) (quo,rem) or BFLOAT (only rem) 1688 1689 # set up parameters 1690 my ($self,$x,$y,$a,$p,$r) = (ref($_[0]),@_); 1691 # objectify is costly, so avoid it 1692 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) 1693 { 1694 ($self,$x,$y,$a,$p,$r) = objectify(2,@_); 1695 } 1696 1697 return $x if $x->modify('bdiv'); 1698 1699 return $self->_div_inf($x,$y) 1700 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero()); 1701 1702 # x== 0 # also: or y == 1 or y == -1 1703 return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero(); 1704 1705 # upgrade ? 1706 return $upgrade->bdiv($upgrade->new($x),$y,$a,$p,$r) if defined $upgrade; 1707 1708 # we need to limit the accuracy to protect against overflow 1709 my $fallback = 0; 1710 my (@params,$scale); 1711 ($x,@params) = $x->_find_round_parameters($a,$p,$r,$y); 1712 1713 return $x if $x->is_nan(); # error in _find_round_parameters? 1714 1715 # no rounding at all, so must use fallback 1716 if (scalar @params == 0) 1717 { 1718 # simulate old behaviour 1719 $params[0] = $self->div_scale(); # and round to it as accuracy 1720 $scale = $params[0]+4; # at least four more for proper round 1721 $params[2] = $r; # round mode by caller or undef 1722 $fallback = 1; # to clear a/p afterwards 1723 } 1724 else 1725 { 1726 # the 4 below is empirical, and there might be cases where it is not 1727 # enough... 1728 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 1729 } 1730 1731 my $rem; $rem = $self->bzero() if wantarray; 1732 1733 $y = $self->new($y) unless $y->isa('Math::BigFloat'); 1734 1735 my $lx = $MBI->_len($x->{_m}); my $ly = $MBI->_len($y->{_m}); 1736 $scale = $lx if $lx > $scale; 1737 $scale = $ly if $ly > $scale; 1738 my $diff = $ly - $lx; 1739 $scale += $diff if $diff > 0; # if lx << ly, but not if ly << lx! 1740 1741 # already handled inf/NaN/-inf above: 1742 1743 # check that $y is not 1 nor -1 and cache the result: 1744 my $y_not_one = !($MBI->_is_zero($y->{_e}) && $MBI->_is_one($y->{_m})); 1745 1746 # flipping the sign of $y will also flip the sign of $x for the special 1747 # case of $x->bsub($x); so we can catch it below: 1748 my $xsign = $x->{sign}; 1749 $y->{sign} =~ tr/+-/-+/; 1750 1751 if ($xsign ne $x->{sign}) 1752 { 1753 # special case of $x /= $x results in 1 1754 $x->bone(); # "fixes" also sign of $y, since $x is $y 1755 } 1756 else 1757 { 1758 # correct $y's sign again 1759 $y->{sign} =~ tr/+-/-+/; 1760 # continue with normal div code: 1761 1762 # make copy of $x in case of list context for later reminder calculation 1763 if (wantarray && $y_not_one) 1764 { 1765 $rem = $x->copy(); 1766 } 1767 1768 $x->{sign} = $x->{sign} ne $y->sign() ? '-' : '+'; 1769 1770 # check for / +-1 ( +/- 1E0) 1771 if ($y_not_one) 1772 { 1773 # promote BigInts and it's subclasses (except when already a BigFloat) 1774 $y = $self->new($y) unless $y->isa('Math::BigFloat'); 1775 1776 # calculate the result to $scale digits and then round it 1777 # a * 10 ** b / c * 10 ** d => a/c * 10 ** (b-d) 1778 $MBI->_lsft($x->{_m},$MBI->_new($scale),10); 1779 $MBI->_div ($x->{_m},$y->{_m}); # a/c 1780 1781 # correct exponent of $x 1782 ($x->{_e},$x->{_es}) = _e_sub($x->{_e}, $y->{_e}, $x->{_es}, $y->{_es}); 1783 # correct for 10**scale 1784 ($x->{_e},$x->{_es}) = _e_sub($x->{_e}, $MBI->_new($scale), $x->{_es}, '+'); 1785 $x->bnorm(); # remove trailing 0's 1786 } 1787 } # ende else $x != $y 1788 1789 # shortcut to not run through _find_round_parameters again 1790 if (defined $params[0]) 1791 { 1792 delete $x->{_a}; # clear before round 1793 $x->bround($params[0],$params[2]); # then round accordingly 1794 } 1795 else 1796 { 1797 delete $x->{_p}; # clear before round 1798 $x->bfround($params[1],$params[2]); # then round accordingly 1799 } 1800 if ($fallback) 1801 { 1802 # clear a/p after round, since user did not request it 1803 delete $x->{_a}; delete $x->{_p}; 1804 } 1805 1806 if (wantarray) 1807 { 1808 if ($y_not_one) 1809 { 1810 $rem->bmod($y,@params); # copy already done 1811 } 1812 if ($fallback) 1813 { 1814 # clear a/p after round, since user did not request it 1815 delete $rem->{_a}; delete $rem->{_p}; 1816 } 1817 return ($x,$rem); 1818 } 1819 $x; 1820 } 1821 1822 sub bmod 1823 { 1824 # (dividend: BFLOAT or num_str, divisor: BFLOAT or num_str) return reminder 1825 1826 # set up parameters 1827 my ($self,$x,$y,$a,$p,$r) = (ref($_[0]),@_); 1828 # objectify is costly, so avoid it 1829 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) 1830 { 1831 ($self,$x,$y,$a,$p,$r) = objectify(2,@_); 1832 } 1833 1834 return $x if $x->modify('bmod'); 1835 1836 # handle NaN, inf, -inf 1837 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/)) 1838 { 1839 my ($d,$re) = $self->SUPER::_div_inf($x,$y); 1840 $x->{sign} = $re->{sign}; 1841 $x->{_e} = $re->{_e}; 1842 $x->{_m} = $re->{_m}; 1843 return $x->round($a,$p,$r,$y); 1844 } 1845 if ($y->is_zero()) 1846 { 1847 return $x->bnan() if $x->is_zero(); 1848 return $x; 1849 } 1850 1851 return $x->bzero() if $x->is_zero() 1852 || ($x->is_int() && 1853 # check that $y == +1 or $y == -1: 1854 ($MBI->_is_zero($y->{_e}) && $MBI->_is_one($y->{_m}))); 1855 1856 my $cmp = $x->bacmp($y); # equal or $x < $y? 1857 return $x->bzero($a,$p) if $cmp == 0; # $x == $y => result 0 1858 1859 # only $y of the operands negative? 1860 my $neg = 0; $neg = 1 if $x->{sign} ne $y->{sign}; 1861 1862 $x->{sign} = $y->{sign}; # calc sign first 1863 return $x->round($a,$p,$r) if $cmp < 0 && $neg == 0; # $x < $y => result $x 1864 1865 my $ym = $MBI->_copy($y->{_m}); 1866 1867 # 2e1 => 20 1868 $MBI->_lsft( $ym, $y->{_e}, 10) 1869 if $y->{_es} eq '+' && !$MBI->_is_zero($y->{_e}); 1870 1871 # if $y has digits after dot 1872 my $shifty = 0; # correct _e of $x by this 1873 if ($y->{_es} eq '-') # has digits after dot 1874 { 1875 # 123 % 2.5 => 1230 % 25 => 5 => 0.5 1876 $shifty = $MBI->_num($y->{_e}); # no more digits after dot 1877 $MBI->_lsft($x->{_m}, $y->{_e}, 10);# 123 => 1230, $y->{_m} is already 25 1878 } 1879 # $ym is now mantissa of $y based on exponent 0 1880 1881 my $shiftx = 0; # correct _e of $x by this 1882 if ($x->{_es} eq '-') # has digits after dot 1883 { 1884 # 123.4 % 20 => 1234 % 200 1885 $shiftx = $MBI->_num($x->{_e}); # no more digits after dot 1886 $MBI->_lsft($ym, $x->{_e}, 10); # 123 => 1230 1887 } 1888 # 123e1 % 20 => 1230 % 20 1889 if ($x->{_es} eq '+' && !$MBI->_is_zero($x->{_e})) 1890 { 1891 $MBI->_lsft( $x->{_m}, $x->{_e},10); # es => '+' here 1892 } 1893 1894 $x->{_e} = $MBI->_new($shiftx); 1895 $x->{_es} = '+'; 1896 $x->{_es} = '-' if $shiftx != 0 || $shifty != 0; 1897 $MBI->_add( $x->{_e}, $MBI->_new($shifty)) if $shifty != 0; 1898 1899 # now mantissas are equalized, exponent of $x is adjusted, so calc result 1900 1901 $x->{_m} = $MBI->_mod( $x->{_m}, $ym); 1902 1903 $x->{sign} = '+' if $MBI->_is_zero($x->{_m}); # fix sign for -0 1904 $x->bnorm(); 1905 1906 if ($neg != 0) # one of them negative => correct in place 1907 { 1908 my $r = $y - $x; 1909 $x->{_m} = $r->{_m}; 1910 $x->{_e} = $r->{_e}; 1911 $x->{_es} = $r->{_es}; 1912 $x->{sign} = '+' if $MBI->_is_zero($x->{_m}); # fix sign for -0 1913 $x->bnorm(); 1914 } 1915 1916 $x->round($a,$p,$r,$y); # round and return 1917 } 1918 1919 sub broot 1920 { 1921 # calculate $y'th root of $x 1922 1923 # set up parameters 1924 my ($self,$x,$y,$a,$p,$r) = (ref($_[0]),@_); 1925 # objectify is costly, so avoid it 1926 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) 1927 { 1928 ($self,$x,$y,$a,$p,$r) = objectify(2,@_); 1929 } 1930 1931 return $x if $x->modify('broot'); 1932 1933 # NaN handling: $x ** 1/0, x or y NaN, or y inf/-inf or y == 0 1934 return $x->bnan() if $x->{sign} !~ /^\+/ || $y->is_zero() || 1935 $y->{sign} !~ /^\+$/; 1936 1937 return $x if $x->is_zero() || $x->is_one() || $x->is_inf() || $y->is_one(); 1938 1939 # we need to limit the accuracy to protect against overflow 1940 my $fallback = 0; 1941 my (@params,$scale); 1942 ($x,@params) = $x->_find_round_parameters($a,$p,$r); 1943 1944 return $x if $x->is_nan(); # error in _find_round_parameters? 1945 1946 # no rounding at all, so must use fallback 1947 if (scalar @params == 0) 1948 { 1949 # simulate old behaviour 1950 $params[0] = $self->div_scale(); # and round to it as accuracy 1951 $scale = $params[0]+4; # at least four more for proper round 1952 $params[2] = $r; # iound mode by caller or undef 1953 $fallback = 1; # to clear a/p afterwards 1954 } 1955 else 1956 { 1957 # the 4 below is empirical, and there might be cases where it is not 1958 # enough... 1959 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 1960 } 1961 1962 # when user set globals, they would interfere with our calculation, so 1963 # disable them and later re-enable them 1964 no strict 'refs'; 1965 my $abr = "$self\::accuracy"; my $ab = $$abr; $$abr = undef; 1966 my $pbr = "$self\::precision"; my $pb = $$pbr; $$pbr = undef; 1967 # we also need to disable any set A or P on $x (_find_round_parameters took 1968 # them already into account), since these would interfere, too 1969 delete $x->{_a}; delete $x->{_p}; 1970 # need to disable $upgrade in BigInt, to avoid deep recursion 1971 local $Math::BigInt::upgrade = undef; # should be really parent class vs MBI 1972 1973 # remember sign and make $x positive, since -4 ** (1/2) => -2 1974 my $sign = 0; $sign = 1 if $x->{sign} eq '-'; $x->{sign} = '+'; 1975 1976 my $is_two = 0; 1977 if ($y->isa('Math::BigFloat')) 1978 { 1979 $is_two = ($y->{sign} eq '+' && $MBI->_is_two($y->{_m}) && $MBI->_is_zero($y->{_e})); 1980 } 1981 else 1982 { 1983 $is_two = ($y == 2); 1984 } 1985 1986 # normal square root if $y == 2: 1987 if ($is_two) 1988 { 1989 $x->bsqrt($scale+4); 1990 } 1991 elsif ($y->is_one('-')) 1992 { 1993 # $x ** -1 => 1/$x 1994 my $u = $self->bone()->bdiv($x,$scale); 1995 # copy private parts over 1996 $x->{_m} = $u->{_m}; 1997 $x->{_e} = $u->{_e}; 1998 $x->{_es} = $u->{_es}; 1999 } 2000 else 2001 { 2002 # calculate the broot() as integer result first, and if it fits, return 2003 # it rightaway (but only if $x and $y are integer): 2004 2005 my $done = 0; # not yet 2006 if ($y->is_int() && $x->is_int()) 2007 { 2008 my $i = $MBI->_copy( $x->{_m} ); 2009 $MBI->_lsft( $i, $x->{_e}, 10 ) unless $MBI->_is_zero($x->{_e}); 2010 my $int = Math::BigInt->bzero(); 2011 $int->{value} = $i; 2012 $int->broot($y->as_number()); 2013 # if ($exact) 2014 if ($int->copy()->bpow($y) == $x) 2015 { 2016 # found result, return it 2017 $x->{_m} = $int->{value}; 2018 $x->{_e} = $MBI->_zero(); 2019 $x->{_es} = '+'; 2020 $x->bnorm(); 2021 $done = 1; 2022 } 2023 } 2024 if ($done == 0) 2025 { 2026 my $u = $self->bone()->bdiv($y,$scale+4); 2027 delete $u->{_a}; delete $u->{_p}; # otherwise it conflicts 2028 $x->bpow($u,$scale+4); # el cheapo 2029 } 2030 } 2031 $x->bneg() if $sign == 1; 2032 2033 # shortcut to not run through _find_round_parameters again 2034 if (defined $params[0]) 2035 { 2036 $x->bround($params[0],$params[2]); # then round accordingly 2037 } 2038 else 2039 { 2040 $x->bfround($params[1],$params[2]); # then round accordingly 2041 } 2042 if ($fallback) 2043 { 2044 # clear a/p after round, since user did not request it 2045 delete $x->{_a}; delete $x->{_p}; 2046 } 2047 # restore globals 2048 $$abr = $ab; $$pbr = $pb; 2049 $x; 2050 } 2051 2052 sub bsqrt 2053 { 2054 # calculate square root 2055 my ($self,$x,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_); 2056 2057 return $x if $x->modify('bsqrt'); 2058 2059 return $x->bnan() if $x->{sign} !~ /^[+]/; # NaN, -inf or < 0 2060 return $x if $x->{sign} eq '+inf'; # sqrt(inf) == inf 2061 return $x->round($a,$p,$r) if $x->is_zero() || $x->is_one(); 2062 2063 # we need to limit the accuracy to protect against overflow 2064 my $fallback = 0; 2065 my (@params,$scale); 2066 ($x,@params) = $x->_find_round_parameters($a,$p,$r); 2067 2068 return $x if $x->is_nan(); # error in _find_round_parameters? 2069 2070 # no rounding at all, so must use fallback 2071 if (scalar @params == 0) 2072 { 2073 # simulate old behaviour 2074 $params[0] = $self->div_scale(); # and round to it as accuracy 2075 $scale = $params[0]+4; # at least four more for proper round 2076 $params[2] = $r; # round mode by caller or undef 2077 $fallback = 1; # to clear a/p afterwards 2078 } 2079 else 2080 { 2081 # the 4 below is empirical, and there might be cases where it is not 2082 # enough... 2083 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 2084 } 2085 2086 # when user set globals, they would interfere with our calculation, so 2087 # disable them and later re-enable them 2088 no strict 'refs'; 2089 my $abr = "$self\::accuracy"; my $ab = $$abr; $$abr = undef; 2090 my $pbr = "$self\::precision"; my $pb = $$pbr; $$pbr = undef; 2091 # we also need to disable any set A or P on $x (_find_round_parameters took 2092 # them already into account), since these would interfere, too 2093 delete $x->{_a}; delete $x->{_p}; 2094 # need to disable $upgrade in BigInt, to avoid deep recursion 2095 local $Math::BigInt::upgrade = undef; # should be really parent class vs MBI 2096 2097 my $i = $MBI->_copy( $x->{_m} ); 2098 $MBI->_lsft( $i, $x->{_e}, 10 ) unless $MBI->_is_zero($x->{_e}); 2099 my $xas = Math::BigInt->bzero(); 2100 $xas->{value} = $i; 2101 2102 my $gs = $xas->copy()->bsqrt(); # some guess 2103 2104 if (($x->{_es} ne '-') # guess can't be accurate if there are 2105 # digits after the dot 2106 && ($xas->bacmp($gs * $gs) == 0)) # guess hit the nail on the head? 2107 { 2108 # exact result, copy result over to keep $x 2109 $x->{_m} = $gs->{value}; $x->{_e} = $MBI->_zero(); $x->{_es} = '+'; 2110 $x->bnorm(); 2111 # shortcut to not run through _find_round_parameters again 2112 if (defined $params[0]) 2113 { 2114 $x->bround($params[0],$params[2]); # then round accordingly 2115 } 2116 else 2117 { 2118 $x->bfround($params[1],$params[2]); # then round accordingly 2119 } 2120 if ($fallback) 2121 { 2122 # clear a/p after round, since user did not request it 2123 delete $x->{_a}; delete $x->{_p}; 2124 } 2125 # re-enable A and P, upgrade is taken care of by "local" 2126 ${"$self\::accuracy"} = $ab; ${"$self\::precision"} = $pb; 2127 return $x; 2128 } 2129 2130 # sqrt(2) = 1.4 because sqrt(2*100) = 1.4*10; so we can increase the accuracy 2131 # of the result by multipyling the input by 100 and then divide the integer 2132 # result of sqrt(input) by 10. Rounding afterwards returns the real result. 2133 2134 # The following steps will transform 123.456 (in $x) into 123456 (in $y1) 2135 my $y1 = $MBI->_copy($x->{_m}); 2136 2137 my $length = $MBI->_len($y1); 2138 2139 # Now calculate how many digits the result of sqrt(y1) would have 2140 my $digits = int($length / 2); 2141 2142 # But we need at least $scale digits, so calculate how many are missing 2143 my $shift = $scale - $digits; 2144 2145 # That should never happen (we take care of integer guesses above) 2146 # $shift = 0 if $shift < 0; 2147 2148 # Multiply in steps of 100, by shifting left two times the "missing" digits 2149 my $s2 = $shift * 2; 2150 2151 # We now make sure that $y1 has the same odd or even number of digits than 2152 # $x had. So when _e of $x is odd, we must shift $y1 by one digit left, 2153 # because we always must multiply by steps of 100 (sqrt(100) is 10) and not 2154 # steps of 10. The length of $x does not count, since an even or odd number 2155 # of digits before the dot is not changed by adding an even number of digits 2156 # after the dot (the result is still odd or even digits long). 2157 $s2++ if $MBI->_is_odd($x->{_e}); 2158 2159 $MBI->_lsft( $y1, $MBI->_new($s2), 10); 2160 2161 # now take the square root and truncate to integer 2162 $y1 = $MBI->_sqrt($y1); 2163 2164 # By "shifting" $y1 right (by creating a negative _e) we calculate the final 2165 # result, which is than later rounded to the desired scale. 2166 2167 # calculate how many zeros $x had after the '.' (or before it, depending 2168 # on sign of $dat, the result should have half as many: 2169 my $dat = $MBI->_num($x->{_e}); 2170 $dat = -$dat if $x->{_es} eq '-'; 2171 $dat += $length; 2172 2173 if ($dat > 0) 2174 { 2175 # no zeros after the dot (e.g. 1.23, 0.49 etc) 2176 # preserve half as many digits before the dot than the input had 2177 # (but round this "up") 2178 $dat = int(($dat+1)/2); 2179 } 2180 else 2181 { 2182 $dat = int(($dat)/2); 2183 } 2184 $dat -= $MBI->_len($y1); 2185 if ($dat < 0) 2186 { 2187 $dat = abs($dat); 2188 $x->{_e} = $MBI->_new( $dat ); 2189 $x->{_es} = '-'; 2190 } 2191 else 2192 { 2193 $x->{_e} = $MBI->_new( $dat ); 2194 $x->{_es} = '+'; 2195 } 2196 $x->{_m} = $y1; 2197 $x->bnorm(); 2198 2199 # shortcut to not run through _find_round_parameters again 2200 if (defined $params[0]) 2201 { 2202 $x->bround($params[0],$params[2]); # then round accordingly 2203 } 2204 else 2205 { 2206 $x->bfround($params[1],$params[2]); # then round accordingly 2207 } 2208 if ($fallback) 2209 { 2210 # clear a/p after round, since user did not request it 2211 delete $x->{_a}; delete $x->{_p}; 2212 } 2213 # restore globals 2214 $$abr = $ab; $$pbr = $pb; 2215 $x; 2216 } 2217 2218 sub bfac 2219 { 2220 # (BFLOAT or num_str, BFLOAT or num_str) return BFLOAT 2221 # compute factorial number, modifies first argument 2222 2223 # set up parameters 2224 my ($self,$x,@r) = (ref($_[0]),@_); 2225 # objectify is costly, so avoid it 2226 ($self,$x,@r) = objectify(1,@_) if !ref($x); 2227 2228 # inf => inf 2229 return $x if $x->modify('bfac') || $x->{sign} eq '+inf'; 2230 2231 return $x->bnan() 2232 if (($x->{sign} ne '+') || # inf, NaN, <0 etc => NaN 2233 ($x->{_es} ne '+')); # digits after dot? 2234 2235 # use BigInt's bfac() for faster calc 2236 if (! $MBI->_is_zero($x->{_e})) 2237 { 2238 $MBI->_lsft($x->{_m}, $x->{_e},10); # change 12e1 to 120e0 2239 $x->{_e} = $MBI->_zero(); # normalize 2240 $x->{_es} = '+'; 2241 } 2242 $MBI->_fac($x->{_m}); # calculate factorial 2243 $x->bnorm()->round(@r); # norm again and round result 2244 } 2245 2246 sub _pow 2247 { 2248 # Calculate a power where $y is a non-integer, like 2 ** 0.3 2249 my ($x,$y,@r) = @_; 2250 my $self = ref($x); 2251 2252 # if $y == 0.5, it is sqrt($x) 2253 $HALF = $self->new($HALF) unless ref($HALF); 2254 return $x->bsqrt(@r,$y) if $y->bcmp($HALF) == 0; 2255 2256 # Using: 2257 # a ** x == e ** (x * ln a) 2258 2259 # u = y * ln x 2260 # _ _ 2261 # Taylor: | u u^2 u^3 | 2262 # x ** y = 1 + | --- + --- + ----- + ... | 2263 # |_ 1 1*2 1*2*3 _| 2264 2265 # we need to limit the accuracy to protect against overflow 2266 my $fallback = 0; 2267 my ($scale,@params); 2268 ($x,@params) = $x->_find_round_parameters(@r); 2269 2270 return $x if $x->is_nan(); # error in _find_round_parameters? 2271 2272 # no rounding at all, so must use fallback 2273 if (scalar @params == 0) 2274 { 2275 # simulate old behaviour 2276 $params[0] = $self->div_scale(); # and round to it as accuracy 2277 $params[1] = undef; # disable P 2278 $scale = $params[0]+4; # at least four more for proper round 2279 $params[2] = $r[2]; # round mode by caller or undef 2280 $fallback = 1; # to clear a/p afterwards 2281 } 2282 else 2283 { 2284 # the 4 below is empirical, and there might be cases where it is not 2285 # enough... 2286 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 2287 } 2288 2289 # when user set globals, they would interfere with our calculation, so 2290 # disable them and later re-enable them 2291 no strict 'refs'; 2292 my $abr = "$self\::accuracy"; my $ab = $$abr; $$abr = undef; 2293 my $pbr = "$self\::precision"; my $pb = $$pbr; $$pbr = undef; 2294 # we also need to disable any set A or P on $x (_find_round_parameters took 2295 # them already into account), since these would interfere, too 2296 delete $x->{_a}; delete $x->{_p}; 2297 # need to disable $upgrade in BigInt, to avoid deep recursion 2298 local $Math::BigInt::upgrade = undef; 2299 2300 my ($limit,$v,$u,$below,$factor,$next,$over); 2301 2302 $u = $x->copy()->blog(undef,$scale)->bmul($y); 2303 $v = $self->bone(); # 1 2304 $factor = $self->new(2); # 2 2305 $x->bone(); # first term: 1 2306 2307 $below = $v->copy(); 2308 $over = $u->copy(); 2309 2310 $limit = $self->new("1E-". ($scale-1)); 2311 #my $steps = 0; 2312 while (3 < 5) 2313 { 2314 # we calculate the next term, and add it to the last 2315 # when the next term is below our limit, it won't affect the outcome 2316 # anymore, so we stop: 2317 $next = $over->copy()->bdiv($below,$scale); 2318 last if $next->bacmp($limit) <= 0; 2319 $x->badd($next); 2320 # calculate things for the next term 2321 $over *= $u; $below *= $factor; $factor->binc(); 2322 2323 last if $x->{sign} !~ /^[-+]$/; 2324 2325 #$steps++; 2326 } 2327 2328 # shortcut to not run through _find_round_parameters again 2329 if (defined $params[0]) 2330 { 2331 $x->bround($params[0],$params[2]); # then round accordingly 2332 } 2333 else 2334 { 2335 $x->bfround($params[1],$params[2]); # then round accordingly 2336 } 2337 if ($fallback) 2338 { 2339 # clear a/p after round, since user did not request it 2340 delete $x->{_a}; delete $x->{_p}; 2341 } 2342 # restore globals 2343 $$abr = $ab; $$pbr = $pb; 2344 $x; 2345 } 2346 2347 sub bpow 2348 { 2349 # (BFLOAT or num_str, BFLOAT or num_str) return BFLOAT 2350 # compute power of two numbers, second arg is used as integer 2351 # modifies first argument 2352 2353 # set up parameters 2354 my ($self,$x,$y,$a,$p,$r) = (ref($_[0]),@_); 2355 # objectify is costly, so avoid it 2356 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) 2357 { 2358 ($self,$x,$y,$a,$p,$r) = objectify(2,@_); 2359 } 2360 2361 return $x if $x->modify('bpow'); 2362 2363 return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan; 2364 return $x if $x->{sign} =~ /^[+-]inf$/; 2365 2366 # cache the result of is_zero 2367 my $y_is_zero = $y->is_zero(); 2368 return $x->bone() if $y_is_zero; 2369 return $x if $x->is_one() || $y->is_one(); 2370 2371 my $x_is_zero = $x->is_zero(); 2372 return $x->_pow($y,$a,$p,$r) if !$x_is_zero && !$y->is_int(); # non-integer power 2373 2374 my $y1 = $y->as_number()->{value}; # make MBI part 2375 2376 # if ($x == -1) 2377 if ($x->{sign} eq '-' && $MBI->_is_one($x->{_m}) && $MBI->_is_zero($x->{_e})) 2378 { 2379 # if $x == -1 and odd/even y => +1/-1 because +-1 ^ (+-1) => +-1 2380 return $MBI->_is_odd($y1) ? $x : $x->babs(1); 2381 } 2382 if ($x_is_zero) 2383 { 2384 return $x if $y->{sign} eq '+'; # 0**y => 0 (if not y <= 0) 2385 # 0 ** -y => 1 / (0 ** y) => 1 / 0! (1 / 0 => +inf) 2386 return $x->binf(); 2387 } 2388 2389 my $new_sign = '+'; 2390 $new_sign = $MBI->_is_odd($y1) ? '-' : '+' if $x->{sign} ne '+'; 2391 2392 # calculate $x->{_m} ** $y and $x->{_e} * $y separately (faster) 2393 $x->{_m} = $MBI->_pow( $x->{_m}, $y1); 2394 $x->{_e} = $MBI->_mul ($x->{_e}, $y1); 2395 2396 $x->{sign} = $new_sign; 2397 $x->bnorm(); 2398 if ($y->{sign} eq '-') 2399 { 2400 # modify $x in place! 2401 my $z = $x->copy(); $x->bone(); 2402 return scalar $x->bdiv($z,$a,$p,$r); # round in one go (might ignore y's A!) 2403 } 2404 $x->round($a,$p,$r,$y); 2405 } 2406 2407 sub bmodpow 2408 { 2409 # takes a very large number to a very large exponent in a given very 2410 # large modulus, quickly, thanks to binary exponentation. Supports 2411 # negative exponents. 2412 my ($self,$num,$exp,$mod,@r) = objectify(3,@_); 2413 2414 return $num if $num->modify('bmodpow'); 2415 2416 # check modulus for valid values 2417 return $num->bnan() if ($mod->{sign} ne '+' # NaN, - , -inf, +inf 2418 || $mod->is_zero()); 2419 2420 # check exponent for valid values 2421 if ($exp->{sign} =~ /\w/) 2422 { 2423 # i.e., if it's NaN, +inf, or -inf... 2424 return $num->bnan(); 2425 } 2426 2427 $num->bmodinv ($mod) if ($exp->{sign} eq '-'); 2428 2429 # check num for valid values (also NaN if there was no inverse but $exp < 0) 2430 return $num->bnan() if $num->{sign} !~ /^[+-]$/; 2431 2432 # $mod is positive, sign on $exp is ignored, result also positive 2433 2434 # XXX TODO: speed it up when all three numbers are integers 2435 $num->bpow($exp)->bmod($mod); 2436 } 2437 2438 ############################################################################### 2439 # trigonometric functions 2440 2441 # helper function for bpi() and batan2(), calculates arcus tanges (1/x) 2442 2443 sub _atan_inv 2444 { 2445 # return a/b so that a/b approximates atan(1/x) to at least limit digits 2446 my ($self, $x, $limit) = @_; 2447 2448 # Taylor: x^3 x^5 x^7 x^9 2449 # atan = x - --- + --- - --- + --- - ... 2450 # 3 5 7 9 2451 2452 # 1 1 1 1 2453 # atan 1/x = - - ------- + ------- - ------- + ... 2454 # x x^3 * 3 x^5 * 5 x^7 * 7 2455 2456 # 1 1 1 1 2457 # atan 1/x = - - --------- + ---------- - ----------- + ... 2458 # 5 3 * 125 5 * 3125 7 * 78125 2459 2460 # Subtraction/addition of a rational: 2461 2462 # 5 7 5*3 +- 7*4 2463 # - +- - = ---------- 2464 # 4 3 4*3 2465 2466 # Term: N N+1 2467 # 2468 # a 1 a * d * c +- b 2469 # ----- +- ------------------ = ---------------- 2470 # b d * c b * d * c 2471 2472 # since b1 = b0 * (d-2) * c 2473 2474 # a 1 a * d +- b / c 2475 # ----- +- ------------------ = ---------------- 2476 # b d * c b * d 2477 2478 # and d = d + 2 2479 # and c = c * x * x 2480 2481 # u = d * c 2482 # stop if length($u) > limit 2483 # a = a * u +- b 2484 # b = b * u 2485 # d = d + 2 2486 # c = c * x * x 2487 # sign = 1 - sign 2488 2489 my $a = $MBI->_one(); 2490 my $b = $MBI->_copy($x); 2491 2492 my $x2 = $MBI->_mul( $MBI->_copy($x), $b); # x2 = x * x 2493 my $d = $MBI->_new( 3 ); # d = 3 2494 my $c = $MBI->_mul( $MBI->_copy($x), $x2); # c = x ^ 3 2495 my $two = $MBI->_new( 2 ); 2496 2497 # run the first step unconditionally 2498 my $u = $MBI->_mul( $MBI->_copy($d), $c); 2499 $a = $MBI->_mul($a, $u); 2500 $a = $MBI->_sub($a, $b); 2501 $b = $MBI->_mul($b, $u); 2502 $d = $MBI->_add($d, $two); 2503 $c = $MBI->_mul($c, $x2); 2504 2505 # a is now a * (d-3) * c 2506 # b is now b * (d-2) * c 2507 2508 # run the second step unconditionally 2509 $u = $MBI->_mul( $MBI->_copy($d), $c); 2510 $a = $MBI->_mul($a, $u); 2511 $a = $MBI->_add($a, $b); 2512 $b = $MBI->_mul($b, $u); 2513 $d = $MBI->_add($d, $two); 2514 $c = $MBI->_mul($c, $x2); 2515 2516 # a is now a * (d-3) * (d-5) * c * c 2517 # b is now b * (d-2) * (d-4) * c * c 2518 2519 # so we can remove c * c from both a and b to shorten the numbers involved: 2520 $a = $MBI->_div($a, $x2); 2521 $b = $MBI->_div($b, $x2); 2522 $a = $MBI->_div($a, $x2); 2523 $b = $MBI->_div($b, $x2); 2524 2525 # my $step = 0; 2526 my $sign = 0; # 0 => -, 1 => + 2527 while (3 < 5) 2528 { 2529 # $step++; 2530 # if (($i++ % 100) == 0) 2531 # { 2532 # print "a=",$MBI->_str($a),"\n"; 2533 # print "b=",$MBI->_str($b),"\n"; 2534 # } 2535 # print "d=",$MBI->_str($d),"\n"; 2536 # print "x2=",$MBI->_str($x2),"\n"; 2537 # print "c=",$MBI->_str($c),"\n"; 2538 2539 my $u = $MBI->_mul( $MBI->_copy($d), $c); 2540 # use _alen() for libs like GMP where _len() would be O(N^2) 2541 last if $MBI->_alen($u) > $limit; 2542 my ($bc,$r) = $MBI->_div( $MBI->_copy($b), $c); 2543 if ($MBI->_is_zero($r)) 2544 { 2545 # b / c is an integer, so we can remove c from all terms 2546 # this happens almost every time: 2547 $a = $MBI->_mul($a, $d); 2548 $a = $MBI->_sub($a, $bc) if $sign == 0; 2549 $a = $MBI->_add($a, $bc) if $sign == 1; 2550 $b = $MBI->_mul($b, $d); 2551 } 2552 else 2553 { 2554 # b / c is not an integer, so we keep c in the terms 2555 # this happens very rarely, for instance for x = 5, this happens only 2556 # at the following steps: 2557 # 1, 5, 14, 32, 72, 157, 340, ... 2558 $a = $MBI->_mul($a, $u); 2559 $a = $MBI->_sub($a, $b) if $sign == 0; 2560 $a = $MBI->_add($a, $b) if $sign == 1; 2561 $b = $MBI->_mul($b, $u); 2562 } 2563 $d = $MBI->_add($d, $two); 2564 $c = $MBI->_mul($c, $x2); 2565 $sign = 1 - $sign; 2566 2567 } 2568 2569 # print "Took $step steps for ", $MBI->_str($x),"\n"; 2570 # print "a=",$MBI->_str($a),"\n"; print "b=",$MBI->_str($b),"\n"; 2571 # return a/b so that a/b approximates atan(1/x) 2572 ($a,$b); 2573 } 2574 2575 sub bpi 2576 { 2577 my ($self,$n) = @_; 2578 if (@_ == 0) 2579 { 2580 $self = $class; 2581 } 2582 if (@_ == 1) 2583 { 2584 # called like Math::BigFloat::bpi(10); 2585 $n = $self; $self = $class; 2586 # called like Math::BigFloat->bpi(); 2587 $n = undef if $n eq 'Math::BigFloat'; 2588 } 2589 $self = ref($self) if ref($self); 2590 my $fallback = defined $n ? 0 : 1; 2591 $n = 40 if !defined $n || $n < 1; 2592 2593 # after 黃見利 (Hwang Chien-Lih) (1997) 2594 # pi/4 = 183 * atan(1/239) + 32 * atan(1/1023) – 68 * atan(1/5832) 2595 # + 12 * atan(1/110443) - 12 * atan(1/4841182) - 100 * atan(1/6826318) 2596 2597 # a few more to prevent rounding errors 2598 $n += 4; 2599 2600 my ($a,$b) = $self->_atan_inv( $MBI->_new(239),$n); 2601 my ($c,$d) = $self->_atan_inv( $MBI->_new(1023),$n); 2602 my ($e,$f) = $self->_atan_inv( $MBI->_new(5832),$n); 2603 my ($g,$h) = $self->_atan_inv( $MBI->_new(110443),$n); 2604 my ($i,$j) = $self->_atan_inv( $MBI->_new(4841182),$n); 2605 my ($k,$l) = $self->_atan_inv( $MBI->_new(6826318),$n); 2606 2607 $MBI->_mul($a, $MBI->_new(732)); 2608 $MBI->_mul($c, $MBI->_new(128)); 2609 $MBI->_mul($e, $MBI->_new(272)); 2610 $MBI->_mul($g, $MBI->_new(48)); 2611 $MBI->_mul($i, $MBI->_new(48)); 2612 $MBI->_mul($k, $MBI->_new(400)); 2613 2614 my $x = $self->bone(); $x->{_m} = $a; my $x_d = $self->bone(); $x_d->{_m} = $b; 2615 my $y = $self->bone(); $y->{_m} = $c; my $y_d = $self->bone(); $y_d->{_m} = $d; 2616 my $z = $self->bone(); $z->{_m} = $e; my $z_d = $self->bone(); $z_d->{_m} = $f; 2617 my $u = $self->bone(); $u->{_m} = $g; my $u_d = $self->bone(); $u_d->{_m} = $h; 2618 my $v = $self->bone(); $v->{_m} = $i; my $v_d = $self->bone(); $v_d->{_m} = $j; 2619 my $w = $self->bone(); $w->{_m} = $k; my $w_d = $self->bone(); $w_d->{_m} = $l; 2620 $x->bdiv($x_d, $n); 2621 $y->bdiv($y_d, $n); 2622 $z->bdiv($z_d, $n); 2623 $u->bdiv($u_d, $n); 2624 $v->bdiv($v_d, $n); 2625 $w->bdiv($w_d, $n); 2626 2627 delete $x->{_a}; delete $y->{_a}; delete $z->{_a}; 2628 delete $u->{_a}; delete $v->{_a}; delete $w->{_a}; 2629 $x->badd($y)->bsub($z)->badd($u)->bsub($v)->bsub($w); 2630 2631 $x->bround($n-4); 2632 delete $x->{_a} if $fallback == 1; 2633 $x; 2634 } 2635 2636 sub bcos 2637 { 2638 # Calculate a cosinus of x. 2639 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_); 2640 2641 # Taylor: x^2 x^4 x^6 x^8 2642 # cos = 1 - --- + --- - --- + --- ... 2643 # 2! 4! 6! 8! 2644 2645 # we need to limit the accuracy to protect against overflow 2646 my $fallback = 0; 2647 my ($scale,@params); 2648 ($x,@params) = $x->_find_round_parameters(@r); 2649 2650 # constant object or error in _find_round_parameters? 2651 return $x if $x->modify('bcos') || $x->is_nan(); 2652 2653 return $x->bone(@r) if $x->is_zero(); 2654 2655 # no rounding at all, so must use fallback 2656 if (scalar @params == 0) 2657 { 2658 # simulate old behaviour 2659 $params[0] = $self->div_scale(); # and round to it as accuracy 2660 $params[1] = undef; # disable P 2661 $scale = $params[0]+4; # at least four more for proper round 2662 $params[2] = $r[2]; # round mode by caller or undef 2663 $fallback = 1; # to clear a/p afterwards 2664 } 2665 else 2666 { 2667 # the 4 below is empirical, and there might be cases where it is not 2668 # enough... 2669 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 2670 } 2671 2672 # when user set globals, they would interfere with our calculation, so 2673 # disable them and later re-enable them 2674 no strict 'refs'; 2675 my $abr = "$self\::accuracy"; my $ab = $$abr; $$abr = undef; 2676 my $pbr = "$self\::precision"; my $pb = $$pbr; $$pbr = undef; 2677 # we also need to disable any set A or P on $x (_find_round_parameters took 2678 # them already into account), since these would interfere, too 2679 delete $x->{_a}; delete $x->{_p}; 2680 # need to disable $upgrade in BigInt, to avoid deep recursion 2681 local $Math::BigInt::upgrade = undef; 2682 2683 my $last = 0; 2684 my $over = $x * $x; # X ^ 2 2685 my $x2 = $over->copy(); # X ^ 2; difference between terms 2686 my $sign = 1; # start with -= 2687 my $below = $self->new(2); my $factorial = $self->new(3); 2688 $x->bone(); delete $x->{_a}; delete $x->{_p}; 2689 2690 my $limit = $self->new("1E-". ($scale-1)); 2691 #my $steps = 0; 2692 while (3 < 5) 2693 { 2694 # we calculate the next term, and add it to the last 2695 # when the next term is below our limit, it won't affect the outcome 2696 # anymore, so we stop: 2697 my $next = $over->copy()->bdiv($below,$scale); 2698 last if $next->bacmp($limit) <= 0; 2699 2700 if ($sign == 0) 2701 { 2702 $x->badd($next); 2703 } 2704 else 2705 { 2706 $x->bsub($next); 2707 } 2708 $sign = 1-$sign; # alternate 2709 # calculate things for the next term 2710 $over->bmul($x2); # $x*$x 2711 $below->bmul($factorial); $factorial->binc(); # n*(n+1) 2712 $below->bmul($factorial); $factorial->binc(); # n*(n+1) 2713 } 2714 2715 # shortcut to not run through _find_round_parameters again 2716 if (defined $params[0]) 2717 { 2718 $x->bround($params[0],$params[2]); # then round accordingly 2719 } 2720 else 2721 { 2722 $x->bfround($params[1],$params[2]); # then round accordingly 2723 } 2724 if ($fallback) 2725 { 2726 # clear a/p after round, since user did not request it 2727 delete $x->{_a}; delete $x->{_p}; 2728 } 2729 # restore globals 2730 $$abr = $ab; $$pbr = $pb; 2731 $x; 2732 } 2733 2734 sub bsin 2735 { 2736 # Calculate a sinus of x. 2737 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_); 2738 2739 # taylor: x^3 x^5 x^7 x^9 2740 # sin = x - --- + --- - --- + --- ... 2741 # 3! 5! 7! 9! 2742 2743 # we need to limit the accuracy to protect against overflow 2744 my $fallback = 0; 2745 my ($scale,@params); 2746 ($x,@params) = $x->_find_round_parameters(@r); 2747 2748 # constant object or error in _find_round_parameters? 2749 return $x if $x->modify('bsin') || $x->is_nan(); 2750 2751 return $x->bzero(@r) if $x->is_zero(); 2752 2753 # no rounding at all, so must use fallback 2754 if (scalar @params == 0) 2755 { 2756 # simulate old behaviour 2757 $params[0] = $self->div_scale(); # and round to it as accuracy 2758 $params[1] = undef; # disable P 2759 $scale = $params[0]+4; # at least four more for proper round 2760 $params[2] = $r[2]; # round mode by caller or undef 2761 $fallback = 1; # to clear a/p afterwards 2762 } 2763 else 2764 { 2765 # the 4 below is empirical, and there might be cases where it is not 2766 # enough... 2767 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 2768 } 2769 2770 # when user set globals, they would interfere with our calculation, so 2771 # disable them and later re-enable them 2772 no strict 'refs'; 2773 my $abr = "$self\::accuracy"; my $ab = $$abr; $$abr = undef; 2774 my $pbr = "$self\::precision"; my $pb = $$pbr; $$pbr = undef; 2775 # we also need to disable any set A or P on $x (_find_round_parameters took 2776 # them already into account), since these would interfere, too 2777 delete $x->{_a}; delete $x->{_p}; 2778 # need to disable $upgrade in BigInt, to avoid deep recursion 2779 local $Math::BigInt::upgrade = undef; 2780 2781 my $last = 0; 2782 my $over = $x * $x; # X ^ 2 2783 my $x2 = $over->copy(); # X ^ 2; difference between terms 2784 $over->bmul($x); # X ^ 3 as starting value 2785 my $sign = 1; # start with -= 2786 my $below = $self->new(6); my $factorial = $self->new(4); 2787 delete $x->{_a}; delete $x->{_p}; 2788 2789 my $limit = $self->new("1E-". ($scale-1)); 2790 #my $steps = 0; 2791 while (3 < 5) 2792 { 2793 # we calculate the next term, and add it to the last 2794 # when the next term is below our limit, it won't affect the outcome 2795 # anymore, so we stop: 2796 my $next = $over->copy()->bdiv($below,$scale); 2797 last if $next->bacmp($limit) <= 0; 2798 2799 if ($sign == 0) 2800 { 2801 $x->badd($next); 2802 } 2803 else 2804 { 2805 $x->bsub($next); 2806 } 2807 $sign = 1-$sign; # alternate 2808 # calculate things for the next term 2809 $over->bmul($x2); # $x*$x 2810 $below->bmul($factorial); $factorial->binc(); # n*(n+1) 2811 $below->bmul($factorial); $factorial->binc(); # n*(n+1) 2812 } 2813 2814 # shortcut to not run through _find_round_parameters again 2815 if (defined $params[0]) 2816 { 2817 $x->bround($params[0],$params[2]); # then round accordingly 2818 } 2819 else 2820 { 2821 $x->bfround($params[1],$params[2]); # then round accordingly 2822 } 2823 if ($fallback) 2824 { 2825 # clear a/p after round, since user did not request it 2826 delete $x->{_a}; delete $x->{_p}; 2827 } 2828 # restore globals 2829 $$abr = $ab; $$pbr = $pb; 2830 $x; 2831 } 2832 2833 sub batan2 2834 { 2835 # calculate arcus tangens of ($y/$x) 2836 2837 # set up parameters 2838 my ($self,$y,$x,@r) = (ref($_[0]),@_); 2839 # objectify is costly, so avoid it 2840 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) 2841 { 2842 ($self,$y,$x,@r) = objectify(2,@_); 2843 } 2844 2845 return $y if $y->modify('batan2'); 2846 2847 return $y->bnan() if ($y->{sign} eq $nan) || ($x->{sign} eq $nan); 2848 2849 return $upgrade->new($y)->batan2($upgrade->new($x),@r) if defined $upgrade; 2850 2851 # Y X 2852 # 0 0 result is 0 2853 # 0 +x result is 0 2854 return $y->bzero(@r) if $y->is_zero() && $x->{sign} eq '+'; 2855 2856 # Y X 2857 # 0 -x result is PI 2858 if ($y->is_zero()) 2859 { 2860 # calculate PI 2861 my $pi = $self->bpi(@r); 2862 # modify $x in place 2863 $y->{_m} = $pi->{_m}; 2864 $y->{_e} = $pi->{_e}; 2865 $y->{_es} = $pi->{_es}; 2866 $y->{sign} = '+'; 2867 return $y; 2868 } 2869 2870 # Y X 2871 # +y 0 result is PI/2 2872 # -y 0 result is -PI/2 2873 if ($y->is_inf() || $x->is_zero()) 2874 { 2875 # calculate PI/2 2876 my $pi = $self->bpi(@r); 2877 # modify $x in place 2878 $y->{_m} = $pi->{_m}; 2879 $y->{_e} = $pi->{_e}; 2880 $y->{_es} = $pi->{_es}; 2881 # -y => -PI/2, +y => PI/2 2882 $y->{sign} = substr($y->{sign},0,1); # +inf => + 2883 $MBI->_div($y->{_m}, $MBI->_new(2)); 2884 return $y; 2885 } 2886 2887 # we need to limit the accuracy to protect against overflow 2888 my $fallback = 0; 2889 my ($scale,@params); 2890 ($y,@params) = $y->_find_round_parameters(@r); 2891 2892 # error in _find_round_parameters? 2893 return $y if $y->is_nan(); 2894 2895 # no rounding at all, so must use fallback 2896 if (scalar @params == 0) 2897 { 2898 # simulate old behaviour 2899 $params[0] = $self->div_scale(); # and round to it as accuracy 2900 $params[1] = undef; # disable P 2901 $scale = $params[0]+4; # at least four more for proper round 2902 $params[2] = $r[2]; # round mode by caller or undef 2903 $fallback = 1; # to clear a/p afterwards 2904 } 2905 else 2906 { 2907 # the 4 below is empirical, and there might be cases where it is not 2908 # enough... 2909 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 2910 } 2911 2912 # inlined is_one() && is_one('-') 2913 if ($MBI->_is_one($y->{_m}) && $MBI->_is_zero($y->{_e})) 2914 { 2915 # shortcut: 1 1 result is PI/4 2916 # inlined is_one() && is_one('-') 2917 if ($MBI->_is_one($x->{_m}) && $MBI->_is_zero($x->{_e})) 2918 { 2919 # 1,1 => PI/4 2920 my $pi_4 = $self->bpi( $scale - 3); 2921 # modify $x in place 2922 $y->{_m} = $pi_4->{_m}; 2923 $y->{_e} = $pi_4->{_e}; 2924 $y->{_es} = $pi_4->{_es}; 2925 # 1 1 => + 2926 # -1 1 => - 2927 # 1 -1 => - 2928 # -1 -1 => + 2929 $y->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-'; 2930 $MBI->_div($y->{_m}, $MBI->_new(4)); 2931 return $y; 2932 } 2933 # shortcut: 1 int(X) result is _atan_inv(X) 2934 2935 # is integer 2936 if ($x->{_es} eq '+') 2937 { 2938 my $x1 = $MBI->_copy($x->{_m}); 2939 $MBI->_lsft($x1, $x->{_e},10) unless $MBI->_is_zero($x->{_e}); 2940 2941 my ($a,$b) = $self->_atan_inv($x1, $scale); 2942 my $y_sign = $y->{sign}; 2943 # calculate A/B 2944 $y->bone(); $y->{_m} = $a; my $y_d = $self->bone(); $y_d->{_m} = $b; 2945 $y->bdiv($y_d, @r); 2946 $y->{sign} = $y_sign; 2947 return $y; 2948 } 2949 } 2950 2951 # handle all other cases 2952 # X Y 2953 # +x +y 0 to PI/2 2954 # -x +y PI/2 to PI 2955 # +x -y 0 to -PI/2 2956 # -x -y -PI/2 to -PI 2957 2958 my $y_sign = $y->{sign}; 2959 2960 # divide $x by $y 2961 $y->bdiv($x, $scale) unless $x->is_one(); 2962 $y->batan(@r); 2963 2964 # restore sign 2965 $y->{sign} = $y_sign; 2966 2967 $y; 2968 } 2969 2970 sub batan 2971 { 2972 # Calculate a arcus tangens of x. 2973 my ($x,@r) = @_; 2974 my $self = ref($x); 2975 2976 # taylor: x^3 x^5 x^7 x^9 2977 # atan = x - --- + --- - --- + --- ... 2978 # 3 5 7 9 2979 2980 # we need to limit the accuracy to protect against overflow 2981 my $fallback = 0; 2982 my ($scale,@params); 2983 ($x,@params) = $x->_find_round_parameters(@r); 2984 2985 # constant object or error in _find_round_parameters? 2986 return $x if $x->modify('batan') || $x->is_nan(); 2987 2988 if ($x->{sign} =~ /^[+-]inf\z/) 2989 { 2990 # +inf result is PI/2 2991 # -inf result is -PI/2 2992 # calculate PI/2 2993 my $pi = $self->bpi(@r); 2994 # modify $x in place 2995 $x->{_m} = $pi->{_m}; 2996 $x->{_e} = $pi->{_e}; 2997 $x->{_es} = $pi->{_es}; 2998 # -y => -PI/2, +y => PI/2 2999 $x->{sign} = substr($x->{sign},0,1); # +inf => + 3000 $MBI->_div($x->{_m}, $MBI->_new(2)); 3001 return $x; 3002 } 3003 3004 return $x->bzero(@r) if $x->is_zero(); 3005 3006 # no rounding at all, so must use fallback 3007 if (scalar @params == 0) 3008 { 3009 # simulate old behaviour 3010 $params[0] = $self->div_scale(); # and round to it as accuracy 3011 $params[1] = undef; # disable P 3012 $scale = $params[0]+4; # at least four more for proper round 3013 $params[2] = $r[2]; # round mode by caller or undef 3014 $fallback = 1; # to clear a/p afterwards 3015 } 3016 else 3017 { 3018 # the 4 below is empirical, and there might be cases where it is not 3019 # enough... 3020 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined 3021 } 3022 3023 # 1 or -1 => PI/4 3024 # inlined is_one() && is_one('-') 3025 if ($MBI->_is_one($x->{_m}) && $MBI->_is_zero($x->{_e})) 3026 { 3027 my $pi = $self->bpi($scale - 3); 3028 # modify $x in place 3029 $x->{_m} = $pi->{_m}; 3030 $x->{_e} = $pi->{_e}; 3031 $x->{_es} = $pi->{_es}; 3032 # leave the sign of $x alone (+1 => +PI/4, -1 => -PI/4) 3033 $MBI->_div($x->{_m}, $MBI->_new(4)); 3034 return $x; 3035 } 3036 3037 # This series is only valid if -1 < x < 1, so for other x we need to 3038 # to calculate PI/2 - atan(1/x): 3039 my $one = $MBI->_new(1); 3040 my $pi = undef; 3041 if ($x->{_es} eq '+' && ($MBI->_acmp($x->{_m},$one) >= 0)) 3042 { 3043 # calculate PI/2 3044 $pi = $self->bpi($scale - 3); 3045 $MBI->_div($pi->{_m}, $MBI->_new(2)); 3046 # calculate 1/$x: 3047 my $x_copy = $x->copy(); 3048 # modify $x in place 3049 $x->bone(); $x->bdiv($x_copy,$scale); 3050 } 3051 3052 # when user set globals, they would interfere with our calculation, so 3053 # disable them and later re-enable them 3054 no strict 'refs'; 3055 my $abr = "$self\::accuracy"; my $ab = $$abr; $$abr = undef; 3056 my $pbr = "$self\::precision"; my $pb = $$pbr; $$pbr = undef; 3057 # we also need to disable any set A or P on $x (_find_round_parameters took 3058 # them already into account), since these would interfere, too 3059 delete $x->{_a}; delete $x->{_p}; 3060 # need to disable $upgrade in BigInt, to avoid deep recursion 3061 local $Math::BigInt::upgrade = undef; 3062 3063 my $last = 0; 3064 my $over = $x * $x; # X ^ 2 3065 my $x2 = $over->copy(); # X ^ 2; difference between terms 3066 $over->bmul($x); # X ^ 3 as starting value 3067 my $sign = 1; # start with -= 3068 my $below = $self->new(3); 3069 my $two = $self->new(2); 3070 delete $x->{_a}; delete $x->{_p}; 3071 3072 my $limit = $self->new("1E-". ($scale-1)); 3073 #my $steps = 0; 3074 while (3 < 5) 3075 { 3076 # we calculate the next term, and add it to the last 3077 # when the next term is below our limit, it won't affect the outcome 3078 # anymore, so we stop: 3079 my $next = $over->copy()->bdiv($below,$scale); 3080 last if $next->bacmp($limit) <= 0; 3081 3082 if ($sign == 0) 3083 { 3084 $x->badd($next); 3085 } 3086 else 3087 { 3088 $x->bsub($next); 3089 } 3090 $sign = 1-$sign; # alternate 3091 # calculate things for the next term 3092 $over->bmul($x2); # $x*$x 3093 $below->badd($two); # n += 2 3094 } 3095 3096 if (defined $pi) 3097 { 3098 my $x_copy = $x->copy(); 3099 # modify $x in place 3100 $x->{_m} = $pi->{_m}; 3101 $x->{_e} = $pi->{_e}; 3102 $x->{_es} = $pi->{_es}; 3103 # PI/2 - $x 3104 $x->bsub($x_copy); 3105 } 3106 3107 # shortcut to not run through _find_round_parameters again 3108 if (defined $params[0]) 3109 { 3110 $x->bround($params[0],$params[2]); # then round accordingly 3111 } 3112 else 3113 { 3114 $x->bfround($params[1],$params[2]); # then round accordingly 3115 } 3116 if ($fallback) 3117 { 3118 # clear a/p after round, since user did not request it 3119 delete $x->{_a}; delete $x->{_p}; 3120 } 3121 # restore globals 3122 $$abr = $ab; $$pbr = $pb; 3123 $x; 3124 } 3125 3126 ############################################################################### 3127 # rounding functions 3128 3129 sub bfround 3130 { 3131 # precision: round to the $Nth digit left (+$n) or right (-$n) from the '.' 3132 # $n == 0 means round to integer 3133 # expects and returns normalized numbers! 3134 my $x = shift; my $self = ref($x) || $x; $x = $self->new(shift) if !ref($x); 3135 3136 my ($scale,$mode) = $x->_scale_p(@_); 3137 return $x if !defined $scale || $x->modify('bfround'); # no-op 3138 3139 # never round a 0, +-inf, NaN 3140 if ($x->is_zero()) 3141 { 3142 $x->{_p} = $scale if !defined $x->{_p} || $x->{_p} < $scale; # -3 < -2 3143 return $x; 3144 } 3145 return $x if $x->{sign} !~ /^[+-]$/; 3146 3147 # don't round if x already has lower precision 3148 return $x if (defined $x->{_p} && $x->{_p} < 0 && $scale < $x->{_p}); 3149 3150 $x->{_p} = $scale; # remember round in any case 3151 delete $x->{_a}; # and clear A 3152 if ($scale < 0) 3153 { 3154 # round right from the '.' 3155 3156 return $x if $x->{_es} eq '+'; # e >= 0 => nothing to round 3157 3158 $scale = -$scale; # positive for simplicity 3159 my $len = $MBI->_len($x->{_m}); # length of mantissa 3160 3161 # the following poses a restriction on _e, but if _e is bigger than a 3162 # scalar, you got other problems (memory etc) anyway 3163 my $dad = -(0+ ($x->{_es}.$MBI->_num($x->{_e}))); # digits after dot 3164 my $zad = 0; # zeros after dot 3165 $zad = $dad - $len if (-$dad < -$len); # for 0.00..00xxx style 3166 3167 # p rint "scale $scale dad $dad zad $zad len $len\n"; 3168 # number bsstr len zad dad 3169 # 0.123 123e-3 3 0 3 3170 # 0.0123 123e-4 3 1 4 3171 # 0.001 1e-3 1 2 3 3172 # 1.23 123e-2 3 0 2 3173 # 1.2345 12345e-4 5 0 4 3174 3175 # do not round after/right of the $dad 3176 return $x if $scale > $dad; # 0.123, scale >= 3 => exit 3177 3178 # round to zero if rounding inside the $zad, but not for last zero like: 3179 # 0.0065, scale -2, round last '0' with following '65' (scale == zad case) 3180 return $x->bzero() if $scale < $zad; 3181 if ($scale == $zad) # for 0.006, scale -3 and trunc 3182 { 3183 $scale = -$len; 3184 } 3185 else 3186 { 3187 # adjust round-point to be inside mantissa 3188 if ($zad != 0) 3189 { 3190 $scale = $scale-$zad; 3191 } 3192 else 3193 { 3194 my $dbd = $len - $dad; $dbd = 0 if $dbd < 0; # digits before dot 3195 $scale = $dbd+$scale; 3196 } 3197 } 3198 } 3199 else 3200 { 3201 # round left from the '.' 3202 3203 # 123 => 100 means length(123) = 3 - $scale (2) => 1 3204 3205 my $dbt = $MBI->_len($x->{_m}); 3206 # digits before dot 3207 my $dbd = $dbt + ($x->{_es} . $MBI->_num($x->{_e})); 3208 # should be the same, so treat it as this 3209 $scale = 1 if $scale == 0; 3210 # shortcut if already integer 3211 return $x if $scale == 1 && $dbt <= $dbd; 3212 # maximum digits before dot 3213 ++$dbd; 3214 3215 if ($scale > $dbd) 3216 { 3217 # not enough digits before dot, so round to zero 3218 return $x->bzero; 3219 } 3220 elsif ( $scale == $dbd ) 3221 { 3222 # maximum 3223 $scale = -$dbt; 3224 } 3225 else 3226 { 3227 $scale = $dbd - $scale; 3228 } 3229 } 3230 # pass sign to bround for rounding modes '+inf' and '-inf' 3231 my $m = bless { sign => $x->{sign}, value => $x->{_m} }, 'Math::BigInt'; 3232 $m->bround($scale,$mode); 3233 $x->{_m} = $m->{value}; # get our mantissa back 3234 $x->bnorm(); 3235 } 3236 3237 sub bround 3238 { 3239 # accuracy: preserve $N digits, and overwrite the rest with 0's 3240 my $x = shift; my $self = ref($x) || $x; $x = $self->new(shift) if !ref($x); 3241 3242 if (($_[0] || 0) < 0) 3243 { 3244 require Carp; Carp::croak ('bround() needs positive accuracy'); 3245 } 3246 3247 my ($scale,$mode) = $x->_scale_a(@_); 3248 return $x if !defined $scale || $x->modify('bround'); # no-op 3249 3250 # scale is now either $x->{_a}, $accuracy, or the user parameter 3251 # test whether $x already has lower accuracy, do nothing in this case 3252 # but do round if the accuracy is the same, since a math operation might 3253 # want to round a number with A=5 to 5 digits afterwards again 3254 return $x if defined $x->{_a} && $x->{_a} < $scale; 3255 3256 # scale < 0 makes no sense 3257 # scale == 0 => keep all digits 3258 # never round a +-inf, NaN 3259 return $x if ($scale <= 0) || $x->{sign} !~ /^[+-]$/; 3260 3261 # 1: never round a 0 3262 # 2: if we should keep more digits than the mantissa has, do nothing 3263 if ($x->is_zero() || $MBI->_len($x->{_m}) <= $scale) 3264 { 3265 $x->{_a} = $scale if !defined $x->{_a} || $x->{_a} > $scale; 3266 return $x; 3267 } 3268 3269 # pass sign to bround for '+inf' and '-inf' rounding modes 3270 my $m = bless { sign => $x->{sign}, value => $x->{_m} }, 'Math::BigInt'; 3271 3272 $m->bround($scale,$mode); # round mantissa 3273 $x->{_m} = $m->{value}; # get our mantissa back 3274 $x->{_a} = $scale; # remember rounding 3275 delete $x->{_p}; # and clear P 3276 $x->bnorm(); # del trailing zeros gen. by bround() 3277 } 3278 3279 sub bfloor 3280 { 3281 # return integer less or equal then $x 3282 my ($self,$x,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_); 3283 3284 return $x if $x->modify('bfloor'); 3285 3286 return $x if $x->{sign} !~ /^[+-]$/; # nan, +inf, -inf 3287 3288 # if $x has digits after dot 3289 if ($x->{_es} eq '-') 3290 { 3291 $x->{_m} = $MBI->_rsft($x->{_m},$x->{_e},10); # cut off digits after dot 3292 $x->{_e} = $MBI->_zero(); # trunc/norm 3293 $x->{_es} = '+'; # abs e 3294 $MBI->_inc($x->{_m}) if $x->{sign} eq '-'; # increment if negative 3295 } 3296 $x->round($a,$p,$r); 3297 } 3298 3299 sub bceil 3300 { 3301 # return integer greater or equal then $x 3302 my ($self,$x,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_); 3303 3304 return $x if $x->modify('bceil'); 3305 return $x if $x->{sign} !~ /^[+-]$/; # nan, +inf, -inf 3306 3307 # if $x has digits after dot 3308 if ($x->{_es} eq '-') 3309 { 3310 $x->{_m} = $MBI->_rsft($x->{_m},$x->{_e},10); # cut off digits after dot 3311 $x->{_e} = $MBI->_zero(); # trunc/norm 3312 $x->{_es} = '+'; # abs e 3313 $MBI->_inc($x->{_m}) if $x->{sign} eq '+'; # increment if positive 3314 } 3315 $x->round($a,$p,$r); 3316 } 3317 3318 sub brsft 3319 { 3320 # shift right by $y (divide by power of $n) 3321 3322 # set up parameters 3323 my ($self,$x,$y,$n,$a,$p,$r) = (ref($_[0]),@_); 3324 # objectify is costly, so avoid it 3325 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) 3326 { 3327 ($self,$x,$y,$n,$a,$p,$r) = objectify(2,@_); 3328 } 3329 3330 return $x if $x->modify('brsft'); 3331 return $x if $x->{sign} !~ /^[+-]$/; # nan, +inf, -inf 3332 3333 $n = 2 if !defined $n; $n = $self->new($n); 3334 3335 # negative amount? 3336 return $x->blsft($y->copy()->babs(),$n) if $y->{sign} =~ /^-/; 3337 3338 # the following call to bdiv() will return either quo or (quo,reminder): 3339 $x->bdiv($n->bpow($y),$a,$p,$r,$y); 3340 } 3341 3342 sub blsft 3343 { 3344 # shift left by $y (multiply by power of $n) 3345 3346 # set up parameters 3347 my ($self,$x,$y,$n,$a,$p,$r) = (ref($_[0]),@_); 3348 # objectify is costly, so avoid it 3349 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) 3350 { 3351 ($self,$x,$y,$n,$a,$p,$r) = objectify(2,@_); 3352 } 3353 3354 return $x if $x->modify('blsft'); 3355 return $x if $x->{sign} !~ /^[+-]$/; # nan, +inf, -inf 3356 3357 $n = 2 if !defined $n; $n = $self->new($n); 3358 3359 # negative amount? 3360 return $x->brsft($y->copy()->babs(),$n) if $y->{sign} =~ /^-/; 3361 3362 $x->bmul($n->bpow($y),$a,$p,$r,$y); 3363 } 3364 3365 ############################################################################### 3366 3367 sub DESTROY 3368 { 3369 # going through AUTOLOAD for every DESTROY is costly, avoid it by empty sub 3370 } 3371 3372 sub AUTOLOAD 3373 { 3374 # make fxxx and bxxx both work by selectively mapping fxxx() to MBF::bxxx() 3375 # or falling back to MBI::bxxx() 3376 my $name = $AUTOLOAD; 3377 3378 $name =~ s/(.*):://; # split package 3379 my $c = $1 || $class; 3380 no strict 'refs'; 3381 $c->import() if $IMPORT == 0; 3382 if (!_method_alias($name)) 3383 { 3384 if (!defined $name) 3385 { 3386 # delayed load of Carp and avoid recursion 3387 require Carp; 3388 Carp::croak ("$c: Can't call a method without name"); 3389 } 3390 if (!_method_hand_up($name)) 3391 { 3392 # delayed load of Carp and avoid recursion 3393 require Carp; 3394 Carp::croak ("Can't call $c\-\>$name, not a valid method"); 3395 } 3396 # try one level up, but subst. bxxx() for fxxx() since MBI only got bxxx() 3397 $name =~ s/^f/b/; 3398 return &{"Math::BigInt"."::$name"}(@_); 3399 } 3400 my $bname = $name; $bname =~ s/^f/b/; 3401 $c .= "::$name"; 3402 *{$c} = \&{$bname}; 3403 &{$c}; # uses @_ 3404 } 3405 3406 sub exponent 3407 { 3408 # return a copy of the exponent 3409 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_); 3410 3411 if ($x->{sign} !~ /^[+-]$/) 3412 { 3413 my $s = $x->{sign}; $s =~ s/^[+-]//; 3414 return Math::BigInt->new($s); # -inf, +inf => +inf 3415 } 3416 Math::BigInt->new( $x->{_es} . $MBI->_str($x->{_e})); 3417 } 3418 3419 sub mantissa 3420 { 3421 # return a copy of the mantissa 3422 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_); 3423 3424 if ($x->{sign} !~ /^[+-]$/) 3425 { 3426 my $s = $x->{sign}; $s =~ s/^[+]//; 3427 return Math::BigInt->new($s); # -inf, +inf => +inf 3428 } 3429 my $m = Math::BigInt->new( $MBI->_str($x->{_m})); 3430 $m->bneg() if $x->{sign} eq '-'; 3431 3432 $m; 3433 } 3434 3435 sub parts 3436 { 3437 # return a copy of both the exponent and the mantissa 3438 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_); 3439 3440 if ($x->{sign} !~ /^[+-]$/) 3441 { 3442 my $s = $x->{sign}; $s =~ s/^[+]//; my $se = $s; $se =~ s/^[-]//; 3443 return ($self->new($s),$self->new($se)); # +inf => inf and -inf,+inf => inf 3444 } 3445 my $m = Math::BigInt->bzero(); 3446 $m->{value} = $MBI->_copy($x->{_m}); 3447 $m->bneg() if $x->{sign} eq '-'; 3448 ($m, Math::BigInt->new( $x->{_es} . $MBI->_num($x->{_e}) )); 3449 } 3450 3451 ############################################################################## 3452 # private stuff (internal use only) 3453 3454 sub import 3455 { 3456 my $self = shift; 3457 my $l = scalar @_; 3458 my $lib = ''; my @a; 3459 my $lib_kind = 'try'; 3460 $IMPORT=1; 3461 for ( my $i = 0; $i < $l ; $i++) 3462 { 3463 if ( $_[$i] eq ':constant' ) 3464 { 3465 # This causes overlord er load to step in. 'binary' and 'integer' 3466 # are handled by BigInt. 3467 overload::constant float => sub { $self->new(shift); }; 3468 } 3469 elsif ($_[$i] eq 'upgrade') 3470 { 3471 # this causes upgrading 3472 $upgrade = $_[$i+1]; # or undef to disable 3473 $i++; 3474 } 3475 elsif ($_[$i] eq 'downgrade') 3476 { 3477 # this causes downgrading 3478 $downgrade = $_[$i+1]; # or undef to disable 3479 $i++; 3480 } 3481 elsif ($_[$i] =~ /^(lib|try|only)\z/) 3482 { 3483 # alternative library 3484 $lib = $_[$i+1] || ''; # default Calc 3485 $lib_kind = $1; # lib, try or only 3486 $i++; 3487 } 3488 elsif ($_[$i] eq 'with') 3489 { 3490 # alternative class for our private parts() 3491 # XXX: no longer supported 3492 # $MBI = $_[$i+1] || 'Math::BigInt'; 3493 $i++; 3494 } 3495 else 3496 { 3497 push @a, $_[$i]; 3498 } 3499 } 3500 3501 $lib =~ tr/a-zA-Z0-9,://cd; # restrict to sane characters 3502 # let use Math::BigInt lib => 'GMP'; use Math::BigFloat; still work 3503 my $mbilib = eval { Math::BigInt->config()->{lib} }; 3504 if ((defined $mbilib) && ($MBI eq 'Math::BigInt::Calc')) 3505 { 3506 # MBI already loaded 3507 Math::BigInt->import( $lib_kind, "$lib,$mbilib", 'objectify'); 3508 } 3509 else 3510 { 3511 # MBI not loaded, or with ne "Math::BigInt::Calc" 3512 $lib .= ",$mbilib" if defined $mbilib; 3513 $lib =~ s/^,//; # don't leave empty 3514 3515 # replacement library can handle lib statement, but also could ignore it 3516 3517 # Perl < 5.6.0 dies with "out of memory!" when eval() and ':constant' is 3518 # used in the same script, or eval inside import(). So we require MBI: 3519 require Math::BigInt; 3520 Math::BigInt->import( $lib_kind => $lib, 'objectify' ); 3521 } 3522 if ($@) 3523 { 3524 require Carp; Carp::croak ("Couldn't load $lib: $! $@"); 3525 } 3526 # find out which one was actually loaded 3527 $MBI = Math::BigInt->config()->{lib}; 3528 3529 # register us with MBI to get notified of future lib changes 3530 Math::BigInt::_register_callback( $self, sub { $MBI = $_[0]; } ); 3531 3532 $self->export_to_level(1,$self,@a); # export wanted functions 3533 } 3534 3535 sub bnorm 3536 { 3537 # adjust m and e so that m is smallest possible 3538 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_); 3539 3540 return $x if $x->{sign} !~ /^[+-]$/; # inf, nan etc 3541 3542 my $zeros = $MBI->_zeros($x->{_m}); # correct for trailing zeros 3543 if ($zeros != 0) 3544 { 3545 my $z = $MBI->_new($zeros); 3546 $x->{_m} = $MBI->_rsft ($x->{_m}, $z, 10); 3547 if ($x->{_es} eq '-') 3548 { 3549 if ($MBI->_acmp($x->{_e},$z) >= 0) 3550 { 3551 $x->{_e} = $MBI->_sub ($x->{_e}, $z); 3552 $x->{_es} = '+' if $MBI->_is_zero($x->{_e}); 3553 } 3554 else 3555 { 3556 $x->{_e} = $MBI->_sub ( $MBI->_copy($z), $x->{_e}); 3557 $x->{_es} = '+'; 3558 } 3559 } 3560 else 3561 { 3562 $x->{_e} = $MBI->_add ($x->{_e}, $z); 3563 } 3564 } 3565 else 3566 { 3567 # $x can only be 0Ey if there are no trailing zeros ('0' has 0 trailing 3568 # zeros). So, for something like 0Ey, set y to 1, and -0 => +0 3569 $x->{sign} = '+', $x->{_es} = '+', $x->{_e} = $MBI->_one() 3570 if $MBI->_is_zero($x->{_m}); 3571 } 3572 3573 $x; # MBI bnorm is no-op, so dont call it 3574 } 3575 3576 ############################################################################## 3577 3578 sub as_hex 3579 { 3580 # return number as hexadecimal string (only for integers defined) 3581 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_); 3582 3583 return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, nan etc 3584 return '0x0' if $x->is_zero(); 3585 3586 return $nan if $x->{_es} ne '+'; # how to do 1e-1 in hex!? 3587 3588 my $z = $MBI->_copy($x->{_m}); 3589 if (! $MBI->_is_zero($x->{_e})) # > 0 3590 { 3591 $MBI->_lsft( $z, $x->{_e},10); 3592 } 3593 $z = Math::BigInt->new( $x->{sign} . $MBI->_num($z)); 3594 $z->as_hex(); 3595 } 3596 3597 sub as_bin 3598 { 3599 # return number as binary digit string (only for integers defined) 3600 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_); 3601 3602 return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, nan etc 3603 return '0b0' if $x->is_zero(); 3604 3605 return $nan if $x->{_es} ne '+'; # how to do 1e-1 in hex!? 3606 3607 my $z = $MBI->_copy($x->{_m}); 3608 if (! $MBI->_is_zero($x->{_e})) # > 0 3609 { 3610 $MBI->_lsft( $z, $x->{_e},10); 3611 } 3612 $z = Math::BigInt->new( $x->{sign} . $MBI->_num($z)); 3613 $z->as_bin(); 3614 } 3615 3616 sub as_oct 3617 { 3618 # return number as octal digit string (only for integers defined) 3619 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_); 3620 3621 return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, nan etc 3622 return '0' if $x->is_zero(); 3623 3624 return $nan if $x->{_es} ne '+'; # how to do 1e-1 in hex!? 3625 3626 my $z = $MBI->_copy($x->{_m}); 3627 if (! $MBI->_is_zero($x->{_e})) # > 0 3628 { 3629 $MBI->_lsft( $z, $x->{_e},10); 3630 } 3631 $z = Math::BigInt->new( $x->{sign} . $MBI->_num($z)); 3632 $z->as_oct(); 3633 } 3634 3635 sub as_number 3636 { 3637 # return copy as a bigint representation of this BigFloat number 3638 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_); 3639 3640 return $x if $x->modify('as_number'); 3641 3642 my $z = $MBI->_copy($x->{_m}); 3643 if ($x->{_es} eq '-') # < 0 3644 { 3645 $MBI->_rsft( $z, $x->{_e},10); 3646 } 3647 elsif (! $MBI->_is_zero($x->{_e})) # > 0 3648 { 3649 $MBI->_lsft( $z, $x->{_e},10); 3650 } 3651 $z = Math::BigInt->new( $x->{sign} . $MBI->_num($z)); 3652 $z; 3653 } 3654 3655 sub length 3656 { 3657 my $x = shift; 3658 my $class = ref($x) || $x; 3659 $x = $class->new(shift) unless ref($x); 3660 3661 return 1 if $MBI->_is_zero($x->{_m}); 3662 3663 my $len = $MBI->_len($x->{_m}); 3664 $len += $MBI->_num($x->{_e}) if $x->{_es} eq '+'; 3665 if (wantarray()) 3666 { 3667 my $t = 0; 3668 $t = $MBI->_num($x->{_e}) if $x->{_es} eq '-'; 3669 return ($len, $t); 3670 } 3671 $len; 3672 } 3673 3674 1; 3675 __END__ 3676 3677 =head1 NAME 3678 3679 Math::BigFloat - Arbitrary size floating point math package 3680 3681 =head1 SYNOPSIS 3682 3683 use Math::BigFloat; 3684 3685 # Number creation 3686 my $x = Math::BigFloat->new($str); # defaults to 0 3687 my $y = $x->copy(); # make a true copy 3688 my $nan = Math::BigFloat->bnan(); # create a NotANumber 3689 my $zero = Math::BigFloat->bzero(); # create a +0 3690 my $inf = Math::BigFloat->binf(); # create a +inf 3691 my $inf = Math::BigFloat->binf('-'); # create a -inf 3692 my $one = Math::BigFloat->bone(); # create a +1 3693 my $mone = Math::BigFloat->bone('-'); # create a -1 3694 3695 my $pi = Math::BigFloat->bpi(100); # PI to 100 digits 3696 3697 # the following examples compute their result to 100 digits accuracy: 3698 my $cos = Math::BigFloat->new(1)->bcos(100); # cosinus(1) 3699 my $sin = Math::BigFloat->new(1)->bsin(100); # sinus(1) 3700 my $atan = Math::BigFloat->new(1)->batan(100); # arcus tangens(1) 3701 3702 my $atan2 = Math::BigFloat->new( 1 )->batan2( 1 ,100); # batan(1) 3703 my $atan2 = Math::BigFloat->new( 1 )->batan2( 8 ,100); # batan(1/8) 3704 my $atan2 = Math::BigFloat->new( -2 )->batan2( 1 ,100); # batan(-2) 3705 3706 # Testing 3707 $x->is_zero(); # true if arg is +0 3708 $x->is_nan(); # true if arg is NaN 3709 $x->is_one(); # true if arg is +1 3710 $x->is_one('-'); # true if arg is -1 3711 $x->is_odd(); # true if odd, false for even 3712 $x->is_even(); # true if even, false for odd 3713 $x->is_pos(); # true if >= 0 3714 $x->is_neg(); # true if < 0 3715 $x->is_inf(sign); # true if +inf, or -inf (default is '+') 3716 3717 $x->bcmp($y); # compare numbers (undef,<0,=0,>0) 3718 $x->bacmp($y); # compare absolutely (undef,<0,=0,>0) 3719 $x->sign(); # return the sign, either +,- or NaN 3720 $x->digit($n); # return the nth digit, counting from right 3721 $x->digit(-$n); # return the nth digit, counting from left 3722 3723 # The following all modify their first argument. If you want to preserve 3724 # $x, use $z = $x->copy()->bXXX($y); See under L<CAVEATS> for why this is 3725 # necessary when mixing $a = $b assignments with non-overloaded math. 3726 3727 # set 3728 $x->bzero(); # set $i to 0 3729 $x->bnan(); # set $i to NaN 3730 $x->bone(); # set $x to +1 3731 $x->bone('-'); # set $x to -1 3732 $x->binf(); # set $x to inf 3733 $x->binf('-'); # set $x to -inf 3734 3735 $x->bneg(); # negation 3736 $x->babs(); # absolute value 3737 $x->bnorm(); # normalize (no-op) 3738 $x->bnot(); # two's complement (bit wise not) 3739 $x->binc(); # increment x by 1 3740 $x->bdec(); # decrement x by 1 3741 3742 $x->badd($y); # addition (add $y to $x) 3743 $x->bsub($y); # subtraction (subtract $y from $x) 3744 $x->bmul($y); # multiplication (multiply $x by $y) 3745 $x->bdiv($y); # divide, set $x to quotient 3746 # return (quo,rem) or quo if scalar 3747 3748 $x->bmod($y); # modulus ($x % $y) 3749 $x->bpow($y); # power of arguments ($x ** $y) 3750 $x->bmodpow($exp,$mod); # modular exponentation (($num**$exp) % $mod)) 3751 $x->blsft($y, $n); # left shift by $y places in base $n 3752 $x->brsft($y, $n); # right shift by $y places in base $n 3753 # returns (quo,rem) or quo if in scalar context 3754 3755 $x->blog(); # logarithm of $x to base e (Euler's number) 3756 $x->blog($base); # logarithm of $x to base $base (f.i. 2) 3757 $x->bexp(); # calculate e ** $x where e is Euler's number 3758 3759 $x->band($y); # bit-wise and 3760 $x->bior($y); # bit-wise inclusive or 3761 $x->bxor($y); # bit-wise exclusive or 3762 $x->bnot(); # bit-wise not (two's complement) 3763 3764 $x->bsqrt(); # calculate square-root 3765 $x->broot($y); # $y'th root of $x (e.g. $y == 3 => cubic root) 3766 $x->bfac(); # factorial of $x (1*2*3*4*..$x) 3767 3768 $x->bround($N); # accuracy: preserve $N digits 3769 $x->bfround($N); # precision: round to the $Nth digit 3770 3771 $x->bfloor(); # return integer less or equal than $x 3772 $x->bceil(); # return integer greater or equal than $x 3773 3774 # The following do not modify their arguments: 3775 3776 bgcd(@values); # greatest common divisor 3777 blcm(@values); # lowest common multiplicator 3778 3779 $x->bstr(); # return string 3780 $x->bsstr(); # return string in scientific notation 3781 3782 $x->as_int(); # return $x as BigInt 3783 $x->exponent(); # return exponent as BigInt 3784 $x->mantissa(); # return mantissa as BigInt 3785 $x->parts(); # return (mantissa,exponent) as BigInt 3786 3787 $x->length(); # number of digits (w/o sign and '.') 3788 ($l,$f) = $x->length(); # number of digits, and length of fraction 3789 3790 $x->precision(); # return P of $x (or global, if P of $x undef) 3791 $x->precision($n); # set P of $x to $n 3792 $x->accuracy(); # return A of $x (or global, if A of $x undef) 3793 $x->accuracy($n); # set A $x to $n 3794 3795 # these get/set the appropriate global value for all BigFloat objects 3796 Math::BigFloat->precision(); # Precision 3797 Math::BigFloat->accuracy(); # Accuracy 3798 Math::BigFloat->round_mode(); # rounding mode 3799 3800 =head1 DESCRIPTION 3801 3802 All operators (including basic math operations) are overloaded if you 3803 declare your big floating point numbers as 3804 3805 $i = new Math::BigFloat '12_3.456_789_123_456_789E-2'; 3806 3807 Operations with overloaded operators preserve the arguments, which is 3808 exactly what you expect. 3809 3810 =head2 Canonical notation 3811 3812 Input to these routines are either BigFloat objects, or strings of the 3813 following four forms: 3814 3815 =over 2 3816 3817 =item * 3818 3819 C</^[+-]\d+$/> 3820 3821 =item * 3822 3823 C</^[+-]\d+\.\d*$/> 3824 3825 =item * 3826 3827 C</^[+-]\d+E[+-]?\d+$/> 3828 3829 =item * 3830 3831 C</^[+-]\d*\.\d+E[+-]?\d+$/> 3832 3833 =back 3834 3835 all with optional leading and trailing zeros and/or spaces. Additionally, 3836 numbers are allowed to have an underscore between any two digits. 3837 3838 Empty strings as well as other illegal numbers results in 'NaN'. 3839 3840 bnorm() on a BigFloat object is now effectively a no-op, since the numbers 3841 are always stored in normalized form. On a string, it creates a BigFloat 3842 object. 3843 3844 =head2 Output 3845 3846 Output values are BigFloat objects (normalized), except for bstr() and bsstr(). 3847 3848 The string output will always have leading and trailing zeros stripped and drop 3849 a plus sign. C<bstr()> will give you always the form with a decimal point, 3850 while C<bsstr()> (s for scientific) gives you the scientific notation. 3851 3852 Input bstr() bsstr() 3853 '-0' '0' '0E1' 3854 ' -123 123 123' '-123123123' '-123123123E0' 3855 '00.0123' '0.0123' '123E-4' 3856 '123.45E-2' '1.2345' '12345E-4' 3857 '10E+3' '10000' '1E4' 3858 3859 Some routines (C<is_odd()>, C<is_even()>, C<is_zero()>, C<is_one()>, 3860 C<is_nan()>) return true or false, while others (C<bcmp()>, C<bacmp()>) 3861 return either undef, <0, 0 or >0 and are suited for sort. 3862 3863 Actual math is done by using the class defined with C<with => Class;> (which 3864 defaults to BigInts) to represent the mantissa and exponent. 3865 3866 The sign C</^[+-]$/> is stored separately. The string 'NaN' is used to 3867 represent the result when input arguments are not numbers, as well as 3868 the result of dividing by zero. 3869 3870 =head2 C<mantissa()>, C<exponent()> and C<parts()> 3871 3872 C<mantissa()> and C<exponent()> return the said parts of the BigFloat 3873 as BigInts such that: 3874 3875 $m = $x->mantissa(); 3876 $e = $x->exponent(); 3877 $y = $m * ( 10 ** $e ); 3878 print "ok\n" if $x == $y; 3879 3880 C<< ($m,$e) = $x->parts(); >> is just a shortcut giving you both of them. 3881 3882 A zero is represented and returned as C<0E1>, B<not> C<0E0> (after Knuth). 3883 3884 Currently the mantissa is reduced as much as possible, favouring higher 3885 exponents over lower ones (e.g. returning 1e7 instead of 10e6 or 10000000e0). 3886 This might change in the future, so do not depend on it. 3887 3888 =head2 Accuracy vs. Precision 3889 3890 See also: L<Rounding|Rounding>. 3891 3892 Math::BigFloat supports both precision (rounding to a certain place before or 3893 after the dot) and accuracy (rounding to a certain number of digits). For a 3894 full documentation, examples and tips on these topics please see the large 3895 section about rounding in L<Math::BigInt>. 3896 3897 Since things like C<sqrt(2)> or C<1 / 3> must presented with a limited 3898 accuracy lest a operation consumes all resources, each operation produces 3899 no more than the requested number of digits. 3900 3901 If there is no gloabl precision or accuracy set, B<and> the operation in 3902 question was not called with a requested precision or accuracy, B<and> the 3903 input $x has no accuracy or precision set, then a fallback parameter will 3904 be used. For historical reasons, it is called C<div_scale> and can be accessed 3905 via: 3906 3907 $d = Math::BigFloat->div_scale(); # query 3908 Math::BigFloat->div_scale($n); # set to $n digits 3909 3910 The default value for C<div_scale> is 40. 3911 3912 In case the result of one operation has more digits than specified, 3913 it is rounded. The rounding mode taken is either the default mode, or the one 3914 supplied to the operation after the I<scale>: 3915 3916 $x = Math::BigFloat->new(2); 3917 Math::BigFloat->accuracy(5); # 5 digits max 3918 $y = $x->copy()->bdiv(3); # will give 0.66667 3919 $y = $x->copy()->bdiv(3,6); # will give 0.666667 3920 $y = $x->copy()->bdiv(3,6,undef,'odd'); # will give 0.666667 3921 Math::BigFloat->round_mode('zero'); 3922 $y = $x->copy()->bdiv(3,6); # will also give 0.666667 3923 3924 Note that C<< Math::BigFloat->accuracy() >> and C<< Math::BigFloat->precision() >> 3925 set the global variables, and thus B<any> newly created number will be subject 3926 to the global rounding B<immediately>. This means that in the examples above, the 3927 C<3> as argument to C<bdiv()> will also get an accuracy of B<5>. 3928 3929 It is less confusing to either calculate the result fully, and afterwards 3930 round it explicitly, or use the additional parameters to the math 3931 functions like so: 3932 3933 use Math::BigFloat; 3934 $x = Math::BigFloat->new(2); 3935 $y = $x->copy()->bdiv(3); 3936 print $y->bround(5),"\n"; # will give 0.66667 3937 3938 or 3939 3940 use Math::BigFloat; 3941 $x = Math::BigFloat->new(2); 3942 $y = $x->copy()->bdiv(3,5); # will give 0.66667 3943 print "$y\n"; 3944 3945 =head2 Rounding 3946 3947 =over 2 3948 3949 =item ffround ( +$scale ) 3950 3951 Rounds to the $scale'th place left from the '.', counting from the dot. 3952 The first digit is numbered 1. 3953 3954 =item ffround ( -$scale ) 3955 3956 Rounds to the $scale'th place right from the '.', counting from the dot. 3957 3958 =item ffround ( 0 ) 3959 3960 Rounds to an integer. 3961 3962 =item fround ( +$scale ) 3963 3964 Preserves accuracy to $scale digits from the left (aka significant digits) 3965 and pads the rest with zeros. If the number is between 1 and -1, the 3966 significant digits count from the first non-zero after the '.' 3967 3968 =item fround ( -$scale ) and fround ( 0 ) 3969 3970 These are effectively no-ops. 3971 3972 =back 3973 3974 All rounding functions take as a second parameter a rounding mode from one of 3975 the following: 'even', 'odd', '+inf', '-inf', 'zero', 'trunc' or 'common'. 3976 3977 The default rounding mode is 'even'. By using 3978 C<< Math::BigFloat->round_mode($round_mode); >> you can get and set the default 3979 mode for subsequent rounding. The usage of C<$Math::BigFloat::$round_mode> is 3980 no longer supported. 3981 The second parameter to the round functions then overrides the default 3982 temporarily. 3983 3984 The C<as_number()> function returns a BigInt from a Math::BigFloat. It uses 3985 'trunc' as rounding mode to make it equivalent to: 3986 3987 $x = 2.5; 3988 $y = int($x) + 2; 3989 3990 You can override this by passing the desired rounding mode as parameter to 3991 C<as_number()>: 3992 3993 $x = Math::BigFloat->new(2.5); 3994 $y = $x->as_number('odd'); # $y = 3 3995 3996 =head1 METHODS 3997 3998 Math::BigFloat supports all methods that Math::BigInt supports, except it 3999 calculates non-integer results when possible. Please see L<Math::BigInt> 4000 for a full description of each method. Below are just the most important 4001 differences: 4002 4003 =head2 accuracy 4004 4005 $x->accuracy(5); # local for $x 4006 CLASS->accuracy(5); # global for all members of CLASS 4007 # Note: This also applies to new()! 4008 4009 $A = $x->accuracy(); # read out accuracy that affects $x 4010 $A = CLASS->accuracy(); # read out global accuracy 4011 4012 Set or get the global or local accuracy, aka how many significant digits the 4013 results have. If you set a global accuracy, then this also applies to new()! 4014 4015 Warning! The accuracy I<sticks>, e.g. once you created a number under the 4016 influence of C<< CLASS->accuracy($A) >>, all results from math operations with 4017 that number will also be rounded. 4018 4019 In most cases, you should probably round the results explicitly using one of 4020 L<round()>, L<bround()> or L<bfround()> or by passing the desired accuracy 4021 to the math operation as additional parameter: 4022 4023 my $x = Math::BigInt->new(30000); 4024 my $y = Math::BigInt->new(7); 4025 print scalar $x->copy()->bdiv($y, 2); # print 4300 4026 print scalar $x->copy()->bdiv($y)->bround(2); # print 4300 4027 4028 =head2 precision() 4029 4030 $x->precision(-2); # local for $x, round at the second digit right of the dot 4031 $x->precision(2); # ditto, round at the second digit left of the dot 4032 4033 CLASS->precision(5); # Global for all members of CLASS 4034 # This also applies to new()! 4035 CLASS->precision(-5); # ditto 4036 4037 $P = CLASS->precision(); # read out global precision 4038 $P = $x->precision(); # read out precision that affects $x 4039 4040 Note: You probably want to use L<accuracy()> instead. With L<accuracy> you 4041 set the number of digits each result should have, with L<precision> you 4042 set the place where to round! 4043 4044 =head2 bexp() 4045 4046 $x->bexp($accuracy); # calculate e ** X 4047 4048 Calculates the expression C<e ** $x> where C<e> is Euler's number. 4049 4050 This method was added in v1.82 of Math::BigInt (April 2007). 4051 4052 =head2 bnok() 4053 4054 $x->bnok($y); # x over y (binomial coefficient n over k) 4055 4056 Calculates the binomial coefficient n over k, also called the "choose" 4057 function. The result is equivalent to: 4058 4059 ( n ) n! 4060 | - | = ------- 4061 ( k ) k!(n-k)! 4062 4063 This method was added in v1.84 of Math::BigInt (April 2007). 4064 4065 =head2 bpi() 4066 4067 print Math::BigFloat->bpi(100), "\n"; 4068 4069 Calculate PI to N digits (including the 3 before the dot). The result is 4070 rounded according to the current rounding mode, which defaults to "even". 4071 4072 This method was added in v1.87 of Math::BigInt (June 2007). 4073 4074 =head2 bcos() 4075 4076 my $x = Math::BigFloat->new(1); 4077 print $x->bcos(100), "\n"; 4078 4079 Calculate the cosinus of $x, modifying $x in place. 4080 4081 This method was added in v1.87 of Math::BigInt (June 2007). 4082 4083 =head2 bsin() 4084 4085 my $x = Math::BigFloat->new(1); 4086 print $x->bsin(100), "\n"; 4087 4088 Calculate the sinus of $x, modifying $x in place. 4089 4090 This method was added in v1.87 of Math::BigInt (June 2007). 4091 4092 =head2 batan2() 4093 4094 my $y = Math::BigFloat->new(2); 4095 my $x = Math::BigFloat->new(3); 4096 print $y->batan2($x), "\n"; 4097 4098 Calculate the arcus tanges of C<$y> divided by C<$x>, modifying $y in place. 4099 See also L<batan()>. 4100 4101 This method was added in v1.87 of Math::BigInt (June 2007). 4102 4103 =head2 batan() 4104 4105 my $x = Math::BigFloat->new(1); 4106 print $x->batan(100), "\n"; 4107 4108 Calculate the arcus tanges of $x, modifying $x in place. See also L<batan2()>. 4109 4110 This method was added in v1.87 of Math::BigInt (June 2007). 4111 4112 =head2 bmuladd() 4113 4114 $x->bmuladd($y,$z); 4115 4116 Multiply $x by $y, and then add $z to the result. 4117 4118 This method was added in v1.87 of Math::BigInt (June 2007). 4119 4120 =head1 Autocreating constants 4121 4122 After C<use Math::BigFloat ':constant'> all the floating point constants 4123 in the given scope are converted to C<Math::BigFloat>. This conversion 4124 happens at compile time. 4125 4126 In particular 4127 4128 perl -MMath::BigFloat=:constant -e 'print 2E-100,"\n"' 4129 4130 prints the value of C<2E-100>. Note that without conversion of 4131 constants the expression 2E-100 will be calculated as normal floating point 4132 number. 4133 4134 Please note that ':constant' does not affect integer constants, nor binary 4135 nor hexadecimal constants. Use L<bignum> or L<Math::BigInt> to get this to 4136 work. 4137 4138 =head2 Math library 4139 4140 Math with the numbers is done (by default) by a module called 4141 Math::BigInt::Calc. This is equivalent to saying: 4142 4143 use Math::BigFloat lib => 'Calc'; 4144 4145 You can change this by using: 4146 4147 use Math::BigFloat lib => 'GMP'; 4148 4149 Note: The keyword 'lib' will warn when the requested library could not be 4150 loaded. To suppress the warning use 'try' instead: 4151 4152 use Math::BigFloat try => 'GMP'; 4153 4154 To turn the warning into a die(), use 'only' instead: 4155 4156 use Math::BigFloat only => 'GMP'; 4157 4158 The following would first try to find Math::BigInt::Foo, then 4159 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc: 4160 4161 use Math::BigFloat lib => 'Foo,Math::BigInt::Bar'; 4162 4163 See the respective low-level library documentation for further details. 4164 4165 Please note that Math::BigFloat does B<not> use the denoted library itself, 4166 but it merely passes the lib argument to Math::BigInt. So, instead of the need 4167 to do: 4168 4169 use Math::BigInt lib => 'GMP'; 4170 use Math::BigFloat; 4171 4172 you can roll it all into one line: 4173 4174 use Math::BigFloat lib => 'GMP'; 4175 4176 It is also possible to just require Math::BigFloat: 4177 4178 require Math::BigFloat; 4179 4180 This will load the necessary things (like BigInt) when they are needed, and 4181 automatically. 4182 4183 See L<Math::BigInt> for more details than you ever wanted to know about using 4184 a different low-level library. 4185 4186 =head2 Using Math::BigInt::Lite 4187 4188 For backwards compatibility reasons it is still possible to 4189 request a different storage class for use with Math::BigFloat: 4190 4191 use Math::BigFloat with => 'Math::BigInt::Lite'; 4192 4193 However, this request is ignored, as the current code now uses the low-level 4194 math libary for directly storing the number parts. 4195 4196 =head1 EXPORTS 4197 4198 C<Math::BigFloat> exports nothing by default, but can export the C<bpi()> method: 4199 4200 use Math::BigFloat qw/bpi/; 4201 4202 print bpi(10), "\n"; 4203 4204 =head1 BUGS 4205 4206 Please see the file BUGS in the CPAN distribution Math::BigInt for known bugs. 4207 4208 =head1 CAVEATS 4209 4210 Do not try to be clever to insert some operations in between switching 4211 libraries: 4212 4213 require Math::BigFloat; 4214 my $matter = Math::BigFloat->bone() + 4; # load BigInt and Calc 4215 Math::BigFloat->import( lib => 'Pari' ); # load Pari, too 4216 my $anti_matter = Math::BigFloat->bone()+4; # now use Pari 4217 4218 This will create objects with numbers stored in two different backend libraries, 4219 and B<VERY BAD THINGS> will happen when you use these together: 4220 4221 my $flash_and_bang = $matter + $anti_matter; # Don't do this! 4222 4223 =over 1 4224 4225 =item stringify, bstr() 4226 4227 Both stringify and bstr() now drop the leading '+'. The old code would return 4228 '+1.23', the new returns '1.23'. See the documentation in L<Math::BigInt> for 4229 reasoning and details. 4230 4231 =item bdiv 4232 4233 The following will probably not print what you expect: 4234 4235 print $c->bdiv(123.456),"\n"; 4236 4237 It prints both quotient and reminder since print works in list context. Also, 4238 bdiv() will modify $c, so be careful. You probably want to use 4239 4240 print $c / 123.456,"\n"; 4241 print scalar $c->bdiv(123.456),"\n"; # or if you want to modify $c 4242 4243 instead. 4244 4245 =item brsft 4246 4247 The following will probably not print what you expect: 4248 4249 my $c = Math::BigFloat->new('3.14159'); 4250 print $c->brsft(3,10),"\n"; # prints 0.00314153.1415 4251 4252 It prints both quotient and remainder, since print calls C<brsft()> in list 4253 context. Also, C<< $c->brsft() >> will modify $c, so be careful. 4254 You probably want to use 4255 4256 print scalar $c->copy()->brsft(3,10),"\n"; 4257 # or if you really want to modify $c 4258 print scalar $c->brsft(3,10),"\n"; 4259 4260 instead. 4261 4262 =item Modifying and = 4263 4264 Beware of: 4265 4266 $x = Math::BigFloat->new(5); 4267 $y = $x; 4268 4269 It will not do what you think, e.g. making a copy of $x. Instead it just makes 4270 a second reference to the B<same> object and stores it in $y. Thus anything 4271 that modifies $x will modify $y (except overloaded math operators), and vice 4272 versa. See L<Math::BigInt> for details and how to avoid that. 4273 4274 =item bpow 4275 4276 C<bpow()> now modifies the first argument, unlike the old code which left 4277 it alone and only returned the result. This is to be consistent with 4278 C<badd()> etc. The first will modify $x, the second one won't: 4279 4280 print bpow($x,$i),"\n"; # modify $x 4281 print $x->bpow($i),"\n"; # ditto 4282 print $x ** $i,"\n"; # leave $x alone 4283 4284 =item precision() vs. accuracy() 4285 4286 A common pitfall is to use L<precision()> when you want to round a result to 4287 a certain number of digits: 4288 4289 use Math::BigFloat; 4290 4291 Math::BigFloat->precision(4); # does not do what you think it does 4292 my $x = Math::BigFloat->new(12345); # rounds $x to "12000"! 4293 print "$x\n"; # print "12000" 4294 my $y = Math::BigFloat->new(3); # rounds $y to "0"! 4295 print "$y\n"; # print "0" 4296 $z = $x / $y; # 12000 / 0 => NaN! 4297 print "$z\n"; 4298 print $z->precision(),"\n"; # 4 4299 4300 Replacing L<precision> with L<accuracy> is probably not what you want, either: 4301 4302 use Math::BigFloat; 4303 4304 Math::BigFloat->accuracy(4); # enables global rounding: 4305 my $x = Math::BigFloat->new(123456); # rounded immediately to "12350" 4306 print "$x\n"; # print "123500" 4307 my $y = Math::BigFloat->new(3); # rounded to "3 4308 print "$y\n"; # print "3" 4309 print $z = $x->copy()->bdiv($y),"\n"; # 41170 4310 print $z->accuracy(),"\n"; # 4 4311 4312 What you want to use instead is: 4313 4314 use Math::BigFloat; 4315 4316 my $x = Math::BigFloat->new(123456); # no rounding 4317 print "$x\n"; # print "123456" 4318 my $y = Math::BigFloat->new(3); # no rounding 4319 print "$y\n"; # print "3" 4320 print $z = $x->copy()->bdiv($y,4),"\n"; # 41150 4321 print $z->accuracy(),"\n"; # undef 4322 4323 In addition to computing what you expected, the last example also does B<not> 4324 "taint" the result with an accuracy or precision setting, which would 4325 influence any further operation. 4326 4327 =back 4328 4329 =head1 SEE ALSO 4330 4331 L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well as 4332 L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and L<Math::BigInt::GMP>. 4333 4334 The pragmas L<bignum>, L<bigint> and L<bigrat> might also be of interest 4335 because they solve the autoupgrading/downgrading issue, at least partly. 4336 4337 The package at L<http://search.cpan.org/~tels/Math-BigInt> contains 4338 more documentation including a full version history, testcases, empty 4339 subclass files and benchmarks. 4340 4341 =head1 LICENSE 4342 4343 This program is free software; you may redistribute it and/or modify it under 4344 the same terms as Perl itself. 4345 4346 =head1 AUTHORS 4347 4348 Mark Biggar, overloaded interface by Ilya Zakharevich. 4349 Completely rewritten by Tels L<http://bloodgate.com> in 2001 - 2006, and still 4350 at it in 2007. 4351 4352 =cut
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 17 22:47:18 2015 | Cross-referenced by PHPXref 0.7.1 |