Upgrade to Math::BigInt 1.53.
[p5sagit/p5-mst-13.2.git] / lib / Math / BigFloat.pm
CommitLineData
13a12e00 1package Math::BigFloat;
2
3#
4# Mike grinned. 'Two down, infinity to go' - Mike Nostrus in Before and After
5#
6
58cde26e 7# The following hash values are internally used:
8# _e: exponent (BigInt)
9# _m: mantissa (absolute BigInt)
10# sign: +,-,"NaN" if not a number
11# _a: accuracy
12# _p: precision
0716bf9b 13# _f: flags, used to signal MBI not to touch our private parts
58cde26e 14
28df3e88 15$VERSION = '1.30';
58cde26e 16require 5.005;
17use Exporter;
0716bf9b 18use Math::BigInt qw/objectify/;
58cde26e 19@ISA = qw( Exporter Math::BigInt);
394e6ffb 20
58cde26e 21use strict;
027dc388 22use vars qw/$AUTOLOAD $accuracy $precision $div_scale $round_mode $rnd_mode/;
b3abae2a 23use vars qw/$upgrade $downgrade/;
58cde26e 24my $class = "Math::BigFloat";
a0d0e21e 25
a5f75d66 26use overload
bd05a461 27'<=>' => sub { $_[2] ?
28 ref($_[0])->bcmp($_[1],$_[0]) :
29 ref($_[0])->bcmp($_[0],$_[1])},
0716bf9b 30'int' => sub { $_[0]->as_number() }, # 'trunc' to bigint
a5f75d66 31;
a0d0e21e 32
0716bf9b 33##############################################################################
34# global constants, flags and accessory
35
36use constant MB_NEVER_ROUND => 0x0001;
37
58cde26e 38# are NaNs ok?
39my $NaNOK=1;
58cde26e 40# constant for easier life
41my $nan = 'NaN';
58cde26e 42
ee15d750 43# class constants, use Class->constant_name() to access
44$round_mode = 'even'; # one of 'even', 'odd', '+inf', '-inf', 'zero' or 'trunc'
45$accuracy = undef;
46$precision = undef;
47$div_scale = 40;
58cde26e 48
b3abae2a 49$upgrade = undef;
50$downgrade = undef;
51
027dc388 52##############################################################################
53# the old code had $rnd_mode, so we need to support it, too
54
55$rnd_mode = 'even';
56sub TIESCALAR { my ($class) = @_; bless \$round_mode, $class; }
57sub FETCH { return $round_mode; }
58sub STORE { $rnd_mode = $_[0]->round_mode($_[1]); }
59
60BEGIN { tie $rnd_mode, 'Math::BigFloat'; }
61
62##############################################################################
63
574bacfe 64# in case we call SUPER::->foo() and this wants to call modify()
65# sub modify () { 0; }
66
58cde26e 67{
ee15d750 68 # valid method aliases for AUTOLOAD
58cde26e 69 my %methods = map { $_ => 1 }
70 qw / fadd fsub fmul fdiv fround ffround fsqrt fmod fstr fsstr fpow fnorm
b3abae2a 71 fint facmp fcmp fzero fnan finf finc fdec flog ffac
61f5c3f5 72 fceil ffloor frsft flsft fone flog
ee15d750 73 /;
61f5c3f5 74 # valid method's that can be hand-ed up (for AUTOLOAD)
ee15d750 75 my %hand_ups = map { $_ => 1 }
76 qw / is_nan is_inf is_negative is_positive
394e6ffb 77 accuracy precision div_scale round_mode fneg fabs babs fnot
28df3e88 78 objectify upgrade downgrade
13a12e00 79 bone binf bnan bzero
58cde26e 80 /;
81
ee15d750 82 sub method_alias { return exists $methods{$_[0]||''}; }
83 sub method_hand_up { return exists $hand_ups{$_[0]||''}; }
a0d0e21e 84}
0e8b9368 85
58cde26e 86##############################################################################
87# constructors
a0d0e21e 88
58cde26e 89sub new
90 {
91 # create a new BigFloat object from a string or another bigfloat object.
92 # _e: exponent
93 # _m: mantissa
94 # sign => sign (+/-), or "NaN"
a0d0e21e 95
61f5c3f5 96 my ($class,$wanted,@r) = @_;
b3abae2a 97
61f5c3f5 98 # avoid numify-calls by not using || on $wanted!
99 return $class->bzero() if !defined $wanted; # default to 0
100 return $wanted->copy() if UNIVERSAL::isa($wanted,'Math::BigFloat');
a0d0e21e 101
58cde26e 102 my $self = {}; bless $self, $class;
b22b3e31 103 # shortcut for bigints and its subclasses
0716bf9b 104 if ((ref($wanted)) && (ref($wanted) ne $class))
58cde26e 105 {
0716bf9b 106 $self->{_m} = $wanted->as_number(); # get us a bigint copy
027dc388 107 $self->{_e} = Math::BigInt->bzero();
58cde26e 108 $self->{_m}->babs();
109 $self->{sign} = $wanted->sign();
0716bf9b 110 return $self->bnorm();
58cde26e 111 }
112 # got string
113 # handle '+inf', '-inf' first
ee15d750 114 if ($wanted =~ /^[+-]?inf$/)
58cde26e 115 {
28df3e88 116 return $downgrade->new($wanted) if $downgrade;
117
027dc388 118 $self->{_e} = Math::BigInt->bzero();
119 $self->{_m} = Math::BigInt->bzero();
58cde26e 120 $self->{sign} = $wanted;
ee15d750 121 $self->{sign} = '+inf' if $self->{sign} eq 'inf';
0716bf9b 122 return $self->bnorm();
58cde26e 123 }
124 #print "new string '$wanted'\n";
125 my ($mis,$miv,$mfv,$es,$ev) = Math::BigInt::_split(\$wanted);
126 if (!ref $mis)
127 {
128 die "$wanted is not a number initialized to $class" if !$NaNOK;
28df3e88 129
130 return $downgrade->bnan() if $downgrade;
131
027dc388 132 $self->{_e} = Math::BigInt->bzero();
133 $self->{_m} = Math::BigInt->bzero();
58cde26e 134 $self->{sign} = $nan;
135 }
136 else
137 {
138 # make integer from mantissa by adjusting exp, then convert to bigint
61f5c3f5 139 # undef,undef to signal MBI that we don't need no bloody rounding
140 $self->{_e} = Math::BigInt->new("$$es$$ev",undef,undef); # exponent
141 $self->{_m} = Math::BigInt->new("$$miv$$mfv",undef,undef); # create mant.
58cde26e 142 # 3.123E0 = 3123E-3, and 3.123E-2 => 3123E-5
027dc388 143 $self->{_e} -= CORE::length($$mfv) if CORE::length($$mfv) != 0;
144 $self->{sign} = $$mis;
58cde26e 145 }
28df3e88 146 # if downgrade, inf, NaN or integers go down
147
148 if ($downgrade && $self->{_e}->{sign} eq '+')
149 {
150# print "downgrading $$miv$$mfv"."E$$es$$ev";
151 if ($self->{_e}->is_zero())
152 {
153 $self->{_m}->{sign} = $$mis; # negative if wanted
154 return $downgrade->new($self->{_m});
155 }
156 return $downgrade->new("$$mis$$miv$$mfv"."E$$es$$ev");
157 }
158
b3abae2a 159 # print "mbf new $self->{sign} $self->{_m} e $self->{_e}\n";
61f5c3f5 160 $self->bnorm()->round(@r); # first normalize, then round
58cde26e 161 }
a0d0e21e 162
13a12e00 163sub _bnan
58cde26e 164 {
13a12e00 165 # used by parent class bone() to initialize number to 1
58cde26e 166 my $self = shift;
574bacfe 167 $self->{_m} = Math::BigInt->bzero();
168 $self->{_e} = Math::BigInt->bzero();
58cde26e 169 }
a0d0e21e 170
13a12e00 171sub _binf
58cde26e 172 {
13a12e00 173 # used by parent class bone() to initialize number to 1
58cde26e 174 my $self = shift;
574bacfe 175 $self->{_m} = Math::BigInt->bzero();
176 $self->{_e} = Math::BigInt->bzero();
58cde26e 177 }
a0d0e21e 178
13a12e00 179sub _bone
574bacfe 180 {
13a12e00 181 # used by parent class bone() to initialize number to 1
574bacfe 182 my $self = shift;
574bacfe 183 $self->{_m} = Math::BigInt->bone();
184 $self->{_e} = Math::BigInt->bzero();
574bacfe 185 }
186
13a12e00 187sub _bzero
58cde26e 188 {
13a12e00 189 # used by parent class bone() to initialize number to 1
58cde26e 190 my $self = shift;
574bacfe 191 $self->{_m} = Math::BigInt->bzero();
192 $self->{_e} = Math::BigInt->bone();
58cde26e 193 }
194
195##############################################################################
196# string conversation
197
198sub bstr
199 {
200 # (ref to BFLOAT or num_str ) return num_str
201 # Convert number from internal format to (non-scientific) string format.
202 # internal format is always normalized (no leading zeros, "-0" => "+0")
ee15d750 203 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
204 #my $x = shift; my $class = ref($x) || $x;
205 #$x = $class->new(shift) unless ref($x);
58cde26e 206
574bacfe 207 #die "Oups! e was $nan" if $x->{_e}->{sign} eq $nan;
208 #die "Oups! m was $nan" if $x->{_m}->{sign} eq $nan;
209 if ($x->{sign} !~ /^[+-]$/)
58cde26e 210 {
574bacfe 211 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN
212 return 'inf'; # +inf
58cde26e 213 }
214
574bacfe 215 my $es = '0'; my $len = 1; my $cad = 0; my $dot = '.';
216
28df3e88 217 my $not_zero = ! $x->is_zero();
574bacfe 218 if ($not_zero)
58cde26e 219 {
574bacfe 220 $es = $x->{_m}->bstr();
221 $len = CORE::length($es);
222 if (!$x->{_e}->is_zero())
58cde26e 223 {
574bacfe 224 if ($x->{_e}->sign() eq '-')
225 {
226 $dot = '';
227 if ($x->{_e} <= -$len)
228 {
229 # print "style: 0.xxxx\n";
230 my $r = $x->{_e}->copy(); $r->babs()->bsub( CORE::length($es) );
231 $es = '0.'. ('0' x $r) . $es; $cad = -($len+$r);
232 }
233 else
234 {
235 # print "insert '.' at $x->{_e} in '$es'\n";
236 substr($es,$x->{_e},0) = '.'; $cad = $x->{_e};
237 }
238 }
239 else
240 {
241 # expand with zeros
242 $es .= '0' x $x->{_e}; $len += $x->{_e}; $cad = 0;
243 }
82cf049f 244 }
574bacfe 245 } # if not zero
246 $es = $x->{sign}.$es if $x->{sign} eq '-';
247 # if set accuracy or precision, pad with zeros
248 if ((defined $x->{_a}) && ($not_zero))
249 {
250 # 123400 => 6, 0.1234 => 4, 0.001234 => 4
251 my $zeros = $x->{_a} - $cad; # cad == 0 => 12340
252 $zeros = $x->{_a} - $len if $cad != $len;
574bacfe 253 $es .= $dot.'0' x $zeros if $zeros > 0;
82cf049f 254 }
574bacfe 255 elsif ($x->{_p} || 0 < 0)
58cde26e 256 {
574bacfe 257 # 123400 => 6, 0.1234 => 4, 0.001234 => 6
258 my $zeros = -$x->{_p} + $cad;
574bacfe 259 $es .= $dot.'0' x $zeros if $zeros > 0;
58cde26e 260 }
58cde26e 261 return $es;
82cf049f 262 }
f216259d 263
58cde26e 264sub bsstr
265 {
266 # (ref to BFLOAT or num_str ) return num_str
267 # Convert number from internal format to scientific string format.
268 # internal format is always normalized (no leading zeros, "-0E0" => "+0E0")
ee15d750 269 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
270 #my $x = shift; my $class = ref($x) || $x;
271 #$x = $class->new(shift) unless ref($x);
a0d0e21e 272
574bacfe 273 #die "Oups! e was $nan" if $x->{_e}->{sign} eq $nan;
274 #die "Oups! m was $nan" if $x->{_m}->{sign} eq $nan;
275 if ($x->{sign} !~ /^[+-]$/)
276 {
277 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN
278 return 'inf'; # +inf
279 }
58cde26e 280 my $sign = $x->{_e}->{sign}; $sign = '' if $sign eq '-';
281 my $sep = 'e'.$sign;
282 return $x->{_m}->bstr().$sep.$x->{_e}->bstr();
283 }
284
285sub numify
286 {
287 # Make a number from a BigFloat object
574bacfe 288 # simple return string and let Perl's atoi()/atof() handle the rest
ee15d750 289 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
58cde26e 290 return $x->bsstr();
291 }
a0d0e21e 292
58cde26e 293##############################################################################
294# public stuff (usually prefixed with "b")
295
574bacfe 296# tels 2001-08-04
297# todo: this must be overwritten and return NaN for non-integer values
298# band(), bior(), bxor(), too
58cde26e 299#sub bnot
300# {
301# $class->SUPER::bnot($class,@_);
302# }
303
304sub bcmp
305 {
306 # Compares 2 values. Returns one of undef, <0, =0, >0. (suitable for sort)
307 # (BFLOAT or num_str, BFLOAT or num_str) return cond_code
308 my ($self,$x,$y) = objectify(2,@_);
58cde26e 309
0716bf9b 310 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
311 {
312 # handle +-inf and NaN
313 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
314 return 0 if ($x->{sign} eq $y->{sign}) && ($x->{sign} =~ /^[+-]inf$/);
315 return +1 if $x->{sign} eq '+inf';
316 return -1 if $x->{sign} eq '-inf';
317 return -1 if $y->{sign} eq '+inf';
b3abae2a 318 return +1;
0716bf9b 319 }
320
321 # check sign for speed first
574bacfe 322 return 1 if $x->{sign} eq '+' && $y->{sign} eq '-'; # does also 0 <=> -y
58cde26e 323 return -1 if $x->{sign} eq '-' && $y->{sign} eq '+'; # does also -x <=> 0
324
574bacfe 325 # shortcut
326 my $xz = $x->is_zero();
327 my $yz = $y->is_zero();
328 return 0 if $xz && $yz; # 0 <=> 0
329 return -1 if $xz && $y->{sign} eq '+'; # 0 <=> +y
330 return 1 if $yz && $x->{sign} eq '+'; # +x <=> 0
58cde26e 331
332 # adjust so that exponents are equal
bd05a461 333 my $lxm = $x->{_m}->length();
334 my $lym = $y->{_m}->length();
28df3e88 335 # the numify somewhat limits our length, but makes it much faster
336 my $lx = $lxm + $x->{_e}->numify();
337 my $ly = $lym + $y->{_e}->numify();
338 my $l = $lx - $ly; $l = -$l if $x->{sign} eq '-';
bd05a461 339 return $l <=> 0 if $l != 0;
58cde26e 340
bd05a461 341 # lengths (corrected by exponent) are equal
28df3e88 342 # so make mantissa equal length by padding with zero (shift left)
bd05a461 343 my $diff = $lxm - $lym;
344 my $xm = $x->{_m}; # not yet copy it
345 my $ym = $y->{_m};
346 if ($diff > 0)
347 {
348 $ym = $y->{_m}->copy()->blsft($diff,10);
349 }
350 elsif ($diff < 0)
351 {
352 $xm = $x->{_m}->copy()->blsft(-$diff,10);
353 }
28df3e88 354 my $rc = $xm->bacmp($ym);
58cde26e 355 $rc = -$rc if $x->{sign} eq '-'; # -124 < -123
b3abae2a 356 $rc <=> 0;
58cde26e 357 }
358
359sub bacmp
360 {
361 # Compares 2 values, ignoring their signs.
362 # Returns one of undef, <0, =0, >0. (suitable for sort)
363 # (BFLOAT or num_str, BFLOAT or num_str) return cond_code
364 my ($self,$x,$y) = objectify(2,@_);
ee15d750 365
366 # handle +-inf and NaN's
abcfbf51 367 if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/)
ee15d750 368 {
369 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
370 return 0 if ($x->is_inf() && $y->is_inf());
371 return 1 if ($x->is_inf() && !$y->is_inf());
b3abae2a 372 return -1;
ee15d750 373 }
374
375 # shortcut
376 my $xz = $x->is_zero();
377 my $yz = $y->is_zero();
378 return 0 if $xz && $yz; # 0 <=> 0
379 return -1 if $xz && !$yz; # 0 <=> +y
380 return 1 if $yz && !$xz; # +x <=> 0
381
382 # adjust so that exponents are equal
383 my $lxm = $x->{_m}->length();
384 my $lym = $y->{_m}->length();
28df3e88 385 # the numify somewhat limits our length, but makes it much faster
386 my $lx = $lxm + $x->{_e}->numify();
387 my $ly = $lym + $y->{_e}->numify();
394e6ffb 388 my $l = $lx - $ly;
ee15d750 389 return $l <=> 0 if $l != 0;
58cde26e 390
ee15d750 391 # lengths (corrected by exponent) are equal
394e6ffb 392 # so make mantissa equal-length by padding with zero (shift left)
ee15d750 393 my $diff = $lxm - $lym;
394 my $xm = $x->{_m}; # not yet copy it
395 my $ym = $y->{_m};
396 if ($diff > 0)
397 {
398 $ym = $y->{_m}->copy()->blsft($diff,10);
399 }
400 elsif ($diff < 0)
401 {
402 $xm = $x->{_m}->copy()->blsft(-$diff,10);
403 }
28df3e88 404 $xm->bacmp($ym) <=> 0;
58cde26e 405 }
a0d0e21e 406
58cde26e 407sub badd
408 {
409 # add second arg (BFLOAT or string) to first (BFLOAT) (modifies first)
410 # return result as BFLOAT
58cde26e 411 my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
412
b3abae2a 413 #print "mbf badd $x $y\n";
574bacfe 414 # inf and NaN handling
415 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
416 {
417 # NaN first
418 return $x->bnan() if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
13a12e00 419 # inf handling
574bacfe 420 if (($x->{sign} =~ /^[+-]inf$/) && ($y->{sign} =~ /^[+-]inf$/))
421 {
13a12e00 422 # +inf++inf or -inf+-inf => same, rest is NaN
423 return $x if $x->{sign} eq $y->{sign};
424 return $x->bnan();
574bacfe 425 }
426 # +-inf + something => +inf
427 # something +-inf => +-inf
428 $x->{sign} = $y->{sign}, return $x if $y->{sign} =~ /^[+-]inf$/;
429 return $x;
430 }
431
58cde26e 432 # speed: no add for 0+y or x+0
28df3e88 433 return $x->bround($a,$p,$r) if $y->is_zero(); # x+0
58cde26e 434 if ($x->is_zero()) # 0+y
435 {
436 # make copy, clobbering up x (modify in place!)
437 $x->{_e} = $y->{_e}->copy();
438 $x->{_m} = $y->{_m}->copy();
439 $x->{sign} = $y->{sign} || $nan;
440 return $x->round($a,$p,$r,$y);
a0d0e21e 441 }
58cde26e 442
443 # take lower of the two e's and adapt m1 to it to match m2
28df3e88 444 my $e = $y->{_e};
445 $e = Math::BigInt::bzero() if !defined $e; # if no BFLOAT ?
446 $e = $e->copy(); # make copy (didn't do it yet)
447 $e->bsub($x->{_e});
58cde26e 448 my $add = $y->{_m}->copy();
28df3e88 449# if ($e < 0) # < 0
450 if ($e->{sign} eq '-') # < 0
58cde26e 451 {
58cde26e 452 my $e1 = $e->copy()->babs();
28df3e88 453 #$x->{_m} *= (10 ** $e1);
454 $x->{_m}->blsft($e1,10);
58cde26e 455 $x->{_e} += $e; # need the sign of e
58cde26e 456 }
28df3e88 457# if ($e > 0) # > 0
458 elsif (!$e->is_zero()) # > 0
58cde26e 459 {
28df3e88 460 #$add *= (10 ** $e);
461 $add->blsft($e,10);
58cde26e 462 }
61f5c3f5 463 # else: both e are the same, so just leave them
464 $x->{_m}->{sign} = $x->{sign}; # fiddle with signs
58cde26e 465 $add->{sign} = $y->{sign};
61f5c3f5 466 $x->{_m} += $add; # finally do add/sub
467 $x->{sign} = $x->{_m}->{sign}; # re-adjust signs
468 $x->{_m}->{sign} = '+'; # mantissa always positiv
469 # delete trailing zeros, then round
470 return $x->bnorm()->round($a,$p,$r,$y);
58cde26e 471 }
472
473sub bsub
474 {
0716bf9b 475 # (BigFloat or num_str, BigFloat or num_str) return BigFloat
58cde26e 476 # subtract second arg from first, modify first
e745a66c 477 my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
a0d0e21e 478
28df3e88 479 if ($y->is_zero()) # still round for not adding zero
e745a66c 480 {
28df3e88 481 return $x->round($a,$p,$r);
e745a66c 482 }
28df3e88 483
484 $y->{sign} =~ tr/+\-/-+/; # does nothing for NaN
485 $x->badd($y,$a,$p,$r); # badd does not leave internal zeros
486 $y->{sign} =~ tr/+\-/-+/; # refix $y (does nothing for NaN)
e745a66c 487 $x; # already rounded by badd()
58cde26e 488 }
489
490sub binc
491 {
492 # increment arg by one
ee15d750 493 my ($self,$x,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
e745a66c 494
495 if ($x->{_e}->sign() eq '-')
496 {
497 return $x->badd($self->bone(),$a,$p,$r); # digits after dot
498 }
499
500 if (!$x->{_e}->is_zero())
501 {
502 $x->{_m}->blsft($x->{_e},10); # 1e2 => 100
503 $x->{_e}->bzero();
504 }
505 # now $x->{_e} == 0
506 if ($x->{sign} eq '+')
507 {
508 $x->{_m}->binc();
509 return $x->bnorm()->bround($a,$p,$r);
510 }
511 elsif ($x->{sign} eq '-')
512 {
513 $x->{_m}->bdec();
514 $x->{sign} = '+' if $x->{_m}->is_zero(); # -1 +1 => -0 => +0
515 return $x->bnorm()->bround($a,$p,$r);
516 }
517 # inf, nan handling etc
518 $x->badd($self->__one(),$a,$p,$r); # does round
58cde26e 519 }
520
521sub bdec
522 {
523 # decrement arg by one
ee15d750 524 my ($self,$x,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
e745a66c 525
526 if ($x->{_e}->sign() eq '-')
527 {
528 return $x->badd($self->bone('-'),$a,$p,$r); # digits after dot
529 }
530
531 if (!$x->{_e}->is_zero())
532 {
533 $x->{_m}->blsft($x->{_e},10); # 1e2 => 100
534 $x->{_e}->bzero();
535 }
536 # now $x->{_e} == 0
537 my $zero = $x->is_zero();
538 # <= 0
539 if (($x->{sign} eq '-') || $zero)
540 {
541 $x->{_m}->binc();
542 $x->{sign} = '-' if $zero; # 0 => 1 => -1
543 $x->{sign} = '+' if $x->{_m}->is_zero(); # -1 +1 => -0 => +0
544 return $x->bnorm()->round($a,$p,$r);
545 }
546 # > 0
547 elsif ($x->{sign} eq '+')
548 {
549 $x->{_m}->bdec();
550 return $x->bnorm()->round($a,$p,$r);
551 }
552 # inf, nan handling etc
553 $x->badd($self->bone('-'),$a,$p,$r); # does round
58cde26e 554 }
555
61f5c3f5 556sub blog
557 {
b3abae2a 558 my ($self,$x,$base,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(2,@_);
61f5c3f5 559
560 # http://www.efunda.com/math/taylor_series/logarithmic.cfm?search_string=log
561
562 # u = x-1, v = x +1
563 # _ _
564 # taylor: | u 1 u^3 1 u^5 |
565 # ln (x) = 2 | --- + - * --- + - * --- + ... | x > 0
b3abae2a 566 # |_ v 3 v^3 5 v^5 _|
61f5c3f5 567
b3abae2a 568 # we need to limit the accuracy to protect against overflow
569 my $fallback = 0;
570 my $scale = 0;
571 my @params = $x->_find_round_parameters($a,$p,$r);
61f5c3f5 572
b3abae2a 573 # no rounding at all, so must use fallback
574 if (scalar @params == 1)
575 {
576 # simulate old behaviour
577 $params[1] = $self->div_scale(); # and round to it as accuracy
578 $scale = $params[1]+4; # at least four more for proper round
579 $params[3] = $r; # round mode by caller or undef
580 $fallback = 1; # to clear a/p afterwards
581 }
582 else
583 {
584 # the 4 below is empirical, and there might be cases where it is not
585 # enough...
586 $scale = abs($params[1] || $params[2]) + 4; # take whatever is defined
587 }
61f5c3f5 588
b3abae2a 589 return $x->bzero(@params) if $x->is_one();
590 return $x->bnan() if $x->{sign} ne '+' || $x->is_zero();
591 #return $x->bone('+',@params) if $x->bcmp($base) == 0;
61f5c3f5 592
b3abae2a 593 # when user set globals, they would interfere with our calculation, so
594 # disable then and later re-enable them
595 no strict 'refs';
596 my $abr = "$self\::accuracy"; my $ab = $$abr; $$abr = undef;
597 my $pbr = "$self\::precision"; my $pb = $$pbr; $$pbr = undef;
598 # we also need to disable any set A or P on $x (_find_round_parameters took
599 # them already into account), since these would interfere, too
600 delete $x->{_a}; delete $x->{_p};
601 # need to disable $upgrade in BigInt, to aoid deep recursion
602 local $Math::BigInt::upgrade = undef;
603
604 my $v = $x->copy(); $v->binc(); # v = x+1
605 $x->bdec(); my $u = $x->copy(); # u = x-1; x = x-1
606
607 $x->bdiv($v,$scale); # first term: u/v
608
609 my $below = $v->copy();
610 my $over = $u->copy();
611 $u *= $u; $v *= $v; # u^2, v^2
612 $below->bmul($v); # u^3, v^3
613 $over->bmul($u);
61f5c3f5 614 my $factor = $self->new(3); my $two = $self->new(2);
615
616 my $diff = $self->bone();
b3abae2a 617 my $limit = $self->new("1E-". ($scale-1)); my $last;
61f5c3f5 618 # print "diff $diff limit $limit\n";
b3abae2a 619 while ($diff->bcmp($limit) > 0)
61f5c3f5 620 {
b3abae2a 621 #print "$x $over $below $factor\n";
61f5c3f5 622 $diff = $x->copy()->bsub($last)->babs();
b3abae2a 623 #print "diff $diff $limit\n";
61f5c3f5 624 $last = $x->copy();
b3abae2a 625 $x += $over->copy()->bdiv($below->copy()->bmul($factor),$scale);
61f5c3f5 626 $over *= $u; $below *= $v; $factor->badd($two);
627 }
628 $x->bmul($two);
b3abae2a 629
630 # shortcut to not run trough _find_round_parameters again
631 if (defined $params[1])
632 {
633 $x->bround($params[1],$params[3]); # then round accordingly
634 }
635 else
636 {
637 $x->bfround($params[2],$params[3]); # then round accordingly
638 }
639 if ($fallback)
640 {
641 # clear a/p after round, since user did not request it
642 $x->{_a} = undef; $x->{_p} = undef;
643 }
644 # restore globals
645 $$abr = $ab; $$pbr = $pb;
646
647 $x;
61f5c3f5 648 }
649
58cde26e 650sub blcm
651 {
ee15d750 652 # (BFLOAT or num_str, BFLOAT or num_str) return BFLOAT
58cde26e 653 # does not modify arguments, but returns new object
654 # Lowest Common Multiplicator
58cde26e 655
656 my ($self,@arg) = objectify(0,@_);
657 my $x = $self->new(shift @arg);
658 while (@arg) { $x = _lcm($x,shift @arg); }
659 $x;
660 }
661
662sub bgcd
663 {
ee15d750 664 # (BFLOAT or num_str, BFLOAT or num_str) return BINT
58cde26e 665 # does not modify arguments, but returns new object
666 # GCD -- Euclids algorithm Knuth Vol 2 pg 296
58cde26e 667
668 my ($self,@arg) = objectify(0,@_);
669 my $x = $self->new(shift @arg);
670 while (@arg) { $x = _gcd($x,shift @arg); }
671 $x;
672 }
673
b3abae2a 674###############################################################################
675# is_foo methods (is_negative, is_positive are inherited from BigInt)
676
677sub is_int
678 {
679 # return true if arg (BFLOAT or num_str) is an integer
680 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
681
682 return 1 if ($x->{sign} =~ /^[+-]$/) && # NaN and +-inf aren't
683 $x->{_e}->{sign} eq '+'; # 1e-1 => no integer
684 0;
685 }
686
58cde26e 687sub is_zero
688 {
b3abae2a 689 # return true if arg (BFLOAT or num_str) is zero
ee15d750 690 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
574bacfe 691
692 return 1 if $x->{sign} eq '+' && $x->{_m}->is_zero();
b3abae2a 693 0;
58cde26e 694 }
695
696sub is_one
697 {
b3abae2a 698 # return true if arg (BFLOAT or num_str) is +1 or -1 if signis given
ee15d750 699 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
700
701 my $sign = shift || ''; $sign = '+' if $sign ne '-';
702 return 1
703 if ($x->{sign} eq $sign && $x->{_e}->is_zero() && $x->{_m}->is_one());
b3abae2a 704 0;
58cde26e 705 }
706
707sub is_odd
708 {
ee15d750 709 # return true if arg (BFLOAT or num_str) is odd or false if even
710 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
0716bf9b 711
b3abae2a 712 return 1 if ($x->{sign} =~ /^[+-]$/) && # NaN & +-inf aren't
713 ($x->{_e}->is_zero() && $x->{_m}->is_odd());
714 0;
58cde26e 715 }
716
717sub is_even
718 {
b22b3e31 719 # return true if arg (BINT or num_str) is even or false if odd
ee15d750 720 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
0716bf9b 721
722 return 0 if $x->{sign} !~ /^[+-]$/; # NaN & +-inf aren't
b3abae2a 723 return 1 if ($x->{_e}->{sign} eq '+' # 123.45 is never
724 && $x->{_m}->is_even()); # but 1200 is
725 0;
58cde26e 726 }
727
728sub bmul
729 {
730 # multiply two numbers -- stolen from Knuth Vol 2 pg 233
731 # (BINT or num_str, BINT or num_str) return BINT
732 my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
58cde26e 733
58cde26e 734 return $x->bnan() if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
735
574bacfe 736 # inf handling
737 if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/))
738 {
13a12e00 739 return $x->bnan() if $x->is_zero() || $y->is_zero();
574bacfe 740 # result will always be +-inf:
741 # +inf * +/+inf => +inf, -inf * -/-inf => +inf
742 # +inf * -/-inf => -inf, -inf * +/+inf => -inf
743 return $x->binf() if ($x->{sign} =~ /^\+/ && $y->{sign} =~ /^\+/);
744 return $x->binf() if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/);
745 return $x->binf('-');
746 }
13a12e00 747 # handle result = 0
748 return $x->bzero() if $x->is_zero() || $y->is_zero();
574bacfe 749
58cde26e 750 # aEb * cEd = (a*c)E(b+d)
394e6ffb 751 $x->{_m}->bmul($y->{_m});
752 $x->{_e}->badd($y->{_e});
58cde26e 753 # adjust sign:
754 $x->{sign} = $x->{sign} ne $y->{sign} ? '-' : '+';
394e6ffb 755 return $x->bnorm()->round($a,$p,$r,$y);
58cde26e 756 }
757
758sub bdiv
759 {
760 # (dividend: BFLOAT or num_str, divisor: BFLOAT or num_str) return
761 # (BFLOAT,BFLOAT) (quo,rem) or BINT (only rem)
762 my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
763
13a12e00 764 return $self->_div_inf($x,$y)
765 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
574bacfe 766
13a12e00 767 # x== 0 # also: or y == 1 or y == -1
394e6ffb 768 return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
0716bf9b 769
13a12e00 770 # upgrade
771 return $upgrade->bdiv($x,$y,$a,$p,$r) if defined $upgrade;
772
58cde26e 773 # we need to limit the accuracy to protect against overflow
574bacfe 774 my $fallback = 0;
ee15d750 775 my $scale = 0;
ee15d750 776 my @params = $x->_find_round_parameters($a,$p,$r,$y);
777
778 # no rounding at all, so must use fallback
779 if (scalar @params == 1)
58cde26e 780 {
0716bf9b 781 # simulate old behaviour
ee15d750 782 $params[1] = $self->div_scale(); # and round to it as accuracy
61f5c3f5 783 $scale = $params[1]+4; # at least four more for proper round
ee15d750 784 $params[3] = $r; # round mode by caller or undef
785 $fallback = 1; # to clear a/p afterwards
786 }
787 else
788 {
789 # the 4 below is empirical, and there might be cases where it is not
790 # enough...
791 $scale = abs($params[1] || $params[2]) + 4; # take whatever is defined
a0d0e21e 792 }
0716bf9b 793 my $lx = $x->{_m}->length(); my $ly = $y->{_m}->length();
58cde26e 794 $scale = $lx if $lx > $scale;
58cde26e 795 $scale = $ly if $ly > $scale;
0716bf9b 796 my $diff = $ly - $lx;
797 $scale += $diff if $diff > 0; # if lx << ly, but not if ly << lx!
b3abae2a 798
799 # make copy of $x in case of list context for later reminder calculation
800 my $rem;
801 if (wantarray && !$y->is_one())
802 {
803 $rem = $x->copy();
804 }
a0d0e21e 805
58cde26e 806 $x->{sign} = $x->{sign} ne $y->sign() ? '-' : '+';
a0d0e21e 807
58cde26e 808 # check for / +-1 ( +/- 1E0)
394e6ffb 809 if (!$y->is_one())
58cde26e 810 {
394e6ffb 811 # promote BigInts and it's subclasses (except when already a BigFloat)
812 $y = $self->new($y) unless $y->isa('Math::BigFloat');
813
814 # calculate the result to $scale digits and then round it
815 # a * 10 ** b / c * 10 ** d => a/c * 10 ** (b-d)
816 $x->{_m}->blsft($scale,10);
817 $x->{_m}->bdiv( $y->{_m} ); # a/c
818 $x->{_e}->bsub( $y->{_e} ); # b-d
819 $x->{_e}->bsub($scale); # correct for 10**scale
820 $x->bnorm(); # remove trailing 0's
a0d0e21e 821 }
a5f75d66 822
ee15d750 823 # shortcut to not run trough _find_round_parameters again
824 if (defined $params[1])
825 {
61f5c3f5 826 $x->bround($params[1],$params[3]); # then round accordingly
ee15d750 827 }
828 else
829 {
830 $x->bfround($params[2],$params[3]); # then round accordingly
831 }
574bacfe 832 if ($fallback)
833 {
834 # clear a/p after round, since user did not request it
ee15d750 835 $x->{_a} = undef; $x->{_p} = undef;
574bacfe 836 }
0716bf9b 837
58cde26e 838 if (wantarray)
839 {
394e6ffb 840 if (!$y->is_one())
841 {
b3abae2a 842 $rem->bmod($y,$params[1],$params[2],$params[3]); # copy already done
394e6ffb 843 }
844 else
845 {
846 $rem = $self->bzero();
847 }
574bacfe 848 if ($fallback)
849 {
850 # clear a/p after round, since user did not request it
ee15d750 851 $rem->{_a} = undef; $rem->{_p} = undef;
574bacfe 852 }
0716bf9b 853 return ($x,$rem);
58cde26e 854 }
855 return $x;
856 }
a0d0e21e 857
58cde26e 858sub bmod
859 {
860 # (dividend: BFLOAT or num_str, divisor: BFLOAT or num_str) return reminder
861 my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
a0d0e21e 862
61f5c3f5 863 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
864 {
865 my ($d,$re) = $self->SUPER::_div_inf($x,$y);
866 return $re->round($a,$p,$r,$y);
867 }
868 return $x->bnan() if $x->is_zero() && $y->is_zero();
869 return $x if $y->is_zero();
870 return $x->bnan() if $x->is_nan() || $y->is_nan();
871 return $x->bzero() if $y->is_one() || $x->is_zero();
58cde26e 872
61f5c3f5 873 # inf handling is missing here
874
875 my $cmp = $x->bacmp($y); # equal or $x < $y?
876 return $x->bzero($a,$p) if $cmp == 0; # $x == $y => result 0
877
878 # only $y of the operands negative?
879 my $neg = 0; $neg = 1 if $x->{sign} ne $y->{sign};
880
881 $x->{sign} = $y->{sign}; # calc sign first
882 return $x->round($a,$p,$r) if $cmp < 0 && $neg == 0; # $x < $y => result $x
883
884 my $ym = $y->{_m}->copy();
885
886 # 2e1 => 20
887 $ym->blsft($y->{_e},10) if $y->{_e}->{sign} eq '+' && !$y->{_e}->is_zero();
888
889 # if $y has digits after dot
890 my $shifty = 0; # correct _e of $x by this
891 if ($y->{_e}->{sign} eq '-') # has digits after dot
892 {
893 # 123 % 2.5 => 1230 % 25 => 5 => 0.5
894 $shifty = $y->{_e}->copy()->babs(); # no more digits after dot
895 $x->blsft($shifty,10); # 123 => 1230, $y->{_m} is already 25
896 }
897 # $ym is now mantissa of $y based on exponent 0
b3abae2a 898
61f5c3f5 899 my $shiftx = 0; # correct _e of $x by this
900 if ($x->{_e}->{sign} eq '-') # has digits after dot
901 {
902 # 123.4 % 20 => 1234 % 200
903 $shiftx = $x->{_e}->copy()->babs(); # no more digits after dot
904 $ym->blsft($shiftx,10);
905 }
906 # 123e1 % 20 => 1230 % 20
907 if ($x->{_e}->{sign} eq '+' && !$x->{_e}->is_zero())
908 {
909 $x->{_m}->blsft($x->{_e},10);
910 }
911 $x->{_e} = Math::BigInt->bzero() unless $x->{_e}->is_zero();
912
913 $x->{_e}->bsub($shiftx) if $shiftx != 0;
914 $x->{_e}->bsub($shifty) if $shifty != 0;
915
916 # now mantissas are equalized, exponent of $x is adjusted, so calc result
b3abae2a 917# $ym->{sign} = '-' if $neg; # bmod() will make the correction for us
918
61f5c3f5 919 $x->{_m}->bmod($ym);
920
921 $x->{sign} = '+' if $x->{_m}->is_zero(); # fix sign for -0
922 $x->bnorm();
923
924 if ($neg != 0) # one of them negative => correct in place
925 {
926 my $r = $y - $x;
927 $x->{_m} = $r->{_m};
928 $x->{_e} = $r->{_e};
929 $x->{sign} = '+' if $x->{_m}->is_zero(); # fix sign for -0
930 $x->bnorm();
931 }
932
933 $x->round($a,$p,$r,$y); # round and return
58cde26e 934 }
935
936sub bsqrt
937 {
0716bf9b 938 # calculate square root; this should probably
939 # use a different test to see whether the accuracy we want is...
ee15d750 940 my ($self,$x,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
58cde26e 941
0716bf9b 942 return $x->bnan() if $x->{sign} eq 'NaN' || $x->{sign} =~ /^-/; # <0, NaN
943 return $x if $x->{sign} eq '+inf'; # +inf
394e6ffb 944 return $x if $x->is_zero() || $x->is_one();
58cde26e 945
61f5c3f5 946 # we need to limit the accuracy to protect against overflow
574bacfe 947 my $fallback = 0;
61f5c3f5 948 my $scale = 0;
949 my @params = $x->_find_round_parameters($a,$p,$r);
950
951 # no rounding at all, so must use fallback
952 if (scalar @params == 1)
0716bf9b 953 {
954 # simulate old behaviour
61f5c3f5 955 $params[1] = $self->div_scale(); # and round to it as accuracy
956 $scale = $params[1]+4; # at least four more for proper round
957 $params[3] = $r; # round mode by caller or undef
ee15d750 958 $fallback = 1; # to clear a/p afterwards
0716bf9b 959 }
61f5c3f5 960 else
961 {
962 # the 4 below is empirical, and there might be cases where it is not
963 # enough...
964 $scale = abs($params[1] || $params[2]) + 4; # take whatever is defined
965 }
966
967 # when user set globals, they would interfere with our calculation, so
968 # disable then and later re-enable them
969 no strict 'refs';
970 my $abr = "$self\::accuracy"; my $ab = $$abr; $$abr = undef;
b3abae2a 971 my $pbr = "$self\::precision"; my $pb = $$pbr; $$pbr = undef;
61f5c3f5 972 # we also need to disable any set A or P on $x (_find_round_parameters took
973 # them already into account), since these would interfere, too
974 delete $x->{_a}; delete $x->{_p};
b3abae2a 975 # need to disable $upgrade in BigInt, to aoid deep recursion
976 local $Math::BigInt::upgrade = undef;
61f5c3f5 977
394e6ffb 978 my $xas = $x->as_number();
979 my $gs = $xas->copy()->bsqrt(); # some guess
b3abae2a 980
394e6ffb 981 if (($x->{_e}->{sign} ne '-') # guess can't be accurate if there are
982 # digits after the dot
b3abae2a 983 && ($xas->bacmp($gs * $gs) == 0)) # guess hit the nail on the head?
394e6ffb 984 {
985 # exact result
61f5c3f5 986 $x->{_m} = $gs; $x->{_e} = Math::BigInt->bzero(); $x->bnorm();
987 # shortcut to not run trough _find_round_parameters again
988 if (defined $params[1])
989 {
990 $x->bround($params[1],$params[3]); # then round accordingly
991 }
992 else
993 {
994 $x->bfround($params[2],$params[3]); # then round accordingly
995 }
996 if ($fallback)
997 {
998 # clear a/p after round, since user did not request it
999 $x->{_a} = undef; $x->{_p} = undef;
1000 }
b3abae2a 1001 ${"$self\::accuracy"} = $ab; ${"$self\::precision"} = $pb;
61f5c3f5 1002 return $x;
394e6ffb 1003 }
61f5c3f5 1004 $gs = $self->new( $gs ); # BigInt to BigFloat
394e6ffb 1005
0716bf9b 1006 my $lx = $x->{_m}->length();
1007 $scale = $lx if $scale < $lx;
394e6ffb 1008 my $e = $self->new("1E-$scale"); # make test variable
b3abae2a 1009# return $x->bnan() if $e->sign() eq 'NaN';
58cde26e 1010
58cde26e 1011 my $y = $x->copy();
394e6ffb 1012 my $two = $self->new(2);
61f5c3f5 1013 my $diff = $e;
ee15d750 1014 # promote BigInts and it's subclasses (except when already a BigFloat)
1015 $y = $self->new($y) unless $y->isa('Math::BigFloat');
61f5c3f5 1016
ee15d750 1017 my $rem;
58cde26e 1018 while ($diff >= $e)
1019 {
61f5c3f5 1020 $rem = $y->copy()->bdiv($gs,$scale)->badd($gs)->bdiv($two,$scale);
1021 $diff = $rem->copy()->bsub($gs)->babs();
1022 $gs = $rem->copy();
a0d0e21e 1023 }
61f5c3f5 1024 # copy over to modify $x
1025 $x->{_m} = $rem->{_m}; $x->{_e} = $rem->{_e};
1026
1027 # shortcut to not run trough _find_round_parameters again
1028 if (defined $params[1])
1029 {
1030 $x->bround($params[1],$params[3]); # then round accordingly
1031 }
1032 else
1033 {
1034 $x->bfround($params[2],$params[3]); # then round accordingly
1035 }
574bacfe 1036 if ($fallback)
1037 {
1038 # clear a/p after round, since user did not request it
ee15d750 1039 $x->{_a} = undef; $x->{_p} = undef;
574bacfe 1040 }
61f5c3f5 1041 # restore globals
b3abae2a 1042 $$abr = $ab; $$pbr = $pb;
574bacfe 1043 $x;
58cde26e 1044 }
1045
b3abae2a 1046sub bfac
1047 {
28df3e88 1048 # (BFLOAT or num_str, BFLOAT or num_str) return BFLOAT
b3abae2a 1049 # compute factorial numbers
1050 # modifies first argument
1051 my ($self,$x,@r) = objectify(1,@_);
1052
28df3e88 1053 return $x->bnan()
1054 if (($x->{sign} ne '+') || # inf, NaN, <0 etc => NaN
1055 ($x->{_e}->{sign} ne '+')); # digits after dot?
b3abae2a 1056
28df3e88 1057 return $x->bone(@r) if $x->is_zero() || $x->is_one(); # 0 or 1 => 1
b3abae2a 1058
1059 # use BigInt's bfac() for faster calc
1060 $x->{_m}->blsft($x->{_e},10); # un-norm m
1061 $x->{_e}->bzero(); # norm $x again
1062 $x->{_m}->bfac(); # factorial
28df3e88 1063 $x->bnorm()->round(@r);
b3abae2a 1064 }
1065
58cde26e 1066sub bpow
1067 {
1068 # (BFLOAT or num_str, BFLOAT or num_str) return BFLOAT
1069 # compute power of two numbers, second arg is used as integer
1070 # modifies first argument
1071
1072 my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
1073
0716bf9b 1074 return $x if $x->{sign} =~ /^[+-]inf$/;
58cde26e 1075 return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;
574bacfe 1076 return $x->bone() if $y->is_zero();
58cde26e 1077 return $x if $x->is_one() || $y->is_one();
ee15d750 1078 my $y1 = $y->as_number(); # make bigint (trunc)
394e6ffb 1079 # if ($x == -1)
1080 if ($x->{sign} eq '-' && $x->{_m}->is_one() && $x->{_e}->is_zero())
58cde26e 1081 {
1082 # if $x == -1 and odd/even y => +1/-1 because +-1 ^ (+-1) => +-1
0716bf9b 1083 return $y1->is_odd() ? $x : $x->babs(1);
288d023a 1084 }
28df3e88 1085 if ($x->is_zero())
1086 {
1087 return $x if $y->{sign} eq '+'; # 0**y => 0 (if not y <= 0)
1088 # 0 ** -y => 1 / (0 ** y) => / 0! (1 / 0 => +inf)
1089 $x->binf();
1090 }
58cde26e 1091
1092 # calculate $x->{_m} ** $y and $x->{_e} * $y separately (faster)
1093 $y1->babs();
1094 $x->{_m}->bpow($y1);
1095 $x->{_e}->bmul($y1);
1096 $x->{sign} = $nan if $x->{_m}->{sign} eq $nan || $x->{_e}->{sign} eq $nan;
1097 $x->bnorm();
1098 if ($y->{sign} eq '-')
1099 {
1100 # modify $x in place!
0716bf9b 1101 my $z = $x->copy(); $x->bzero()->binc();
58cde26e 1102 return $x->bdiv($z,$a,$p,$r); # round in one go (might ignore y's A!)
a0d0e21e 1103 }
28df3e88 1104 $x->round($a,$p,$r,$y);
58cde26e 1105 }
1106
1107###############################################################################
1108# rounding functions
1109
1110sub bfround
1111 {
1112 # precision: round to the $Nth digit left (+$n) or right (-$n) from the '.'
1113 # $n == 0 means round to integer
1114 # expects and returns normalized numbers!
ee15d750 1115 my $x = shift; my $self = ref($x) || $x; $x = $self->new(shift) if !ref($x);
a0d0e21e 1116
58cde26e 1117 return $x if $x->modify('bfround');
1118
ee15d750 1119 my ($scale,$mode) = $x->_scale_p($self->precision(),$self->round_mode(),@_);
58cde26e 1120 return $x if !defined $scale; # no-op
1121
574bacfe 1122 # never round a 0, +-inf, NaN
61f5c3f5 1123 if ($x->is_zero())
1124 {
1125 $x->{_p} = $scale if !defined $x->{_p} || $x->{_p} < $scale; # -3 < -2
1126 return $x;
1127 }
1128 return $x if $x->{sign} !~ /^[+-]$/;
58cde26e 1129 # print "MBF bfround $x to scale $scale mode $mode\n";
58cde26e 1130
ee15d750 1131 # don't round if x already has lower precision
1132 return $x if (defined $x->{_p} && $x->{_p} < 0 && $scale < $x->{_p});
1133
1134 $x->{_p} = $scale; # remember round in any case
1135 $x->{_a} = undef; # and clear A
58cde26e 1136 if ($scale < 0)
1137 {
1138 # print "bfround scale $scale e $x->{_e}\n";
1139 # round right from the '.'
1140 return $x if $x->{_e} >= 0; # nothing to round
1141 $scale = -$scale; # positive for simplicity
1142 my $len = $x->{_m}->length(); # length of mantissa
1143 my $dad = -$x->{_e}; # digits after dot
1144 my $zad = 0; # zeros after dot
1145 $zad = -$len-$x->{_e} if ($x->{_e} < -$len);# for 0.00..00xxx style
ee15d750 1146 #print "scale $scale dad $dad zad $zad len $len\n";
58cde26e 1147
1148 # number bsstr len zad dad
1149 # 0.123 123e-3 3 0 3
1150 # 0.0123 123e-4 3 1 4
1151 # 0.001 1e-3 1 2 3
1152 # 1.23 123e-2 3 0 2
1153 # 1.2345 12345e-4 5 0 4
1154
1155 # do not round after/right of the $dad
1156 return $x if $scale > $dad; # 0.123, scale >= 3 => exit
1157
ee15d750 1158 # round to zero if rounding inside the $zad, but not for last zero like:
1159 # 0.0065, scale -2, round last '0' with following '65' (scale == zad case)
1160 return $x->bzero() if $scale < $zad;
1161 if ($scale == $zad) # for 0.006, scale -3 and trunc
58cde26e 1162 {
b3abae2a 1163 $scale = -$len;
58cde26e 1164 }
1165 else
1166 {
1167 # adjust round-point to be inside mantissa
1168 if ($zad != 0)
1169 {
1170 $scale = $scale-$zad;
1171 }
1172 else
1173 {
1174 my $dbd = $len - $dad; $dbd = 0 if $dbd < 0; # digits before dot
1175 $scale = $dbd+$scale;
1176 }
1177 }
1178 # print "round to $x->{_m} to $scale\n";
a0d0e21e 1179 }
58cde26e 1180 else
1181 {
1182 # 123 => 100 means length(123) = 3 - $scale (2) => 1
a5f75d66 1183
b3abae2a 1184 my $dbt = $x->{_m}->length();
1185 # digits before dot
1186 my $dbd = $dbt + $x->{_e};
1187 # should be the same, so treat it as this
1188 $scale = 1 if $scale == 0;
1189 # shortcut if already integer
1190 return $x if $scale == 1 && $dbt <= $dbd;
1191 # maximum digits before dot
1192 ++$dbd;
1193
1194 if ($scale > $dbd)
1195 {
1196 # not enough digits before dot, so round to zero
1197 return $x->bzero;
1198 }
1199 elsif ( $scale == $dbd )
1200 {
1201 # maximum
1202 $scale = -$dbt;
1203 }
58cde26e 1204 else
b3abae2a 1205 {
1206 $scale = $dbd - $scale;
1207 }
1208
a0d0e21e 1209 }
574bacfe 1210 # print "using $scale for $x->{_m} with '$mode'\n";
1211 # pass sign to bround for rounding modes '+inf' and '-inf'
58cde26e 1212 $x->{_m}->{sign} = $x->{sign};
1213 $x->{_m}->bround($scale,$mode);
1214 $x->{_m}->{sign} = '+'; # fix sign back
1215 $x->bnorm();
1216 }
1217
1218sub bround
1219 {
1220 # accuracy: preserve $N digits, and overwrite the rest with 0's
ee15d750 1221 my $x = shift; my $self = ref($x) || $x; $x = $self->new(shift) if !ref($x);
1222
1223 die ('bround() needs positive accuracy') if ($_[0] || 0) < 0;
58cde26e 1224
ee15d750 1225 my ($scale,$mode) = $x->_scale_a($self->accuracy(),$self->round_mode(),@_);
1226 return $x if !defined $scale; # no-op
61f5c3f5 1227
58cde26e 1228 return $x if $x->modify('bround');
61f5c3f5 1229
ee15d750 1230 # scale is now either $x->{_a}, $accuracy, or the user parameter
1231 # test whether $x already has lower accuracy, do nothing in this case
1232 # but do round if the accuracy is the same, since a math operation might
1233 # want to round a number with A=5 to 5 digits afterwards again
1234 return $x if defined $_[0] && defined $x->{_a} && $x->{_a} < $_[0];
58cde26e 1235
61f5c3f5 1236 # scale < 0 makes no sense
1237 # never round a +-inf, NaN
1238 return $x if ($scale < 0) || $x->{sign} !~ /^[+-]$/;
58cde26e 1239
61f5c3f5 1240 # 1: $scale == 0 => keep all digits
1241 # 2: never round a 0
1242 # 3: if we should keep more digits than the mantissa has, do nothing
1243 if ($scale == 0 || $x->is_zero() || $x->{_m}->length() <= $scale)
1244 {
1245 $x->{_a} = $scale if !defined $x->{_a} || $x->{_a} > $scale;
1246 return $x;
1247 }
f216259d 1248
58cde26e 1249 # pass sign to bround for '+inf' and '-inf' rounding modes
1250 $x->{_m}->{sign} = $x->{sign};
1251 $x->{_m}->bround($scale,$mode); # round mantissa
1252 $x->{_m}->{sign} = '+'; # fix sign back
61f5c3f5 1253 # $x->{_m}->{_a} = undef; $x->{_m}->{_p} = undef;
ee15d750 1254 $x->{_a} = $scale; # remember rounding
1255 $x->{_p} = undef; # and clear P
574bacfe 1256 $x->bnorm(); # del trailing zeros gen. by bround()
58cde26e 1257 }
1258
1259sub bfloor
1260 {
1261 # return integer less or equal then $x
ee15d750 1262 my ($self,$x,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
58cde26e 1263
1264 return $x if $x->modify('bfloor');
1265
1266 return $x if $x->{sign} !~ /^[+-]$/; # nan, +inf, -inf
1267
1268 # if $x has digits after dot
1269 if ($x->{_e}->{sign} eq '-')
1270 {
28df3e88 1271 #$x->{_m}->brsft(-$x->{_e},10);
1272 #$x->{_e}->bzero();
1273 #$x-- if $x->{sign} eq '-';
1274
1275 $x->{_e}->{sign} = '+'; # negate e
1276 $x->{_m}->brsft($x->{_e},10); # cut off digits after dot
1277 $x->{_e}->bzero(); # trunc/norm
1278 $x->{_m}->binc() if $x->{sign} eq '-'; # decrement if negative
f216259d 1279 }
61f5c3f5 1280 $x->round($a,$p,$r);
58cde26e 1281 }
288d023a 1282
58cde26e 1283sub bceil
1284 {
1285 # return integer greater or equal then $x
ee15d750 1286 my ($self,$x,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
58cde26e 1287
1288 return $x if $x->modify('bceil');
1289 return $x if $x->{sign} !~ /^[+-]$/; # nan, +inf, -inf
1290
1291 # if $x has digits after dot
1292 if ($x->{_e}->{sign} eq '-')
1293 {
28df3e88 1294 #$x->{_m}->brsft(-$x->{_e},10);
1295 #$x->{_e}->bzero();
1296 #$x++ if $x->{sign} eq '+';
1297
1298 $x->{_e}->{sign} = '+'; # negate e
1299 $x->{_m}->brsft($x->{_e},10); # cut off digits after dot
1300 $x->{_e}->bzero(); # trunc/norm
1301 $x->{_m}->binc() if $x->{sign} eq '+'; # decrement if negative
a0d0e21e 1302 }
61f5c3f5 1303 $x->round($a,$p,$r);
58cde26e 1304 }
1305
394e6ffb 1306sub brsft
1307 {
1308 # shift right by $y (divide by power of 2)
1309 my ($self,$x,$y,$n,$a,$p,$r) = objectify(2,@_);
1310
1311 return $x if $x->modify('brsft');
1312 return $x if $x->{sign} !~ /^[+-]$/; # nan, +inf, -inf
1313
1314 $n = 2 if !defined $n; $n = Math::BigFloat->new($n);
1315 $x->bdiv($n ** $y,$a,$p,$r,$y);
1316 }
1317
1318sub blsft
1319 {
1320 # shift right by $y (divide by power of 2)
1321 my ($self,$x,$y,$n,$a,$p,$r) = objectify(2,@_);
1322
1323 return $x if $x->modify('brsft');
1324 return $x if $x->{sign} !~ /^[+-]$/; # nan, +inf, -inf
1325
1326 $n = 2 if !defined $n; $n = Math::BigFloat->new($n);
1327 $x->bmul($n ** $y,$a,$p,$r,$y);
1328 }
1329
58cde26e 1330###############################################################################
a5f75d66 1331
58cde26e 1332sub DESTROY
1333 {
ee15d750 1334 # going through AUTOLOAD for every DESTROY is costly, so avoid it by empty sub
58cde26e 1335 }
1336
1337sub AUTOLOAD
1338 {
b3abae2a 1339 # make fxxx and bxxx both work by selectively mapping fxxx() to MBF::bxxx()
1340 # or falling back to MBI::bxxx()
58cde26e 1341 my $name = $AUTOLOAD;
1342
1343 $name =~ s/.*:://; # split package
ee15d750 1344 no strict 'refs';
1345 if (!method_alias($name))
58cde26e 1346 {
ee15d750 1347 if (!defined $name)
1348 {
1349 # delayed load of Carp and avoid recursion
1350 require Carp;
1351 Carp::croak ("Can't call a method without name");
1352 }
ee15d750 1353 if (!method_hand_up($name))
1354 {
1355 # delayed load of Carp and avoid recursion
1356 require Carp;
1357 Carp::croak ("Can't call $class\-\>$name, not a valid method");
1358 }
1359 # try one level up, but subst. bxxx() for fxxx() since MBI only got bxxx()
1360 $name =~ s/^f/b/;
1361 return &{'Math::BigInt'."::$name"}(@_);
a0d0e21e 1362 }
58cde26e 1363 my $bname = $name; $bname =~ s/^f/b/;
b3abae2a 1364 *{$class."::$name"} = \&$bname;
58cde26e 1365 &$bname; # uses @_
1366 }
1367
1368sub exponent
1369 {
1370 # return a copy of the exponent
ee15d750 1371 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
58cde26e 1372
ee15d750 1373 if ($x->{sign} !~ /^[+-]$/)
1374 {
1375 my $s = $x->{sign}; $s =~ s/^[+-]//;
1376 return $self->new($s); # -inf, +inf => +inf
1377 }
1378 return $x->{_e}->copy();
58cde26e 1379 }
1380
1381sub mantissa
1382 {
1383 # return a copy of the mantissa
ee15d750 1384 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
58cde26e 1385
ee15d750 1386 if ($x->{sign} !~ /^[+-]$/)
1387 {
1388 my $s = $x->{sign}; $s =~ s/^[+]//;
1389 return $self->new($s); # -inf, +inf => +inf
1390 }
1391 my $m = $x->{_m}->copy(); # faster than going via bstr()
1392 $m->bneg() if $x->{sign} eq '-';
58cde26e 1393
61f5c3f5 1394 $m;
58cde26e 1395 }
1396
1397sub parts
1398 {
1399 # return a copy of both the exponent and the mantissa
ee15d750 1400 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
58cde26e 1401
ee15d750 1402 if ($x->{sign} !~ /^[+-]$/)
1403 {
1404 my $s = $x->{sign}; $s =~ s/^[+]//; my $se = $s; $se =~ s/^[-]//;
1405 return ($self->new($s),$self->new($se)); # +inf => inf and -inf,+inf => inf
1406 }
1407 my $m = $x->{_m}->copy(); # faster than going via bstr()
1408 $m->bneg() if $x->{sign} eq '-';
1409 return ($m,$x->{_e}->copy());
58cde26e 1410 }
1411
1412##############################################################################
1413# private stuff (internal use only)
1414
58cde26e 1415sub import
1416 {
1417 my $self = shift;
b3abae2a 1418 my $l = scalar @_; my $j = 0; my @a = @_;
1419 for ( my $i = 0; $i < $l ; $i++, $j++)
58cde26e 1420 {
1421 if ( $_[$i] eq ':constant' )
1422 {
1423 # this rest causes overlord er load to step in
1424 # print "overload @_\n";
1425 overload::constant float => sub { $self->new(shift); };
b3abae2a 1426 splice @a, $j, 1; $j--;
1427 }
1428 elsif ($_[$i] eq 'upgrade')
1429 {
1430 # this causes upgrading
28df3e88 1431 $upgrade = $_[$i+1]; # or undef to disable
1432 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
1433 splice @a, $j, $s; $j -= $s;
1434 }
1435 elsif ($_[$i] eq 'downgrade')
1436 {
1437 # this causes downgrading
1438 $downgrade = $_[$i+1]; # or undef to disable
b3abae2a 1439 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
1440 splice @a, $j, $s; $j -= $s;
58cde26e 1441 }
1442 }
1443 # any non :constant stuff is handled by our parent, Exporter
1444 # even if @_ is empty, to give it a chance
b3abae2a 1445 $self->SUPER::import(@a); # for subclasses
1446 $self->export_to_level(1,$self,@a); # need this, too
58cde26e 1447 }
1448
1449sub bnorm
1450 {
1451 # adjust m and e so that m is smallest possible
1452 # round number according to accuracy and precision settings
ee15d750 1453 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
58cde26e 1454
0716bf9b 1455 return $x if $x->{sign} !~ /^[+-]$/; # inf, nan etc
58cde26e 1456
28df3e88 1457# if (!$x->{_m}->is_odd())
1458# {
1459 my $zeros = $x->{_m}->_trailing_zeros(); # correct for trailing zeros
1460 if ($zeros != 0)
1461 {
1462 $x->{_m}->brsft($zeros,10); $x->{_e}->badd($zeros);
1463 }
1464 # for something like 0Ey, set y to 1, and -0 => +0
1465 $x->{sign} = '+', $x->{_e}->bone() if $x->{_m}->is_zero();
1466# }
ee15d750 1467 # this is to prevent automatically rounding when MBI's globals are set
0716bf9b 1468 $x->{_m}->{_f} = MB_NEVER_ROUND;
1469 $x->{_e}->{_f} = MB_NEVER_ROUND;
ee15d750 1470 # 'forget' that mantissa was rounded via MBI::bround() in MBF's bfround()
1471 $x->{_m}->{_a} = undef; $x->{_e}->{_a} = undef;
1472 $x->{_m}->{_p} = undef; $x->{_e}->{_p} = undef;
61f5c3f5 1473 $x; # MBI bnorm is no-op, so dont call it
1474 }
58cde26e 1475
1476##############################################################################
1477# internal calculation routines
1478
1479sub as_number
1480 {
394e6ffb 1481 # return copy as a bigint representation of this BigFloat number
1482 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
58cde26e 1483
28df3e88 1484 my $z = $x->{_m}->copy();
1485 if ($x->{_e}->{sign} eq '-') # < 0
58cde26e 1486 {
28df3e88 1487 $x->{_e}->{sign} = '+'; # flip
1488 $z->brsft($x->{_e},10);
1489 $x->{_e}->{sign} = '-'; # flip back
0716bf9b 1490 }
28df3e88 1491 elsif (!$x->{_e}->is_zero()) # > 0
0716bf9b 1492 {
1493 $z->blsft($x->{_e},10);
58cde26e 1494 }
58cde26e 1495 $z->{sign} = $x->{sign};
61f5c3f5 1496 $z;
58cde26e 1497 }
1498
1499sub length
1500 {
ee15d750 1501 my $x = shift;
1502 my $class = ref($x) || $x;
1503 $x = $class->new(shift) unless ref($x);
58cde26e 1504
ee15d750 1505 return 1 if $x->{_m}->is_zero();
58cde26e 1506 my $len = $x->{_m}->length();
1507 $len += $x->{_e} if $x->{_e}->sign() eq '+';
1508 if (wantarray())
1509 {
1510 my $t = Math::BigInt::bzero();
1511 $t = $x->{_e}->copy()->babs() if $x->{_e}->sign() eq '-';
1512 return ($len,$t);
1513 }
61f5c3f5 1514 $len;
58cde26e 1515 }
a0d0e21e 1516
15171;
a5f75d66 1518__END__
1519
1520=head1 NAME
1521
58cde26e 1522Math::BigFloat - Arbitrary size floating point math package
a5f75d66 1523
1524=head1 SYNOPSIS
1525
a2008d6d 1526 use Math::BigFloat;
58cde26e 1527
b3abae2a 1528 # Number creation
1529 $x = Math::BigFloat->new($str); # defaults to 0
1530 $nan = Math::BigFloat->bnan(); # create a NotANumber
1531 $zero = Math::BigFloat->bzero(); # create a +0
1532 $inf = Math::BigFloat->binf(); # create a +inf
1533 $inf = Math::BigFloat->binf('-'); # create a -inf
1534 $one = Math::BigFloat->bone(); # create a +1
1535 $one = Math::BigFloat->bone('-'); # create a -1
58cde26e 1536
1537 # Testing
b3abae2a 1538 $x->is_zero(); # true if arg is +0
1539 $x->is_nan(); # true if arg is NaN
0716bf9b 1540 $x->is_one(); # true if arg is +1
1541 $x->is_one('-'); # true if arg is -1
1542 $x->is_odd(); # true if odd, false for even
1543 $x->is_even(); # true if even, false for odd
1544 $x->is_positive(); # true if >= 0
1545 $x->is_negative(); # true if < 0
b3abae2a 1546 $x->is_inf(sign); # true if +inf, or -inf (default is '+')
1547
58cde26e 1548 $x->bcmp($y); # compare numbers (undef,<0,=0,>0)
1549 $x->bacmp($y); # compare absolutely (undef,<0,=0,>0)
1550 $x->sign(); # return the sign, either +,- or NaN
b3abae2a 1551 $x->digit($n); # return the nth digit, counting from right
1552 $x->digit(-$n); # return the nth digit, counting from left
58cde26e 1553
1554 # The following all modify their first argument:
b3abae2a 1555
58cde26e 1556 # set
1557 $x->bzero(); # set $i to 0
1558 $x->bnan(); # set $i to NaN
b3abae2a 1559 $x->bone(); # set $x to +1
1560 $x->bone('-'); # set $x to -1
1561 $x->binf(); # set $x to inf
1562 $x->binf('-'); # set $x to -inf
58cde26e 1563
1564 $x->bneg(); # negation
1565 $x->babs(); # absolute value
1566 $x->bnorm(); # normalize (no-op)
1567 $x->bnot(); # two's complement (bit wise not)
1568 $x->binc(); # increment x by 1
1569 $x->bdec(); # decrement x by 1
1570
1571 $x->badd($y); # addition (add $y to $x)
1572 $x->bsub($y); # subtraction (subtract $y from $x)
1573 $x->bmul($y); # multiplication (multiply $x by $y)
1574 $x->bdiv($y); # divide, set $i to quotient
1575 # return (quo,rem) or quo if scalar
1576
1577 $x->bmod($y); # modulus
1578 $x->bpow($y); # power of arguments (a**b)
1579 $x->blsft($y); # left shift
1580 $x->brsft($y); # right shift
1581 # return (quo,rem) or quo if scalar
1582
61f5c3f5 1583 $x->blog($base); # logarithm of $x, base defaults to e
1584 # (other bases than e not supported yet)
1585
58cde26e 1586 $x->band($y); # bit-wise and
1587 $x->bior($y); # bit-wise inclusive or
1588 $x->bxor($y); # bit-wise exclusive or
1589 $x->bnot(); # bit-wise not (two's complement)
b3abae2a 1590
1591 $x->bsqrt(); # calculate square-root
1592 $x->bfac(); # factorial of $x (1*2*3*4*..$x)
1593
58cde26e 1594 $x->bround($N); # accuracy: preserver $N digits
1595 $x->bfround($N); # precision: round to the $Nth digit
1596
1597 # The following do not modify their arguments:
58cde26e 1598 bgcd(@values); # greatest common divisor
1599 blcm(@values); # lowest common multiplicator
1600
1601 $x->bstr(); # return string
1602 $x->bsstr(); # return string in scientific notation
b3abae2a 1603
1604 $x->bfloor(); # return integer less or equal than $x
1605 $x->bceil(); # return integer greater or equal than $x
1606
58cde26e 1607 $x->exponent(); # return exponent as BigInt
1608 $x->mantissa(); # return mantissa as BigInt
1609 $x->parts(); # return (mantissa,exponent) as BigInt
1610
1611 $x->length(); # number of digits (w/o sign and '.')
1612 ($l,$f) = $x->length(); # number of digits, and length of fraction
a5f75d66 1613
1614=head1 DESCRIPTION
1615
58cde26e 1616All operators (inlcuding basic math operations) are overloaded if you
1617declare your big floating point numbers as
a5f75d66 1618
58cde26e 1619 $i = new Math::BigFloat '12_3.456_789_123_456_789E-2';
1620
1621Operations with overloaded operators preserve the arguments, which is
1622exactly what you expect.
1623
1624=head2 Canonical notation
1625
1626Input to these routines are either BigFloat objects, or strings of the
1627following four forms:
a5f75d66 1628
1629=over 2
1630
58cde26e 1631=item *
1632
1633C</^[+-]\d+$/>
a5f75d66 1634
58cde26e 1635=item *
a5f75d66 1636
58cde26e 1637C</^[+-]\d+\.\d*$/>
a5f75d66 1638
58cde26e 1639=item *
a5f75d66 1640
58cde26e 1641C</^[+-]\d+E[+-]?\d+$/>
a5f75d66 1642
58cde26e 1643=item *
a5f75d66 1644
58cde26e 1645C</^[+-]\d*\.\d+E[+-]?\d+$/>
5d7098d5 1646
58cde26e 1647=back
1648
1649all with optional leading and trailing zeros and/or spaces. Additonally,
1650numbers are allowed to have an underscore between any two digits.
1651
1652Empty strings as well as other illegal numbers results in 'NaN'.
1653
1654bnorm() on a BigFloat object is now effectively a no-op, since the numbers
1655are always stored in normalized form. On a string, it creates a BigFloat
1656object.
1657
1658=head2 Output
1659
1660Output values are BigFloat objects (normalized), except for bstr() and bsstr().
1661
1662The string output will always have leading and trailing zeros stripped and drop
1663a plus sign. C<bstr()> will give you always the form with a decimal point,
1664while C<bsstr()> (for scientific) gives you the scientific notation.
1665
1666 Input bstr() bsstr()
1667 '-0' '0' '0E1'
1668 ' -123 123 123' '-123123123' '-123123123E0'
1669 '00.0123' '0.0123' '123E-4'
1670 '123.45E-2' '1.2345' '12345E-4'
1671 '10E+3' '10000' '1E4'
1672
1673Some routines (C<is_odd()>, C<is_even()>, C<is_zero()>, C<is_one()>,
1674C<is_nan()>) return true or false, while others (C<bcmp()>, C<bacmp()>)
1675return either undef, <0, 0 or >0 and are suited for sort.
1676
1677Actual math is done by using BigInts to represent the mantissa and exponent.
1678The sign C</^[+-]$/> is stored separately. The string 'NaN' is used to
1679represent the result when input arguments are not numbers, as well as
1680the result of dividing by zero.
1681
1682=head2 C<mantissa()>, C<exponent()> and C<parts()>
1683
1684C<mantissa()> and C<exponent()> return the said parts of the BigFloat
1685as BigInts such that:
1686
1687 $m = $x->mantissa();
1688 $e = $x->exponent();
1689 $y = $m * ( 10 ** $e );
1690 print "ok\n" if $x == $y;
1691
1692C<< ($m,$e) = $x->parts(); >> is just a shortcut giving you both of them.
1693
1694A zero is represented and returned as C<0E1>, B<not> C<0E0> (after Knuth).
1695
1696Currently the mantissa is reduced as much as possible, favouring higher
1697exponents over lower ones (e.g. returning 1e7 instead of 10e6 or 10000000e0).
1698This might change in the future, so do not depend on it.
1699
1700=head2 Accuracy vs. Precision
1701
1702See also: L<Rounding|Rounding>.
1703
027dc388 1704Math::BigFloat supports both precision and accuracy. For a full documentation,
1705examples and tips on these topics please see the large section in
1706L<Math::BigInt>.
5d7098d5 1707
58cde26e 1708Since things like sqrt(2) or 1/3 must presented with a limited precision lest
1709a operation consumes all resources, each operation produces no more than
1710C<Math::BigFloat::precision()> digits.
1711
1712In case the result of one operation has more precision than specified,
1713it is rounded. The rounding mode taken is either the default mode, or the one
1714supplied to the operation after the I<scale>:
1715
1716 $x = Math::BigFloat->new(2);
1717 Math::BigFloat::precision(5); # 5 digits max
1718 $y = $x->copy()->bdiv(3); # will give 0.66666
1719 $y = $x->copy()->bdiv(3,6); # will give 0.666666
1720 $y = $x->copy()->bdiv(3,6,'odd'); # will give 0.666667
1721 Math::BigFloat::round_mode('zero');
1722 $y = $x->copy()->bdiv(3,6); # will give 0.666666
1723
1724=head2 Rounding
1725
1726=over 2
1727
5dc6f178 1728=item ffround ( +$scale )
58cde26e 1729
0716bf9b 1730Rounds to the $scale'th place left from the '.', counting from the dot.
1731The first digit is numbered 1.
58cde26e 1732
5dc6f178 1733=item ffround ( -$scale )
58cde26e 1734
0716bf9b 1735Rounds to the $scale'th place right from the '.', counting from the dot.
58cde26e 1736
5dc6f178 1737=item ffround ( 0 )
1738
0716bf9b 1739Rounds to an integer.
5dc6f178 1740
1741=item fround ( +$scale )
1742
0716bf9b 1743Preserves accuracy to $scale digits from the left (aka significant digits)
1744and pads the rest with zeros. If the number is between 1 and -1, the
1745significant digits count from the first non-zero after the '.'
5dc6f178 1746
1747=item fround ( -$scale ) and fround ( 0 )
1748
0716bf9b 1749These are effetively no-ops.
5d7098d5 1750
a5f75d66 1751=back
1752
0716bf9b 1753All rounding functions take as a second parameter a rounding mode from one of
1754the following: 'even', 'odd', '+inf', '-inf', 'zero' or 'trunc'.
58cde26e 1755
1756The default rounding mode is 'even'. By using
ee15d750 1757C<< Math::BigFloat::round_mode($round_mode); >> you can get and set the default
1758mode for subsequent rounding. The usage of C<$Math::BigFloat::$round_mode> is
0716bf9b 1759no longer supported.
b22b3e31 1760The second parameter to the round functions then overrides the default
0716bf9b 1761temporarily.
58cde26e 1762
1763The C<< as_number() >> function returns a BigInt from a Math::BigFloat. It uses
1764'trunc' as rounding mode to make it equivalent to:
1765
1766 $x = 2.5;
1767 $y = int($x) + 2;
1768
1769You can override this by passing the desired rounding mode as parameter to
1770C<as_number()>:
1771
1772 $x = Math::BigFloat->new(2.5);
1773 $y = $x->as_number('odd'); # $y = 3
1774
1775=head1 EXAMPLES
1776
58cde26e 1777 # not ready yet
58cde26e 1778
1779=head1 Autocreating constants
1780
1781After C<use Math::BigFloat ':constant'> all the floating point constants
1782in the given scope are converted to C<Math::BigFloat>. This conversion
1783happens at compile time.
1784
1785In particular
1786
1787 perl -MMath::BigFloat=:constant -e 'print 2E-100,"\n"'
1788
1789prints the value of C<2E-100>. Note that without conversion of
1790constants the expression 2E-100 will be calculated as normal floating point
1791number.
1792
a5f75d66 1793=head1 BUGS
1794
58cde26e 1795=over 2
1796
1797=item *
1798
1799The following does not work yet:
1800
1801 $m = $x->mantissa();
1802 $e = $x->exponent();
1803 $y = $m * ( 10 ** $e );
1804 print "ok\n" if $x == $y;
1805
1806=item *
1807
1808There is no fmod() function yet.
1809
1810=back
1811
1812=head1 CAVEAT
1813
1814=over 1
1815
1816=item stringify, bstr()
1817
1818Both stringify and bstr() now drop the leading '+'. The old code would return
1819'+1.23', the new returns '1.23'. See the documentation in L<Math::BigInt> for
1820reasoning and details.
1821
1822=item bdiv
1823
1824The following will probably not do what you expect:
1825
1826 print $c->bdiv(123.456),"\n";
1827
1828It prints both quotient and reminder since print works in list context. Also,
1829bdiv() will modify $c, so be carefull. You probably want to use
1830
1831 print $c / 123.456,"\n";
1832 print scalar $c->bdiv(123.456),"\n"; # or if you want to modify $c
1833
1834instead.
1835
1836=item Modifying and =
1837
1838Beware of:
1839
1840 $x = Math::BigFloat->new(5);
1841 $y = $x;
1842
1843It will not do what you think, e.g. making a copy of $x. Instead it just makes
1844a second reference to the B<same> object and stores it in $y. Thus anything
1845that modifies $x will modify $y, and vice versa.
1846
1847 $x->bmul(2);
1848 print "$x, $y\n"; # prints '10, 10'
1849
1850If you want a true copy of $x, use:
1851
1852 $y = $x->copy();
1853
1854See also the documentation in L<overload> regarding C<=>.
1855
1856=item bpow
1857
1858C<bpow()> now modifies the first argument, unlike the old code which left
1859it alone and only returned the result. This is to be consistent with
1860C<badd()> etc. The first will modify $x, the second one won't:
1861
1862 print bpow($x,$i),"\n"; # modify $x
1863 print $x->bpow($i),"\n"; # ditto
1864 print $x ** $i,"\n"; # leave $x alone
1865
1866=back
1867
1868=head1 LICENSE
a5f75d66 1869
58cde26e 1870This program is free software; you may redistribute it and/or modify it under
1871the same terms as Perl itself.
5d7098d5 1872
58cde26e 1873=head1 AUTHORS
5d7098d5 1874
58cde26e 1875Mark Biggar, overloaded interface by Ilya Zakharevich.
1876Completely rewritten by Tels http://bloodgate.com in 2001.
a5f75d66 1877
a5f75d66 1878=cut