The #11593 wasn't right.
[p5sagit/p5-mst-13.2.git] / lib / Math / BigFloat.pm
CommitLineData
58cde26e 1#!/usr/bin/perl -w
2
58cde26e 3# The following hash values are internally used:
4# _e: exponent (BigInt)
5# _m: mantissa (absolute BigInt)
6# sign: +,-,"NaN" if not a number
7# _a: accuracy
8# _p: precision
0716bf9b 9# _f: flags, used to signal MBI not to touch our private parts
58cde26e 10# _cow: Copy-On-Write (NRY)
11
a0d0e21e 12package Math::BigFloat;
13
574bacfe 14$VERSION = '1.20';
58cde26e 15require 5.005;
16use Exporter;
0716bf9b 17use Math::BigInt qw/objectify/;
58cde26e 18@ISA = qw( Exporter Math::BigInt);
19# can not export bneg/babs since the are only in MBI
20@EXPORT_OK = qw(
21 bcmp
22 badd bmul bdiv bmod bnorm bsub
23 bgcd blcm bround bfround
24 bpow bnan bzero bfloor bceil
574bacfe 25 bacmp bstr binc bdec binf
0716bf9b 26 is_odd is_even is_nan is_inf is_positive is_negative
58cde26e 27 is_zero is_one sign
28 );
a0d0e21e 29
58cde26e 30#@EXPORT = qw( );
31use strict;
32use vars qw/$AUTOLOAD $accuracy $precision $div_scale $rnd_mode/;
33my $class = "Math::BigFloat";
a0d0e21e 34
a5f75d66 35use overload
58cde26e 36'<=>' => sub {
37 $_[2] ?
38 $class->bcmp($_[1],$_[0]) :
39 $class->bcmp($_[0],$_[1])},
0716bf9b 40'int' => sub { $_[0]->as_number() }, # 'trunc' to bigint
a5f75d66 41;
a0d0e21e 42
0716bf9b 43##############################################################################
44# global constants, flags and accessory
45
46use constant MB_NEVER_ROUND => 0x0001;
47
58cde26e 48# are NaNs ok?
49my $NaNOK=1;
58cde26e 50# constant for easier life
51my $nan = 'NaN';
58cde26e 52
53# Rounding modes one of 'even', 'odd', '+inf', '-inf', 'zero' or 'trunc'
54$rnd_mode = 'even';
55$accuracy = undef;
56$precision = undef;
57$div_scale = 40;
58
574bacfe 59# in case we call SUPER::->foo() and this wants to call modify()
60# sub modify () { 0; }
61
58cde26e 62{
63 # checks for AUTOLOAD
64 my %methods = map { $_ => 1 }
65 qw / fadd fsub fmul fdiv fround ffround fsqrt fmod fstr fsstr fpow fnorm
66 fabs fneg fint fcmp fzero fnan finc fdec
67 /;
68
69 sub method_valid { return exists $methods{$_[0]||''}; }
a0d0e21e 70}
0e8b9368 71
58cde26e 72##############################################################################
73# constructors
a0d0e21e 74
58cde26e 75sub new
76 {
77 # create a new BigFloat object from a string or another bigfloat object.
78 # _e: exponent
79 # _m: mantissa
80 # sign => sign (+/-), or "NaN"
a0d0e21e 81
58cde26e 82 my $class = shift;
83
84 my $wanted = shift; # avoid numify call by not using || here
85 return $class->bzero() if !defined $wanted; # default to 0
86 return $wanted->copy() if ref($wanted) eq $class;
a0d0e21e 87
58cde26e 88 my $round = shift; $round = 0 if !defined $round; # no rounding as default
89 my $self = {}; bless $self, $class;
b22b3e31 90 # shortcut for bigints and its subclasses
0716bf9b 91 if ((ref($wanted)) && (ref($wanted) ne $class))
58cde26e 92 {
0716bf9b 93 $self->{_m} = $wanted->as_number(); # get us a bigint copy
58cde26e 94 $self->{_e} = Math::BigInt->new(0);
95 $self->{_m}->babs();
96 $self->{sign} = $wanted->sign();
0716bf9b 97 return $self->bnorm();
58cde26e 98 }
99 # got string
100 # handle '+inf', '-inf' first
101 if ($wanted =~ /^[+-]inf$/)
102 {
103 $self->{_e} = Math::BigInt->new(0);
104 $self->{_m} = Math::BigInt->new(0);
105 $self->{sign} = $wanted;
0716bf9b 106 return $self->bnorm();
58cde26e 107 }
108 #print "new string '$wanted'\n";
109 my ($mis,$miv,$mfv,$es,$ev) = Math::BigInt::_split(\$wanted);
110 if (!ref $mis)
111 {
112 die "$wanted is not a number initialized to $class" if !$NaNOK;
113 $self->{_e} = Math::BigInt->new(0);
114 $self->{_m} = Math::BigInt->new(0);
115 $self->{sign} = $nan;
116 }
117 else
118 {
119 # make integer from mantissa by adjusting exp, then convert to bigint
120 $self->{_e} = Math::BigInt->new("$$es$$ev"); # exponent
121 $self->{_m} = Math::BigInt->new("$$mis$$miv$$mfv"); # create mantissa
122 # 3.123E0 = 3123E-3, and 3.123E-2 => 3123E-5
123 $self->{_e} -= CORE::length($$mfv);
124 $self->{sign} = $self->{_m}->sign(); $self->{_m}->babs();
125 }
0716bf9b 126 #print "$wanted => $self->{sign} $self->{value}\n";
58cde26e 127 $self->bnorm(); # first normalize
128 # if any of the globals is set, round to them and thus store them insid $self
129 $self->round($accuracy,$precision,$rnd_mode)
130 if defined $accuracy || defined $precision;
131 return $self;
132 }
a0d0e21e 133
58cde26e 134sub bnan
135 {
136 # create a bigfloat 'NaN', if given a BigFloat, set it to 'NaN'
137 my $self = shift;
138 $self = $class if !defined $self;
139 if (!ref($self))
288d023a 140 {
58cde26e 141 my $c = $self; $self = {}; bless $self, $c;
a0d0e21e 142 }
574bacfe 143 $self->{_m} = Math::BigInt->bzero();
144 $self->{_e} = Math::BigInt->bzero();
58cde26e 145 $self->{sign} = $nan;
58cde26e 146 return $self;
147 }
a0d0e21e 148
58cde26e 149sub binf
150 {
151 # create a bigfloat '+-inf', if given a BigFloat, set it to '+-inf'
152 my $self = shift;
153 my $sign = shift; $sign = '+' if !defined $sign || $sign ne '-';
a0d0e21e 154
58cde26e 155 $self = $class if !defined $self;
156 if (!ref($self))
157 {
158 my $c = $self; $self = {}; bless $self, $c;
159 }
574bacfe 160 $self->{_m} = Math::BigInt->bzero();
161 $self->{_e} = Math::BigInt->bzero();
58cde26e 162 $self->{sign} = $sign.'inf';
58cde26e 163 return $self;
164 }
a0d0e21e 165
574bacfe 166sub bone
167 {
168 # create a bigfloat '+-1', if given a BigFloat, set it to '+-1'
169 my $self = shift;
170 my $sign = shift; $sign = '+' if !defined $sign || $sign ne '-';
171
172 $self = $class if !defined $self;
173 if (!ref($self))
174 {
175 my $c = $self; $self = {}; bless $self, $c;
176 }
177 $self->{_m} = Math::BigInt->bone();
178 $self->{_e} = Math::BigInt->bzero();
179 $self->{sign} = $sign;
180 return $self;
181 }
182
58cde26e 183sub bzero
184 {
185 # create a bigfloat '+0', if given a BigFloat, set it to 0
186 my $self = shift;
187 $self = $class if !defined $self;
188 if (!ref($self))
189 {
190 my $c = $self; $self = {}; bless $self, $c;
191 }
574bacfe 192 $self->{_m} = Math::BigInt->bzero();
193 $self->{_e} = Math::BigInt->bone();
58cde26e 194 $self->{sign} = '+';
58cde26e 195 return $self;
196 }
197
198##############################################################################
199# string conversation
200
201sub bstr
202 {
203 # (ref to BFLOAT or num_str ) return num_str
204 # Convert number from internal format to (non-scientific) string format.
205 # internal format is always normalized (no leading zeros, "-0" => "+0")
58cde26e 206 my ($self,$x) = objectify(1,@_);
207
574bacfe 208 #die "Oups! e was $nan" if $x->{_e}->{sign} eq $nan;
209 #die "Oups! m was $nan" if $x->{_m}->{sign} eq $nan;
210 if ($x->{sign} !~ /^[+-]$/)
58cde26e 211 {
574bacfe 212 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN
213 return 'inf'; # +inf
58cde26e 214 }
215
574bacfe 216 my $es = '0'; my $len = 1; my $cad = 0; my $dot = '.';
217
218 my $not_zero = !$x->is_zero();
219 if ($not_zero)
58cde26e 220 {
574bacfe 221 $es = $x->{_m}->bstr();
222 $len = CORE::length($es);
223 if (!$x->{_e}->is_zero())
224# {
225# $es = $x->{sign}.$es if $x->{sign} eq '-';
226# }
227# else
58cde26e 228 {
574bacfe 229 if ($x->{_e}->sign() eq '-')
230 {
231 $dot = '';
232 if ($x->{_e} <= -$len)
233 {
234 # print "style: 0.xxxx\n";
235 my $r = $x->{_e}->copy(); $r->babs()->bsub( CORE::length($es) );
236 $es = '0.'. ('0' x $r) . $es; $cad = -($len+$r);
237 }
238 else
239 {
240 # print "insert '.' at $x->{_e} in '$es'\n";
241 substr($es,$x->{_e},0) = '.'; $cad = $x->{_e};
242 }
243 }
244 else
245 {
246 # expand with zeros
247 $es .= '0' x $x->{_e}; $len += $x->{_e}; $cad = 0;
248 }
82cf049f 249 }
574bacfe 250 } # if not zero
251 $es = $x->{sign}.$es if $x->{sign} eq '-';
252 # if set accuracy or precision, pad with zeros
253 if ((defined $x->{_a}) && ($not_zero))
254 {
255 # 123400 => 6, 0.1234 => 4, 0.001234 => 4
256 my $zeros = $x->{_a} - $cad; # cad == 0 => 12340
257 $zeros = $x->{_a} - $len if $cad != $len;
258 #print "acc padd $x->{_a} $zeros (len $len cad $cad)\n";
259 $es .= $dot.'0' x $zeros if $zeros > 0;
82cf049f 260 }
574bacfe 261 elsif ($x->{_p} || 0 < 0)
58cde26e 262 {
574bacfe 263 # 123400 => 6, 0.1234 => 4, 0.001234 => 6
264 my $zeros = -$x->{_p} + $cad;
265 #print "pre padd $x->{_p} $zeros (len $len cad $cad)\n";
266 $es .= $dot.'0' x $zeros if $zeros > 0;
58cde26e 267 }
58cde26e 268 return $es;
82cf049f 269 }
f216259d 270
58cde26e 271sub bsstr
272 {
273 # (ref to BFLOAT or num_str ) return num_str
274 # Convert number from internal format to scientific string format.
275 # internal format is always normalized (no leading zeros, "-0E0" => "+0E0")
58cde26e 276 my ($self,$x) = objectify(1,@_);
a0d0e21e 277
574bacfe 278 #die "Oups! e was $nan" if $x->{_e}->{sign} eq $nan;
279 #die "Oups! m was $nan" if $x->{_m}->{sign} eq $nan;
280 if ($x->{sign} !~ /^[+-]$/)
281 {
282 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN
283 return 'inf'; # +inf
284 }
58cde26e 285 my $sign = $x->{_e}->{sign}; $sign = '' if $sign eq '-';
286 my $sep = 'e'.$sign;
287 return $x->{_m}->bstr().$sep.$x->{_e}->bstr();
288 }
289
290sub numify
291 {
292 # Make a number from a BigFloat object
574bacfe 293 # simple return string and let Perl's atoi()/atof() handle the rest
58cde26e 294 my ($self,$x) = objectify(1,@_);
295 return $x->bsstr();
296 }
a0d0e21e 297
58cde26e 298##############################################################################
299# public stuff (usually prefixed with "b")
300
301# really? Just for exporting them is not what I had in mind
302#sub babs
303# {
304# $class->SUPER::babs($class,@_);
305# }
306#sub bneg
307# {
308# $class->SUPER::bneg($class,@_);
309# }
574bacfe 310
311# tels 2001-08-04
312# todo: this must be overwritten and return NaN for non-integer values
313# band(), bior(), bxor(), too
58cde26e 314#sub bnot
315# {
316# $class->SUPER::bnot($class,@_);
317# }
318
319sub bcmp
320 {
321 # Compares 2 values. Returns one of undef, <0, =0, >0. (suitable for sort)
322 # (BFLOAT or num_str, BFLOAT or num_str) return cond_code
323 my ($self,$x,$y) = objectify(2,@_);
58cde26e 324
0716bf9b 325 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
326 {
327 # handle +-inf and NaN
328 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
329 return 0 if ($x->{sign} eq $y->{sign}) && ($x->{sign} =~ /^[+-]inf$/);
330 return +1 if $x->{sign} eq '+inf';
331 return -1 if $x->{sign} eq '-inf';
332 return -1 if $y->{sign} eq '+inf';
333 return +1 if $y->{sign} eq '-inf';
334 }
335
336 # check sign for speed first
574bacfe 337 return 1 if $x->{sign} eq '+' && $y->{sign} eq '-'; # does also 0 <=> -y
58cde26e 338 return -1 if $x->{sign} eq '-' && $y->{sign} eq '+'; # does also -x <=> 0
339
574bacfe 340 # shortcut
341 my $xz = $x->is_zero();
342 my $yz = $y->is_zero();
343 return 0 if $xz && $yz; # 0 <=> 0
344 return -1 if $xz && $y->{sign} eq '+'; # 0 <=> +y
345 return 1 if $yz && $x->{sign} eq '+'; # +x <=> 0
58cde26e 346
347 # adjust so that exponents are equal
348 my $lx = $x->{_m}->length() + $x->{_e};
349 my $ly = $y->{_m}->length() + $y->{_e};
350 # print "x $x y $y lx $lx ly $ly\n";
351 my $l = $lx - $ly; $l = -$l if $x->{sign} eq '-';
352 # print "$l $x->{sign}\n";
353 return $l if $l != 0;
354
0716bf9b 355 # lengths are equal, so compare mantissa, if equal, compare exponents
b22b3e31 356 # this assumes normalized numbers (no trailing zeros etc!)
58cde26e 357 my $rc = $x->{_m} <=> $y->{_m} || $x->{_e} <=> $y->{_e};
358 $rc = -$rc if $x->{sign} eq '-'; # -124 < -123
359 return $rc;
360 }
361
362sub bacmp
363 {
364 # Compares 2 values, ignoring their signs.
365 # Returns one of undef, <0, =0, >0. (suitable for sort)
366 # (BFLOAT or num_str, BFLOAT or num_str) return cond_code
367 my ($self,$x,$y) = objectify(2,@_);
368 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
369
370 # signs are ignored, so check length
371 # length(x) is length(m)+e aka length of non-fraction part
372 # the longer one is bigger
373 my $l = $x->length() - $y->length();
374 #print "$l\n";
375 return $l if $l != 0;
376 #print "equal lengths\n";
377
378 # if both are equal long, make full compare
379 # first compare only the mantissa
380 # if mantissa are equal, compare fractions
381
382 return $x->{_m} <=> $y->{_m} || $x->{_e} <=> $y->{_e};
383 }
a0d0e21e 384
58cde26e 385sub badd
386 {
387 # add second arg (BFLOAT or string) to first (BFLOAT) (modifies first)
388 # return result as BFLOAT
58cde26e 389 my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
390
574bacfe 391 # inf and NaN handling
392 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
393 {
394 # NaN first
395 return $x->bnan() if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
396 # inf handline
397 if (($x->{sign} =~ /^[+-]inf$/) && ($y->{sign} =~ /^[+-]inf$/))
398 {
399 # + and + => +, - and - => -, + and - => 0, - and + => 0
400 return $x->bzero() if $x->{sign} ne $y->{sign};
401 return $x;
402 }
403 # +-inf + something => +inf
404 # something +-inf => +-inf
405 $x->{sign} = $y->{sign}, return $x if $y->{sign} =~ /^[+-]inf$/;
406 return $x;
407 }
408
58cde26e 409 # speed: no add for 0+y or x+0
410 return $x if $y->is_zero(); # x+0
411 if ($x->is_zero()) # 0+y
412 {
413 # make copy, clobbering up x (modify in place!)
414 $x->{_e} = $y->{_e}->copy();
415 $x->{_m} = $y->{_m}->copy();
416 $x->{sign} = $y->{sign} || $nan;
417 return $x->round($a,$p,$r,$y);
a0d0e21e 418 }
58cde26e 419
420 # take lower of the two e's and adapt m1 to it to match m2
421 my $e = $y->{_e}; $e = Math::BigInt::bzero() if !defined $e; # if no BFLOAT
422 $e = $e - $x->{_e};
423 my $add = $y->{_m}->copy();
424 if ($e < 0)
425 {
0716bf9b 426 # print "e < 0\n";
58cde26e 427 #print "\$x->{_m}: $x->{_m} ";
428 #print "\$x->{_e}: $x->{_e}\n";
429 my $e1 = $e->copy()->babs();
430 $x->{_m} *= (10 ** $e1);
431 $x->{_e} += $e; # need the sign of e
432 #$x->{_m} += $y->{_m};
433 #print "\$x->{_m}: $x->{_m} ";
434 #print "\$x->{_e}: $x->{_e}\n";
435 }
436 elsif ($e > 0)
437 {
0716bf9b 438 # print "e > 0\n";
58cde26e 439 #print "\$x->{_m}: $x->{_m} \$y->{_m}: $y->{_m} \$e: $e ",ref($e),"\n";
440 $add *= (10 ** $e);
441 #$x->{_m} += $y->{_m} * (10 ** $e);
442 #print "\$x->{_m}: $x->{_m}\n";
443 }
444 # else: both e are same, so leave them
445 #print "badd $x->{sign}$x->{_m} + $y->{sign}$add\n";
446 # fiddle with signs
447 $x->{_m}->{sign} = $x->{sign};
448 $add->{sign} = $y->{sign};
449 # finally do add/sub
450 $x->{_m} += $add;
451 # re-adjust signs
452 $x->{sign} = $x->{_m}->{sign};
453 $x->{_m}->{sign} = '+';
0716bf9b 454 #$x->bnorm(); # delete trailing zeros
58cde26e 455 return $x->round($a,$p,$r,$y);
456 }
457
458sub bsub
459 {
0716bf9b 460 # (BigFloat or num_str, BigFloat or num_str) return BigFloat
58cde26e 461 # subtract second arg from first, modify first
462 my ($self,$x,$y) = objectify(2,@_);
a0d0e21e 463
58cde26e 464 $x->badd($y->bneg()); # badd does not leave internal zeros
465 $y->bneg(); # refix y, assumes no one reads $y in between
0716bf9b 466 return $x; # badd() already normalized and rounded
58cde26e 467 }
468
469sub binc
470 {
471 # increment arg by one
472 my ($self,$x,$a,$p,$r) = objectify(1,@_);
58cde26e 473 $x->badd($self->_one())->round($a,$p,$r);
474 }
475
476sub bdec
477 {
478 # decrement arg by one
479 my ($self,$x,$a,$p,$r) = objectify(1,@_);
58cde26e 480 $x->badd($self->_one('-'))->round($a,$p,$r);
481 }
482
483sub blcm
484 {
485 # (BINT or num_str, BINT or num_str) return BINT
486 # does not modify arguments, but returns new object
487 # Lowest Common Multiplicator
58cde26e 488
489 my ($self,@arg) = objectify(0,@_);
490 my $x = $self->new(shift @arg);
491 while (@arg) { $x = _lcm($x,shift @arg); }
492 $x;
493 }
494
495sub bgcd
496 {
497 # (BINT or num_str, BINT or num_str) return BINT
498 # does not modify arguments, but returns new object
499 # GCD -- Euclids algorithm Knuth Vol 2 pg 296
58cde26e 500
501 my ($self,@arg) = objectify(0,@_);
502 my $x = $self->new(shift @arg);
503 while (@arg) { $x = _gcd($x,shift @arg); }
504 $x;
505 }
506
507sub is_zero
508 {
509 # return true if arg (BINT or num_str) is zero (array '+', '0')
510 my $x = shift; $x = $class->new($x) unless ref $x;
574bacfe 511
512 return 1 if $x->{sign} eq '+' && $x->{_m}->is_zero();
513 return 0;
58cde26e 514 }
515
516sub is_one
517 {
518 # return true if arg (BINT or num_str) is +1 (array '+', '1')
519 # or -1 if signis given
520 my $x = shift; $x = $class->new($x) unless ref $x;
521 #my ($self,$x) = objectify(1,@_);
522 my $sign = $_[2] || '+';
523 return ($x->{sign} eq $sign && $x->{_e}->is_zero() && $x->{_m}->is_one());
524 }
525
526sub is_odd
527 {
b22b3e31 528 # return true if arg (BINT or num_str) is odd or false if even
58cde26e 529 my $x = shift; $x = $class->new($x) unless ref $x;
530 #my ($self,$x) = objectify(1,@_);
0716bf9b 531
532 return 0 if $x->{sign} !~ /^[+-]$/; # NaN & +-inf aren't
533 return ($x->{_e}->is_zero() && $x->{_m}->is_odd());
58cde26e 534 }
535
536sub is_even
537 {
b22b3e31 538 # return true if arg (BINT or num_str) is even or false if odd
58cde26e 539 my $x = shift; $x = $class->new($x) unless ref $x;
540 #my ($self,$x) = objectify(1,@_);
0716bf9b 541
542 return 0 if $x->{sign} !~ /^[+-]$/; # NaN & +-inf aren't
543 return 1 if $x->{_m}->is_zero(); # 0e1 is even
544 return ($x->{_e}->is_zero() && $x->{_m}->is_even()); # 123.45 is never
58cde26e 545 }
546
547sub bmul
548 {
549 # multiply two numbers -- stolen from Knuth Vol 2 pg 233
550 # (BINT or num_str, BINT or num_str) return BINT
551 my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
58cde26e 552
0716bf9b 553 # print "mbf bmul $x->{_m}e$x->{_e} $y->{_m}e$y->{_e}\n";
58cde26e 554 return $x->bnan() if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
555
574bacfe 556 # handle result = 0
557 return $x->bzero() if $x->is_zero() || $y->is_zero();
558 # inf handling
559 if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/))
560 {
561 # result will always be +-inf:
562 # +inf * +/+inf => +inf, -inf * -/-inf => +inf
563 # +inf * -/-inf => -inf, -inf * +/+inf => -inf
564 return $x->binf() if ($x->{sign} =~ /^\+/ && $y->{sign} =~ /^\+/);
565 return $x->binf() if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/);
566 return $x->binf('-');
567 }
568
58cde26e 569 # aEb * cEd = (a*c)E(b+d)
570 $x->{_m} = $x->{_m} * $y->{_m};
571 #print "m: $x->{_m}\n";
572 $x->{_e} = $x->{_e} + $y->{_e};
573 #print "e: $x->{_m}\n";
574 # adjust sign:
575 $x->{sign} = $x->{sign} ne $y->{sign} ? '-' : '+';
576 #print "s: $x->{sign}\n";
0716bf9b 577 $x->bnorm();
58cde26e 578 return $x->round($a,$p,$r,$y);
579 }
580
581sub bdiv
582 {
583 # (dividend: BFLOAT or num_str, divisor: BFLOAT or num_str) return
584 # (BFLOAT,BFLOAT) (quo,rem) or BINT (only rem)
585 my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
586
574bacfe 587 # x / +-inf => 0, reminder x
588 return wantarray ? ($x->bzero(),$x->copy()) : $x->bzero()
589 if $y->{sign} =~ /^[+-]inf$/;
590
591 # NaN if x == NaN or y == NaN or x==y==0
58cde26e 592 return wantarray ? ($x->bnan(),bnan()) : $x->bnan()
574bacfe 593 if (($x->is_nan() || $y->is_nan()) ||
594 ($x->is_zero() && $y->is_zero()));
595
596 # 5 / 0 => +inf, -6 / 0 => -inf
597 return wantarray
598 ? ($x->binf($x->{sign}),$self->bnan()) : $x->binf($x->{sign})
599 if ($x->{sign} =~ /^[+-]$/ && $y->is_zero());
0716bf9b 600
601 $y = $class->new($y) if ref($y) ne $class; # promote bigints
602
603 # print "mbf bdiv $x ",ref($x)," ",$y," ",ref($y),"\n";
58cde26e 604 # we need to limit the accuracy to protect against overflow
0716bf9b 605 my ($scale) = $x->_scale_a($accuracy,$rnd_mode,$a,$r); # ignore $p
574bacfe 606 my $fallback = 0;
58cde26e 607 if (!defined $scale)
608 {
0716bf9b 609 # simulate old behaviour
610 $scale = $div_scale+1; # one more for proper riund
574bacfe 611 $a = $div_scale; # and round to it
612 $fallback = 1; # to clear a/p afterwards
a0d0e21e 613 }
0716bf9b 614 my $lx = $x->{_m}->length(); my $ly = $y->{_m}->length();
58cde26e 615 $scale = $lx if $lx > $scale;
58cde26e 616 $scale = $ly if $ly > $scale;
617 #print "scale $scale $lx $ly\n";
0716bf9b 618 my $diff = $ly - $lx;
619 $scale += $diff if $diff > 0; # if lx << ly, but not if ly << lx!
a0d0e21e 620
58cde26e 621 return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
622
623 $x->{sign} = $x->{sign} ne $y->sign() ? '-' : '+';
a0d0e21e 624
58cde26e 625 # check for / +-1 ( +/- 1E0)
626 if ($y->is_one())
627 {
628 return wantarray ? ($x,$self->bzero()) : $x;
a0d0e21e 629 }
a5f75d66 630
58cde26e 631 # a * 10 ** b / c * 10 ** d => a/c * 10 ** (b-d)
632 #print "self: $self x: $x ref(x) ", ref($x)," m: $x->{_m}\n";
633 # my $scale_10 = 10 ** $scale; $x->{_m}->bmul($scale_10);
634 $x->{_m}->blsft($scale,10);
0716bf9b 635 #print "m: $x->{_m} $y->{_m}\n";
58cde26e 636 $x->{_m}->bdiv( $y->{_m} ); # a/c
637 #print "m: $x->{_m}\n";
638 #print "e: $x->{_e} $y->{_e}",$scale,"\n";
639 $x->{_e}->bsub($y->{_e}); # b-d
640 #print "e: $x->{_e}\n";
641 $x->{_e}->bsub($scale); # correct for 10**scale
0716bf9b 642 #print "after div: m: $x->{_m} e: $x->{_e}\n";
643 $x->bnorm(); # remove trailing 0's
644 #print "after div: m: $x->{_m} e: $x->{_e}\n";
645 $x->round($a,$p,$r); # then round accordingly
574bacfe 646 if ($fallback)
647 {
648 # clear a/p after round, since user did not request it
649 $x->{_a} = undef;
650 $x->{_p} = undef;
651 }
0716bf9b 652
58cde26e 653 if (wantarray)
654 {
655 my $rem = $x->copy();
656 $rem->bmod($y,$a,$p,$r);
574bacfe 657 if ($fallback)
658 {
659 # clear a/p after round, since user did not request it
660 $x->{_a} = undef;
661 $x->{_p} = undef;
662 }
0716bf9b 663 return ($x,$rem);
58cde26e 664 }
665 return $x;
666 }
a0d0e21e 667
58cde26e 668sub bmod
669 {
670 # (dividend: BFLOAT or num_str, divisor: BFLOAT or num_str) return reminder
671 my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
a0d0e21e 672
58cde26e 673 return $x->bnan() if ($x->{sign} eq $nan || $y->is_nan() || $y->is_zero());
674 return $x->bzero() if $y->is_one();
675
676 # XXX tels: not done yet
677 return $x->round($a,$p,$r,$y);
678 }
679
680sub bsqrt
681 {
0716bf9b 682 # calculate square root; this should probably
683 # use a different test to see whether the accuracy we want is...
58cde26e 684 my ($self,$x,$a,$p,$r) = objectify(1,@_);
685
0716bf9b 686 return $x->bnan() if $x->{sign} eq 'NaN' || $x->{sign} =~ /^-/; # <0, NaN
687 return $x if $x->{sign} eq '+inf'; # +inf
58cde26e 688 return $x if $x->is_zero() || $x == 1;
689
0716bf9b 690 # we need to limit the accuracy to protect against overflow
691 my ($scale) = $x->_scale_a($accuracy,$rnd_mode,$a,$r); # ignore $p
574bacfe 692 my $fallback = 0;
0716bf9b 693 if (!defined $scale)
694 {
695 # simulate old behaviour
696 $scale = $div_scale+1; # one more for proper riund
697 $a = $div_scale; # and round to it
574bacfe 698 $fallback = 1; # to clear a/p afterwards
0716bf9b 699 }
700 my $lx = $x->{_m}->length();
701 $scale = $lx if $scale < $lx;
58cde26e 702 my $e = Math::BigFloat->new("1E-$scale"); # make test variable
703 return $x->bnan() if $e->sign() eq 'NaN';
704
58cde26e 705 # start with some reasonable guess
0716bf9b 706 #$x *= 10 ** ($len - $org->{_e}); $x /= 2; # !?!?
574bacfe 707 $lx = $lx+$x->{_e};
0716bf9b 708 $lx = 1 if $lx < 1;
709 my $gs = Math::BigFloat->new('1'. ('0' x $lx));
710
711 # print "first guess: $gs (x $x) scale $scale\n";
58cde26e 712
713 my $diff = $e;
714 my $y = $x->copy();
715 my $two = Math::BigFloat->new(2);
716 $x = Math::BigFloat->new($x) if ref($x) ne $class; # promote BigInts
717 # $scale = 2;
718 while ($diff >= $e)
719 {
58cde26e 720 return $x->bnan() if $gs->is_zero();
0716bf9b 721 $r = $y->copy(); $r->bdiv($gs,$scale);
58cde26e 722 $x = ($r + $gs);
0716bf9b 723 $x->bdiv($two,$scale);
58cde26e 724 $diff = $x->copy()->bsub($gs)->babs();
58cde26e 725 $gs = $x->copy();
a0d0e21e 726 }
0716bf9b 727 $x->round($a,$p,$r);
574bacfe 728 if ($fallback)
729 {
730 # clear a/p after round, since user did not request it
731 $x->{_a} = undef;
732 $x->{_p} = undef;
733 }
734 $x;
58cde26e 735 }
736
737sub bpow
738 {
739 # (BFLOAT or num_str, BFLOAT or num_str) return BFLOAT
740 # compute power of two numbers, second arg is used as integer
741 # modifies first argument
742
743 my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
744
0716bf9b 745 return $x if $x->{sign} =~ /^[+-]inf$/;
58cde26e 746 return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;
574bacfe 747 return $x->bone() if $y->is_zero();
58cde26e 748 return $x if $x->is_one() || $y->is_one();
749 my $y1 = $y->as_number(); # make bigint
750 if ($x == -1)
751 {
752 # if $x == -1 and odd/even y => +1/-1 because +-1 ^ (+-1) => +-1
0716bf9b 753 return $y1->is_odd() ? $x : $x->babs(1);
288d023a 754 }
58cde26e 755 return $x if $x->is_zero() && $y->{sign} eq '+'; # 0**y => 0 (if not y <= 0)
574bacfe 756 # 0 ** -y => 1 / (0 ** y) => / 0! (1 / 0 => +inf)
757 return $x->binf() if $x->is_zero() && $y->{sign} eq '-';
58cde26e 758
759 # calculate $x->{_m} ** $y and $x->{_e} * $y separately (faster)
760 $y1->babs();
761 $x->{_m}->bpow($y1);
762 $x->{_e}->bmul($y1);
763 $x->{sign} = $nan if $x->{_m}->{sign} eq $nan || $x->{_e}->{sign} eq $nan;
764 $x->bnorm();
765 if ($y->{sign} eq '-')
766 {
767 # modify $x in place!
0716bf9b 768 my $z = $x->copy(); $x->bzero()->binc();
58cde26e 769 return $x->bdiv($z,$a,$p,$r); # round in one go (might ignore y's A!)
a0d0e21e 770 }
58cde26e 771 return $x->round($a,$p,$r,$y);
772 }
773
774###############################################################################
775# rounding functions
776
777sub bfround
778 {
779 # precision: round to the $Nth digit left (+$n) or right (-$n) from the '.'
780 # $n == 0 means round to integer
781 # expects and returns normalized numbers!
782 my $x = shift; $x = $class->new($x) unless ref $x;
a0d0e21e 783
58cde26e 784 return $x if $x->modify('bfround');
785
786 my ($scale,$mode) = $x->_scale_p($precision,$rnd_mode,@_);
787 return $x if !defined $scale; # no-op
788
574bacfe 789 # never round a 0, +-inf, NaN
790 return $x if $x->{sign} !~ /^[+-]$/ || $x->is_zero();
58cde26e 791 # print "MBF bfround $x to scale $scale mode $mode\n";
58cde26e 792
793 if ($scale < 0)
794 {
795 # print "bfround scale $scale e $x->{_e}\n";
796 # round right from the '.'
797 return $x if $x->{_e} >= 0; # nothing to round
798 $scale = -$scale; # positive for simplicity
799 my $len = $x->{_m}->length(); # length of mantissa
800 my $dad = -$x->{_e}; # digits after dot
801 my $zad = 0; # zeros after dot
802 $zad = -$len-$x->{_e} if ($x->{_e} < -$len);# for 0.00..00xxx style
803 # print "scale $scale dad $dad zad $zad len $len\n";
804
805 # number bsstr len zad dad
806 # 0.123 123e-3 3 0 3
807 # 0.0123 123e-4 3 1 4
808 # 0.001 1e-3 1 2 3
809 # 1.23 123e-2 3 0 2
810 # 1.2345 12345e-4 5 0 4
811
812 # do not round after/right of the $dad
813 return $x if $scale > $dad; # 0.123, scale >= 3 => exit
814
815 # round to zero if rounding inside the $zad, but not for last zero like:
816 # 0.0065, scale -2, round last '0' with following '65' (scale == zad case)
817 if ($scale < $zad)
818 {
574bacfe 819 return $x->bzero();
58cde26e 820 }
821 if ($scale == $zad) # for 0.006, scale -2 and trunc
822 {
823 $scale = -$len;
824 }
825 else
826 {
827 # adjust round-point to be inside mantissa
828 if ($zad != 0)
829 {
830 $scale = $scale-$zad;
831 }
832 else
833 {
834 my $dbd = $len - $dad; $dbd = 0 if $dbd < 0; # digits before dot
835 $scale = $dbd+$scale;
836 }
837 }
838 # print "round to $x->{_m} to $scale\n";
a0d0e21e 839 }
58cde26e 840 else
841 {
842 # 123 => 100 means length(123) = 3 - $scale (2) => 1
a5f75d66 843
58cde26e 844 # calculate digits before dot
845 my $dbt = $x->{_m}->length(); $dbt += $x->{_e} if $x->{_e}->sign() eq '-';
846 if (($scale > $dbt) && ($dbt < 0))
847 {
848 # if not enough digits before dot, round to zero
574bacfe 849 return $x->bzero();
58cde26e 850 }
851 if (($scale >= 0) && ($dbt == 0))
852 {
853 # 0.49->bfround(1): scale == 1, dbt == 0: => 0.0
854 # 0.51->bfround(0): scale == 0, dbt == 0: => 1.0
855 # 0.5->bfround(0): scale == 0, dbt == 0: => 0
856 # 0.05->bfround(0): scale == 0, dbt == 0: => 0
857 # print "$scale $dbt $x->{_m}\n";
858 $scale = -$x->{_m}->length();
859 }
860 elsif ($dbt > 0)
861 {
862 # correct by subtracting scale
863 $scale = $dbt - $scale;
864 }
865 else
866 {
867 $scale = $x->{_m}->length() - $scale;
868 }
a0d0e21e 869 }
574bacfe 870 # print "using $scale for $x->{_m} with '$mode'\n";
871 # pass sign to bround for rounding modes '+inf' and '-inf'
58cde26e 872 $x->{_m}->{sign} = $x->{sign};
873 $x->{_m}->bround($scale,$mode);
874 $x->{_m}->{sign} = '+'; # fix sign back
875 $x->bnorm();
876 }
877
878sub bround
879 {
880 # accuracy: preserve $N digits, and overwrite the rest with 0's
881 my $x = shift; $x = $class->new($x) unless ref $x;
882 my ($scale,$mode) = $x->_scale_a($accuracy,$rnd_mode,@_);
883 return $x if !defined $scale; # no-op
884
885 return $x if $x->modify('bround');
886
887 # print "bround $scale $mode\n";
888 # 0 => return all digits, scale < 0 makes no sense
889 return $x if ($scale <= 0);
574bacfe 890 # never round a 0, +-inf, NaN
891 return $x if $x->{sign} !~ /^[+-]$/ || $x->is_zero();
58cde26e 892
893 # if $e longer than $m, we have 0.0000xxxyyy style number, and must
894 # subtract the delta from scale, to simulate keeping the zeros
895 # -5 +5 => 1; -10 +5 => -4
896 my $delta = $x->{_e} + $x->{_m}->length() + 1;
897 # removed by tlr, since causes problems with fraction tests:
898 # $scale += $delta if $delta < 0;
899
900 # if we should keep more digits than the mantissa has, do nothing
901 return $x if $x->{_m}->length() <= $scale;
f216259d 902
58cde26e 903 # pass sign to bround for '+inf' and '-inf' rounding modes
904 $x->{_m}->{sign} = $x->{sign};
905 $x->{_m}->bround($scale,$mode); # round mantissa
906 $x->{_m}->{sign} = '+'; # fix sign back
574bacfe 907 $x->bnorm(); # del trailing zeros gen. by bround()
58cde26e 908 }
909
910sub bfloor
911 {
912 # return integer less or equal then $x
913 my ($self,$x,$a,$p,$r) = objectify(1,@_);
914
915 return $x if $x->modify('bfloor');
916
917 return $x if $x->{sign} !~ /^[+-]$/; # nan, +inf, -inf
918
919 # if $x has digits after dot
920 if ($x->{_e}->{sign} eq '-')
921 {
922 $x->{_m}->brsft(-$x->{_e},10);
923 $x->{_e}->bzero();
924 $x-- if $x->{sign} eq '-';
f216259d 925 }
58cde26e 926 return $x->round($a,$p,$r);
927 }
288d023a 928
58cde26e 929sub bceil
930 {
931 # return integer greater or equal then $x
932 my ($self,$x,$a,$p,$r) = objectify(1,@_);
933
934 return $x if $x->modify('bceil');
935 return $x if $x->{sign} !~ /^[+-]$/; # nan, +inf, -inf
936
937 # if $x has digits after dot
938 if ($x->{_e}->{sign} eq '-')
939 {
940 $x->{_m}->brsft(-$x->{_e},10);
941 $x->{_e}->bzero();
942 $x++ if $x->{sign} eq '+';
a0d0e21e 943 }
58cde26e 944 return $x->round($a,$p,$r);
945 }
946
947###############################################################################
a5f75d66 948
58cde26e 949sub DESTROY
950 {
951 # going trough AUTOLOAD for every DESTROY is costly, so avoid it by empty sub
952 }
953
954sub AUTOLOAD
955 {
956 # make fxxx and bxxx work
957 # my $self = $_[0];
958 my $name = $AUTOLOAD;
959
960 $name =~ s/.*:://; # split package
961 #print "$name\n";
962 if (!method_valid($name))
963 {
964 #no strict 'refs';
965 ## try one level up
966 #&{$class."::SUPER->$name"}(@_);
967 # delayed load of Carp and avoid recursion
968 require Carp;
969 Carp::croak ("Can't call $class\-\>$name, not a valid method");
a0d0e21e 970 }
58cde26e 971 no strict 'refs';
972 my $bname = $name; $bname =~ s/^f/b/;
973 *{$class."\:\:$name"} = \&$bname;
974 &$bname; # uses @_
975 }
976
977sub exponent
978 {
979 # return a copy of the exponent
980 my $self = shift;
981 $self = $class->new($self) unless ref $self;
982
983 return bnan() if $self->is_nan();
984 return $self->{_e}->copy();
985 }
986
987sub mantissa
988 {
989 # return a copy of the mantissa
990 my $self = shift;
991 $self = $class->new($self) unless ref $self;
992
993 return bnan() if $self->is_nan();
994 my $m = $self->{_m}->copy(); # faster than going via bstr()
995 $m->bneg() if $self->{sign} eq '-';
996
997 return $m;
998 }
999
1000sub parts
1001 {
1002 # return a copy of both the exponent and the mantissa
1003 my $self = shift;
1004 $self = $class->new($self) unless ref $self;
1005
1006 return (bnan(),bnan()) if $self->is_nan();
1007 my $m = $self->{_m}->copy(); # faster than going via bstr()
1008 $m->bneg() if $self->{sign} eq '-';
1009 return ($m,$self->{_e}->copy());
1010 }
1011
1012##############################################################################
1013# private stuff (internal use only)
1014
1015sub _one
1016 {
1017 # internal speedup, set argument to 1, or create a +/- 1
0716bf9b 1018 my $self = shift; $self = ref($self) if ref($self);
1019 my $x = {}; bless $x, $self;
1020 $x->{_m} = Math::BigInt->new(1);
1021 $x->{_e} = Math::BigInt->new(0);
58cde26e 1022 $x->{sign} = shift || '+';
1023 return $x;
1024 }
1025
1026sub import
1027 {
1028 my $self = shift;
1029 #print "import $self\n";
1030 for ( my $i = 0; $i < @_ ; $i++ )
1031 {
1032 if ( $_[$i] eq ':constant' )
1033 {
1034 # this rest causes overlord er load to step in
1035 # print "overload @_\n";
1036 overload::constant float => sub { $self->new(shift); };
1037 splice @_, $i, 1; last;
1038 }
1039 }
1040 # any non :constant stuff is handled by our parent, Exporter
1041 # even if @_ is empty, to give it a chance
1042 #$self->SUPER::import(@_); # does not work (would call MBI)
1043 $self->export_to_level(1,$self,@_); # need this instead
1044 }
1045
1046sub bnorm
1047 {
1048 # adjust m and e so that m is smallest possible
1049 # round number according to accuracy and precision settings
1050 my $x = shift;
1051
0716bf9b 1052 return $x if $x->{sign} !~ /^[+-]$/; # inf, nan etc
58cde26e 1053
1054 my $zeros = $x->{_m}->_trailing_zeros(); # correct for trailing zeros
1055 if ($zeros != 0)
1056 {
1057 $x->{_m}->brsft($zeros,10); $x->{_e} += $zeros;
1058 }
1059 # for something like 0Ey, set y to 1
574bacfe 1060 $x->{sign} = '+', $x->{_e}->bzero()->binc() if $x->{_m}->is_zero();
0716bf9b 1061 $x->{_m}->{_f} = MB_NEVER_ROUND;
1062 $x->{_e}->{_f} = MB_NEVER_ROUND;
1063 return $x; # MBI bnorm is no-op
58cde26e 1064 }
1065
1066##############################################################################
1067# internal calculation routines
1068
1069sub as_number
1070 {
1071 # return a bigint representation of this BigFloat number
1072 my ($self,$x) = objectify(1,@_);
1073
1074 my $z;
1075 if ($x->{_e}->is_zero())
1076 {
1077 $z = $x->{_m}->copy();
1078 $z->{sign} = $x->{sign};
1079 return $z;
1080 }
0716bf9b 1081 $z = $x->{_m}->copy();
58cde26e 1082 if ($x->{_e} < 0)
1083 {
0716bf9b 1084 $z->brsft(-$x->{_e},10);
1085 }
1086 else
1087 {
1088 $z->blsft($x->{_e},10);
58cde26e 1089 }
58cde26e 1090 $z->{sign} = $x->{sign};
1091 return $z;
1092 }
1093
1094sub length
1095 {
1096 my $x = shift; $x = $class->new($x) unless ref $x;
1097
1098 my $len = $x->{_m}->length();
1099 $len += $x->{_e} if $x->{_e}->sign() eq '+';
1100 if (wantarray())
1101 {
1102 my $t = Math::BigInt::bzero();
1103 $t = $x->{_e}->copy()->babs() if $x->{_e}->sign() eq '-';
1104 return ($len,$t);
1105 }
1106 return $len;
1107 }
a0d0e21e 1108
11091;
a5f75d66 1110__END__
1111
1112=head1 NAME
1113
58cde26e 1114Math::BigFloat - Arbitrary size floating point math package
a5f75d66 1115
1116=head1 SYNOPSIS
1117
a2008d6d 1118 use Math::BigFloat;
58cde26e 1119
1120 # Number creation
1121 $x = Math::BigInt->new($str); # defaults to 0
1122 $nan = Math::BigInt->bnan(); # create a NotANumber
1123 $zero = Math::BigInt->bzero();# create a "+0"
1124
1125 # Testing
1126 $x->is_zero(); # return whether arg is zero or not
0716bf9b 1127 $x->is_nan(); # return whether arg is NaN or not
1128 $x->is_one(); # true if arg is +1
1129 $x->is_one('-'); # true if arg is -1
1130 $x->is_odd(); # true if odd, false for even
1131 $x->is_even(); # true if even, false for odd
1132 $x->is_positive(); # true if >= 0
1133 $x->is_negative(); # true if < 0
1134 $x->is_inf(sign) # true if +inf or -inf (sign default '+')
58cde26e 1135 $x->bcmp($y); # compare numbers (undef,<0,=0,>0)
1136 $x->bacmp($y); # compare absolutely (undef,<0,=0,>0)
1137 $x->sign(); # return the sign, either +,- or NaN
1138
1139 # The following all modify their first argument:
1140
1141 # set
1142 $x->bzero(); # set $i to 0
1143 $x->bnan(); # set $i to NaN
1144
1145 $x->bneg(); # negation
1146 $x->babs(); # absolute value
1147 $x->bnorm(); # normalize (no-op)
1148 $x->bnot(); # two's complement (bit wise not)
1149 $x->binc(); # increment x by 1
1150 $x->bdec(); # decrement x by 1
1151
1152 $x->badd($y); # addition (add $y to $x)
1153 $x->bsub($y); # subtraction (subtract $y from $x)
1154 $x->bmul($y); # multiplication (multiply $x by $y)
1155 $x->bdiv($y); # divide, set $i to quotient
1156 # return (quo,rem) or quo if scalar
1157
1158 $x->bmod($y); # modulus
1159 $x->bpow($y); # power of arguments (a**b)
1160 $x->blsft($y); # left shift
1161 $x->brsft($y); # right shift
1162 # return (quo,rem) or quo if scalar
1163
1164 $x->band($y); # bit-wise and
1165 $x->bior($y); # bit-wise inclusive or
1166 $x->bxor($y); # bit-wise exclusive or
1167 $x->bnot(); # bit-wise not (two's complement)
1168
1169 $x->bround($N); # accuracy: preserver $N digits
1170 $x->bfround($N); # precision: round to the $Nth digit
1171
1172 # The following do not modify their arguments:
1173
1174 bgcd(@values); # greatest common divisor
1175 blcm(@values); # lowest common multiplicator
1176
1177 $x->bstr(); # return string
1178 $x->bsstr(); # return string in scientific notation
1179
1180 $x->exponent(); # return exponent as BigInt
1181 $x->mantissa(); # return mantissa as BigInt
1182 $x->parts(); # return (mantissa,exponent) as BigInt
1183
1184 $x->length(); # number of digits (w/o sign and '.')
1185 ($l,$f) = $x->length(); # number of digits, and length of fraction
a5f75d66 1186
1187=head1 DESCRIPTION
1188
58cde26e 1189All operators (inlcuding basic math operations) are overloaded if you
1190declare your big floating point numbers as
a5f75d66 1191
58cde26e 1192 $i = new Math::BigFloat '12_3.456_789_123_456_789E-2';
1193
1194Operations with overloaded operators preserve the arguments, which is
1195exactly what you expect.
1196
1197=head2 Canonical notation
1198
1199Input to these routines are either BigFloat objects, or strings of the
1200following four forms:
a5f75d66 1201
1202=over 2
1203
58cde26e 1204=item *
1205
1206C</^[+-]\d+$/>
a5f75d66 1207
58cde26e 1208=item *
a5f75d66 1209
58cde26e 1210C</^[+-]\d+\.\d*$/>
a5f75d66 1211
58cde26e 1212=item *
a5f75d66 1213
58cde26e 1214C</^[+-]\d+E[+-]?\d+$/>
a5f75d66 1215
58cde26e 1216=item *
a5f75d66 1217
58cde26e 1218C</^[+-]\d*\.\d+E[+-]?\d+$/>
5d7098d5 1219
58cde26e 1220=back
1221
1222all with optional leading and trailing zeros and/or spaces. Additonally,
1223numbers are allowed to have an underscore between any two digits.
1224
1225Empty strings as well as other illegal numbers results in 'NaN'.
1226
1227bnorm() on a BigFloat object is now effectively a no-op, since the numbers
1228are always stored in normalized form. On a string, it creates a BigFloat
1229object.
1230
1231=head2 Output
1232
1233Output values are BigFloat objects (normalized), except for bstr() and bsstr().
1234
1235The string output will always have leading and trailing zeros stripped and drop
1236a plus sign. C<bstr()> will give you always the form with a decimal point,
1237while C<bsstr()> (for scientific) gives you the scientific notation.
1238
1239 Input bstr() bsstr()
1240 '-0' '0' '0E1'
1241 ' -123 123 123' '-123123123' '-123123123E0'
1242 '00.0123' '0.0123' '123E-4'
1243 '123.45E-2' '1.2345' '12345E-4'
1244 '10E+3' '10000' '1E4'
1245
1246Some routines (C<is_odd()>, C<is_even()>, C<is_zero()>, C<is_one()>,
1247C<is_nan()>) return true or false, while others (C<bcmp()>, C<bacmp()>)
1248return either undef, <0, 0 or >0 and are suited for sort.
1249
1250Actual math is done by using BigInts to represent the mantissa and exponent.
1251The sign C</^[+-]$/> is stored separately. The string 'NaN' is used to
1252represent the result when input arguments are not numbers, as well as
1253the result of dividing by zero.
1254
1255=head2 C<mantissa()>, C<exponent()> and C<parts()>
1256
1257C<mantissa()> and C<exponent()> return the said parts of the BigFloat
1258as BigInts such that:
1259
1260 $m = $x->mantissa();
1261 $e = $x->exponent();
1262 $y = $m * ( 10 ** $e );
1263 print "ok\n" if $x == $y;
1264
1265C<< ($m,$e) = $x->parts(); >> is just a shortcut giving you both of them.
1266
1267A zero is represented and returned as C<0E1>, B<not> C<0E0> (after Knuth).
1268
1269Currently the mantissa is reduced as much as possible, favouring higher
1270exponents over lower ones (e.g. returning 1e7 instead of 10e6 or 10000000e0).
1271This might change in the future, so do not depend on it.
1272
1273=head2 Accuracy vs. Precision
1274
1275See also: L<Rounding|Rounding>.
1276
1277Math::BigFloat supports both precision and accuracy. (here should follow
1278a short description of both).
5d7098d5 1279
58cde26e 1280Precision: digits after the '.', laber, schwad
1281Accuracy: Significant digits blah blah
5d7098d5 1282
58cde26e 1283Since things like sqrt(2) or 1/3 must presented with a limited precision lest
1284a operation consumes all resources, each operation produces no more than
1285C<Math::BigFloat::precision()> digits.
1286
1287In case the result of one operation has more precision than specified,
1288it is rounded. The rounding mode taken is either the default mode, or the one
1289supplied to the operation after the I<scale>:
1290
1291 $x = Math::BigFloat->new(2);
1292 Math::BigFloat::precision(5); # 5 digits max
1293 $y = $x->copy()->bdiv(3); # will give 0.66666
1294 $y = $x->copy()->bdiv(3,6); # will give 0.666666
1295 $y = $x->copy()->bdiv(3,6,'odd'); # will give 0.666667
1296 Math::BigFloat::round_mode('zero');
1297 $y = $x->copy()->bdiv(3,6); # will give 0.666666
1298
1299=head2 Rounding
1300
1301=over 2
1302
5dc6f178 1303=item ffround ( +$scale )
58cde26e 1304
0716bf9b 1305Rounds to the $scale'th place left from the '.', counting from the dot.
1306The first digit is numbered 1.
58cde26e 1307
5dc6f178 1308=item ffround ( -$scale )
58cde26e 1309
0716bf9b 1310Rounds to the $scale'th place right from the '.', counting from the dot.
58cde26e 1311
5dc6f178 1312=item ffround ( 0 )
1313
0716bf9b 1314Rounds to an integer.
5dc6f178 1315
1316=item fround ( +$scale )
1317
0716bf9b 1318Preserves accuracy to $scale digits from the left (aka significant digits)
1319and pads the rest with zeros. If the number is between 1 and -1, the
1320significant digits count from the first non-zero after the '.'
5dc6f178 1321
1322=item fround ( -$scale ) and fround ( 0 )
1323
0716bf9b 1324These are effetively no-ops.
5d7098d5 1325
a5f75d66 1326=back
1327
0716bf9b 1328All rounding functions take as a second parameter a rounding mode from one of
1329the following: 'even', 'odd', '+inf', '-inf', 'zero' or 'trunc'.
58cde26e 1330
1331The default rounding mode is 'even'. By using
0716bf9b 1332C<< Math::BigFloat::round_mode($rnd_mode); >> you can get and set the default
1333mode for subsequent rounding. The usage of C<$Math::BigFloat::$rnd_mode> is
1334no longer supported.
b22b3e31 1335The second parameter to the round functions then overrides the default
0716bf9b 1336temporarily.
58cde26e 1337
1338The C<< as_number() >> function returns a BigInt from a Math::BigFloat. It uses
1339'trunc' as rounding mode to make it equivalent to:
1340
1341 $x = 2.5;
1342 $y = int($x) + 2;
1343
1344You can override this by passing the desired rounding mode as parameter to
1345C<as_number()>:
1346
1347 $x = Math::BigFloat->new(2.5);
1348 $y = $x->as_number('odd'); # $y = 3
1349
1350=head1 EXAMPLES
1351
58cde26e 1352 # not ready yet
58cde26e 1353
1354=head1 Autocreating constants
1355
1356After C<use Math::BigFloat ':constant'> all the floating point constants
1357in the given scope are converted to C<Math::BigFloat>. This conversion
1358happens at compile time.
1359
1360In particular
1361
1362 perl -MMath::BigFloat=:constant -e 'print 2E-100,"\n"'
1363
1364prints the value of C<2E-100>. Note that without conversion of
1365constants the expression 2E-100 will be calculated as normal floating point
1366number.
1367
a5f75d66 1368=head1 BUGS
1369
58cde26e 1370=over 2
1371
1372=item *
1373
1374The following does not work yet:
1375
1376 $m = $x->mantissa();
1377 $e = $x->exponent();
1378 $y = $m * ( 10 ** $e );
1379 print "ok\n" if $x == $y;
1380
1381=item *
1382
1383There is no fmod() function yet.
1384
1385=back
1386
1387=head1 CAVEAT
1388
1389=over 1
1390
1391=item stringify, bstr()
1392
1393Both stringify and bstr() now drop the leading '+'. The old code would return
1394'+1.23', the new returns '1.23'. See the documentation in L<Math::BigInt> for
1395reasoning and details.
1396
1397=item bdiv
1398
1399The following will probably not do what you expect:
1400
1401 print $c->bdiv(123.456),"\n";
1402
1403It prints both quotient and reminder since print works in list context. Also,
1404bdiv() will modify $c, so be carefull. You probably want to use
1405
1406 print $c / 123.456,"\n";
1407 print scalar $c->bdiv(123.456),"\n"; # or if you want to modify $c
1408
1409instead.
1410
1411=item Modifying and =
1412
1413Beware of:
1414
1415 $x = Math::BigFloat->new(5);
1416 $y = $x;
1417
1418It will not do what you think, e.g. making a copy of $x. Instead it just makes
1419a second reference to the B<same> object and stores it in $y. Thus anything
1420that modifies $x will modify $y, and vice versa.
1421
1422 $x->bmul(2);
1423 print "$x, $y\n"; # prints '10, 10'
1424
1425If you want a true copy of $x, use:
1426
1427 $y = $x->copy();
1428
1429See also the documentation in L<overload> regarding C<=>.
1430
1431=item bpow
1432
1433C<bpow()> now modifies the first argument, unlike the old code which left
1434it alone and only returned the result. This is to be consistent with
1435C<badd()> etc. The first will modify $x, the second one won't:
1436
1437 print bpow($x,$i),"\n"; # modify $x
1438 print $x->bpow($i),"\n"; # ditto
1439 print $x ** $i,"\n"; # leave $x alone
1440
1441=back
1442
1443=head1 LICENSE
a5f75d66 1444
58cde26e 1445This program is free software; you may redistribute it and/or modify it under
1446the same terms as Perl itself.
5d7098d5 1447
58cde26e 1448=head1 AUTHORS
5d7098d5 1449
58cde26e 1450Mark Biggar, overloaded interface by Ilya Zakharevich.
1451Completely rewritten by Tels http://bloodgate.com in 2001.
a5f75d66 1452
a5f75d66 1453=cut