b7120ccf84fe05452b356dc189e018994590ddd1
[p5sagit/p5-mst-13.2.git] / lib / Math / BigFloat.pm
1 package Math::BigFloat;
2
3
4 # Mike grinned. 'Two down, infinity to go' - Mike Nostrus in Before and After
5 #
6
7 # The following hash values are internally used:
8 #   _e: exponent (BigInt)
9 #   _m: mantissa (absolute BigInt)
10 # sign: +,-,"NaN" if not a number
11 #   _a: accuracy
12 #   _p: precision
13 #   _f: flags, used to signal MBI not to touch our private parts
14
15 $VERSION = '1.30';
16 require 5.005;
17 use Exporter;
18 use Math::BigInt qw/objectify/;
19 @ISA =       qw( Exporter Math::BigInt);
20
21 use strict;
22 use vars qw/$AUTOLOAD $accuracy $precision $div_scale $round_mode $rnd_mode/;
23 use vars qw/$upgrade $downgrade/;
24 my $class = "Math::BigFloat";
25
26 use overload
27 '<=>'   =>      sub { $_[2] ?
28                       ref($_[0])->bcmp($_[1],$_[0]) : 
29                       ref($_[0])->bcmp($_[0],$_[1])},
30 'int'   =>      sub { $_[0]->as_number() },             # 'trunc' to bigint
31 ;
32
33 ##############################################################################
34 # global constants, flags and accessory
35
36 use constant MB_NEVER_ROUND => 0x0001;
37
38 # are NaNs ok?
39 my $NaNOK=1;
40 # constant for easier life
41 my $nan = 'NaN'; 
42
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;
48
49 $upgrade = undef;
50 $downgrade = undef;
51
52 ##############################################################################
53 # the old code had $rnd_mode, so we need to support it, too
54
55 $rnd_mode   = 'even';
56 sub TIESCALAR   { my ($class) = @_; bless \$round_mode, $class; }
57 sub FETCH       { return $round_mode; }
58 sub STORE       { $rnd_mode = $_[0]->round_mode($_[1]); }
59
60 BEGIN { tie $rnd_mode, 'Math::BigFloat'; }
61  
62 ##############################################################################
63
64 # in case we call SUPER::->foo() and this wants to call modify()
65 # sub modify () { 0; }
66
67 {
68   # valid method aliases for AUTOLOAD
69   my %methods = map { $_ => 1 }  
70    qw / fadd fsub fmul fdiv fround ffround fsqrt fmod fstr fsstr fpow fnorm
71         fint facmp fcmp fzero fnan finf finc fdec flog ffac
72         fceil ffloor frsft flsft fone flog
73       /;
74   # valid method's that can be hand-ed up (for AUTOLOAD)
75   my %hand_ups = map { $_ => 1 }  
76    qw / is_nan is_inf is_negative is_positive
77         accuracy precision div_scale round_mode fneg fabs babs fnot
78         objectify upgrade downgrade
79         bone binf bnan bzero
80       /;
81
82   sub method_alias { return exists $methods{$_[0]||''}; } 
83   sub method_hand_up { return exists $hand_ups{$_[0]||''}; } 
84 }
85
86 ##############################################################################
87 # constructors
88
89 sub 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"
95
96   my ($class,$wanted,@r) = @_;
97
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');
101
102   my $self = {}; bless $self, $class;
103   # shortcut for bigints and its subclasses
104   if ((ref($wanted)) && (ref($wanted) ne $class))
105     {
106     $self->{_m} = $wanted->as_number();         # get us a bigint copy
107     $self->{_e} = Math::BigInt->bzero();
108     $self->{_m}->babs();
109     $self->{sign} = $wanted->sign();
110     return $self->bnorm();
111     }
112   # got string
113   # handle '+inf', '-inf' first
114   if ($wanted =~ /^[+-]?inf$/)
115     {
116     return $downgrade->new($wanted) if $downgrade;
117
118     $self->{_e} = Math::BigInt->bzero();
119     $self->{_m} = Math::BigInt->bzero();
120     $self->{sign} = $wanted;
121     $self->{sign} = '+inf' if $self->{sign} eq 'inf';
122     return $self->bnorm();
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;
129     
130     return $downgrade->bnan() if $downgrade;
131     
132     $self->{_e} = Math::BigInt->bzero();
133     $self->{_m} = Math::BigInt->bzero();
134     $self->{sign} = $nan;
135     }
136   else
137     {
138     # make integer from mantissa by adjusting exp, then convert to bigint
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.
142     # 3.123E0 = 3123E-3, and 3.123E-2 => 3123E-5
143     $self->{_e} -= CORE::length($$mfv) if CORE::length($$mfv) != 0;             
144     $self->{sign} = $$mis;
145     }
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
159   # print "mbf new $self->{sign} $self->{_m} e $self->{_e}\n";
160   $self->bnorm()->round(@r);            # first normalize, then round
161   }
162
163 sub _bnan
164   {
165   # used by parent class bone() to initialize number to 1
166   my $self = shift;
167   $self->{_m} = Math::BigInt->bzero();
168   $self->{_e} = Math::BigInt->bzero();
169   }
170
171 sub _binf
172   {
173   # used by parent class bone() to initialize number to 1
174   my $self = shift;
175   $self->{_m} = Math::BigInt->bzero();
176   $self->{_e} = Math::BigInt->bzero();
177   }
178
179 sub _bone
180   {
181   # used by parent class bone() to initialize number to 1
182   my $self = shift;
183   $self->{_m} = Math::BigInt->bone();
184   $self->{_e} = Math::BigInt->bzero();
185   }
186
187 sub _bzero
188   {
189   # used by parent class bone() to initialize number to 1
190   my $self = shift;
191   $self->{_m} = Math::BigInt->bzero();
192   $self->{_e} = Math::BigInt->bone();
193   }
194
195 ##############################################################################
196 # string conversation
197
198 sub 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")
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);
206
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} !~ /^[+-]$/)
210     {
211     return $x->{sign} unless $x->{sign} eq '+inf';      # -inf, NaN
212     return 'inf';                                       # +inf
213     }
214  
215   my $es = '0'; my $len = 1; my $cad = 0; my $dot = '.';
216
217   my $not_zero = ! $x->is_zero();
218   if ($not_zero)
219     {
220     $es = $x->{_m}->bstr();
221     $len = CORE::length($es);
222     if (!$x->{_e}->is_zero())
223       {
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         }
244       }
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;
253     $es .= $dot.'0' x $zeros if $zeros > 0;
254     }
255   elsif ($x->{_p} || 0 < 0)
256     {
257     # 123400 => 6, 0.1234 => 4, 0.001234 => 6
258     my $zeros = -$x->{_p} + $cad;
259     $es .= $dot.'0' x $zeros if $zeros > 0;
260     }
261   return $es;
262   }
263
264 sub 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")
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);
272
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     }
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     
285 sub numify 
286   {
287   # Make a number from a BigFloat object
288   # simple return string and let Perl's atoi()/atof() handle the rest
289   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
290   return $x->bsstr(); 
291   }
292
293 ##############################################################################
294 # public stuff (usually prefixed with "b")
295
296 # tels 2001-08-04 
297 # todo: this must be overwritten and return NaN for non-integer values
298 # band(), bior(), bxor(), too
299 #sub bnot
300 #  {
301 #  $class->SUPER::bnot($class,@_);
302 #  }
303
304 sub 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,@_);
309
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';
318     return +1;
319     }
320
321   # check sign for speed first
322   return 1 if $x->{sign} eq '+' && $y->{sign} eq '-';   # does also 0 <=> -y
323   return -1 if $x->{sign} eq '-' && $y->{sign} eq '+';  # does also -x <=> 0
324
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
331
332   # adjust so that exponents are equal
333   my $lxm = $x->{_m}->length();
334   my $lym = $y->{_m}->length();
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 '-';
339   return $l <=> 0 if $l != 0;
340   
341   # lengths (corrected by exponent) are equal
342   # so make mantissa equal length by padding with zero (shift left)
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     }
354   my $rc = $xm->bacmp($ym);
355   $rc = -$rc if $x->{sign} eq '-';              # -124 < -123
356   $rc <=> 0;
357   }
358
359 sub 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,@_);
365
366   # handle +-inf and NaN's
367   if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/)
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());
372     return -1;
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();
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();
388   my $l = $lx - $ly;
389   return $l <=> 0 if $l != 0;
390   
391   # lengths (corrected by exponent) are equal
392   # so make mantissa equal-length by padding with zero (shift left)
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     }
404   $xm->bacmp($ym) <=> 0;
405   }
406
407 sub badd 
408   {
409   # add second arg (BFLOAT or string) to first (BFLOAT) (modifies first)
410   # return result as BFLOAT
411   my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
412
413   #print "mbf badd $x $y\n";
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));
419     # inf handling
420     if (($x->{sign} =~ /^[+-]inf$/) && ($y->{sign} =~ /^[+-]inf$/))
421       {
422       # +inf++inf or -inf+-inf => same, rest is NaN
423       return $x if $x->{sign} eq $y->{sign};
424       return $x->bnan();
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
432   # speed: no add for 0+y or x+0
433   return $x->bround($a,$p,$r) if $y->is_zero();         # x+0
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);
441     }
442  
443   # take lower of the two e's and adapt m1 to it to match m2
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});
448   my $add = $y->{_m}->copy();
449 #  if ($e < 0)                          # < 0
450   if ($e->{sign} eq '-')                # < 0
451     {
452     my $e1 = $e->copy()->babs();
453     #$x->{_m} *= (10 ** $e1);
454     $x->{_m}->blsft($e1,10);
455     $x->{_e} += $e;                     # need the sign of e
456     }
457 #  if ($e > 0)                          # > 0
458   elsif (!$e->is_zero())                # > 0
459     {
460     #$add *= (10 ** $e);
461     $add->blsft($e,10);
462     }
463   # else: both e are the same, so just leave them
464   $x->{_m}->{sign} = $x->{sign};                # fiddle with signs
465   $add->{sign} = $y->{sign};
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);
471   }
472
473 sub bsub 
474   {
475   # (BigFloat or num_str, BigFloat or num_str) return BigFloat
476   # subtract second arg from first, modify first
477   my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
478
479   if ($y->is_zero())            # still round for not adding zero
480     {
481     return $x->round($a,$p,$r);
482     }
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)
487   $x;                           # already rounded by badd()
488   }
489
490 sub binc
491   {
492   # increment arg by one
493   my ($self,$x,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
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 
519   }
520
521 sub bdec
522   {
523   # decrement arg by one
524   my ($self,$x,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
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 
554   } 
555
556 sub blog
557   {
558   my ($self,$x,$base,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(2,@_);
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
566   #             |_   v    3   v^3   5   v^5      _|
567
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);
572
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     }
588
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;
592
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);
614   my $factor = $self->new(3); my $two = $self->new(2);
615
616   my $diff = $self->bone();
617   my $limit = $self->new("1E-". ($scale-1)); my $last;
618   # print "diff $diff limit $limit\n";
619   while ($diff->bcmp($limit) > 0)
620     {
621     #print "$x $over $below $factor\n";
622     $diff = $x->copy()->bsub($last)->babs();
623     #print "diff $diff $limit\n";
624     $last = $x->copy();
625     $x += $over->copy()->bdiv($below->copy()->bmul($factor),$scale);
626     $over *= $u; $below *= $v; $factor->badd($two);
627     }
628   $x->bmul($two);
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;
648   }
649
650 sub blcm 
651   { 
652   # (BFLOAT or num_str, BFLOAT or num_str) return BFLOAT
653   # does not modify arguments, but returns new object
654   # Lowest Common Multiplicator
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
662 sub bgcd 
663   { 
664   # (BFLOAT or num_str, BFLOAT or num_str) return BINT
665   # does not modify arguments, but returns new object
666   # GCD -- Euclids algorithm Knuth Vol 2 pg 296
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
674 ###############################################################################
675 # is_foo methods (is_negative, is_positive are inherited from BigInt)
676
677 sub 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
687 sub is_zero
688   {
689   # return true if arg (BFLOAT or num_str) is zero
690   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
691
692   return 1 if $x->{sign} eq '+' && $x->{_m}->is_zero();
693   0;
694   }
695
696 sub is_one
697   {
698   # return true if arg (BFLOAT or num_str) is +1 or -1 if signis given
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()); 
704   0;
705   }
706
707 sub is_odd
708   {
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,@_);
711   
712   return 1 if ($x->{sign} =~ /^[+-]$/) &&               # NaN & +-inf aren't
713     ($x->{_e}->is_zero() && $x->{_m}->is_odd()); 
714   0;
715   }
716
717 sub is_even
718   {
719   # return true if arg (BINT or num_str) is even or false if odd
720   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
721
722   return 0 if $x->{sign} !~ /^[+-]$/;                   # NaN & +-inf aren't
723   return 1 if ($x->{_e}->{sign} eq '+'                  # 123.45 is never
724      && $x->{_m}->is_even());                           # but 1200 is
725   0;
726   }
727
728 sub 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,@_);
733
734   return $x->bnan() if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
735
736   # inf handling
737   if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/))
738     {
739     return $x->bnan() if $x->is_zero() || $y->is_zero(); 
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     }
747   # handle result = 0
748   return $x->bzero() if $x->is_zero() || $y->is_zero();
749
750   # aEb * cEd = (a*c)E(b+d)
751   $x->{_m}->bmul($y->{_m});
752   $x->{_e}->badd($y->{_e});
753   # adjust sign:
754   $x->{sign} = $x->{sign} ne $y->{sign} ? '-' : '+';
755   return $x->bnorm()->round($a,$p,$r,$y);
756   }
757
758 sub 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
764   return $self->_div_inf($x,$y)
765    if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
766
767   # x== 0 # also: or y == 1 or y == -1
768   return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
769
770   # upgrade 
771   return $upgrade->bdiv($x,$y,$a,$p,$r) if defined $upgrade;
772
773   # we need to limit the accuracy to protect against overflow
774   my $fallback = 0;
775   my $scale = 0;
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)
780     {
781     # simulate old behaviour
782     $params[1] = $self->div_scale();    # and round to it as accuracy
783     $scale = $params[1]+4;              # at least four more for proper round
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
792     }
793   my $lx = $x->{_m}->length(); my $ly = $y->{_m}->length();
794   $scale = $lx if $lx > $scale;
795   $scale = $ly if $ly > $scale;
796   my $diff = $ly - $lx;
797   $scale += $diff if $diff > 0;         # if lx << ly, but not if ly << lx!
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     }
805
806   $x->{sign} = $x->{sign} ne $y->sign() ? '-' : '+'; 
807
808   # check for / +-1 ( +/- 1E0)
809   if (!$y->is_one())
810     {
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
821     }
822
823   # shortcut to not run trough _find_round_parameters again
824   if (defined $params[1])
825     {
826     $x->bround($params[1],$params[3]);          # then round accordingly
827     }
828   else
829     {
830     $x->bfround($params[2],$params[3]);         # then round accordingly
831     }
832   if ($fallback)
833     {
834     # clear a/p after round, since user did not request it
835     $x->{_a} = undef; $x->{_p} = undef;
836     }
837   
838   if (wantarray)
839     {
840     if (!$y->is_one())
841       {
842       $rem->bmod($y,$params[1],$params[2],$params[3]);  # copy already done
843       }
844     else
845       {
846       $rem = $self->bzero();
847       }
848     if ($fallback)
849       {
850       # clear a/p after round, since user did not request it
851       $rem->{_a} = undef; $rem->{_p} = undef;
852       }
853     return ($x,$rem);
854     }
855   return $x;
856   }
857
858 sub 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,@_);
862
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();
872
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
898
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
917 #  $ym->{sign} = '-' if $neg; # bmod() will make the correction for us
918
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
934   }
935
936 sub bsqrt
937   { 
938   # calculate square root; this should probably
939   # use a different test to see whether the accuracy we want is...
940   my ($self,$x,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
941
942   return $x->bnan() if $x->{sign} eq 'NaN' || $x->{sign} =~ /^-/; # <0, NaN
943   return $x if $x->{sign} eq '+inf';                              # +inf
944   return $x if $x->is_zero() || $x->is_one();
945
946   # we need to limit the accuracy to protect against overflow
947   my $fallback = 0;
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)
953     {
954     # simulate old behaviour
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
958     $fallback = 1;                      # to clear a/p afterwards
959     }
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;
971   my $pbr = "$self\::precision"; my $pb = $$pbr; $$pbr = undef;
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};
975   # need to disable $upgrade in BigInt, to aoid deep recursion
976   local $Math::BigInt::upgrade = undef;
977
978   my $xas = $x->as_number();
979   my $gs = $xas->copy()->bsqrt();       # some guess
980
981   if (($x->{_e}->{sign} ne '-')         # guess can't be accurate if there are
982                                         # digits after the dot
983    && ($xas->bacmp($gs * $gs) == 0))    # guess hit the nail on the head?
984     {
985     # exact result
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       }
1001     ${"$self\::accuracy"} = $ab; ${"$self\::precision"} = $pb;
1002     return $x;
1003     }
1004   $gs = $self->new( $gs );              # BigInt to BigFloat
1005
1006   my $lx = $x->{_m}->length();
1007   $scale = $lx if $scale < $lx;
1008   my $e = $self->new("1E-$scale");      # make test variable
1009 #  return $x->bnan() if $e->sign() eq 'NaN';
1010
1011   my $y = $x->copy();
1012   my $two = $self->new(2);
1013   my $diff = $e;
1014   # promote BigInts and it's subclasses (except when already a BigFloat)
1015   $y = $self->new($y) unless $y->isa('Math::BigFloat'); 
1016
1017   my $rem;
1018   while ($diff >= $e)
1019     {
1020     $rem = $y->copy()->bdiv($gs,$scale)->badd($gs)->bdiv($two,$scale);
1021     $diff = $rem->copy()->bsub($gs)->babs();
1022     $gs = $rem->copy();
1023     }
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     }
1036   if ($fallback)
1037     {
1038     # clear a/p after round, since user did not request it
1039     $x->{_a} = undef; $x->{_p} = undef;
1040     }
1041   # restore globals
1042   $$abr = $ab; $$pbr = $pb;
1043   $x;
1044   }
1045
1046 sub bfac
1047   {
1048   # (BFLOAT or num_str, BFLOAT or num_str) return BFLOAT
1049   # compute factorial numbers
1050   # modifies first argument
1051   my ($self,$x,@r) = objectify(1,@_);
1052
1053   return $x->bnan() 
1054     if (($x->{sign} ne '+') ||          # inf, NaN, <0 etc => NaN
1055      ($x->{_e}->{sign} ne '+'));        # digits after dot?
1056
1057   return $x->bone(@r) if $x->is_zero() || $x->is_one();         # 0 or 1 => 1
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
1063   $x->bnorm()->round(@r);
1064   }
1065
1066 sub 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
1074   return $x if $x->{sign} =~ /^[+-]inf$/;
1075   return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;
1076   return $x->bone() if $y->is_zero();
1077   return $x         if $x->is_one() || $y->is_one();
1078   my $y1 = $y->as_number();             # make bigint (trunc)
1079   # if ($x == -1)
1080   if ($x->{sign} eq '-' && $x->{_m}->is_one() && $x->{_e}->is_zero())
1081     {
1082     # if $x == -1 and odd/even y => +1/-1  because +-1 ^ (+-1) => +-1
1083     return $y1->is_odd() ? $x : $x->babs(1);
1084     }
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     }
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!
1101     my $z = $x->copy(); $x->bzero()->binc();
1102     return $x->bdiv($z,$a,$p,$r);       # round in one go (might ignore y's A!)
1103     }
1104   $x->round($a,$p,$r,$y);
1105   }
1106
1107 ###############################################################################
1108 # rounding functions
1109
1110 sub 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!
1115   my $x = shift; my $self = ref($x) || $x; $x = $self->new(shift) if !ref($x);
1116
1117   return $x if $x->modify('bfround');
1118   
1119   my ($scale,$mode) = $x->_scale_p($self->precision(),$self->round_mode(),@_);
1120   return $x if !defined $scale;                 # no-op
1121
1122   # never round a 0, +-inf, NaN
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} !~ /^[+-]$/;
1129   # print "MBF bfround $x to scale $scale mode $mode\n";
1130
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
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
1146     #print "scale $scale dad $dad zad $zad len $len\n";
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
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
1162       {
1163       $scale = -$len;
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";
1179     }
1180   else
1181     {
1182     # 123 => 100 means length(123) = 3 - $scale (2) => 1
1183
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        } 
1204     else
1205        { 
1206        $scale = $dbd - $scale; 
1207        }
1208
1209     }
1210   # print "using $scale for $x->{_m} with '$mode'\n";
1211   # pass sign to bround for rounding modes '+inf' and '-inf'
1212   $x->{_m}->{sign} = $x->{sign};
1213   $x->{_m}->bround($scale,$mode);
1214   $x->{_m}->{sign} = '+';               # fix sign back
1215   $x->bnorm();
1216   }
1217
1218 sub bround
1219   {
1220   # accuracy: preserve $N digits, and overwrite the rest with 0's
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;
1224
1225   my ($scale,$mode) = $x->_scale_a($self->accuracy(),$self->round_mode(),@_);
1226   return $x if !defined $scale;                         # no-op
1227
1228   return $x if $x->modify('bround');
1229
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];
1235
1236   # scale < 0 makes no sense
1237   # never round a +-inf, NaN
1238   return $x if ($scale < 0) ||  $x->{sign} !~ /^[+-]$/;
1239
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     }
1248
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
1253   # $x->{_m}->{_a} = undef; $x->{_m}->{_p} = undef;
1254   $x->{_a} = $scale;                    # remember rounding
1255   $x->{_p} = undef;                     # and clear P
1256   $x->bnorm();                          # del trailing zeros gen. by bround()
1257   }
1258
1259 sub bfloor
1260   {
1261   # return integer less or equal then $x
1262   my ($self,$x,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
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     {
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
1279     }
1280   $x->round($a,$p,$r);
1281   }
1282
1283 sub bceil
1284   {
1285   # return integer greater or equal then $x
1286   my ($self,$x,$a,$p,$r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
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     {
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
1302     }
1303   $x->round($a,$p,$r);
1304   }
1305
1306 sub 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
1318 sub 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
1330 ###############################################################################
1331
1332 sub DESTROY
1333   {
1334   # going through AUTOLOAD for every DESTROY is costly, so avoid it by empty sub
1335   }
1336
1337 sub AUTOLOAD
1338   {
1339   # make fxxx and bxxx both work by selectively mapping fxxx() to MBF::bxxx()
1340   # or falling back to MBI::bxxx()
1341   my $name = $AUTOLOAD;
1342
1343   $name =~ s/.*:://;    # split package
1344   no strict 'refs';
1345   if (!method_alias($name))
1346     {
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       }
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"}(@_);
1362     }
1363   my $bname = $name; $bname =~ s/^f/b/;
1364   *{$class."::$name"} = \&$bname;
1365   &$bname;      # uses @_
1366   }
1367
1368 sub exponent
1369   {
1370   # return a copy of the exponent
1371   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
1372
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();
1379   }
1380
1381 sub mantissa
1382   {
1383   # return a copy of the mantissa
1384   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
1385  
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 '-';
1393
1394   $m;
1395   }
1396
1397 sub parts
1398   {
1399   # return a copy of both the exponent and the mantissa
1400   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
1401
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());
1410   }
1411
1412 ##############################################################################
1413 # private stuff (internal use only)
1414
1415 sub import
1416   {
1417   my $self = shift;
1418   my $l = scalar @_; my $j = 0; my @a = @_;
1419   for ( my $i = 0; $i < $l ; $i++, $j++)
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); }; 
1426       splice @a, $j, 1; $j--;
1427       }
1428     elsif ($_[$i] eq 'upgrade')
1429       {
1430       # this causes upgrading
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
1439       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
1440       splice @a, $j, $s; $j -= $s;
1441       }
1442     }
1443   # any non :constant stuff is handled by our parent, Exporter
1444   # even if @_ is empty, to give it a chance
1445   $self->SUPER::import(@a);             # for subclasses
1446   $self->export_to_level(1,$self,@a);   # need this, too
1447   }
1448
1449 sub bnorm
1450   {
1451   # adjust m and e so that m is smallest possible
1452   # round number according to accuracy and precision settings
1453   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
1454
1455   return $x if $x->{sign} !~ /^[+-]$/;          # inf, nan etc
1456
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 #    }
1467   # this is to prevent automatically rounding when MBI's globals are set
1468   $x->{_m}->{_f} = MB_NEVER_ROUND;
1469   $x->{_e}->{_f} = MB_NEVER_ROUND;
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;
1473   $x;                                   # MBI bnorm is no-op, so dont call it
1474   } 
1475  
1476 ##############################################################################
1477 # internal calculation routines
1478
1479 sub as_number
1480   {
1481   # return copy as a bigint representation of this BigFloat number
1482   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
1483
1484   my $z = $x->{_m}->copy();
1485   if ($x->{_e}->{sign} eq '-')          # < 0
1486     {
1487     $x->{_e}->{sign} = '+';             # flip
1488     $z->brsft($x->{_e},10);
1489     $x->{_e}->{sign} = '-';             # flip back
1490     } 
1491   elsif (!$x->{_e}->is_zero())          # > 0 
1492     {
1493     $z->blsft($x->{_e},10);
1494     }
1495   $z->{sign} = $x->{sign};
1496   $z;
1497   }
1498
1499 sub length
1500   {
1501   my $x = shift;
1502   my $class = ref($x) || $x;
1503   $x = $class->new(shift) unless ref($x);
1504
1505   return 1 if $x->{_m}->is_zero();
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     }
1514   $len;
1515   }
1516
1517 1;
1518 __END__
1519
1520 =head1 NAME
1521
1522 Math::BigFloat - Arbitrary size floating point math package
1523
1524 =head1 SYNOPSIS
1525
1526   use Math::BigFloat;
1527
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
1536
1537   # Testing
1538   $x->is_zero();                # true if arg is +0
1539   $x->is_nan();                 # true if arg is NaN
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
1546   $x->is_inf(sign);             # true if +inf, or -inf (default is '+')
1547
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
1551   $x->digit($n);                # return the nth digit, counting from right
1552   $x->digit(-$n);               # return the nth digit, counting from left 
1553
1554   # The following all modify their first argument:
1555   
1556   # set 
1557   $x->bzero();                  # set $i to 0
1558   $x->bnan();                   # set $i to NaN
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
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   
1583   $x->blog($base);              # logarithm of $x, base defaults to e
1584                                 # (other bases than e not supported yet)
1585   
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)
1590  
1591   $x->bsqrt();                  # calculate square-root
1592   $x->bfac();                   # factorial of $x (1*2*3*4*..$x)
1593  
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:
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
1603  
1604   $x->bfloor();                 # return integer less or equal than $x
1605   $x->bceil();                  # return integer greater or equal than $x
1606  
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      
1613
1614 =head1 DESCRIPTION
1615
1616 All operators (inlcuding basic math operations) are overloaded if you
1617 declare your big floating point numbers as
1618
1619   $i = new Math::BigFloat '12_3.456_789_123_456_789E-2';
1620
1621 Operations with overloaded operators preserve the arguments, which is
1622 exactly what you expect.
1623
1624 =head2 Canonical notation
1625
1626 Input to these routines are either BigFloat objects, or strings of the
1627 following four forms:
1628
1629 =over 2
1630
1631 =item *
1632
1633 C</^[+-]\d+$/>
1634
1635 =item *
1636
1637 C</^[+-]\d+\.\d*$/>
1638
1639 =item *
1640
1641 C</^[+-]\d+E[+-]?\d+$/>
1642
1643 =item *
1644
1645 C</^[+-]\d*\.\d+E[+-]?\d+$/>
1646
1647 =back
1648
1649 all with optional leading and trailing zeros and/or spaces. Additonally,
1650 numbers are allowed to have an underscore between any two digits.
1651
1652 Empty strings as well as other illegal numbers results in 'NaN'.
1653
1654 bnorm() on a BigFloat object is now effectively a no-op, since the numbers 
1655 are always stored in normalized form. On a string, it creates a BigFloat 
1656 object.
1657
1658 =head2 Output
1659
1660 Output values are BigFloat objects (normalized), except for bstr() and bsstr().
1661
1662 The string output will always have leading and trailing zeros stripped and drop
1663 a plus sign. C<bstr()> will give you always the form with a decimal point,
1664 while 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
1673 Some routines (C<is_odd()>, C<is_even()>, C<is_zero()>, C<is_one()>,
1674 C<is_nan()>) return true or false, while others (C<bcmp()>, C<bacmp()>)
1675 return either undef, <0, 0 or >0 and are suited for sort.
1676
1677 Actual math is done by using BigInts to represent the mantissa and exponent.
1678 The sign C</^[+-]$/> is stored separately. The string 'NaN' is used to 
1679 represent the result when input arguments are not numbers, as well as 
1680 the result of dividing by zero.
1681
1682 =head2 C<mantissa()>, C<exponent()> and C<parts()>
1683
1684 C<mantissa()> and C<exponent()> return the said parts of the BigFloat 
1685 as 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
1692 C<< ($m,$e) = $x->parts(); >> is just a shortcut giving you both of them.
1693
1694 A zero is represented and returned as C<0E1>, B<not> C<0E0> (after Knuth).
1695
1696 Currently the mantissa is reduced as much as possible, favouring higher
1697 exponents over lower ones (e.g. returning 1e7 instead of 10e6 or 10000000e0).
1698 This might change in the future, so do not depend on it.
1699
1700 =head2 Accuracy vs. Precision
1701
1702 See also: L<Rounding|Rounding>.
1703
1704 Math::BigFloat supports both precision and accuracy. For a full documentation,
1705 examples and tips on these topics please see the large section in
1706 L<Math::BigInt>.
1707
1708 Since things like sqrt(2) or 1/3 must presented with a limited precision lest
1709 a operation consumes all resources, each operation produces no more than
1710 C<Math::BigFloat::precision()> digits.
1711
1712 In case the result of one operation has more precision than specified,
1713 it is rounded. The rounding mode taken is either the default mode, or the one
1714 supplied 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
1728 =item ffround ( +$scale )
1729
1730 Rounds to the $scale'th place left from the '.', counting from the dot.
1731 The first digit is numbered 1. 
1732
1733 =item ffround ( -$scale )
1734
1735 Rounds to the $scale'th place right from the '.', counting from the dot.
1736
1737 =item ffround ( 0 )
1738
1739 Rounds to an integer.
1740
1741 =item fround  ( +$scale )
1742
1743 Preserves accuracy to $scale digits from the left (aka significant digits)
1744 and pads the rest with zeros. If the number is between 1 and -1, the
1745 significant digits count from the first non-zero after the '.'
1746
1747 =item fround  ( -$scale ) and fround ( 0 )
1748
1749 These are effetively no-ops.
1750
1751 =back
1752
1753 All rounding functions take as a second parameter a rounding mode from one of
1754 the following: 'even', 'odd', '+inf', '-inf', 'zero' or 'trunc'.
1755
1756 The default rounding mode is 'even'. By using
1757 C<< Math::BigFloat::round_mode($round_mode); >> you can get and set the default
1758 mode for subsequent rounding. The usage of C<$Math::BigFloat::$round_mode> is
1759 no longer supported.
1760 The second parameter to the round functions then overrides the default
1761 temporarily. 
1762
1763 The 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
1769 You can override this by passing the desired rounding mode as parameter to
1770 C<as_number()>:
1771
1772         $x = Math::BigFloat->new(2.5);
1773         $y = $x->as_number('odd');      # $y = 3
1774
1775 =head1 EXAMPLES
1776  
1777   # not ready yet
1778
1779 =head1 Autocreating constants
1780
1781 After C<use Math::BigFloat ':constant'> all the floating point constants
1782 in the given scope are converted to C<Math::BigFloat>. This conversion
1783 happens at compile time.
1784
1785 In particular
1786
1787   perl -MMath::BigFloat=:constant -e 'print 2E-100,"\n"'
1788
1789 prints the value of C<2E-100>.  Note that without conversion of 
1790 constants the expression 2E-100 will be calculated as normal floating point 
1791 number.
1792
1793 =head1 BUGS
1794
1795 =over 2
1796
1797 =item *
1798
1799 The 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
1808 There is no fmod() function yet.
1809
1810 =back
1811
1812 =head1 CAVEAT
1813
1814 =over 1
1815
1816 =item stringify, bstr()
1817
1818 Both 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
1820 reasoning and details.
1821
1822 =item bdiv
1823
1824 The following will probably not do what you expect:
1825
1826         print $c->bdiv(123.456),"\n";
1827
1828 It prints both quotient and reminder since print works in list context. Also,
1829 bdiv() 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
1834 instead.
1835
1836 =item Modifying and =
1837
1838 Beware of:
1839
1840         $x = Math::BigFloat->new(5);
1841         $y = $x;
1842
1843 It will not do what you think, e.g. making a copy of $x. Instead it just makes
1844 a second reference to the B<same> object and stores it in $y. Thus anything
1845 that modifies $x will modify $y, and vice versa.
1846
1847         $x->bmul(2);
1848         print "$x, $y\n";       # prints '10, 10'
1849
1850 If you want a true copy of $x, use:
1851         
1852         $y = $x->copy();
1853
1854 See also the documentation in L<overload> regarding C<=>.
1855
1856 =item bpow
1857
1858 C<bpow()> now modifies the first argument, unlike the old code which left
1859 it alone and only returned the result. This is to be consistent with
1860 C<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
1869
1870 This program is free software; you may redistribute it and/or modify it under
1871 the same terms as Perl itself.
1872
1873 =head1 AUTHORS
1874
1875 Mark Biggar, overloaded interface by Ilya Zakharevich.
1876 Completely rewritten by Tels http://bloodgate.com in 2001.
1877
1878 =cut