File Coverage

blib/lib/Math/BigInt.pm
Criterion Covered Total %
statement 1549 2178 71.1
branch 1213 2036 59.5
condition 634 1050 60.3
subroutine 181 235 77.0
pod 135 136 99.2
total 3712 5635 65.8


line stmt bran cond sub pod time code
1             # -*- coding: utf-8-unix -*-
2              
3             package Math::BigInt;
4              
5             #
6             # "Mike had an infinite amount to do and a negative amount of time in which
7             # to do it." - Before and After
8             #
9              
10             # The following hash values are used:
11             # value: unsigned int with actual value (as a Math::BigInt::Calc or similar)
12             # sign : +, -, NaN, +inf, -inf
13             # _a : accuracy
14             # _p : precision
15              
16             # Remember not to take shortcuts ala $xs = $x->{value}; $LIB->foo($xs); since
17             # underlying lib might change the reference!
18              
19 51     51   2023559 use 5.006001;
  51         464  
20 51     51   280 use strict;
  51         96  
  51         1204  
21 51     51   257 use warnings;
  51         131  
  51         1996  
22              
23 51     51   371 use Carp qw< carp croak >;
  51         141  
  51         3062  
24 51     51   481 use Scalar::Util qw< blessed refaddr >;
  51         120  
  51         90448  
25              
26             our $VERSION = '1.999842';
27             $VERSION =~ tr/_//d;
28              
29             require Exporter;
30             our @ISA = qw(Exporter);
31             our @EXPORT_OK = qw(objectify bgcd blcm);
32              
33             # Inside overload, the first arg is always an object. If the original code had
34             # it reversed (like $x = 2 * $y), then the third parameter is true.
35             # In some cases (like add, $x = $x + 2 is the same as $x = 2 + $x) this makes
36             # no difference, but in some cases it does.
37              
38             # For overloaded ops with only one argument we simple use $_[0]->copy() to
39             # preserve the argument.
40              
41             # Thus inheritance of overload operators becomes possible and transparent for
42             # our subclasses without the need to repeat the entire overload section there.
43              
44             use overload
45              
46             # overload key: with_assign
47              
48 309     309   1030 '+' => sub { $_[0] -> copy() -> badd($_[1]); },
49              
50 356     356   2230 '-' => sub { my $c = $_[0] -> copy();
51 356 100       1100 $_[2] ? $c -> bneg() -> badd($_[1])
52             : $c -> bsub($_[1]); },
53              
54 960     960   5236 '*' => sub { $_[0] -> copy() -> bmul($_[1]); },
55              
56 341 100   341   1616 '/' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bdiv($_[0])
57             : $_[0] -> copy() -> bdiv($_[1]); },
58              
59 353 100   353   4320 '%' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bmod($_[0])
60             : $_[0] -> copy() -> bmod($_[1]); },
61              
62 439 100   439   6557 '**' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bpow($_[0])
63             : $_[0] -> copy() -> bpow($_[1]); },
64              
65 20 50   20   276 '<<' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bblsft($_[0])
66             : $_[0] -> copy() -> bblsft($_[1]); },
67              
68 20 50   20   291 '>>' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bbrsft($_[0])
69             : $_[0] -> copy() -> bbrsft($_[1]); },
70              
71             # overload key: assign
72              
73 27     27   1306 '+=' => sub { $_[0] -> badd($_[1]); },
74              
75 29     29   1261 '-=' => sub { $_[0] -> bsub($_[1]); },
76              
77 17     17   224 '*=' => sub { $_[0] -> bmul($_[1]); },
78              
79 14     14   213 '/=' => sub { scalar $_[0] -> bdiv($_[1]); },
80              
81 17     17   227 '%=' => sub { $_[0] -> bmod($_[1]); },
82              
83 6     6   111 '**=' => sub { $_[0] -> bpow($_[1]); },
84              
85 3     3   60 '<<=' => sub { $_[0] -> bblsft($_[1]); },
86              
87 3     3   21 '>>=' => sub { $_[0] -> bbrsft($_[1]); },
88              
89             # 'x=' => sub { },
90              
91             # '.=' => sub { },
92              
93             # overload key: num_comparison
94              
95 318 50   318   1029 '<' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> blt($_[0])
96             : $_[0] -> blt($_[1]); },
97              
98 621 100   621   3715 '<=' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> ble($_[0])
99             : $_[0] -> ble($_[1]); },
100              
101 506 50   506   1823 '>' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bgt($_[0])
102             : $_[0] -> bgt($_[1]); },
103              
104 140 50   140   5684 '>=' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bge($_[0])
105             : $_[0] -> bge($_[1]); },
106              
107 241     241   103559 '==' => sub { $_[0] -> beq($_[1]); },
108              
109 9     9   499 '!=' => sub { $_[0] -> bne($_[1]); },
110              
111             # overload key: 3way_comparison
112              
113 0     0   0 '<=>' => sub { my $cmp = $_[0] -> bcmp($_[1]);
114 0 0 0     0 defined($cmp) && $_[2] ? -$cmp : $cmp; },
115              
116 7947 50   7947   2008550 'cmp' => sub { $_[2] ? "$_[1]" cmp $_[0] -> bstr()
117             : $_[0] -> bstr() cmp "$_[1]"; },
118              
119             # overload key: str_comparison
120              
121             # 'lt' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bstrlt($_[0])
122             # : $_[0] -> bstrlt($_[1]); },
123             #
124             # 'le' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bstrle($_[0])
125             # : $_[0] -> bstrle($_[1]); },
126             #
127             # 'gt' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bstrgt($_[0])
128             # : $_[0] -> bstrgt($_[1]); },
129             #
130             # 'ge' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bstrge($_[0])
131             # : $_[0] -> bstrge($_[1]); },
132             #
133             # 'eq' => sub { $_[0] -> bstreq($_[1]); },
134             #
135             # 'ne' => sub { $_[0] -> bstrne($_[1]); },
136              
137             # overload key: binary
138              
139 140 100   140   2002 '&' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> band($_[0])
140             : $_[0] -> copy() -> band($_[1]); },
141              
142 4     4   80 '&=' => sub { $_[0] -> band($_[1]); },
143              
144 201 100   201   3663 '|' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bior($_[0])
145             : $_[0] -> copy() -> bior($_[1]); },
146              
147 4     4   93 '|=' => sub { $_[0] -> bior($_[1]); },
148              
149 199 100   199   2771 '^' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bxor($_[0])
150             : $_[0] -> copy() -> bxor($_[1]); },
151              
152 4     4   83 '^=' => sub { $_[0] -> bxor($_[1]); },
153              
154             # '&.' => sub { },
155              
156             # '&.=' => sub { },
157              
158             # '|.' => sub { },
159              
160             # '|.=' => sub { },
161              
162             # '^.' => sub { },
163              
164             # '^.=' => sub { },
165              
166             # overload key: unary
167              
168 285     285   814 'neg' => sub { $_[0] -> copy() -> bneg(); },
169              
170             # '!' => sub { },
171              
172 0     0   0 '~' => sub { $_[0] -> copy() -> bnot(); },
173              
174             # '~.' => sub { },
175              
176             # overload key: mutators
177              
178 23     23   205 '++' => sub { $_[0] -> binc() },
179              
180 3     3   45 '--' => sub { $_[0] -> bdec() },
181              
182             # overload key: func
183              
184 0 0   0   0 'atan2' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> batan2($_[0])
185             : $_[0] -> copy() -> batan2($_[1]); },
186              
187 0     0   0 'cos' => sub { $_[0] -> copy() -> bcos(); },
188              
189 0     0   0 'sin' => sub { $_[0] -> copy() -> bsin(); },
190              
191 0     0   0 'exp' => sub { $_[0] -> copy() -> bexp($_[1]); },
192              
193 3     3   37 'abs' => sub { $_[0] -> copy() -> babs(); },
194              
195 30     30   436 'log' => sub { $_[0] -> copy() -> blog(); },
196              
197 1     1   6 'sqrt' => sub { $_[0] -> copy() -> bsqrt(); },
198              
199 6     6   40 'int' => sub { $_[0] -> copy() -> bint(); },
200              
201             # overload key: conversion
202              
203 6 100   6   120 'bool' => sub { $_[0] -> is_zero() ? '' : 1; },
204              
205 1855     1855   5467 '""' => sub { $_[0] -> bstr(); },
206              
207 51     51   147 '0+' => sub { $_[0] -> numify(); },
208              
209 0     0   0 '=' => sub { $_[0] -> copy(); },
210              
211 51     51   52798 ;
  51         43538  
  51         4105  
212              
213             ##############################################################################
214             # global constants, flags and accessory
215              
216             # These vars are public, but their direct usage is not recommended, use the
217             # accessor methods instead
218              
219             # $round_mode is 'even', 'odd', '+inf', '-inf', 'zero', 'trunc', or 'common'.
220             our $round_mode = 'even';
221             our $accuracy = undef;
222             our $precision = undef;
223             our $div_scale = 40;
224             our $upgrade = undef; # default is no upgrade
225             our $downgrade = undef; # default is no downgrade
226              
227             # These are internally, and not to be used from the outside at all
228              
229             our $_trap_nan = 0; # are NaNs ok? set w/ config()
230             our $_trap_inf = 0; # are infs ok? set w/ config()
231              
232             my $nan = 'NaN'; # constants for easier life
233              
234             # Module to do the low level math.
235              
236             my $DEFAULT_LIB = 'Math::BigInt::Calc';
237             my $LIB;
238              
239             # Has import() been called yet? Needed to make "require" work.
240              
241             my $IMPORT = 0;
242              
243             ##############################################################################
244             # the old code had $rnd_mode, so we need to support it, too
245              
246             our $rnd_mode = 'even';
247              
248             sub TIESCALAR {
249 51     51   189 my ($class) = @_;
250 51         219 bless \$round_mode, $class;
251             }
252              
253             sub FETCH {
254 3     3   85 return $round_mode;
255             }
256              
257             sub STORE {
258 52     52   837 $rnd_mode = $_[0]->round_mode($_[1]);
259             }
260              
261             BEGIN {
262             # tie to enable $rnd_mode to work transparently
263 51     51   41111 tie $rnd_mode, 'Math::BigInt';
264              
265             # set up some handy alias names
266 51         358 *is_pos = \&is_positive;
267 51         416 *is_neg = \&is_negative;
268 51         9609 *as_number = \&as_int;
269             }
270              
271             ###############################################################################
272             # Configuration methods
273             ###############################################################################
274              
275             sub round_mode {
276 410     410 1 12061 my $self = shift;
277 410   50     2106 my $class = ref($self) || $self || __PACKAGE__;
278              
279 410 100       1093 if (@_) { # setter
280 367         680 my $m = shift;
281 367 50       810 croak("The value for 'round_mode' must be defined")
282             unless defined $m;
283 367 100       2638 croak("Unknown round mode '$m'")
284             unless $m =~ /^(even|odd|\+inf|\-inf|zero|trunc|common)$/;
285 51     51   419 no strict 'refs';
  51         125  
  51         2815  
286 363         637 ${"${class}::round_mode"} = $m;
  363         4120  
287             }
288              
289             else { # getter
290 51     51   287 no strict 'refs';
  51         147  
  51         4079  
291 43         88 my $m = ${"${class}::round_mode"};
  43         222  
292 43 100       224 defined($m) ? $m : $round_mode;
293             }
294             }
295              
296             sub upgrade {
297 51     51   352 no strict 'refs';
  51         107  
  51         6447  
298             # make Class->upgrade() work
299 3332     3332 1 7257 my $self = shift;
300 3332   50     10857 my $class = ref($self) || $self || __PACKAGE__;
301              
302             # need to set new value?
303 3332 100       7393 if (@_ > 0) {
304 2023         3043 return ${"${class}::upgrade"} = $_[0];
  2023         5632  
305             }
306 1309         1809 ${"${class}::upgrade"};
  1309         4408  
307             }
308              
309             sub downgrade {
310 51     51   362 no strict 'refs';
  51         119  
  51         9674  
311             # make Class->downgrade() work
312 3140     3140 1 11139 my $self = shift;
313 3140   50     9588 my $class = ref($self) || $self || __PACKAGE__;
314             # need to set new value?
315 3140 100       6227 if (@_ > 0) {
316 2093         3073 return ${"${class}::downgrade"} = $_[0];
  2093         5421  
317             }
318 1047         1418 ${"${class}::downgrade"};
  1047         2917  
319             }
320              
321             sub div_scale {
322 946     946 1 5041 my $self = shift;
323 946   50     3875 my $class = ref($self) || $self || __PACKAGE__;
324              
325 946 100       2181 if (@_) { # setter
326 15         31 my $ds = shift;
327 15 50       41 croak("The value for 'div_scale' must be defined") unless defined $ds;
328             # It is not documented what div_scale <= 0 means, but Astro::Units sets
329             # div_scale to 0 and fails its tests if this is not supported.
330             #croak("The value for 'div_scale' must be positive") unless $ds > 0;
331 15 50       89 $ds = $ds -> numify() if defined(blessed($ds));
332 51     51   425 no strict 'refs';
  51         186  
  51         2998  
333 15         26 ${"${class}::div_scale"} = $ds;
  15         86  
334             }
335              
336             else { # getter
337 51     51   374 no strict 'refs';
  51         107  
  51         5157  
338 931         1393 my $ds = ${"${class}::div_scale"};
  931         2392  
339 931 100       2969 defined($ds) ? $ds : $div_scale;
340             }
341             }
342              
343             sub accuracy {
344             # $x->accuracy($a); ref($x) $a
345             # $x->accuracy(); ref($x)
346             # Class->accuracy(); class
347             # Class->accuracy($a); class $a
348              
349 8021     8021 1 69221 my $x = shift;
350 8021   50     28754 my $class = ref($x) || $x || __PACKAGE__;
351              
352 51     51   405 no strict 'refs';
  51         128  
  51         18686  
353 8021 100       18107 if (@_ > 0) {
354 526         898 my $a = shift;
355 526 100       1203 if (defined $a) {
356 433 0       909 $a = $a -> can('numify') ? $a -> numify() : 0 + "$a" if ref($a);
    50          
357             # also croak on non-numerical
358 433 50       2434 croak "accuracy must be a number, not '$a'"
359             unless $a =~/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[Ee][+-]?\d+)?\z/;
360 433 50       1146 croak "accuracy must be an integer, not '$a'"
361             if $a != int $a;
362 433 50       931 croak "accuracy must be greater than zero, not '$a'"
363             if $a <= 0;
364             }
365              
366 526 100       1173 if (ref($x)) {
367             # Set instance variable.
368 442 100       1528 $x = $x->bround($a) if defined $a;
369 442         861 $x->{_a} = $a; # set/overwrite, even if not rounded
370 442         805 $x->{_p} = undef; # clear P
371             # Why return class variable here? Fixme!
372 442 100       1065 $a = ${"${class}::accuracy"} unless defined $a;
  53         157  
373             } else {
374             # Set class variable.
375 84         129 ${"${class}::accuracy"} = $a; # set global A
  84         317  
376 84         134 ${"${class}::precision"} = undef; # clear global P
  84         212  
377             }
378              
379 526         2818 return $a; # shortcut
380             }
381              
382             # Return instance variable.
383 7495 100       14809 return $x->{_a} if ref($x);
384              
385             # Return class variable.
386 7409         9635 return ${"${class}::accuracy"};
  7409         25319  
387             }
388              
389             sub precision {
390             # $x->precision($p); ref($x) $p
391             # $x->precision(); ref($x)
392             # Class->precision(); class
393             # Class->precision($p); class $p
394              
395 7795     7795 1 23346 my $x = shift;
396 7795   50     25921 my $class = ref($x) || $x || __PACKAGE__;
397              
398 51     51   398 no strict 'refs';
  51         111  
  51         16747  
399 7795 100       16918 if (@_ > 0) {
400 293         474 my $p = shift;
401 293 100       688 if (defined $p) {
402 208 0       426 $p = $p -> can('numify') ? $p -> numify() : 0 + "$p" if ref($p);
    50          
403 208 50       1353 croak "precision must be a number, not '$p'"
404             unless $p =~/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[Ee][+-]?\d+)?\z/;
405 208 50       553 croak "precision must be an integer, not '$p'"
406             if $p != int $p;
407             }
408              
409 293 100       652 if (ref($x)) {
410             # Set instance variable.
411 207 100       678 $x = $x->bfround($p) if defined $p;
412 207         419 $x->{_p} = $p; # set/overwrite, even if not rounded
413 207         342 $x->{_a} = undef; # clear A
414             # Why return class variable here? Fixme!
415 207 100       444 $p = ${"${class}::precision"} unless defined $p;
  49         149  
416             } else {
417             # Set class variable.
418 86         150 ${"${class}::precision"} = $p; # set global P
  86         354  
419 86         147 ${"${class}::accuracy"} = undef; # clear global A
  86         195  
420             }
421              
422 293         2081 return $p; # shortcut
423             }
424              
425             # Return instance variable.
426 7502 100       14265 return $x->{_p} if ref($x);
427              
428             # Return class variable.
429 7415         9815 return ${"${class}::precision"};
  7415         22837  
430             }
431              
432             sub config {
433             # return (or set) configuration data.
434 286   50 286 1 47503 my $class = shift || __PACKAGE__;
435              
436 51     51   425 no strict 'refs';
  51         380  
  51         23881  
437 286 100 100     2034 if (@_ > 1 || (@_ == 1 && (ref($_[0]) eq 'HASH'))) {
      100        
438             # try to set given options as arguments from hash
439              
440 30         54 my $args = $_[0];
441 30 100       90 if (ref($args) ne 'HASH') {
442 28         80 $args = { @_ };
443             }
444             # these values can be "set"
445 30         47 my $set_args = {};
446 30         59 foreach my $key (qw/
447             accuracy precision
448             round_mode div_scale
449             upgrade downgrade
450             trap_inf trap_nan
451             /)
452             {
453 240 100       426 $set_args->{$key} = $args->{$key} if exists $args->{$key};
454 240         368 delete $args->{$key};
455             }
456 30 100       99 if (keys %$args > 0) {
457 2         426 croak("Illegal key(s) '", join("', '", keys %$args),
458             "' passed to $class\->config()");
459             }
460 28         69 foreach my $key (keys %$set_args) {
461 28 100       127 if ($key =~ /^trap_(inf|nan)\z/) {
462 16 100       66 ${"${class}::_trap_$1"} = ($set_args->{"trap_$1"} ? 1 : 0);
  16         75  
463 16         52 next;
464             }
465             # use a call instead of just setting the $variable to check argument
466 12         76 $class->$key($set_args->{$key});
467             }
468             }
469              
470             # now return actual configuration
471              
472             my $cfg = {
473             lib => $LIB,
474 284         1232 lib_version => ${"${LIB}::VERSION"},
475             class => $class,
476 284         811 trap_nan => ${"${class}::_trap_nan"},
477 284         746 trap_inf => ${"${class}::_trap_inf"},
478 284         641 version => ${"${class}::VERSION"},
  284         1660  
479             };
480 284         700 foreach my $key (qw/
481             accuracy precision
482             round_mode div_scale
483             upgrade downgrade
484             /)
485             {
486 1704         2173 $cfg->{$key} = ${"${class}::$key"};
  1704         4872  
487             }
488 284 100 100     1291 if (@_ == 1 && (ref($_[0]) ne 'HASH')) {
489             # calls of the style config('lib') return just this value
490 230         1667 return $cfg->{$_[0]};
491             }
492 54         146 $cfg;
493             }
494              
495             sub _scale_a {
496             # select accuracy parameter based on precedence,
497             # used by bround() and bfround(), may return undef for scale (means no op)
498 67505     67505   122275 my ($x, $scale, $mode) = @_;
499              
500 67505 100       128031 $scale = $x->{_a} unless defined $scale;
501              
502 51     51   420 no strict 'refs';
  51         120  
  51         8976  
503 67505         101568 my $class = ref($x);
504              
505 67505 100       119260 $scale = ${ $class . '::accuracy' } unless defined $scale;
  3891         11181  
506 67505 100       114498 $mode = ${ $class . '::round_mode' } unless defined $mode;
  12203         32667  
507              
508 67505 100       120274 if (defined $scale) {
509 63614 50       110921 $scale = $scale->can('numify') ? $scale->numify()
    100          
510             : "$scale" if ref($scale);
511 63614         84388 $scale = int($scale);
512             }
513              
514 67505         180201 ($scale, $mode);
515             }
516              
517             sub _scale_p {
518             # select precision parameter based on precedence,
519             # used by bround() and bfround(), may return undef for scale (means no op)
520 936     936   1942 my ($x, $scale, $mode) = @_;
521              
522 936 100       1977 $scale = $x->{_p} unless defined $scale;
523              
524 51     51   381 no strict 'refs';
  51         123  
  51         156169  
525 936         1505 my $class = ref($x);
526              
527 936 100       1766 $scale = ${ $class . '::precision' } unless defined $scale;
  4         15  
528 936 100       1777 $mode = ${ $class . '::round_mode' } unless defined $mode;
  716         2154  
529              
530 936 100       2049 if (defined $scale) {
531 932 0       1743 $scale = $scale->can('numify') ? $scale->numify()
    50          
532             : "$scale" if ref($scale);
533 932         1418 $scale = int($scale);
534             }
535              
536 936         3017 ($scale, $mode);
537             }
538              
539             ###############################################################################
540             # Constructor methods
541             ###############################################################################
542              
543             sub new {
544             # Create a new Math::BigInt object from a string or another Math::BigInt
545             # object. See hash keys documented at top.
546              
547             # The argument could be an object, so avoid ||, && etc. on it. This would
548             # cause costly overloaded code to be called. The only allowed ops are ref()
549             # and defined.
550              
551 19924     19924 1 5161196 my $self = shift;
552 19924         36485 my $selfref = ref $self;
553 19924   33     66356 my $class = $selfref || $self;
554              
555             # Make "require" work.
556              
557 19924 100       43574 $class -> import() if $IMPORT == 0;
558              
559             # Calling new() with no input arguments has been discouraged for more than
560             # 10 years, but people apparently still use it, so we still support it.
561              
562 19924 100       41844 return $class -> bzero() unless @_;
563              
564 19916         40989 my ($wanted, @r) = @_;
565              
566 19916 50       39848 if (!defined($wanted)) {
567             #carp("Use of uninitialized value in new()")
568             # if warnings::enabled("uninitialized");
569 0         0 return $class -> bzero(@r);
570             }
571              
572 19916 100 100     67932 if (!ref($wanted) && $wanted eq "") {
573             #carp(q|Argument "" isn't numeric in new()|)
574             # if warnings::enabled("numeric");
575             #return $class -> bzero(@r);
576 4         17 return $class -> bnan(@r);
577             }
578              
579             # Initialize a new object.
580              
581 19912         44173 $self = bless {}, $class;
582              
583             # Math::BigInt or subclass
584              
585 19912 100 100     64327 if (defined(blessed($wanted)) && $wanted -> isa(__PACKAGE__)) {
586              
587             # Don't copy the accuracy and precision, because a new object should get
588             # them from the global configuration.
589              
590 5         17 $self -> {sign} = $wanted -> {sign};
591 5         32 $self -> {value} = $LIB -> _copy($wanted -> {value});
592 5 50 66     30 $self = $self->round(@r)
      66        
593             unless @r >= 2 && !defined($r[0]) && !defined($r[1]);
594 5         60 return $self;
595             }
596              
597             # Shortcut for non-zero scalar integers with no non-zero exponent.
598              
599 19907 100       95804 if ($wanted =~
600             / ^
601             ( [+-]? ) # optional sign
602             ( [1-9] [0-9]* ) # non-zero significand
603             ( \.0* )? # ... with optional zero fraction
604             ( [Ee] [+-]? 0+ )? # optional zero exponent
605             \z
606             /x)
607             {
608 12829         28441 my $sgn = $1;
609 12829         21955 my $abs = $2;
610 12829   100     46236 $self->{sign} = $sgn || '+';
611 12829         40699 $self->{value} = $LIB->_new($abs);
612 12829         33255 $self = $self->round(@r);
613 12829         111014 return $self;
614             }
615              
616             # Handle Infs.
617              
618 7078 100       21987 if ($wanted =~ / ^
619             \s*
620             ( [+-]? )
621             inf (?: inity )?
622             \s*
623             \z
624             /ix)
625             {
626 1755   100     6667 my $sgn = $1 || '+';
627 1755         5618 return $class -> binf($sgn, @r);
628             }
629              
630             # Handle explicit NaNs (not the ones returned due to invalid input).
631              
632 5323 100       12579 if ($wanted =~ / ^
633             \s*
634             ( [+-]? )
635             nan
636             \s*
637             \z
638             /ix)
639             {
640 391         1465 return $class -> bnan(@r);
641             }
642              
643 4932         7805 my @parts;
644              
645 4932 100 100     43175 if (
      33        
      66        
      100        
      66        
      100        
      33        
      66        
646             # Handle hexadecimal numbers. We auto-detect hexadecimal numbers if they
647             # have a "0x", "0X", "x", or "X" prefix, cf. CORE::oct().
648              
649             $wanted =~ /^\s*[+-]?0?[Xx]/ and
650             @parts = $class -> _hex_str_to_flt_lib_parts($wanted)
651              
652             or
653              
654             # Handle octal numbers. We auto-detect octal numbers if they have a
655             # "0o", "0O", "o", "O" prefix, cf. CORE::oct().
656              
657             $wanted =~ /^\s*[+-]?0?[Oo]/ and
658             @parts = $class -> _oct_str_to_flt_lib_parts($wanted)
659              
660             or
661              
662             # Handle binary numbers. We auto-detect binary numbers if they have a
663             # "0b", "0B", "b", or "B" prefix, cf. CORE::oct().
664              
665             $wanted =~ /^\s*[+-]?0?[Bb]/ and
666             @parts = $class -> _bin_str_to_flt_lib_parts($wanted)
667              
668             or
669              
670             # At this point, what is left are decimal numbers that aren't handled
671             # above and octal floating point numbers that don't have any of the
672             # "0o", "0O", "o", or "O" prefixes. First see if it is a decimal number.
673              
674             @parts = $class -> _dec_str_to_flt_lib_parts($wanted)
675             or
676              
677             # See if it is an octal floating point number. The extra check is
678             # included because _oct_str_to_flt_lib_parts() accepts octal numbers
679             # that don't have a prefix (this is needed to make it work with, e.g.,
680             # from_oct() that don't require a prefix). However, Perl requires a
681             # prefix for octal floating point literals. For example, "1p+0" is not
682             # valid, but "01p+0" and "0__1p+0" are.
683              
684             $wanted =~ /^\s*[+-]?0_*\d/ and
685             @parts = $class -> _oct_str_to_flt_lib_parts($wanted))
686             {
687             # The value is an integer iff the exponent is non-negative.
688              
689 4293 100       10566 if ($parts[2] eq '+') {
690 4252         10688 $self -> {sign} = $parts[0];
691 4252         13810 $self -> {value} = $LIB -> _lsft($parts[1], $parts[3], 10);
692 4252 100 100     18436 $self = $self->round(@r)
      66        
693             unless @r >= 2 && !defined($r[0]) && !defined($r[1]);
694 4252         36293 return $self;
695             }
696              
697             # The value is not an integer, so upgrade if upgrading is enabled.
698              
699 41 100       203 return $upgrade -> new($wanted, @r) if defined $upgrade;
700             }
701              
702             # If we get here, the value is neither a valid decimal, binary, octal, or
703             # hexadecimal number. It is not explicit an Inf or a NaN either.
704              
705 670         2063 return $class -> bnan(@r);
706             }
707              
708             # Create a Math::BigInt from a decimal string. This is an equivalent to
709             # from_hex(), from_oct(), and from_bin(). It is like new() except that it does
710             # not accept anything but a string representing a finite decimal number.
711              
712             sub from_dec {
713 0     0 1 0 my $self = shift;
714 0         0 my $selfref = ref $self;
715 0   0     0 my $class = $selfref || $self;
716              
717             # Don't modify constant (read-only) objects.
718              
719 0 0 0     0 return $self if $selfref && $self->modify('from_dec');
720              
721 0         0 my $str = shift;
722 0         0 my @r = @_;
723              
724             # If called as a class method, initialize a new object.
725              
726 0 0       0 $self = $class -> bzero(@r) unless $selfref;
727              
728 0 0       0 if (my @parts = $class -> _dec_str_to_flt_lib_parts($str)) {
729              
730             # The value is an integer iff the exponent is non-negative.
731              
732 0 0       0 if ($parts[2] eq '+') {
733 0         0 $self -> {sign} = $parts[0];
734 0         0 $self -> {value} = $LIB -> _lsft($parts[1], $parts[3], 10);
735 0         0 return $self -> round(@r);
736             }
737              
738             # The value is not an integer, so upgrade if upgrading is enabled.
739              
740 0 0       0 return $upgrade -> new($str, @r) if defined $upgrade;
741             }
742              
743 0         0 return $self -> bnan(@r);
744             }
745              
746             # Create a Math::BigInt from a hexadecimal string.
747              
748             sub from_hex {
749 2     2 1 652 my $self = shift;
750 2         5 my $selfref = ref $self;
751 2   33     10 my $class = $selfref || $self;
752              
753             # Don't modify constant (read-only) objects.
754              
755 2 50 33     8 return $self if $selfref && $self->modify('from_hex');
756              
757 2         4 my $str = shift;
758 2         4 my @r = @_;
759              
760             # If called as a class method, initialize a new object.
761              
762 2 50       8 $self = $class -> bzero(@r) unless $selfref;
763              
764 2 50       7 if (my @parts = $class -> _hex_str_to_flt_lib_parts($str)) {
765              
766             # The value is an integer iff the exponent is non-negative.
767              
768 2 50       6 if ($parts[2] eq '+') {
769 2         34 $self -> {sign} = $parts[0];
770 2         14 $self -> {value} = $LIB -> _lsft($parts[1], $parts[3], 10);
771 2         7 return $self -> round(@r);
772             }
773              
774             # The value is not an integer, so upgrade if upgrading is enabled.
775              
776 0 0       0 return $upgrade -> new($str, @r) if defined $upgrade;
777             }
778              
779 0         0 return $self -> bnan(@r);
780             }
781              
782             # Create a Math::BigInt from an octal string.
783              
784             sub from_oct {
785 2     2 1 639 my $self = shift;
786 2         4 my $selfref = ref $self;
787 2   33     11 my $class = $selfref || $self;
788              
789             # Don't modify constant (read-only) objects.
790              
791 2 50 33     8 return $self if $selfref && $self->modify('from_oct');
792              
793 2         3 my $str = shift;
794 2         5 my @r = @_;
795              
796             # If called as a class method, initialize a new object.
797              
798 2 50       9 $self = $class -> bzero(@r) unless $selfref;
799              
800 2 50       7 if (my @parts = $class -> _oct_str_to_flt_lib_parts($str)) {
801              
802             # The value is an integer iff the exponent is non-negative.
803              
804 2 50       7 if ($parts[2] eq '+') {
805 2         5 $self -> {sign} = $parts[0];
806 2         7 $self -> {value} = $LIB -> _lsft($parts[1], $parts[3], 10);
807 2         8 return $self -> round(@r);
808             }
809              
810             # The value is not an integer, so upgrade if upgrading is enabled.
811              
812 0 0       0 return $upgrade -> new($str, @r) if defined $upgrade;
813             }
814              
815 0         0 return $self -> bnan(@r);
816             }
817              
818             # Create a Math::BigInt from a binary string.
819              
820             sub from_bin {
821 53     53 1 734 my $self = shift;
822 53         86 my $selfref = ref $self;
823 53   33     170 my $class = $selfref || $self;
824              
825             # Don't modify constant (read-only) objects.
826              
827 53 50 33     119 return $self if $selfref && $self->modify('from_bin');
828              
829 53         87 my $str = shift;
830 53         102 my @r = @_;
831              
832             # If called as a class method, initialize a new object.
833              
834 53 50       171 $self = $class -> bzero(@r) unless $selfref;
835              
836 53 50       141 if (my @parts = $class -> _bin_str_to_flt_lib_parts($str)) {
837              
838             # The value is an integer iff the exponent is non-negative.
839              
840 53 50       136 if ($parts[2] eq '+') {
841 53         128 $self -> {sign} = $parts[0];
842 53         166 $self -> {value} = $LIB -> _lsft($parts[1], $parts[3], 10);
843 53         175 return $self -> round(@r);
844             }
845              
846             # The value is not an integer, so upgrade if upgrading is enabled.
847              
848 0 0       0 return $upgrade -> new($str, @r) if defined $upgrade;
849             }
850              
851 0         0 return $self -> bnan(@r);
852             }
853              
854             # Create a Math::BigInt from a byte string.
855              
856             sub from_bytes {
857 0     0 1 0 my $self = shift;
858 0         0 my $selfref = ref $self;
859 0   0     0 my $class = $selfref || $self;
860              
861             # Don't modify constant (read-only) objects.
862              
863 0 0 0     0 return $self if $selfref && $self->modify('from_bytes');
864              
865 0 0       0 croak("from_bytes() requires a newer version of the $LIB library.")
866             unless $LIB->can('_from_bytes');
867              
868 0         0 my $str = shift;
869 0         0 my @r = @_;
870              
871             # If called as a class method, initialize a new object.
872              
873 0 0       0 $self = $class -> bzero(@r) unless $selfref;
874 0         0 $self -> {sign} = '+';
875 0         0 $self -> {value} = $LIB -> _from_bytes($str);
876 0         0 return $self -> round(@r);
877             }
878              
879             sub from_base {
880 0     0 1 0 my $self = shift;
881 0         0 my $selfref = ref $self;
882 0   0     0 my $class = $selfref || $self;
883              
884             # Don't modify constant (read-only) objects.
885              
886 0 0 0     0 return $self if $selfref && $self->modify('from_base');
887              
888 0         0 my ($str, $base, $cs, @r) = @_; # $cs is the collation sequence
889              
890 0 0       0 $base = $class->new($base) unless ref($base);
891              
892 0 0 0     0 croak("the base must be a finite integer >= 2")
893             if $base < 2 || ! $base -> is_int();
894              
895             # If called as a class method, initialize a new object.
896              
897 0 0       0 $self = $class -> bzero() unless $selfref;
898              
899             # If no collating sequence is given, pass some of the conversions to
900             # methods optimized for those cases.
901              
902 0 0       0 unless (defined $cs) {
903 0 0       0 return $self -> from_bin($str, @r) if $base == 2;
904 0 0       0 return $self -> from_oct($str, @r) if $base == 8;
905 0 0       0 return $self -> from_hex($str, @r) if $base == 16;
906 0 0       0 if ($base == 10) {
907 0         0 my $tmp = $class -> from_dec($str, @r);
908 0         0 $self -> {value} = $tmp -> {value};
909 0         0 $self -> {sign} = '+';
910 0         0 return $self -> bround(@r);
911             }
912             }
913              
914 0 0       0 croak("from_base() requires a newer version of the $LIB library.")
915             unless $LIB->can('_from_base');
916              
917 0         0 $self -> {sign} = '+';
918             $self -> {value}
919 0 0       0 = $LIB->_from_base($str, $base -> {value}, defined($cs) ? $cs : ());
920 0         0 return $self -> bround(@r);
921             }
922              
923             sub from_base_num {
924 0     0 1 0 my $self = shift;
925 0         0 my $selfref = ref $self;
926 0   0     0 my $class = $selfref || $self;
927              
928             # Don't modify constant (read-only) objects.
929              
930 0 0 0     0 return $self if $selfref && $self->modify('from_base_num');
931              
932             # Make sure we have an array of non-negative, finite, numerical objects.
933              
934 0         0 my $nums = shift;
935 0         0 $nums = [ @$nums ]; # create new reference
936              
937 0         0 for my $i (0 .. $#$nums) {
938             # Make sure we have an object.
939 0 0 0     0 $nums -> [$i] = $class -> new($nums -> [$i])
940             unless defined(blessed($nums -> [$i]))
941             && $nums -> [$i] -> isa(__PACKAGE__);
942             # Make sure we have a finite, non-negative integer.
943 0 0 0     0 croak "the elements must be finite non-negative integers"
944             if $nums -> [$i] -> is_neg() || ! $nums -> [$i] -> is_int();
945             }
946              
947 0         0 my $base = shift;
948 0 0 0     0 $base = $class -> new($base)
949             unless defined(blessed($base)) && $base -> isa(__PACKAGE__);
950              
951 0         0 my @r = @_;
952              
953             # If called as a class method, initialize a new object.
954              
955 0 0       0 $self = $class -> bzero(@r) unless $selfref;
956              
957 0 0       0 croak("from_base_num() requires a newer version of the $LIB library.")
958             unless $LIB->can('_from_base_num');
959              
960 0         0 $self -> {sign} = '+';
961 0         0 $self -> {value} = $LIB -> _from_base_num([ map { $_ -> {value} } @$nums ],
962 0         0 $base -> {value});
963              
964 0         0 return $self -> round(@r);
965             }
966              
967             sub bzero {
968             # create/assign '+0'
969              
970             # Class::method(...) -> Class->method(...)
971 2343 50 66 2343 1 30867 unless (@_ && (defined(blessed($_[0])) && $_[0] -> isa(__PACKAGE__) ||
      33        
972             $_[0] =~ /^[a-z]\w*(?:::[a-z]\w*)*$/i))
973             {
974             #carp "Using ", (caller(0))[3], "() as a function is deprecated;",
975             # " use is as a method instead";
976 0         0 unshift @_, __PACKAGE__;
977             }
978              
979 2343         4728 my $self = shift;
980 2343         3908 my $selfref = ref $self;
981 2343   66     6406 my $class = $selfref || $self;
982              
983 2343 50       4771 $self->import() if $IMPORT == 0; # make require work
984              
985             # Don't modify constant (read-only) objects.
986              
987 2343 50 66     5905 return $self if $selfref && $self->modify('bzero');
988              
989             # Get the rounding parameters, if any.
990              
991 2343         4072 my @r = @_;
992              
993             # If called as a class method, initialize a new object.
994              
995 2343 100       6009 $self = bless {}, $class unless $selfref;
996              
997 2343         5493 $self->{sign} = '+';
998 2343         6485 $self->{value} = $LIB->_zero();
999              
1000             # If rounding parameters are given as arguments, use them. If no rounding
1001             # parameters are given, and if called as a class method, initialize the new
1002             # instance with the class variables.
1003              
1004 2343 100       7733 if (@r) {
    100          
1005 12 50 100     66 croak "can't specify both accuracy and precision"
      66        
1006             if @r >= 2 && defined($r[0]) && defined($r[1]);
1007 12         79 $self->{_a} = $_[0];
1008 12         27 $self->{_p} = $_[1];
1009             } elsif (!$selfref) {
1010 1897         4448 $self->{_a} = $class -> accuracy();
1011 1897         4616 $self->{_p} = $class -> precision();
1012             }
1013              
1014 2343         7091 return $self;
1015             }
1016              
1017             sub bone {
1018             # Create or assign '+1' (or -1 if given sign '-').
1019              
1020             # Class::method(...) -> Class->method(...)
1021 476 50 66 476 1 11142 unless (@_ && (defined(blessed($_[0])) && $_[0] -> isa(__PACKAGE__) ||
      66        
1022             $_[0] =~ /^[a-z]\w*(?:::[a-z]\w*)*$/i))
1023             {
1024             #carp "Using ", (caller(0))[3], "() as a function is deprecated;",
1025             # " use is as a method instead";
1026 0         0 unshift @_, __PACKAGE__;
1027             }
1028              
1029 476         1010 my $self = shift;
1030 476         843 my $selfref = ref $self;
1031 476   66     1241 my $class = $selfref || $self;
1032              
1033 476 50       932 $self->import() if $IMPORT == 0; # make require work
1034              
1035             # Don't modify constant (read-only) objects.
1036              
1037 476 50 66     1390 return $self if $selfref && $self->modify('bone');
1038              
1039 476         946 my ($sign, @r) = @_;
1040              
1041             # Get the sign.
1042              
1043 476 100 100     1644 if (defined($_[0]) && $_[0] =~ /^\s*([+-])\s*$/) {
1044 104         267 $sign = $1;
1045 104         179 shift;
1046             } else {
1047 372         636 $sign = '+';
1048             }
1049              
1050             # If called as a class method, initialize a new object.
1051              
1052 476 100       1146 $self = bless {}, $class unless $selfref;
1053              
1054 476         1068 $self->{sign} = $sign;
1055 476         1407 $self->{value} = $LIB->_one();
1056              
1057             # If rounding parameters are given as arguments, use them. If no rounding
1058             # parameters are given, and if called as a class method, initialize the new
1059             # instance with the class variables.
1060              
1061 476 100       1565 if (@r) {
    100          
1062 18 50 100     88 croak "can't specify both accuracy and precision"
      66        
1063             if @r >= 2 && defined($r[0]) && defined($r[1]);
1064 18         36 $self->{_a} = $_[0];
1065 18         33 $self->{_p} = $_[1];
1066             } elsif (!$selfref) {
1067 266         603 $self->{_a} = $class -> accuracy();
1068 266         630 $self->{_p} = $class -> precision();
1069             }
1070              
1071 476         2619 return $self;
1072             }
1073              
1074             sub binf {
1075             # create/assign a '+inf' or '-inf'
1076              
1077             # Class::method(...) -> Class->method(...)
1078 2088 50 66 2088 1 20936 unless (@_ && (defined(blessed($_[0])) && $_[0] -> isa(__PACKAGE__) ||
      66        
1079             $_[0] =~ /^[a-z]\w*(?:::[a-z]\w*)*$/i))
1080             {
1081             #carp "Using ", (caller(0))[3], "() as a function is deprecated;",
1082             # " use is as a method instead";
1083 0         0 unshift @_, __PACKAGE__;
1084             }
1085              
1086 2088         4114 my $self = shift;
1087 2088         3313 my $selfref = ref $self;
1088 2088   66     5881 my $class = $selfref || $self;
1089              
1090             {
1091 51     51   507 no strict 'refs';
  51         144  
  51         24027  
  2088         3149  
1092 2088 100       2829 if (${"${class}::_trap_inf"}) {
  2088         8129  
1093 5         536 croak("Tried to create +-inf in $class->binf()");
1094             }
1095             }
1096              
1097 2083 50       4218 $self->import() if $IMPORT == 0; # make require work
1098              
1099             # Don't modify constant (read-only) objects.
1100              
1101 2083 50 66     5119 return $self if $selfref && $self->modify('binf');
1102              
1103             # Get the sign.
1104              
1105 2083         3403 my $sign = '+'; # default is to return positive infinity
1106 2083 100 66     10056 if (defined($_[0]) && $_[0] =~ /^\s*([+-])(inf|$)/i) {
1107 2032         4263 $sign = $1;
1108 2032         2921 shift;
1109             }
1110              
1111             # Get the rounding parameters, if any.
1112              
1113 2083         3783 my @r = @_;
1114              
1115             # If called as a class method, initialize a new object.
1116              
1117 2083 100       5257 $self = bless {}, $class unless $selfref;
1118              
1119 2083         6427 $self -> {sign} = $sign . 'inf';
1120 2083         6661 $self -> {value} = $LIB -> _zero();
1121              
1122             # If rounding parameters are given as arguments, use them. If no rounding
1123             # parameters are given, and if called as a class method, initialize the new
1124             # instance with the class variables.
1125              
1126 2083 100       6203 if (@r) {
    100          
1127 575 50 33     2472 croak "can't specify both accuracy and precision"
      33        
1128             if @r >= 2 && defined($r[0]) && defined($r[1]);
1129 575         1099 $self->{_a} = $_[0];
1130 575         1118 $self->{_p} = $_[1];
1131             } elsif (!$selfref) {
1132 1235         3027 $self->{_a} = $class -> accuracy();
1133 1235         2998 $self->{_p} = $class -> precision();
1134             }
1135              
1136 2083         19720 return $self;
1137             }
1138              
1139             sub bnan {
1140             # create/assign a 'NaN'
1141              
1142             # Class::method(...) -> Class->method(...)
1143 2246 50 66 2246 1 23934 unless (@_ && (defined(blessed($_[0])) && $_[0] -> isa(__PACKAGE__) ||
      66        
1144             $_[0] =~ /^[a-z]\w*(?:::[a-z]\w*)*$/i))
1145             {
1146             #carp "Using ", (caller(0))[3], "() as a function is deprecated;",
1147             # " use is as a method instead";
1148 0         0 unshift @_, __PACKAGE__;
1149             }
1150              
1151 2246         4513 my $self = shift;
1152 2246         3852 my $selfref = ref($self);
1153 2246   66     5846 my $class = $selfref || $self;
1154              
1155             {
1156 51     51   501 no strict 'refs';
  51         163  
  51         849356  
  2246         3142  
1157 2246 100       2966 if (${"${class}::_trap_nan"}) {
  2246         8320  
1158 4         539 croak("Tried to create NaN in $class->bnan()");
1159             }
1160             }
1161              
1162 2242 50       4687 $self->import() if $IMPORT == 0; # make require work
1163              
1164             # Don't modify constant (read-only) objects.
1165              
1166 2242 50 66     6821 return $self if $selfref && $self->modify('bnan');
1167              
1168             # Get the rounding parameters, if any.
1169              
1170 2242         4227 my @r = @_;
1171              
1172 2242 100       5271 $self = bless {}, $class unless $selfref;
1173              
1174 2242         5191 $self -> {sign} = $nan;
1175 2242         7099 $self -> {value} = $LIB -> _zero();
1176              
1177             # If rounding parameters are given as arguments, use them. If no rounding
1178             # parameters are given, and if called as a class method, initialize the new
1179             # instance with the class variables.
1180              
1181 2242 100       6799 if (@r) {
    100          
1182 541 50 66     2542 croak "can't specify both accuracy and precision"
      33        
1183             if @r >= 2 && defined($r[0]) && defined($r[1]);
1184 541         999 $self->{_a} = $_[0];
1185 541         946 $self->{_p} = $_[1];
1186             } elsif (!$selfref) {
1187 900         2412 $self->{_a} = $class -> accuracy();
1188 900         2365 $self->{_p} = $class -> precision();
1189             }
1190              
1191 2242         18982 return $self;
1192             }
1193              
1194             sub bpi {
1195              
1196             # Class::method(...) -> Class->method(...)
1197 9 50 33 9 1 263 unless (@_ && (defined(blessed($_[0])) && $_[0] -> isa(__PACKAGE__) ||
      33        
1198             $_[0] =~ /^[a-z]\w*(?:::[a-z]\w*)*$/i))
1199             {
1200             #carp "Using ", (caller(0))[3], "() as a function is deprecated;",
1201             # " use is as a method instead";
1202 0         0 unshift @_, __PACKAGE__;
1203             }
1204              
1205             # Called as Argument list
1206             # --------- -------------
1207             # Math::BigFloat->bpi() ("Math::BigFloat")
1208             # Math::BigFloat->bpi(10) ("Math::BigFloat", 10)
1209             # $x->bpi() ($x)
1210             # $x->bpi(10) ($x, 10)
1211             # Math::BigFloat::bpi() ()
1212             # Math::BigFloat::bpi(10) (10)
1213             #
1214             # In ambiguous cases, we favour the OO-style, so the following case
1215             #
1216             # $n = Math::BigFloat->new("10");
1217             # $x = Math::BigFloat->bpi($n);
1218             #
1219             # which gives an argument list with the single element $n, is resolved as
1220             #
1221             # $n->bpi();
1222              
1223 9         22 my $self = shift;
1224 9         31 my $selfref = ref $self;
1225 9   33     37 my $class = $selfref || $self;
1226 9         28 my @r = @_; # rounding paramters
1227              
1228 9 50       32 if ($selfref) { # bpi() called as an instance method
1229 0 0       0 return $self if $self -> modify('bpi');
1230             } else { # bpi() called as a class method
1231 9         25 $self = bless {}, $class; # initialize new instance
1232             }
1233              
1234 9 50       29 return $upgrade -> bpi(@r) if defined $upgrade;
1235              
1236             # hard-wired to "3"
1237 9         24 $self -> {sign} = '+';
1238 9         29 $self -> {value} = $LIB -> _new("3");
1239 9         30 $self = $self -> round(@r);
1240 9         90 return $self;
1241             }
1242              
1243             sub copy {
1244 4824     4824 1 11319 my ($x, $class);
1245 4824 50       10041 if (ref($_[0])) { # $y = $x -> copy()
1246 4824         7699 $x = shift;
1247 4824         7759 $class = ref($x);
1248             } else { # $y = Math::BigInt -> copy($y)
1249 0         0 $class = shift;
1250 0         0 $x = shift;
1251             }
1252              
1253 4824 50       10340 carp "Rounding is not supported for ", (caller(0))[3], "()" if @_;
1254              
1255 4824         9245 my $copy = bless {}, $class;
1256              
1257 4824         11312 $copy->{sign} = $x->{sign};
1258 4824         13236 $copy->{value} = $LIB->_copy($x->{value});
1259 4824 100       11241 $copy->{_a} = $x->{_a} if exists $x->{_a};
1260 4824 100       10014 $copy->{_p} = $x->{_p} if exists $x->{_p};
1261              
1262 4824         13745 return $copy;
1263             }
1264              
1265             sub as_int {
1266 3 50   3 1 17 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1267 3 50       22 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
1268              
1269             # If called as an instance method, and the instance class is something we
1270             # upgrade to, $x might not be a Math::BigInt, so don't just call copy().
1271              
1272 3 50       22 return $x -> copy() if $x -> isa("Math::BigInt");
1273              
1274             # disable upgrading and downgrading
1275              
1276 0         0 my $upg = Math::BigInt -> upgrade();
1277 0         0 my $dng = Math::BigInt -> downgrade();
1278 0         0 Math::BigInt -> upgrade(undef);
1279 0         0 Math::BigInt -> downgrade(undef);
1280              
1281 0         0 my $y = Math::BigInt -> new($x);
1282              
1283             # reset upgrading and downgrading
1284              
1285 0         0 Math::BigInt -> upgrade($upg);
1286 0         0 Math::BigInt -> downgrade($dng);
1287              
1288 0         0 return $y;
1289             }
1290              
1291             sub as_float {
1292 343 50   343 1 995 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1293 343 50       743 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
1294              
1295             # disable upgrading and downgrading
1296              
1297 343         1911 require Math::BigFloat;
1298 343         731 my $upg = Math::BigFloat -> upgrade();
1299 343         811 my $dng = Math::BigFloat -> downgrade();
1300 343         866 Math::BigFloat -> upgrade(undef);
1301 343         870 Math::BigFloat -> downgrade(undef);
1302              
1303 343         991 my $y = Math::BigFloat -> new($x);
1304              
1305             # reset upgrading and downgrading
1306              
1307 343         1413 Math::BigFloat -> upgrade($upg);
1308 343         1145 Math::BigFloat -> downgrade($dng);
1309              
1310 343         859 return $y;
1311             }
1312              
1313             sub as_rat {
1314 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1315 0 0       0 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
1316              
1317             # disable upgrading and downgrading
1318              
1319 0         0 require Math::BigRat;
1320 0         0 my $upg = Math::BigRat -> upgrade();
1321 0         0 my $dng = Math::BigRat -> downgrade();
1322 0         0 Math::BigRat -> upgrade(undef);
1323 0         0 Math::BigRat -> downgrade(undef);
1324              
1325 0         0 my $y = Math::BigRat -> new($x);
1326              
1327             # reset upgrading and downgrading
1328              
1329 0         0 Math::BigRat -> upgrade($upg);
1330 0         0 Math::BigRat -> downgrade($dng);
1331              
1332 0         0 return $y;
1333             }
1334              
1335             ###############################################################################
1336             # Boolean methods
1337             ###############################################################################
1338              
1339             sub is_zero {
1340             # return true if arg (BINT or num_str) is zero (array '+', '0')
1341 32532 100   32532 1 75416 my (undef, $x) = ref($_[0]) ? (undef, @_) : objectify(1, @_);
1342              
1343 32532 100       115791 return 0 if $x->{sign} !~ /^\+$/; # -, NaN & +-inf aren't
1344 29725         82159 $LIB->_is_zero($x->{value});
1345             }
1346              
1347             sub is_one {
1348             # return true if arg (BINT or num_str) is +1, or -1 if sign is given
1349 1731 100   1731 1 7947 my (undef, $x, $sign) = ref($_[0]) ? (undef, @_) : objectify(1, @_);
1350              
1351 1731 100 100     5789 $sign = '+' if !defined($sign) || $sign ne '-';
1352              
1353 1731 100       4793 return 0 if $x->{sign} ne $sign; # -1 != +1, NaN, +-inf aren't either
1354 1125         3252 $LIB->_is_one($x->{value});
1355             }
1356              
1357             sub is_finite {
1358 364 50   364 1 893 my (undef, $x) = ref($_[0]) ? (undef, @_) : objectify(1, @_);
1359 364   100     1745 return $x->{sign} eq '+' || $x->{sign} eq '-';
1360             }
1361              
1362             sub is_inf {
1363             # return true if arg (BINT or num_str) is +-inf
1364 38693 100   38693 1 94360 my (undef, $x, $sign) = ref($_[0]) ? (undef, @_) : objectify(1, @_);
1365              
1366 38693 100       71219 if (defined $sign) {
1367 7080 100       13727 $sign = '[+-]inf' if $sign eq ''; # +- doesn't matter, only that's inf
1368 7080 100       32240 $sign = "[$1]inf" if $sign =~ /^([+-])(inf)?$/; # extract '+' or '-'
1369 7080 100       106829 return $x->{sign} =~ /^$sign$/ ? 1 : 0;
1370             }
1371 31613 100       95293 $x->{sign} =~ /^[+-]inf$/ ? 1 : 0; # only +-inf is infinity
1372             }
1373              
1374             sub is_nan {
1375             # return true if arg (BINT or num_str) is NaN
1376 48850 100   48850 1 115053 my (undef, $x) = ref($_[0]) ? (undef, @_) : objectify(1, @_);
1377              
1378 48850 100       168405 $x->{sign} eq $nan ? 1 : 0;
1379             }
1380              
1381             sub is_positive {
1382             # return true when arg (BINT or num_str) is positive (> 0)
1383 454 100   454 1 7949 my (undef, $x) = ref($_[0]) ? (undef, @_) : objectify(1, @_);
1384              
1385 454 100       1347 return 1 if $x->{sign} eq '+inf'; # +inf is positive
1386              
1387             # 0+ is neither positive nor negative
1388 439 100 100     1931 ($x->{sign} eq '+' && !$x->is_zero()) ? 1 : 0;
1389             }
1390              
1391             sub is_negative {
1392             # return true when arg (BINT or num_str) is negative (< 0)
1393 2826 100   2826 1 14091 my (undef, $x) = ref($_[0]) ? (undef, @_) : objectify(1, @_);
1394              
1395 2826 100       13133 $x->{sign} =~ /^-/ ? 1 : 0; # -inf is negative, but NaN is not
1396             }
1397              
1398             sub is_non_negative {
1399             # Return true if argument is non-negative (>= 0).
1400 64 100   64 1 6533 my (undef, $x) = ref($_[0]) ? (undef, @_) : objectify(1, @_);
1401              
1402 64 100       480 return 1 if $x->{sign} =~ /^\+/;
1403 32 50       149 return 1 if $x -> is_zero();
1404 32         305 return 0;
1405             }
1406              
1407             sub is_non_positive {
1408             # Return true if argument is non-positive (<= 0).
1409 64 100   64 1 6427 my (undef, $x) = ref($_[0]) ? (undef, @_) : objectify(1, @_);
1410              
1411 64 100       449 return 1 if $x->{sign} =~ /^\-/;
1412 40 100       256 return 1 if $x -> is_zero();
1413 32         314 return 0;
1414             }
1415              
1416             sub is_odd {
1417             # return true when arg (BINT or num_str) is odd, false for even
1418 185 50   185 1 922 my (undef, $x) = ref($_[0]) ? (undef, @_) : objectify(1, @_);
1419              
1420 185 100       651 return 0 if $x->{sign} !~ /^[+-]$/; # NaN & +-inf aren't
1421 178         578 $LIB->_is_odd($x->{value});
1422             }
1423              
1424             sub is_even {
1425             # return true when arg (BINT or num_str) is even, false for odd
1426 44 50   44 1 524 my (undef, $x) = ref($_[0]) ? (undef, @_) : objectify(1, @_);
1427              
1428 44 100       188 return 0 if $x->{sign} !~ /^[+-]$/; # NaN & +-inf aren't
1429 40         172 $LIB->_is_even($x->{value});
1430             }
1431              
1432             sub is_int {
1433             # return true when arg (BINT or num_str) is an integer
1434 46 50   46 1 382 my (undef, $x) = ref($_[0]) ? (undef, @_) : objectify(1, @_);
1435              
1436 46 100       434 $x->{sign} =~ /^[+-]$/ ? 1 : 0; # inf/-inf/NaN aren't
1437             }
1438              
1439             ###############################################################################
1440             # Comparison methods
1441             ###############################################################################
1442              
1443             sub bcmp {
1444             # Compares 2 values. Returns one of undef, <0, =0, >0. (suitable for sort)
1445             # (BINT or num_str, BINT or num_str) return cond_code
1446              
1447             # set up parameters
1448 2401 100 66 2401 1 11632 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
1449             ? (ref($_[0]), @_)
1450             : objectify(2, @_);
1451              
1452 2401 50       4852 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
1453              
1454 2401 100 66     5958 return $upgrade->bcmp($x, $y)
      100        
1455             if defined($upgrade) && (!$x->isa(__PACKAGE__) || !$y->isa(__PACKAGE__));
1456              
1457 2400 100 100     12475 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/)) {
1458             # handle +-inf and NaN
1459 320 100 100     1587 return if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1460 256 100 66     920 return 0 if $x->{sign} eq $y->{sign} && $x->{sign} =~ /^[+-]inf$/;
1461 229 100       924 return +1 if $x->{sign} eq '+inf';
1462 133 100       698 return -1 if $x->{sign} eq '-inf';
1463 19 100       127 return -1 if $y->{sign} eq '+inf';
1464 11         85 return +1;
1465             }
1466              
1467             # check sign for speed first
1468 2080 100 100     7505 return 1 if $x->{sign} eq '+' && $y->{sign} eq '-'; # does also 0 <=> -y
1469 1818 100 100     5159 return -1 if $x->{sign} eq '-' && $y->{sign} eq '+'; # does also -x <=> 0
1470              
1471             # have same sign, so compare absolute values. Don't make tests for zero
1472             # here because it's actually slower than testing in Calc (especially w/ Pari
1473             # et al)
1474              
1475             # post-normalized compare for internal use (honors signs)
1476 1624 100       3361 if ($x->{sign} eq '+') {
1477             # $x and $y both > 0
1478 1534         4780 return $LIB->_acmp($x->{value}, $y->{value});
1479             }
1480              
1481             # $x && $y both < 0
1482 90         331 $LIB->_acmp($y->{value}, $x->{value}); # swapped acmp (lib returns 0, 1, -1)
1483             }
1484              
1485             sub bacmp {
1486             # Compares 2 values, ignoring their signs.
1487             # Returns one of undef, <0, =0, >0. (suitable for sort)
1488             # (BINT, BINT) return cond_code
1489              
1490             # set up parameters
1491 238 50 33 238 1 2225 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
1492             ? (ref($_[0]), @_)
1493             : objectify(2, @_);
1494              
1495 238 50       572 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
1496              
1497 238 50 33     748 return $upgrade->bacmp($x, $y)
      66        
1498             if defined($upgrade) && (!$x->isa(__PACKAGE__) || !$y->isa(__PACKAGE__));
1499              
1500 238 100 100     1317 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/)) {
1501             # handle +-inf and NaN
1502 72 100 100     502 return if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1503 44 100 100     390 return 0 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} =~ /^[+-]inf$/;
1504 28 100 66     298 return 1 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} !~ /^[+-]inf$/;
1505 12         114 return -1;
1506             }
1507 166         646 $LIB->_acmp($x->{value}, $y->{value}); # lib does only 0, 1, -1
1508             }
1509              
1510             sub beq {
1511 427 100 66 427 1 2490 my (undef, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
1512             ? (undef, @_)
1513             : objectify(2, @_);
1514              
1515 427 50       1118 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
1516              
1517 427         1311 my $cmp = $x -> bcmp($y); # bcmp() upgrades if necessary
1518 427   100     4134 return defined($cmp) && !$cmp;
1519             }
1520              
1521             sub bne {
1522 18 50 33 18 1 114 my (undef, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
1523             ? (undef, @_)
1524             : objectify(2, @_);
1525              
1526 18 50       45 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
1527              
1528 18         54 my $cmp = $x -> bcmp($y); # bcmp() upgrades if necessary
1529 18 50 33     134 return defined($cmp) && !$cmp ? '' : 1;
1530             }
1531              
1532             sub blt {
1533 619 100 66 619 1 2910 my (undef, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
1534             ? (undef, @_)
1535             : objectify(2, @_);
1536              
1537 619 50       1622 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
1538              
1539 619         1686 my $cmp = $x -> bcmp($y); # bcmp() upgrades if necessary
1540 619   100     4975 return defined($cmp) && $cmp < 0;
1541             }
1542              
1543             sub ble {
1544 1478 100 66 1478 1 6400 my (undef, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
1545             ? (undef, @_)
1546             : objectify(2, @_);
1547              
1548 1478 50       3177 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
1549              
1550 1478         3981 my $cmp = $x -> bcmp($y); # bcmp() upgrades if necessary
1551 1478   100     8634 return defined($cmp) && $cmp <= 0;
1552             }
1553              
1554             sub bgt {
1555 1385 100 66 1385 1 6725 my (undef, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
1556             ? (undef, @_)
1557             : objectify(2, @_);
1558              
1559 1385 50       3296 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
1560              
1561 1385         3696 my $cmp = $x -> bcmp($y); # bcmp() upgrades if necessary
1562 1385   66     8285 return defined($cmp) && $cmp > 0;
1563             }
1564              
1565             sub bge {
1566 317 100 66 317 1 1844 my (undef, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
1567             ? (undef, @_)
1568             : objectify(2, @_);
1569              
1570 317 50       1954 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
1571              
1572 317         905 my $cmp = $x -> bcmp($y); # bcmp() upgrades if necessary
1573 317   100     2321 return defined($cmp) && $cmp >= 0;
1574             }
1575              
1576             ###############################################################################
1577             # Arithmetic methods
1578             ###############################################################################
1579              
1580             sub bneg {
1581             # (BINT or num_str) return BINT
1582             # negate number or make a negated number from string
1583 486 50   486 1 1821 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1584              
1585 486 50       1448 return $x if $x->modify('bneg');
1586              
1587 486 50 66     1323 return $upgrade -> bneg($x, @r)
1588             if defined($upgrade) && !$x->isa(__PACKAGE__);
1589              
1590             # Don't negate +0 so we always have the normalized form +0. Does nothing for
1591             # 'NaN'.
1592             $x->{sign} =~ tr/+-/-+/
1593 486 100 100     2042 unless $x->{sign} eq '+' && $LIB->_is_zero($x->{value});
1594              
1595 486         1225 $x -> round(@r);
1596             }
1597              
1598             sub babs {
1599             # (BINT or num_str) return BINT
1600             # make number absolute, or return absolute BINT from string
1601 321 100   321 1 6025 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1602              
1603 321 50       1038 return $x if $x->modify('babs');
1604              
1605 321 50 66     855 return $upgrade -> babs($x, @r)
      33        
1606             if defined($upgrade) && !$x->isa(__PACKAGE__) && !$x -> isa($upgrade);
1607              
1608 321         884 $x->{sign} =~ s/^-/+/;
1609              
1610 321         788 $x -> round(@r);
1611             }
1612              
1613             sub bsgn {
1614             # Signum function.
1615 18 50   18 1 225 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1616              
1617 18 50       62 return $x if $x->modify('bsgn');
1618              
1619 18 0 33     52 return $upgrade -> bsgn($x, @r)
      33        
1620             if defined($upgrade) && !$x->isa(__PACKAGE__) && !$x -> isa($upgrade);
1621              
1622 18 100       49 return $x -> bone("+", @r) if $x -> is_pos();
1623 12 100       30 return $x -> bone("-", @r) if $x -> is_neg();
1624              
1625 6         21 $x -> round(@r);
1626             }
1627              
1628             sub bnorm {
1629             # (numstr or BINT) return BINT
1630             # Normalize number -- no-op here
1631 792 50   792 1 378859 my ($class, $x, @r) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1632              
1633             # This method is called from the rounding methods, so if this method
1634             # supports rounding by calling the rounding methods, we get an infinite
1635             # recursion.
1636              
1637 792 50       1916 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
1638              
1639 792         7246 $x;
1640             }
1641              
1642             sub binc {
1643             # increment arg by one
1644 191 50   191 1 772 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1645              
1646 191 50       558 return $x if $x->modify('binc');
1647              
1648 191 100 100     450 return $x->round(@r) if $x -> is_inf() || $x -> is_nan();
1649              
1650 175 50 66     504 return $upgrade -> binc($x, @r)
1651             if defined($upgrade) && !$x -> isa(__PACKAGE__);
1652              
1653 175 100       468 if ($x->{sign} eq '+') {
    50          
1654 101         355 $x->{value} = $LIB->_inc($x->{value});
1655             } elsif ($x->{sign} eq '-') {
1656 74         614 $x->{value} = $LIB->_dec($x->{value});
1657 74 100       204 $x->{sign} = '+' if $LIB->_is_zero($x->{value}); # -1 +1 => -0 => +0
1658             }
1659              
1660 175         449 return $x->round(@r);
1661             }
1662              
1663             sub bdec {
1664             # decrement arg by one
1665 31 50   31 1 310 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1666              
1667 31 50       118 return $x if $x->modify('bdec');
1668              
1669 31 100 100     81 return $x->round(@r) if $x -> is_inf() || $x -> is_nan();
1670              
1671 19 50 66     90 return $upgrade -> bdec($x, @r)
1672             if defined($upgrade) && !$x -> isa(__PACKAGE__);;
1673              
1674 19 100       102 if ($x->{sign} eq '-') {
    50          
1675 4         38 $x->{value} = $LIB->_inc($x->{value});
1676             } elsif ($x->{sign} eq '+') {
1677 15 100       67 if ($LIB->_is_zero($x->{value})) { # +1 - 1 => +0
1678 4         24 $x->{value} = $LIB->_one();
1679 4         15 $x->{sign} = '-';
1680             } else {
1681 11         58 $x->{value} = $LIB->_dec($x->{value});
1682             }
1683             }
1684              
1685 19         61 return $x->round(@r);
1686             }
1687              
1688             #sub bstrcmp {
1689             # my $self = shift;
1690             # my $selfref = ref $self;
1691             # my $class = $selfref || $self;
1692             #
1693             # croak 'bstrcmp() is an instance method, not a class method'
1694             # unless $selfref;
1695             # croak 'Wrong number of arguments for bstrcmp()' unless @_ == 1;
1696             #
1697             # return $self -> bstr() CORE::cmp shift;
1698             #}
1699             #
1700             #sub bstreq {
1701             # my $self = shift;
1702             # my $selfref = ref $self;
1703             # my $class = $selfref || $self;
1704             #
1705             # croak 'bstreq() is an instance method, not a class method'
1706             # unless $selfref;
1707             # croak 'Wrong number of arguments for bstreq()' unless @_ == 1;
1708             #
1709             # my $cmp = $self -> bstrcmp(shift);
1710             # return defined($cmp) && ! $cmp;
1711             #}
1712             #
1713             #sub bstrne {
1714             # my $self = shift;
1715             # my $selfref = ref $self;
1716             # my $class = $selfref || $self;
1717             #
1718             # croak 'bstrne() is an instance method, not a class method'
1719             # unless $selfref;
1720             # croak 'Wrong number of arguments for bstrne()' unless @_ == 1;
1721             #
1722             # my $cmp = $self -> bstrcmp(shift);
1723             # return defined($cmp) && ! $cmp ? '' : 1;
1724             #}
1725             #
1726             #sub bstrlt {
1727             # my $self = shift;
1728             # my $selfref = ref $self;
1729             # my $class = $selfref || $self;
1730             #
1731             # croak 'bstrlt() is an instance method, not a class method'
1732             # unless $selfref;
1733             # croak 'Wrong number of arguments for bstrlt()' unless @_ == 1;
1734             #
1735             # my $cmp = $self -> bstrcmp(shift);
1736             # return defined($cmp) && $cmp < 0;
1737             #}
1738             #
1739             #sub bstrle {
1740             # my $self = shift;
1741             # my $selfref = ref $self;
1742             # my $class = $selfref || $self;
1743             #
1744             # croak 'bstrle() is an instance method, not a class method'
1745             # unless $selfref;
1746             # croak 'Wrong number of arguments for bstrle()' unless @_ == 1;
1747             #
1748             # my $cmp = $self -> bstrcmp(shift);
1749             # return defined($cmp) && $cmp <= 0;
1750             #}
1751             #
1752             #sub bstrgt {
1753             # my $self = shift;
1754             # my $selfref = ref $self;
1755             # my $class = $selfref || $self;
1756             #
1757             # croak 'bstrgt() is an instance method, not a class method'
1758             # unless $selfref;
1759             # croak 'Wrong number of arguments for bstrgt()' unless @_ == 1;
1760             #
1761             # my $cmp = $self -> bstrcmp(shift);
1762             # return defined($cmp) && $cmp > 0;
1763             #}
1764             #
1765             #sub bstrge {
1766             # my $self = shift;
1767             # my $selfref = ref $self;
1768             # my $class = $selfref || $self;
1769             #
1770             # croak 'bstrge() is an instance method, not a class method'
1771             # unless $selfref;
1772             # croak 'Wrong number of arguments for bstrge()' unless @_ == 1;
1773             #
1774             # my $cmp = $self -> bstrcmp(shift);
1775             # return defined($cmp) && $cmp >= 0;
1776             #}
1777              
1778             sub badd {
1779             # add second arg (BINT or string) to first (BINT) (modifies first)
1780             # return result as BINT
1781              
1782             # set up parameters
1783 1818 100 100 1818 1 12058 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
1784             ? (ref($_[0]), @_)
1785             : objectify(2, @_);
1786              
1787 1818 50       5113 return $x if $x->modify('badd');
1788              
1789 1818         3040 $r[3] = $y; # no push!
1790              
1791 1818 100 66     4436 return $upgrade->badd($x, $y, @r)
      100        
1792             if defined($upgrade) && (!$x->isa(__PACKAGE__) || !$y->isa(__PACKAGE__));
1793              
1794             # Inf and NaN handling
1795 1816 100 100     9360 if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/) {
1796             # NaN first
1797 197 100 100     938 return $x->bnan(@r) if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1798             # Inf handling
1799 109 100 100     612 if (($x->{sign} =~ /^[+-]inf$/) && ($y->{sign} =~ /^[+-]inf$/)) {
1800             # +Inf + +Inf or -Inf + -Inf => same, rest is NaN
1801 54 100       206 return $x->round(@r) if $x->{sign} eq $y->{sign};
1802 24         102 return $x->bnan(@r);
1803             }
1804             # ±Inf + something => ±Inf
1805             # something + ±Inf => ±Inf
1806 55 100       191 if ($y->{sign} =~ /^[+-]inf$/) {
1807 35         75 $x->{sign} = $y->{sign};
1808             }
1809 55         156 return $x -> round(@r);
1810             }
1811              
1812             ($x->{value}, $x->{sign})
1813 1619         5838 = $LIB -> _sadd($x->{value}, $x->{sign}, $y->{value}, $y->{sign});
1814 1619         4010 $x->round(@r);
1815             }
1816              
1817             sub bsub {
1818             # (BINT or num_str, BINT or num_str) return BINT
1819             # subtract second arg from first, modify first
1820              
1821             # set up parameters
1822 1116 100 100 1116 1 7980 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
1823             ? (ref($_[0]), @_)
1824             : objectify(2, @_);
1825              
1826 1116 50       3371 return $x if $x -> modify('bsub');
1827              
1828 1116 50 33     2863 return $upgrade -> bsub($x, $y, @r)
      66        
1829             if defined($upgrade) && (!$x->isa(__PACKAGE__) || !$y->isa(__PACKAGE__));
1830              
1831 1116 100       2440 return $x -> round(@r) if $y -> is_zero();
1832              
1833             # To correctly handle the lone special case $x -> bsub($x), we note the
1834             # sign of $x, then flip the sign from $y, and if the sign of $x did change,
1835             # too, then we caught the special case:
1836              
1837 1083         2191 my $xsign = $x -> {sign};
1838 1083         2327 $y -> {sign} =~ tr/+-/-+/; # does nothing for NaN
1839 1083 100       2563 if ($xsign ne $x -> {sign}) {
1840             # special case of $x -> bsub($x) results in 0
1841 12 100       58 return $x -> bzero(@r) if $xsign =~ /^[+-]$/;
1842 6         24 return $x -> bnan(@r); # NaN, -inf, +inf
1843             }
1844              
1845 1071         2454 $x = $x -> badd($y, @r); # badd() does not leave internal zeros
1846 1071         2415 $y -> {sign} =~ tr/+-/-+/; # refix $y (does nothing for NaN)
1847 1071         5302 $x; # already rounded by badd() or no rounding
1848             }
1849              
1850             sub bmul {
1851             # multiply the first number by the second number
1852             # (BINT or num_str, BINT or num_str) return BINT
1853              
1854             # set up parameters
1855 1644 100 100 1644 1 10660 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
1856             ? (ref($_[0]), @_)
1857             : objectify(2, @_);
1858              
1859 1644 50       4808 return $x if $x->modify('bmul');
1860              
1861 1644 100 100     6246 return $x->bnan(@r) if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1862              
1863             # inf handling
1864 1592 100 100     5756 if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/)) {
1865 52 100 100     166 return $x->bnan(@r) if $x->is_zero() || $y->is_zero();
1866             # result will always be +-inf:
1867             # +inf * +/+inf => +inf, -inf * -/-inf => +inf
1868             # +inf * -/-inf => -inf, -inf * +/+inf => -inf
1869 40 100 100     266 return $x->binf(@r) if ($x->{sign} =~ /^\+/ && $y->{sign} =~ /^\+/);
1870 30 100 100     231 return $x->binf(@r) if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/);
1871 20         58 return $x->binf('-', @r);
1872             }
1873              
1874 1540 100 66     3649 return $upgrade->bmul($x, $y, @r)
      100        
1875             if defined($upgrade) && (!$x->isa(__PACKAGE__) || !$y->isa(__PACKAGE__));
1876              
1877 1532         2426 $r[3] = $y; # no push here
1878              
1879 1532 100       3524 $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-'; # +1 * +1 or -1 * -1 => +
1880              
1881 1532         4531 $x->{value} = $LIB->_mul($x->{value}, $y->{value}); # do actual math
1882 1532 100       4307 $x->{sign} = '+' if $LIB->_is_zero($x->{value}); # no -0
1883              
1884 1532         3622 $x->round(@r);
1885             }
1886              
1887             sub bmuladd {
1888             # multiply two numbers and then add the third to the result
1889             # (BINT or num_str, BINT or num_str, BINT or num_str) return BINT
1890              
1891             # set up parameters
1892 177 50 33 177 1 2835 my ($class, $x, $y, $z, @r)
1893             = ref($_[0]) && ref($_[0]) eq ref($_[1]) && ref($_[1]) eq ref($_[2])
1894             ? (ref($_[0]), @_)
1895             : objectify(3, @_);
1896              
1897 177 50       542 return $x if $x->modify('bmuladd');
1898              
1899             # x, y, and z are finite numbers
1900              
1901 177 100 100     1130 if ($x->{sign} =~ /^[+-]$/ &&
      100        
1902             $y->{sign} =~ /^[+-]$/ &&
1903             $z->{sign} =~ /^[+-]$/)
1904             {
1905 141 50 0     371 return $upgrade->bmuladd($x, $y, $z, @r)
      33        
1906             if defined($upgrade) && (!$x->isa(__PACKAGE__) ||
1907             !$y->isa(__PACKAGE__) ||
1908             !$z->isa(__PACKAGE__));
1909              
1910             # TODO: what if $y and $z have A or P set?
1911 141         234 $r[3] = $z; # no push here
1912              
1913 141         216 my $zs = $z->{sign};
1914 141         220 my $zv = $z->{value};
1915 141 50       528 $zv = $LIB -> _copy($zv) if refaddr($x) eq refaddr($z);
1916              
1917 141 100       365 $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-'; # +1 * +1 or -1 * -1 => +
1918 141         470 $x->{value} = $LIB->_mul($x->{value}, $y->{value}); # do actual math
1919 141 100       426 $x->{sign} = '+' if $LIB->_is_zero($x->{value}); # no -0
1920              
1921             ($x->{value}, $x->{sign})
1922 141         472 = $LIB -> _sadd($x->{value}, $x->{sign}, $zv, $zs);
1923 141         394 return $x->round(@r);
1924             }
1925              
1926             # At least one of x, y, and z is a NaN
1927              
1928             return $x->bnan(@r) if (($x->{sign} eq $nan) ||
1929             ($y->{sign} eq $nan) ||
1930 36 100 100     239 ($z->{sign} eq $nan));
      100        
1931              
1932             # At least one of x, y, and z is an Inf
1933              
1934 12 100       56 if ($x->{sign} eq "-inf") {
    50          
    0          
    0          
    0          
1935              
1936 6 100       27 if ($y -> is_neg()) { # x = -inf, y < 0
    50          
1937 3 50       15 if ($z->{sign} eq "-inf") {
1938 0         0 return $x->bnan(@r);
1939             } else {
1940 3         29 return $x->binf("+", @r);
1941             }
1942             } elsif ($y -> is_zero()) { # x = -inf, y = 0
1943 0         0 return $x->bnan(@r);
1944             } else { # x = -inf, y > 0
1945 3 50       12 if ($z->{sign} eq "+inf") {
1946 0         0 return $x->bnan(@r);
1947             } else {
1948 3         11 return $x->binf("-", @r);
1949             }
1950             }
1951              
1952             } elsif ($x->{sign} eq "+inf") {
1953              
1954 6 100       23 if ($y -> is_neg()) { # x = +inf, y < 0
    50          
1955 3 50       21 if ($z->{sign} eq "+inf") {
1956 0         0 return $x->bnan(@r);
1957             } else {
1958 3         13 return $x->binf("-", @r);
1959             }
1960             } elsif ($y -> is_zero()) { # x = +inf, y = 0
1961 0         0 return $x->bnan(@r);
1962             } else { # x = +inf, y > 0
1963 3 50       14 if ($z->{sign} eq "-inf") {
1964 0         0 return $x->bnan(@r);
1965             } else {
1966 3         12 return $x->binf("+", @r);
1967             }
1968             }
1969              
1970             } elsif ($x -> is_neg()) {
1971              
1972 0 0       0 if ($y->{sign} eq "-inf") { # -inf < x < 0, y = -inf
    0          
1973 0 0       0 if ($z->{sign} eq "-inf") {
1974 0         0 return $x->bnan(@r);
1975             } else {
1976 0         0 return $x->binf("+", @r);
1977             }
1978             } elsif ($y->{sign} eq "+inf") { # -inf < x < 0, y = +inf
1979 0 0       0 if ($z->{sign} eq "+inf") {
1980 0         0 return $x->bnan(@r);
1981             } else {
1982 0         0 return $x->binf("-", @r);
1983             }
1984             } else { # -inf < x < 0, -inf < y < +inf
1985 0 0       0 if ($z->{sign} eq "-inf") {
    0          
1986 0         0 return $x->binf("-", @r);
1987             } elsif ($z->{sign} eq "+inf") {
1988 0         0 return $x->binf("+", @r);
1989             }
1990             }
1991              
1992             } elsif ($x -> is_zero()) {
1993              
1994 0 0       0 if ($y->{sign} eq "-inf") { # x = 0, y = -inf
    0          
1995 0         0 return $x->bnan(@r);
1996             } elsif ($y->{sign} eq "+inf") { # x = 0, y = +inf
1997 0         0 return $x->bnan(@r);
1998             } else { # x = 0, -inf < y < +inf
1999 0 0       0 if ($z->{sign} eq "-inf") {
    0          
2000 0         0 return $x->binf("-", @r);
2001             } elsif ($z->{sign} eq "+inf") {
2002 0         0 return $x->binf("+", @r);
2003             }
2004             }
2005              
2006             } elsif ($x -> is_pos()) {
2007              
2008 0 0       0 if ($y->{sign} eq "-inf") { # 0 < x < +inf, y = -inf
    0          
2009 0 0       0 if ($z->{sign} eq "+inf") {
2010 0         0 return $x->bnan(@r);
2011             } else {
2012 0         0 return $x->binf("-", @r);
2013             }
2014             } elsif ($y->{sign} eq "+inf") { # 0 < x < +inf, y = +inf
2015 0 0       0 if ($z->{sign} eq "-inf") {
2016 0         0 return $x->bnan(@r);
2017             } else {
2018 0         0 return $x->binf("+", @r);
2019             }
2020             } else { # 0 < x < +inf, -inf < y < +inf
2021 0 0       0 if ($z->{sign} eq "-inf") {
    0          
2022 0         0 return $x->binf("-", @r);
2023             } elsif ($z->{sign} eq "+inf") {
2024 0         0 return $x->binf("+", @r);
2025             }
2026             }
2027             }
2028              
2029 0         0 die;
2030             }
2031              
2032             sub bdiv {
2033             # This does floored division, where the quotient is floored, i.e., rounded
2034             # towards negative infinity. As a consequence, the remainder has the same
2035             # sign as the divisor.
2036              
2037             # Set up parameters.
2038 1467 100 100 1467 1 14765 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
2039             ? (ref($_[0]), @_)
2040             : objectify(2, @_);
2041              
2042 1467 50       4552 return $x if $x -> modify('bdiv');
2043              
2044 1467         2458 my $wantarray = wantarray; # call only once
2045              
2046             # At least one argument is NaN. Return NaN for both quotient and the
2047             # modulo/remainder.
2048              
2049 1467 100 100     3263 if ($x -> is_nan() || $y -> is_nan()) {
2050 51 100       179 return $wantarray ? ($x -> bnan(@r), $class -> bnan(@r))
2051             : $x -> bnan(@r);
2052             }
2053              
2054             # Divide by zero and modulo zero.
2055             #
2056             # Division: Use the common convention that x / 0 is inf with the same sign
2057             # as x, except when x = 0, where we return NaN. This is also what earlier
2058             # versions did.
2059             #
2060             # Modulo: In modular arithmetic, the congruence relation z = x (mod y)
2061             # means that there is some integer k such that z - x = k y. If y = 0, we
2062             # get z - x = 0 or z = x. This is also what earlier versions did, except
2063             # that 0 % 0 returned NaN.
2064             #
2065             # inf / 0 = inf inf % 0 = inf
2066             # 5 / 0 = inf 5 % 0 = 5
2067             # 0 / 0 = NaN 0 % 0 = 0
2068             # -5 / 0 = -inf -5 % 0 = -5
2069             # -inf / 0 = -inf -inf % 0 = -inf
2070              
2071 1416 100       3313 if ($y -> is_zero()) {
2072 67         121 my $rem;
2073 67 100       153 if ($wantarray) {
2074 32         108 $rem = $x -> copy() -> round(@r);
2075             }
2076 67 100       151 if ($x -> is_zero()) {
2077 17         79 $x = $x -> bnan(@r);
2078             } else {
2079 50         156 $x = $x -> binf($x -> {sign}, @r);
2080             }
2081 64 100       478 return $wantarray ? ($x, $rem) : $x;
2082             }
2083              
2084             # Numerator (dividend) is +/-inf, and denominator is finite and non-zero.
2085             # The divide by zero cases are covered above. In all of the cases listed
2086             # below we return the same as core Perl.
2087             #
2088             # inf / -inf = NaN inf % -inf = NaN
2089             # inf / -5 = -inf inf % -5 = NaN
2090             # inf / 5 = inf inf % 5 = NaN
2091             # inf / inf = NaN inf % inf = NaN
2092             #
2093             # -inf / -inf = NaN -inf % -inf = NaN
2094             # -inf / -5 = inf -inf % -5 = NaN
2095             # -inf / 5 = -inf -inf % 5 = NaN
2096             # -inf / inf = NaN -inf % inf = NaN
2097              
2098 1349 100       3038 if ($x -> is_inf()) {
2099 96         174 my $rem;
2100 96 100       289 $rem = $class -> bnan(@r) if $wantarray;
2101 96 100       215 if ($y -> is_inf()) {
2102 48         227 $x = $x -> bnan(@r);
2103             } else {
2104 48 100       182 my $sign = $x -> bcmp(0) == $y -> bcmp(0) ? '+' : '-';
2105 48         151 $x = $x -> binf($sign, @r);
2106             }
2107 96 100       790 return $wantarray ? ($x, $rem) : $x;
2108             }
2109              
2110             # Denominator (divisor) is +/-inf. The cases when the numerator is +/-inf
2111             # are covered above. In the modulo cases (in the right column) we return
2112             # the same as core Perl, which does floored division, so for consistency we
2113             # also do floored division in the division cases (in the left column).
2114             #
2115             # -5 / inf = -1 -5 % inf = inf
2116             # 0 / inf = 0 0 % inf = 0
2117             # 5 / inf = 0 5 % inf = 5
2118             #
2119             # -5 / -inf = 0 -5 % -inf = -5
2120             # 0 / -inf = 0 0 % -inf = 0
2121             # 5 / -inf = -1 5 % -inf = -inf
2122              
2123 1253 100       2326 if ($y -> is_inf()) {
2124 80         141 my $rem;
2125 80 100 100     216 if ($x -> is_zero() || $x -> bcmp(0) == $y -> bcmp(0)) {
2126 56 100       210 $rem = $x -> copy() -> round(@r) if $wantarray;
2127 56         190 $x = $x -> bzero(@r);
2128             } else {
2129 24 100       121 $rem = $class -> binf($y -> {sign}, @r) if $wantarray;
2130 24         104 $x = $x -> bone('-', @r);
2131             }
2132 80 100       579 return $wantarray ? ($x, $rem) : $x;
2133             }
2134              
2135             # At this point, both the numerator and denominator are finite numbers, and
2136             # the denominator (divisor) is non-zero.
2137              
2138             # Division might return a non-integer result, so upgrade unconditionally, if
2139             # upgrading is enabled.
2140              
2141 1173 100       2640 return $upgrade -> bdiv($x, $y, @r) if defined $upgrade;
2142              
2143 1103         1770 $r[3] = $y; # no push!
2144              
2145             # Inialize remainder.
2146              
2147 1103         2382 my $rem = $class -> bzero();
2148              
2149             # Are both operands the same object, i.e., like $x -> bdiv($x)? If so,
2150             # flipping the sign of $y also flips the sign of $x.
2151              
2152 1103         2072 my $xsign = $x -> {sign};
2153 1103         1831 my $ysign = $y -> {sign};
2154              
2155 1103         2367 $y -> {sign} =~ tr/+-/-+/; # Flip the sign of $y, and see ...
2156 1103         2017 my $same = $xsign ne $x -> {sign}; # ... if that changed the sign of $x.
2157 1103         1845 $y -> {sign} = $ysign; # Re-insert the original sign.
2158              
2159 1103 100       1987 if ($same) {
2160 6         21 $x = $x -> bone();
2161             } else {
2162             ($x -> {value}, $rem -> {value}) =
2163 1097         3490 $LIB -> _div($x -> {value}, $y -> {value});
2164              
2165 1097 100       3513 if ($LIB -> _is_zero($rem -> {value})) {
2166 522 100 100     1689 if ($xsign eq $ysign || $LIB -> _is_zero($x -> {value})) {
2167 469         927 $x -> {sign} = '+';
2168             } else {
2169 53         125 $x -> {sign} = '-';
2170             }
2171             } else {
2172 575 100       1201 if ($xsign eq $ysign) {
2173 524         1014 $x -> {sign} = '+';
2174             } else {
2175 51 100       165 if ($xsign eq '+') {
2176 24         62 $x = $x -> badd(1);
2177             } else {
2178 27         95 $x = $x -> bsub(1);
2179             }
2180 51         105 $x -> {sign} = '-';
2181             }
2182             }
2183             }
2184              
2185 1103         2597 $x = $x -> round(@r);
2186              
2187 1103 100       2449 if ($wantarray) {
2188 491 100       1370 unless ($LIB -> _is_zero($rem -> {value})) {
2189 379 100       831 if ($xsign ne $ysign) {
2190 24         80 $rem = $y -> copy() -> babs() -> bsub($rem);
2191             }
2192 379         669 $rem -> {sign} = $ysign;
2193             }
2194 491         874 $rem -> {_a} = $x -> {_a};
2195 491         718 $rem -> {_p} = $x -> {_p};
2196 491         912 $rem = $rem -> round(@r);
2197 491         2040 return ($x, $rem);
2198             }
2199              
2200 612         5621 return $x;
2201             }
2202              
2203             sub btdiv {
2204             # This does truncated division, where the quotient is truncted, i.e.,
2205             # rounded towards zero.
2206             #
2207             # ($q, $r) = $x -> btdiv($y) returns $q and $r so that $q is int($x / $y)
2208             # and $q * $y + $r = $x.
2209              
2210             # Set up parameters
2211 366 50 33 366 1 5337 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
2212             ? (ref($_[0]), @_)
2213             : objectify(2, @_);
2214              
2215 366 50       1125 return $x if $x -> modify('btdiv');
2216              
2217 366         625 my $wantarray = wantarray; # call only once
2218              
2219             # At least one argument is NaN. Return NaN for both quotient and the
2220             # modulo/remainder.
2221              
2222 366 50 33     754 if ($x -> is_nan() || $y -> is_nan()) {
2223 0 0       0 return $wantarray ? ($x -> bnan(@r), $class -> bnan(@r))
2224             : $x -> bnan(@r);
2225             }
2226              
2227             # Divide by zero and modulo zero.
2228             #
2229             # Division: Use the common convention that x / 0 is inf with the same sign
2230             # as x, except when x = 0, where we return NaN. This is also what earlier
2231             # versions did.
2232             #
2233             # Modulo: In modular arithmetic, the congruence relation z = x (mod y)
2234             # means that there is some integer k such that z - x = k y. If y = 0, we
2235             # get z - x = 0 or z = x. This is also what earlier versions did, except
2236             # that 0 % 0 returned NaN.
2237             #
2238             # inf / 0 = inf inf % 0 = inf
2239             # 5 / 0 = inf 5 % 0 = 5
2240             # 0 / 0 = NaN 0 % 0 = 0
2241             # -5 / 0 = -inf -5 % 0 = -5
2242             # -inf / 0 = -inf -inf % 0 = -inf
2243              
2244 366 100       924 if ($y -> is_zero()) {
2245 30         54 my $rem;
2246 30 100       66 if ($wantarray) {
2247 15         48 $rem = $x -> copy(@r);
2248             }
2249 30 100       56 if ($x -> is_zero()) {
2250 6         27 $x = $x -> bnan(@r);
2251             } else {
2252 24         74 $x = $x -> binf($x -> {sign}, @r);
2253             }
2254 30 100       252 return $wantarray ? ($x, $rem) : $x;
2255             }
2256              
2257             # Numerator (dividend) is +/-inf, and denominator is finite and non-zero.
2258             # The divide by zero cases are covered above. In all of the cases listed
2259             # below we return the same as core Perl.
2260             #
2261             # inf / -inf = NaN inf % -inf = NaN
2262             # inf / -5 = -inf inf % -5 = NaN
2263             # inf / 5 = inf inf % 5 = NaN
2264             # inf / inf = NaN inf % inf = NaN
2265             #
2266             # -inf / -inf = NaN -inf % -inf = NaN
2267             # -inf / -5 = inf -inf % -5 = NaN
2268             # -inf / 5 = -inf -inf % 5 = NaN
2269             # -inf / inf = NaN -inf % inf = NaN
2270              
2271 336 100       730 if ($x -> is_inf()) {
2272 48         105 my $rem;
2273 48 100       127 $rem = $class -> bnan(@r) if $wantarray;
2274 48 100       100 if ($y -> is_inf()) {
2275 24         70 $x = $x -> bnan(@r);
2276             } else {
2277 24 100       87 my $sign = $x -> bcmp(0) == $y -> bcmp(0) ? '+' : '-';
2278 24         73 $x = $x -> binf($sign,@r );
2279             }
2280 48 100       421 return $wantarray ? ($x, $rem) : $x;
2281             }
2282              
2283             # Denominator (divisor) is +/-inf. The cases when the numerator is +/-inf
2284             # are covered above. In the modulo cases (in the right column) we return
2285             # the same as core Perl, which does floored division, so for consistency we
2286             # also do floored division in the division cases (in the left column).
2287             #
2288             # -5 / inf = 0 -5 % inf = -5
2289             # 0 / inf = 0 0 % inf = 0
2290             # 5 / inf = 0 5 % inf = 5
2291             #
2292             # -5 / -inf = 0 -5 % -inf = -5
2293             # 0 / -inf = 0 0 % -inf = 0
2294             # 5 / -inf = 0 5 % -inf = 5
2295              
2296 288 100       488 if ($y -> is_inf()) {
2297 36         88 my $rem;
2298 36 100       89 $rem = $x -> copy() -> round(@r) if $wantarray;
2299 36         113 $x = $x -> bzero(@r);
2300 36 100       293 return $wantarray ? ($x, $rem) : $x;
2301             }
2302              
2303             # Division might return a non-integer result, so upgrade unconditionally, if
2304             # upgrading is enabled.
2305              
2306 252 50       533 return $upgrade -> btdiv($x, $y, @r) if defined $upgrade;
2307              
2308 252         418 $r[3] = $y; # no push!
2309              
2310             # Inialize remainder.
2311              
2312 252         531 my $rem = $class -> bzero();
2313              
2314             # Are both operands the same object, i.e., like $x -> bdiv($x)? If so,
2315             # flipping the sign of $y also flips the sign of $x.
2316              
2317 252         485 my $xsign = $x -> {sign};
2318 252         413 my $ysign = $y -> {sign};
2319              
2320 252         498 $y -> {sign} =~ tr/+-/-+/; # Flip the sign of $y, and see ...
2321 252         461 my $same = $xsign ne $x -> {sign}; # ... if that changed the sign of $x.
2322 252         401 $y -> {sign} = $ysign; # Re-insert the original sign.
2323              
2324 252 50       455 if ($same) {
2325 0         0 $x = $x -> bone(@r);
2326             } else {
2327             ($x -> {value}, $rem -> {value}) =
2328 252         784 $LIB -> _div($x -> {value}, $y -> {value});
2329              
2330 252 100       629 $x -> {sign} = $xsign eq $ysign ? '+' : '-';
2331 252 100       635 $x -> {sign} = '+' if $LIB -> _is_zero($x -> {value});
2332 252         611 $x = $x -> round(@r);
2333             }
2334              
2335 252 100       538 if (wantarray) {
2336 126         247 $rem -> {sign} = $xsign;
2337 126 100       340 $rem -> {sign} = '+' if $LIB -> _is_zero($rem -> {value});
2338 126         228 $rem -> {_a} = $x -> {_a};
2339 126         176 $rem -> {_p} = $x -> {_p};
2340 126         246 $rem = $rem -> round(@r);
2341 126         547 return ($x, $rem);
2342             }
2343              
2344 126         1502 return $x;
2345             }
2346              
2347             sub bmod {
2348             # This is the remainder after floored division.
2349              
2350             # Set up parameters.
2351 700 100 100 700 1 4766 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
2352             ? (ref($_[0]), @_)
2353             : objectify(2, @_);
2354              
2355 700 50       2225 return $x if $x -> modify('bmod');
2356              
2357 700         1286 $r[3] = $y; # no push!
2358              
2359             # At least one argument is NaN.
2360              
2361 700 100 100     1494 if ($x -> is_nan() || $y -> is_nan()) {
2362 27         79 return $x -> bnan(@r);
2363             }
2364              
2365             # Modulo zero. See documentation for bdiv().
2366              
2367 673 100       1543 if ($y -> is_zero()) {
2368 34         99 return $x -> round(@r);
2369             }
2370              
2371             # Numerator (dividend) is +/-inf.
2372              
2373 639 100       1615 if ($x -> is_inf()) {
2374 48         172 return $x -> bnan(@r);
2375             }
2376              
2377             # Denominator (divisor) is +/-inf.
2378              
2379 591 100       1189 if ($y -> is_inf()) {
2380 40 100 100     198 if ($x -> is_zero() || $x -> bcmp(0) == $y -> bcmp(0)) {
2381 28         103 return $x -> round(@r);
2382             } else {
2383 12         86 return $x -> binf($y -> sign(), @r);
2384             }
2385             }
2386              
2387 551 50 33     1526 return $upgrade -> bmod($x, $y, @r)
      66        
2388             if defined($upgrade) && (!$x -> isa(__PACKAGE__) ||
2389             !$y -> isa(__PACKAGE__));
2390              
2391             # Calc new sign and in case $y == +/- 1, return $x.
2392              
2393 551         1735 $x -> {value} = $LIB -> _mod($x -> {value}, $y -> {value});
2394 551 100       1516 if ($LIB -> _is_zero($x -> {value})) {
2395 154         365 $x -> {sign} = '+'; # do not leave -0
2396             } else {
2397             $x -> {value} = $LIB -> _sub($y -> {value}, $x -> {value}, 1) # $y-$x
2398 397 100       1294 if ($x -> {sign} ne $y -> {sign});
2399 397         743 $x -> {sign} = $y -> {sign};
2400             }
2401              
2402 551         1353 $x -> round(@r);
2403             }
2404              
2405             sub btmod {
2406             # Remainder after truncated division.
2407              
2408             # set up parameters
2409 0 0 0 0 1 0 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
2410             ? (ref($_[0]), @_)
2411             : objectify(2, @_);
2412              
2413 0 0       0 return $x if $x -> modify('btmod');
2414              
2415             # At least one argument is NaN.
2416              
2417 0 0 0     0 if ($x -> is_nan() || $y -> is_nan()) {
2418 0         0 return $x -> bnan(@r);
2419             }
2420              
2421             # Modulo zero. See documentation for btdiv().
2422              
2423 0 0       0 if ($y -> is_zero()) {
2424 0         0 return $x -> round(@r);
2425             }
2426              
2427             # Numerator (dividend) is +/-inf.
2428              
2429 0 0       0 if ($x -> is_inf()) {
2430 0         0 return $x -> bnan(@r);
2431             }
2432              
2433             # Denominator (divisor) is +/-inf.
2434              
2435 0 0       0 if ($y -> is_inf()) {
2436 0         0 return $x -> round(@r);
2437             }
2438              
2439 0 0 0     0 return $upgrade -> btmod($x, $y, @r)
      0        
2440             if defined($upgrade) && (!$x -> isa(__PACKAGE__) ||
2441             !$y -> isa(__PACKAGE__));
2442              
2443 0         0 $r[3] = $y; # no push!
2444              
2445 0         0 my $xsign = $x -> {sign};
2446              
2447 0         0 $x -> {value} = $LIB -> _mod($x -> {value}, $y -> {value});
2448              
2449 0         0 $x -> {sign} = $xsign;
2450 0 0       0 $x -> {sign} = '+' if $LIB -> _is_zero($x -> {value});
2451 0         0 $x -> round(@r);
2452             }
2453              
2454             sub bmodinv {
2455             # Return modular multiplicative inverse:
2456             #
2457             # z is the modular inverse of x (mod y) if and only if
2458             #
2459             # x*z ≡ 1 (mod y)
2460             #
2461             # If the modulus y is larger than one, x and z are relative primes (i.e.,
2462             # their greatest common divisor is one).
2463             #
2464             # If no modular multiplicative inverse exists, NaN is returned.
2465              
2466             # set up parameters
2467 243 50 33 243 1 2228 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
2468             ? (ref($_[0]), @_)
2469             : objectify(2, @_);
2470              
2471 243 50       720 return $x if $x->modify('bmodinv');
2472              
2473             # Return NaN if one or both arguments is +inf, -inf, or nan.
2474              
2475             return $x->bnan(@r) if ($y->{sign} !~ /^[+-]$/ ||
2476 243 100 100     1246 $x->{sign} !~ /^[+-]$/);
2477              
2478             # Return NaN if $y is zero; 1 % 0 makes no sense.
2479              
2480 222 50       560 return $x->bnan(@r) if $y->is_zero();
2481              
2482             # Return 0 in the trivial case. $x % 1 or $x % -1 is zero for all finite
2483             # integers $x.
2484              
2485 222 100 66     545 return $x->bzero(@r) if ($y->is_one('+') ||
2486             $y->is_one('-'));
2487              
2488 159 50 0     437 return $upgrade -> bmodinv($x, $y, @r)
      33        
2489             if defined($upgrade) && (!$x -> isa(__PACKAGE__) ||
2490             !$y -> isa(__PACKAGE__));
2491              
2492             # Return NaN if $x = 0, or $x modulo $y is zero. The only valid case when
2493             # $x = 0 is when $y = 1 or $y = -1, but that was covered above.
2494             #
2495             # Note that computing $x modulo $y here affects the value we'll feed to
2496             # $LIB->_modinv() below when $x and $y have opposite signs. E.g., if $x =
2497             # 5 and $y = 7, those two values are fed to _modinv(), but if $x = -5 and
2498             # $y = 7, the values fed to _modinv() are $x = 2 (= -5 % 7) and $y = 7.
2499             # The value if $x is affected only when $x and $y have opposite signs.
2500              
2501 159         422 $x = $x->bmod($y);
2502 159 100       453 return $x->bnan(@r) if $x->is_zero();
2503              
2504             # Compute the modular multiplicative inverse of the absolute values. We'll
2505             # correct for the signs of $x and $y later. Return NaN if no GCD is found.
2506              
2507 123         432 ($x->{value}, $x->{sign}) = $LIB->_modinv($x->{value}, $y->{value});
2508 123 100       382 return $x->bnan(@r) if !defined($x->{value});
2509              
2510             # Library inconsistency workaround: _modinv() in Math::BigInt::GMP versions
2511             # <= 1.32 return undef rather than a "+" for the sign.
2512              
2513 102 50       230 $x->{sign} = '+' unless defined $x->{sign};
2514              
2515             # When one or both arguments are negative, we have the following
2516             # relations. If x and y are positive:
2517             #
2518             # modinv(-x, -y) = -modinv(x, y)
2519             # modinv(-x, y) = y - modinv(x, y) = -modinv(x, y) (mod y)
2520             # modinv( x, -y) = modinv(x, y) - y = modinv(x, y) (mod -y)
2521              
2522             # We must swap the sign of the result if the original $x is negative.
2523             # However, we must compensate for ignoring the signs when computing the
2524             # inverse modulo. The net effect is that we must swap the sign of the
2525             # result if $y is negative.
2526              
2527 102 100       260 $x = $x -> bneg() if $y->{sign} eq '-';
2528              
2529             # Compute $x modulo $y again after correcting the sign.
2530              
2531 102 100       305 $x = $x -> bmod($y) if $x->{sign} ne $y->{sign};
2532              
2533 102         238 $x -> round(@r);
2534             }
2535              
2536             sub bmodpow {
2537             # Modular exponentiation. Raises a very large number to a very large
2538             # exponent in a given very large modulus quickly, thanks to binary
2539             # exponentiation. Supports negative exponents.
2540 501 50 33 501 1 7721 my ($class, $num, $exp, $mod, @r)
2541             = ref($_[0]) && ref($_[0]) eq ref($_[1]) && ref($_[1]) eq ref($_[2])
2542             ? (ref($_[0]), @_)
2543             : objectify(3, @_);
2544              
2545 501 50       1483 return $num if $num->modify('bmodpow');
2546              
2547             # When the exponent 'e' is negative, use the following relation, which is
2548             # based on finding the multiplicative inverse 'd' of 'b' modulo 'm':
2549             #
2550             # b^(-e) (mod m) = d^e (mod m) where b*d = 1 (mod m)
2551              
2552 501 100       1377 $num = $num -> bmodinv($mod) if ($exp->{sign} eq '-');
2553              
2554             # Check for valid input. All operands must be finite, and the modulus must
2555             # be non-zero.
2556              
2557             return $num->bnan(@r) if ($num->{sign} =~ /NaN|inf/ || # NaN, -inf, +inf
2558             $exp->{sign} =~ /NaN|inf/ || # NaN, -inf, +inf
2559 501 100 100     2800 $mod->{sign} =~ /NaN|inf/); # NaN, -inf, +inf
      100        
2560              
2561             # Modulo zero. See documentation for Math::BigInt's bmod() method.
2562              
2563 435 100       1022 if ($mod -> is_zero()) {
2564 3 50       15 if ($num -> is_zero()) {
2565 0         0 return $class -> bnan(@r);
2566             } else {
2567 3         37 return $num -> copy(@r);
2568             }
2569             }
2570              
2571 432 50 0     1179 return $upgrade -> bmodinv($num, $exp, $mod, @r)
      33        
2572             if defined($upgrade) && (!$num -> isa(__PACKAGE__) ||
2573             !$exp -> isa(__PACKAGE__) ||
2574             !$mod -> ($class));
2575              
2576             # Compute 'a (mod m)', ignoring the signs on 'a' and 'm'. If the resulting
2577             # value is zero, the output is also zero, regardless of the signs on 'a' and
2578             # 'm'.
2579              
2580 432         1285 my $value = $LIB->_modpow($num->{value}, $exp->{value}, $mod->{value});
2581 432         703 my $sign = '+';
2582              
2583             # If the resulting value is non-zero, we have four special cases, depending
2584             # on the signs on 'a' and 'm'.
2585              
2586 432 100       991 unless ($LIB->_is_zero($value)) {
2587              
2588             # There is a negative sign on 'a' (= $num**$exp) only if the number we
2589             # are exponentiating ($num) is negative and the exponent ($exp) is odd.
2590              
2591 213 100 100     683 if ($num->{sign} eq '-' && $exp->is_odd()) {
2592              
2593             # When both the number 'a' and the modulus 'm' have a negative sign,
2594             # use this relation:
2595             #
2596             # -a (mod -m) = -(a (mod m))
2597              
2598 21 50       60 if ($mod->{sign} eq '-') {
2599 0         0 $sign = '-';
2600             }
2601              
2602             # When only the number 'a' has a negative sign, use this relation:
2603             #
2604             # -a (mod m) = m - (a (mod m))
2605              
2606             else {
2607             # Use copy of $mod since _sub() modifies the first argument.
2608 21         57 my $mod = $LIB->_copy($mod->{value});
2609 21         73 $value = $LIB->_sub($mod, $value);
2610 21         42 $sign = '+';
2611             }
2612              
2613             } else {
2614              
2615             # When only the modulus 'm' has a negative sign, use this relation:
2616             #
2617             # a (mod -m) = (a (mod m)) - m
2618             # = -(m - (a (mod m)))
2619              
2620 192 100       428 if ($mod->{sign} eq '-') {
2621             # Use copy of $mod since _sub() modifies the first argument.
2622 3         14 my $mod = $LIB->_copy($mod->{value});
2623 3         15 $value = $LIB->_sub($mod, $value);
2624 3         14 $sign = '-';
2625             }
2626              
2627             # When neither the number 'a' nor the modulus 'm' have a negative
2628             # sign, directly return the already computed value.
2629             #
2630             # (a (mod m))
2631              
2632             }
2633              
2634             }
2635              
2636 432         773 $num->{value} = $value;
2637 432         714 $num->{sign} = $sign;
2638              
2639 432         967 return $num -> round(@r);
2640             }
2641              
2642             sub bpow {
2643             # (BINT or num_str, BINT or num_str) return BINT
2644             # compute power of two numbers -- stolen from Knuth Vol 2 pg 233
2645             # modifies first argument
2646              
2647             # set up parameters
2648 575 100 100 575 1 3309 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
2649             ? (ref($_[0]), @_)
2650             : objectify(2, @_);
2651              
2652 575 50       1835 return $x if $x -> modify('bpow');
2653              
2654             # $x and/or $y is a NaN
2655 575 100 100     1238 return $x -> bnan(@r) if $x -> is_nan() || $y -> is_nan();
2656              
2657             # $x and/or $y is a +/-Inf
2658 510 100       1321 if ($x -> is_inf("-")) {
    100          
    100          
    100          
2659 39 100       123 return $x -> bzero(@r) if $y -> is_negative();
2660 23 100       90 return $x -> bnan(@r) if $y -> is_zero();
2661 20 100       90 return $x -> round(@r) if $y -> is_odd();
2662 10         55 return $x -> bneg(@r);
2663             } elsif ($x -> is_inf("+")) {
2664 35 100       139 return $x -> bzero(@r) if $y -> is_negative();
2665 19 100       77 return $x -> bnan(@r) if $y -> is_zero();
2666 16         68 return $x -> round(@r);
2667             } elsif ($y -> is_inf("-")) {
2668 21 100       79 return $x -> bnan(@r) if $x -> is_one("-");
2669 18 100       47 return $x -> binf("+", @r) if $x -> is_zero();
2670 15 100       44 return $x -> bone(@r) if $x -> is_one("+");
2671 12         41 return $x -> bzero(@r);
2672             } elsif ($y -> is_inf("+")) {
2673 21 100       83 return $x -> bnan(@r) if $x -> is_one("-");
2674 18 100       85 return $x -> bzero(@r) if $x -> is_zero();
2675 15 100       45 return $x -> bone(@r) if $x -> is_one("+");
2676 12         48 return $x -> binf("+", @r);
2677             }
2678              
2679 394 100       1271 if ($x -> is_zero()) {
2680 26 100       89 return $x -> bone(@r) if $y -> is_zero();
2681 22 100       59 return $x -> binf(@r) if $y -> is_negative();
2682 11         71 return $x -> round(@r);
2683             }
2684              
2685 368 100       1057 if ($x -> is_one("+")) {
2686 28         90 return $x -> round(@r);
2687             }
2688              
2689 340 100       799 if ($x -> is_one("-")) {
2690 31 100       124 return $x -> round(@r) if $y -> is_odd();
2691 14         54 return $x -> bneg(@r);
2692             }
2693              
2694 309 100       874 return $upgrade -> bpow($x, $y, @r) if defined $upgrade;
2695              
2696             # We don't support finite non-integers, so return zero. The reason for
2697             # returning zero, not NaN, is that all output is in the open interval (0,1),
2698             # and truncating that to integer gives zero.
2699              
2700 271 100 66     1549 if ($y->{sign} eq '-' || !$y -> isa(__PACKAGE__)) {
2701 36         99 return $x -> bzero(@r);
2702             }
2703              
2704 235         493 $r[3] = $y; # no push!
2705              
2706 235         880 $x->{value} = $LIB -> _pow($x->{value}, $y->{value});
2707 235 100 100     731 $x->{sign} = $x -> is_negative() && $y -> is_odd() ? '-' : '+';
2708 235         707 $x -> round(@r);
2709             }
2710              
2711             sub blog {
2712             # Return the logarithm of the operand. If a second operand is defined, that
2713             # value is used as the base, otherwise the base is assumed to be Euler's
2714             # constant.
2715              
2716 199     199 1 2770 my ($class, $x, $base, @r);
2717              
2718             # Only objectify the base if it is defined, since an undefined base, as in
2719             # $x->blog() or $x->blog(undef) signals that the base is Euler's number =
2720             # 2.718281828...
2721              
2722 199 50 33     659 if (!ref($_[0]) && $_[0] =~ /^[a-z]\w*(?:::\w+)*$/i) {
2723             # E.g., Math::BigInt->blog(256, 2)
2724 0 0       0 ($class, $x, $base, @r) =
2725             defined $_[2] ? objectify(2, @_) : objectify(1, @_);
2726             } else {
2727             # E.g., $x->blog(2) or the deprecated Math::BigInt::blog(256, 2)
2728 199 100       674 ($class, $x, $base, @r) =
2729             defined $_[1] ? objectify(2, @_) : objectify(1, @_);
2730             }
2731              
2732 199 50       667 return $x if $x->modify('blog');
2733              
2734             # Handle all exception cases and all trivial cases. I have used Wolfram
2735             # Alpha (http://www.wolframalpha.com) as the reference for these cases.
2736              
2737 199 100       455 return $x -> bnan(@r) if $x -> is_nan();
2738              
2739 190 100       416 if (defined $base) {
2740 160 50 33     928 $base = $class -> new($base)
2741             unless defined(blessed($base)) && $base -> isa(__PACKAGE__);
2742 160 100 100     322 if ($base -> is_nan() || $base -> is_one()) {
    100 100        
    100          
2743 12         99 return $x -> bnan(@r);
2744             } elsif ($base -> is_inf() || $base -> is_zero()) {
2745 36 100 100     65 return $x -> bnan(@r) if $x -> is_inf() || $x -> is_zero();
2746 15         45 return $x -> bzero(@r);
2747             } elsif ($base -> is_negative()) { # -inf < base < 0
2748 12 100       35 return $x -> bzero(@r) if $x -> is_one(); # x = 1
2749 9 50       31 return $x -> bone('+', @r) if $x == $base; # x = base
2750             # we can't handle these cases, so upgrade, if we can
2751 9 50       25 return $upgrade -> blog($x, $base, @r) if defined $upgrade;
2752 9         31 return $x -> bnan(@r);
2753             }
2754 100 100       302 return $x -> bone(@r) if $x == $base; # 0 < base && 0 < x < inf
2755             }
2756              
2757             # We now know that the base is either undefined or >= 2 and finite.
2758              
2759 127 100       357 if ($x -> is_inf()) { # x = +/-inf
    100          
    100          
    100          
2760 15         51 return $x -> binf('+', @r);
2761             } elsif ($x -> is_neg()) { # -inf < x < 0
2762 6 50       26 return $upgrade -> blog($x, $base, @r) if defined $upgrade;
2763 6         24 return $x -> bnan(@r);
2764             } elsif ($x -> is_one()) { # x = 1
2765 9         44 return $x -> bzero(@r);
2766             } elsif ($x -> is_zero()) { # x = 0
2767 6         42 return $x -> binf('-', @r);
2768             }
2769              
2770             # At this point we are done handling all exception cases and trivial cases.
2771              
2772 91 100       291 return $upgrade -> blog($x, $base, @r) if defined $upgrade;
2773              
2774             # fix for bug #24969:
2775             # the default base is e (Euler's number) which is not an integer
2776 89 100       206 if (!defined $base) {
2777 15         114 require Math::BigFloat;
2778              
2779             # disable upgrading and downgrading
2780              
2781 15         85 my $upg = Math::BigFloat -> upgrade();
2782 15         67 my $dng = Math::BigFloat -> downgrade();
2783 15         65 Math::BigFloat -> upgrade(undef);
2784 15         58 Math::BigFloat -> downgrade(undef);
2785              
2786 15         112 my $u = Math::BigFloat -> blog($x) -> as_int();
2787              
2788             # reset upgrading and downgrading
2789              
2790 15         120 Math::BigFloat -> upgrade($upg);
2791 15         73 Math::BigFloat -> downgrade($dng);
2792              
2793             # modify $x in place
2794              
2795 15         91 $x->{value} = $u->{value};
2796 15         49 $x->{sign} = $u->{sign};
2797              
2798 15         59 return $x -> round(@r);
2799             }
2800              
2801 74         240 my ($rc) = $LIB -> _log_int($x->{value}, $base->{value});
2802 74 50       187 return $x -> bnan(@r) unless defined $rc; # not possible to take log?
2803 74         131 $x->{value} = $rc;
2804 74         189 $x = $x -> round(@r);
2805             }
2806              
2807             sub bexp {
2808             # Calculate e ** $x (Euler's number to the power of X), truncated to
2809             # an integer value.
2810 15 50   15 1 207 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
2811              
2812 15 50       64 return $x if $x->modify('bexp');
2813              
2814             # inf, -inf, NaN, <0 => NaN
2815 15 100       64 return $x -> bnan(@r) if $x->{sign} eq 'NaN';
2816 12 50       38 return $x -> bone(@r) if $x->is_zero();
2817 12 100       64 return $x -> round(@r) if $x->{sign} eq '+inf';
2818 9 50       34 return $x -> bzero(@r) if $x->{sign} eq '-inf';
2819              
2820 9 50       34 return $upgrade -> bexp($x, @r) if defined $upgrade;
2821              
2822 9         4669 require Math::BigFloat;
2823 9         54 my $tmp = Math::BigFloat -> bexp($x, @r) -> as_int();
2824 9         60 $x->{value} = $tmp->{value};
2825 9         27 return $x -> round(@r);
2826             }
2827              
2828             sub bnok {
2829             # Calculate n over k (binomial coefficient or "choose" function) as
2830             # integer.
2831              
2832             # Set up parameters.
2833 93 50 33 93 1 998 my ($class, $n, $k, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
2834             ? (ref($_[0]), @_)
2835             : objectify(2, @_);
2836              
2837 93 50       238 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
2838              
2839 93 50       286 return $n if $n->modify('bnok');
2840              
2841             # All cases where at least one argument is NaN.
2842              
2843 93 100 100     395 return $n->bnan(@r) if $n->{sign} eq 'NaN' || $k->{sign} eq 'NaN';
2844              
2845             # All cases where at least one argument is +/-inf.
2846              
2847 84 100       201 if ($n -> is_inf()) {
    50          
2848 7 50       40 if ($k -> is_inf()) { # bnok(+/-inf,+/-inf)
    50          
    50          
2849 0         0 return $n -> bnan(@r);
2850             } elsif ($k -> is_neg()) { # bnok(+/-inf,k), k < 0
2851 0         0 return $n -> bzero(@r);
2852             } elsif ($k -> is_zero()) { # bnok(+/-inf,k), k = 0
2853 0         0 return $n -> bone(@r);
2854             } else {
2855 7 50       52 if ($n -> is_inf("+", @r)) { # bnok(+inf,k), 0 < k < +inf
2856 7         56 return $n -> binf("+");
2857             } else { # bnok(-inf,k), k > 0
2858 0 0       0 my $sign = $k -> is_even() ? "+" : "-";
2859 0         0 return $n -> binf($sign, @r);
2860             }
2861             }
2862             }
2863              
2864             elsif ($k -> is_inf()) { # bnok(n,+/-inf), -inf <= n <= inf
2865 0         0 return $n -> bnan(@r);
2866             }
2867              
2868             # At this point, both n and k are real numbers.
2869              
2870 77 50 0     231 return $upgrade -> bnok($n, $k, @r)
      33        
2871             if defined($upgrade) && (!$n -> isa(__PACKAGE__) ||
2872             !$k -> isa(__PACKAGE__));
2873              
2874 77         115 my $sign = 1;
2875              
2876 77 50       231 if ($n >= 0) {
2877 77 100 100     230 if ($k < 0 || $k > $n) {
2878 21         129 return $n -> bzero(@r);
2879             }
2880             } else {
2881              
2882 0 0       0 if ($k >= 0) {
    0          
2883              
2884             # n < 0 and k >= 0: bnok(n,k) = (-1)^k * bnok(-n+k-1,k)
2885              
2886 0         0 $sign = (-1) ** $k;
2887 0         0 $n = $n -> bneg() -> badd($k) -> bdec();
2888              
2889             } elsif ($k <= $n) {
2890              
2891             # n < 0 and k <= n: bnok(n,k) = (-1)^(n-k) * bnok(-k-1,n-k)
2892              
2893 0         0 $sign = (-1) ** ($n - $k);
2894 0         0 my $x0 = $n -> copy();
2895 0         0 $n = $n -> bone() -> badd($k) -> bneg();
2896 0         0 $k = $k -> copy();
2897 0         0 $k = $k -> bneg() -> badd($x0);
2898              
2899             } else {
2900              
2901             # n < 0 and n < k < 0:
2902              
2903 0         0 return $n -> bzero(@r);
2904             }
2905             }
2906              
2907 56         257 $n->{value} = $LIB->_nok($n->{value}, $k->{value});
2908 56 50       149 $n = $n -> bneg() if $sign == -1;
2909              
2910 56         155 $n -> round(@r);
2911             }
2912              
2913             sub buparrow {
2914 0     0 1 0 my $a = shift;
2915 0         0 my $y = $a -> uparrow(@_);
2916 0         0 $a -> {value} = $y -> {value};
2917 0         0 return $a;
2918             }
2919              
2920             sub uparrow {
2921             # Knuth's up-arrow notation buparrow(a, n, b)
2922             #
2923             # The following is a simple, recursive implementation of the up-arrow
2924             # notation, just to show the idea. Such implementations cause "Deep
2925             # recursion on subroutine ..." warnings, so we use a faster, non-recursive
2926             # algorithm below with @_ as a stack.
2927             #
2928             # sub buparrow {
2929             # my ($a, $n, $b) = @_;
2930             # return $a ** $b if $n == 1;
2931             # return $a * $b if $n == 0;
2932             # return 1 if $b == 0;
2933             # return buparrow($a, $n - 1, buparrow($a, $n, $b - 1));
2934             # }
2935              
2936 0     0 1 0 my ($a, $b, $n) = @_;
2937 0         0 my $class = ref $a;
2938 0 0       0 croak("a must be non-negative") if $a < 0;
2939 0 0       0 croak("n must be non-negative") if $n < 0;
2940 0 0       0 croak("b must be non-negative") if $b < 0;
2941              
2942 0         0 while (@_ >= 3) {
2943              
2944             # return $a ** $b if $n == 1;
2945              
2946 0 0       0 if ($_[-2] == 1) {
2947 0         0 my ($a, $n, $b) = splice @_, -3;
2948 0         0 push @_, $a ** $b;
2949 0         0 next;
2950             }
2951              
2952             # return $a * $b if $n == 0;
2953              
2954 0 0       0 if ($_[-2] == 0) {
2955 0         0 my ($a, $n, $b) = splice @_, -3;
2956 0         0 push @_, $a * $b;
2957 0         0 next;
2958             }
2959              
2960             # return 1 if $b == 0;
2961              
2962 0 0       0 if ($_[-1] == 0) {
2963 0         0 splice @_, -3;
2964 0         0 push @_, $class -> bone();
2965 0         0 next;
2966             }
2967              
2968             # return buparrow($a, $n - 1, buparrow($a, $n, $b - 1));
2969              
2970 0         0 my ($a, $n, $b) = splice @_, -3;
2971 0         0 push @_, ($a, $n - 1,
2972             $a, $n, $b - 1);
2973              
2974             }
2975              
2976 0         0 pop @_;
2977             }
2978              
2979             sub backermann {
2980 0     0 1 0 my $m = shift;
2981 0         0 my $y = $m -> ackermann(@_);
2982 0         0 $m -> {value} = $y -> {value};
2983 0         0 return $m;
2984             }
2985              
2986             sub ackermann {
2987             # Ackermann's function ackermann(m, n)
2988             #
2989             # The following is a simple, recursive implementation of the ackermann
2990             # function, just to show the idea. Such implementations cause "Deep
2991             # recursion on subroutine ..." warnings, so we use a faster, non-recursive
2992             # algorithm below with @_ as a stack.
2993             #
2994             # sub ackermann {
2995             # my ($m, $n) = @_;
2996             # return $n + 1 if $m == 0;
2997             # return ackermann($m - 1, 1) if $m > 0 && $n == 0;
2998             # return ackermann($m - 1, ackermann($m, $n - 1) if $m > 0 && $n > 0;
2999             # }
3000              
3001 0     0 1 0 my ($m, $n) = @_;
3002 0         0 my $class = ref $m;
3003 0 0       0 croak("m must be non-negative") if $m < 0;
3004 0 0       0 croak("n must be non-negative") if $n < 0;
3005              
3006 0         0 my $two = $class -> new("2");
3007 0         0 my $three = $class -> new("3");
3008 0         0 my $thirteen = $class -> new("13");
3009              
3010 0         0 $n = pop;
3011 0 0       0 $n = $class -> new($n) unless ref($n);
3012 0         0 while (@_) {
3013 0         0 my $m = pop;
3014 0 0       0 if ($m > $three) {
    0          
    0          
    0          
3015 0         0 push @_, (--$m) x $n;
3016 0         0 while (--$m >= $three) {
3017 0         0 push @_, $m;
3018             }
3019 0         0 $n = $thirteen;
3020             } elsif ($m == $three) {
3021 0         0 $n = $class -> bone() -> blsft($n + $three) -> bsub($three);
3022             } elsif ($m == $two) {
3023 0         0 $n = $n -> bmul($two) -> badd($three);
3024             } elsif ($m >= 0) {
3025 0         0 $n = $n -> badd($m) -> binc();
3026             } else {
3027 0         0 die "negative m!";
3028             }
3029             }
3030 0         0 $n;
3031             }
3032              
3033             sub bsin {
3034             # Calculate sin(x) to N digits. Unless upgrading is in effect, returns the
3035             # result truncated to an integer.
3036 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
3037              
3038 0 0       0 return $x if $x->modify('bsin');
3039              
3040 0 0       0 return $x->bnan(@r) if $x->{sign} !~ /^[+-]\z/; # -inf +inf or NaN => NaN
3041 0 0       0 return $x->bzero(@r) if $x->is_zero();
3042              
3043 0 0       0 return $upgrade -> bsin($x, @r) if defined $upgrade;
3044              
3045 0         0 require Math::BigFloat;
3046             # calculate the result and truncate it to integer
3047 0         0 my $t = Math::BigFloat->new($x)->bsin(@r)->as_int();
3048              
3049 0 0       0 $x = $x->bone(@r) if $t->is_one();
3050 0 0       0 $x = $x->bzero(@r) if $t->is_zero();
3051 0         0 $x->round(@r);
3052             }
3053              
3054             sub bcos {
3055             # Calculate cos(x) to N digits. Unless upgrading is in effect, returns the
3056             # result truncated to an integer.
3057 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
3058              
3059 0 0       0 return $x if $x->modify('bcos');
3060              
3061 0 0       0 return $x->bnan(@r) if $x->{sign} !~ /^[+-]\z/; # -inf +inf or NaN => NaN
3062 0 0       0 return $x->bone(@r) if $x->is_zero();
3063              
3064 0 0       0 return $upgrade -> bcos($x, @r) if defined $upgrade;
3065              
3066 0         0 require Math::BigFloat;
3067 0         0 my $tmp = Math::BigFloat -> bcos($x, @r) -> as_int();
3068 0         0 $x->{value} = $tmp->{value};
3069 0         0 return $x -> round(@r);
3070             }
3071              
3072             sub batan {
3073             # Calculate arctan(x) to N digits. Unless upgrading is in effect, returns
3074             # the result truncated to an integer.
3075 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
3076              
3077 0 0       0 return $x if $x->modify('batan');
3078              
3079 0 0       0 return $x -> bnan(@r) if $x -> is_nan();
3080 0 0       0 return $x -> bzero(@r) if $x -> is_zero();
3081              
3082 0 0       0 return $upgrade -> batan($x, @r) if defined $upgrade;
3083              
3084 0 0       0 return $x -> bone("+", @r) if $x -> bgt("1");
3085 0 0       0 return $x -> bone("-", @r) if $x -> blt("-1");
3086              
3087 0         0 $x -> bzero(@r);
3088             }
3089              
3090             sub batan2 {
3091             # calculate arcus tangens of ($y/$x)
3092              
3093 84 50 33 84 1 1436 my ($class, $y, $x, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
3094             ? (ref($_[0]), @_) : objectify(2, @_);
3095              
3096 84 50       313 return $y if $y->modify('batan2');
3097              
3098 84 100 100     626 return $y->bnan() if ($y->{sign} eq $nan) || ($x->{sign} eq $nan);
3099              
3100 75 50       213 return $upgrade->batan2($y, $x, @r) if defined $upgrade;
3101              
3102             # Y X
3103             # != 0 -inf result is +- pi
3104 75 100 100     221 if ($x->is_inf() || $y->is_inf()) {
3105 30 100       60 if ($y->is_inf()) {
3106 18 100       63 if ($x->{sign} eq '-inf') {
    100          
3107             # calculate 3 pi/4 => 2.3.. => 2
3108 6         34 $y = $y->bone(substr($y->{sign}, 0, 1));
3109 6         59 $y = $y->bmul($class->new(2));
3110             } elsif ($x->{sign} eq '+inf') {
3111             # calculate pi/4 => 0.7 => 0
3112 6         20 $y = $y->bzero();
3113             } else {
3114             # calculate pi/2 => 1.5 => 1
3115 6         33 $y = $y->bone(substr($y->{sign}, 0, 1));
3116             }
3117             } else {
3118 12 100       53 if ($x->{sign} eq '+inf') {
3119             # calculate pi/4 => 0.7 => 0
3120 3         24 $y = $y->bzero();
3121             } else {
3122             # PI => 3.1415.. => 3
3123 9         37 $y = $y->bone(substr($y->{sign}, 0, 1));
3124 9         44 $y = $y->bmul($class->new(3));
3125             }
3126             }
3127 30         418 return $y;
3128             }
3129              
3130 45         301 require Math::BigFloat;
3131 45         182 my $r = Math::BigFloat->new($y)
3132             ->batan2(Math::BigFloat->new($x), @r)
3133             ->as_int();
3134              
3135 45         331 $x->{value} = $r->{value};
3136 45         137 $x->{sign} = $r->{sign};
3137              
3138 45         132 $x->round(@r);
3139             }
3140              
3141             sub bsqrt {
3142             # calculate square root of $x
3143 523 100   523 1 5197 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
3144              
3145 523 50       1615 return $x if $x->modify('bsqrt');
3146              
3147 523 100       2174 return $x->bnan(@r) if $x->{sign} !~ /^\+/; # -x or -inf or NaN => NaN
3148 507 100       1250 return $x->round(@r) if $x->{sign} eq '+inf'; # sqrt(+inf) == inf
3149              
3150 503 100       1141 return $upgrade->bsqrt($x, @r) if defined $upgrade;
3151              
3152 481         1603 $x->{value} = $LIB->_sqrt($x->{value});
3153 481         1401 $x->round(@r);
3154             }
3155              
3156             sub broot {
3157             # calculate $y'th root of $x
3158              
3159             # set up parameters
3160              
3161 174 100 66 174 1 2353 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
3162             ? (ref($_[0]), @_) : objectify(2, @_);
3163              
3164 174 50       454 $y = $class->new(2) unless defined $y;
3165              
3166 174 50       540 return $x if $x->modify('broot');
3167              
3168             # NaN handling: $x ** 1/0, x or y NaN, or y inf/-inf or y == 0
3169             return $x->bnan(@r) if $x->{sign} !~ /^\+/ || $y->is_zero() ||
3170 174 100 100     871 $y->{sign} !~ /^\+$/;
      100        
3171              
3172 99 100 100     242 return $x->round(@r)
      100        
      100        
3173             if $x->is_zero() || $x->is_one() || $x->is_inf() || $y->is_one();
3174              
3175 87 100       285 return $upgrade->broot($x, $y, @r) if defined $upgrade;
3176              
3177 85         333 $x->{value} = $LIB->_root($x->{value}, $y->{value});
3178 85         299 $x->round(@r);
3179             }
3180              
3181             sub bfac {
3182             # (BINT or num_str, BINT or num_str) return BINT
3183             # compute factorial number from $x, modify $x in place
3184 81 50   81 1 867 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
3185              
3186 81 100 66     446 return $x if $x->modify('bfac') || $x->{sign} eq '+inf'; # inf => inf
3187              
3188 78 100       202 return $x->bnan(@r) if $x->{sign} ne '+'; # NaN, <0 => NaN
3189              
3190 69 50 33     170 return $upgrade -> bfac($x, @r)
3191             if defined($upgrade) && !$x -> isa(__PACKAGE__);
3192              
3193 69         229 $x->{value} = $LIB->_fac($x->{value});
3194 69         235 $x->round(@r);
3195             }
3196              
3197             sub bdfac {
3198             # compute double factorial, modify $x in place
3199 54 50   54 1 644 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
3200              
3201 54 100 66     307 return $x if $x->modify('bdfac') || $x->{sign} eq '+inf'; # inf => inf
3202              
3203 51 100 100     123 return $x->bnan(@r) if $x->is_nan() || $x <= -2;
3204 42 100       371 return $x->bone(@r) if $x <= 1;
3205              
3206 33 50 33     117 return $upgrade -> bdfac($x, @r)
3207             if defined($upgrade) && !$x -> isa(__PACKAGE__);
3208              
3209 33 50       188 croak("bdfac() requires a newer version of the $LIB library.")
3210             unless $LIB->can('_dfac');
3211              
3212 33         112 $x->{value} = $LIB->_dfac($x->{value});
3213 33         92 $x->round(@r);
3214             }
3215              
3216             sub btfac {
3217             # compute triple factorial, modify $x in place
3218 57 50   57 1 877 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
3219              
3220 57 100 66     327 return $x if $x->modify('btfac') || $x->{sign} eq '+inf'; # inf => inf
3221              
3222 54 100       133 return $x->bnan(@r) if $x->is_nan();
3223              
3224 51 50 33     160 return $upgrade -> btfac($x, @r)
3225             if defined($upgrade) && !$x -> isa(__PACKAGE__);
3226              
3227 51         115 my $k = $class -> new("3");
3228 51 100       241 return $x->bnan(@r) if $x <= -$k;
3229              
3230 45         190 my $one = $class -> bone();
3231 45 100       100 return $x->bone(@r) if $x <= $one;
3232              
3233 33         112 my $f = $x -> copy();
3234 33         107 while ($f -> bsub($k) > $one) {
3235 45         143 $x = $x -> bmul($f);
3236             }
3237 33         88 $x->round(@r);
3238             }
3239              
3240             sub bmfac {
3241             # compute multi-factorial
3242              
3243 270 50 33 270 1 4057 my ($class, $x, $k, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
3244             ? (ref($_[0]), @_) : objectify(2, @_);
3245              
3246 270 100 66     1434 return $x if $x->modify('bmfac') || $x->{sign} eq '+inf';
3247 255 100 100     596 return $x->bnan(@r) if $x->is_nan() || $k->is_nan() || $k < 1 || $x <= -$k;
      100        
      100        
3248              
3249 198 50 33     732 return $upgrade -> bmfac($x, $k, @r)
3250             if defined($upgrade) && !$x -> isa(__PACKAGE__);
3251              
3252 198         478 my $one = $class -> bone();
3253 198 100       431 return $x->bone(@r) if $x <= $one;
3254              
3255 138         352 my $f = $x -> copy();
3256 138         400 while ($f -> bsub($k) > $one) {
3257 213         559 $x = $x -> bmul($f);
3258             }
3259 138         338 $x->round(@r);
3260             }
3261              
3262             sub bfib {
3263             # compute Fibonacci number(s)
3264 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
3265              
3266 0 0       0 croak("bfib() requires a newer version of the $LIB library.")
3267             unless $LIB->can('_fib');
3268              
3269 0 0       0 return $x if $x->modify('bfib');
3270              
3271 0 0 0     0 return $upgrade -> bfib($x, @r)
3272             if defined($upgrade) && !$x -> isa(__PACKAGE__);
3273              
3274             # List context.
3275              
3276 0 0       0 if (wantarray) {
3277 0 0       0 return () if $x -> is_nan();
3278 0 0       0 croak("bfib() can't return an infinitely long list of numbers")
3279             if $x -> is_inf();
3280              
3281             # Use the backend library to compute the first $x Fibonacci numbers.
3282              
3283 0         0 my @values = $LIB->_fib($x->{value});
3284              
3285             # Make objects out of them. The last element in the array is the
3286             # invocand.
3287              
3288 0         0 for (my $i = 0 ; $i < $#values ; ++ $i) {
3289 0         0 my $fib = $class -> bzero();
3290 0         0 $fib -> {value} = $values[$i];
3291 0         0 $values[$i] = $fib;
3292             }
3293              
3294 0         0 $x -> {value} = $values[-1];
3295 0         0 $values[-1] = $x;
3296              
3297             # If negative, insert sign as appropriate.
3298              
3299 0 0       0 if ($x -> is_neg()) {
3300 0         0 for (my $i = 2 ; $i <= $#values ; $i += 2) {
3301 0         0 $values[$i]{sign} = '-';
3302             }
3303             }
3304              
3305 0         0 @values = map { $_ -> round(@r) } @values;
  0         0  
3306 0         0 return @values;
3307             }
3308              
3309             # Scalar context.
3310              
3311             else {
3312 0 0 0     0 return $x if $x->modify('bdfac') || $x -> is_inf('+');
3313 0 0 0     0 return $x->bnan() if $x -> is_nan() || $x -> is_inf('-');
3314              
3315 0 0 0     0 $x->{sign} = $x -> is_neg() && $x -> is_even() ? '-' : '+';
3316 0         0 $x->{value} = $LIB->_fib($x->{value});
3317 0         0 return $x->round(@r);
3318             }
3319             }
3320              
3321             sub blucas {
3322             # compute Lucas number(s)
3323 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
3324              
3325 0 0       0 croak("blucas() requires a newer version of the $LIB library.")
3326             unless $LIB->can('_lucas');
3327              
3328 0 0       0 return $x if $x->modify('blucas');
3329              
3330 0 0 0     0 return $upgrade -> blucas($x, @r)
3331             if defined($upgrade) && !$x -> isa(__PACKAGE__);
3332              
3333             # List context.
3334              
3335 0 0       0 if (wantarray) {
3336 0 0       0 return () if $x -> is_nan();
3337 0 0       0 croak("blucas() can't return an infinitely long list of numbers")
3338             if $x -> is_inf();
3339              
3340             # Use the backend library to compute the first $x Lucas numbers.
3341              
3342 0         0 my @values = $LIB->_lucas($x->{value});
3343              
3344             # Make objects out of them. The last element in the array is the
3345             # invocand.
3346              
3347 0         0 for (my $i = 0 ; $i < $#values ; ++ $i) {
3348 0         0 my $lucas = $class -> bzero();
3349 0         0 $lucas -> {value} = $values[$i];
3350 0         0 $values[$i] = $lucas;
3351             }
3352              
3353 0         0 $x -> {value} = $values[-1];
3354 0         0 $values[-1] = $x;
3355              
3356             # If negative, insert sign as appropriate.
3357              
3358 0 0       0 if ($x -> is_neg()) {
3359 0         0 for (my $i = 2 ; $i <= $#values ; $i += 2) {
3360 0         0 $values[$i]{sign} = '-';
3361             }
3362             }
3363              
3364 0         0 @values = map { $_ -> round(@r) } @values;
  0         0  
3365 0         0 return @values;
3366             }
3367              
3368             # Scalar context.
3369              
3370             else {
3371 0 0       0 return $x if $x -> is_inf('+');
3372 0 0 0     0 return $x->bnan() if $x -> is_nan() || $x -> is_inf('-');
3373              
3374 0 0 0     0 $x->{sign} = $x -> is_neg() && $x -> is_even() ? '-' : '+';
3375 0         0 $x->{value} = $LIB->_lucas($x->{value});
3376 0         0 return $x->round(@r);
3377             }
3378             }
3379              
3380             sub blsft {
3381             # (BINT or num_str, BINT or num_str) return BINT
3382             # compute $x << $y, base $n
3383              
3384 62     62 1 542 my ($class, $x, $y, $b, @r);
3385              
3386             # Objectify the base only when it is defined, since an undefined base, as
3387             # in $x->blsft(3) or $x->blog(3, undef) means use the default base 2.
3388              
3389 62 100 66     268 if (!ref($_[0]) && $_[0] =~ /^[A-Za-z]|::/) {
3390             # E.g., Math::BigInt->blog(256, 5, 2)
3391 12 50       73 ($class, $x, $y, $b, @r) =
3392             defined $_[3] ? objectify(3, @_) : objectify(2, @_);
3393             } else {
3394             # E.g., Math::BigInt::blog(256, 5, 2) or $x->blog(5, 2)
3395 50 100       195 ($class, $x, $y, $b, @r) =
3396             defined $_[2] ? objectify(3, @_) : objectify(2, @_);
3397             }
3398              
3399 62 50       303 return $x if $x -> modify('blsft');
3400              
3401 62 100       155 $b = 2 unless defined $b;
3402 62 100       238 $b = $class -> new($b) unless defined(blessed($b));
3403              
3404 62 50 33     260 return $upgrade -> blsft($x, $y, $b, @r)
      66        
3405             if defined($upgrade) && (!$x -> isa(__PACKAGE__) ||
3406             !$y -> isa(__PACKAGE__) ||
3407             !$b -> isa(__PACKAGE__));
3408              
3409 62 50 33     150 return $x -> bnan(@r) if $x -> is_nan() || $y -> is_nan() || $b -> is_nan();
      33        
3410              
3411             # blsft($x, -$y, $b) = brsft($x, $y, $b)
3412              
3413 62 100       149 return $x -> brsft($y -> copy() -> bneg(), $b, @r) if $y -> is_neg();
3414              
3415 58         191 return $x -> bmul($b -> bpow($y));
3416              
3417             # Base $b = 1 changes nothing, not even when $b = Inf. Shifting zero places
3418             # ($y = 0) doesn't change anything either.
3419 0 0 0     0 return $x -> bround(@r) if $b -> is_one("+") || $y -> is_zero();
3420              
3421             # Shifting infinitely far to the left.
3422 0 0       0 if ($y -> is_inf("+")) {
3423 0 0       0 return $x -> binf("+", @r) if $x -> is_pos();
3424 0 0       0 return $x -> binf("-", @r) if $x -> is_neg();
3425 0         0 return $x -> bnan(@r); # Inf * 0 = NaN
3426             }
3427              
3428             # At this point we know that $b > 1, so we are essentially computing 0 *
3429             # Inf = NaN.
3430 0 0 0     0 return $x -> bnan(@r) if $x -> is_zero() && $y -> is_inf("+");
3431              
3432             # Handle trivial zero case.
3433 0 0       0 return $x -> bzero(@r) if $x -> is_zero();
3434              
3435 0 0       0 return $x -> binf("+", @r) if $y -> is_inf("+");
3436 0 0       0 return $x -> bzero(@r) if $x -> is_zero();
3437              
3438             # While some of the libraries support an arbitrarily large base, not all of
3439             # them do, so rather than returning an incorrect result in those cases,
3440             # disallow bases that don't work with all libraries.
3441              
3442 0         0 my $uintmax = ~0;
3443 0 0       0 if ($x -> bcmp($uintmax) > 0) {
3444 0         0 $x = $x -> bmul($b -> bpow($y));
3445             } else {
3446 0         0 $b = $b -> numify();
3447 0         0 $x -> {value} = $LIB -> _lsft($x -> {value}, $y -> {value}, $b);
3448             }
3449 0         0 $x -> round(@r);
3450             }
3451              
3452             sub brsft {
3453             # (BINT or num_str, BINT or num_str) return BINT
3454             # compute $x >> $y, base $n
3455              
3456 134     134 1 1350 my ($class, $x, $y, $b, @r) = (ref($_[0]), @_);
3457              
3458             # Objectify the base only when it is defined, since an undefined base, as
3459             # in $x->blsft(3) or $x->blog(3, undef) means use the default base 2.
3460              
3461 134 100 66     484 if (!ref($_[0]) && $_[0] =~ /^[A-Za-z]|::/) {
3462             # E.g., Math::BigInt->blog(256, 5, 2)
3463 12 50       60 ($class, $x, $y, $b, @r) =
3464             defined $_[3] ? objectify(3, @_) : objectify(2, @_);
3465             } else {
3466             # E.g., Math::BigInt::blog(256, 5, 2) or $x->blog(5, 2)
3467 122 100       404 ($class, $x, $y, $b, @r) =
3468             defined $_[2] ? objectify(3, @_) : objectify(2, @_);
3469             }
3470              
3471 134 50       566 return $x if $x -> modify('brsft');
3472              
3473 134 100       315 $b = 2 unless defined $b;
3474 134 100       485 $b = $class -> new($b) unless defined(blessed($b));
3475              
3476 134 50 33     1495 return $upgrade -> brsft($x, $y, $b, @r)
      66        
3477             if defined($upgrade) && (!$x -> isa(__PACKAGE__) ||
3478             !$y -> isa(__PACKAGE__) ||
3479             !$b -> isa(__PACKAGE__));
3480              
3481 134 50 33     310 return $x -> bnan(@r) if $x -> is_nan() || $y -> is_nan() || $b -> is_nan();
      33        
3482              
3483             # brsft($x, -$y, $b) = blsft($x, $y, $b)
3484              
3485 134 100       352 return $x -> blsft($y -> copy() -> bneg(), $b, @r) if $y -> is_neg();
3486              
3487 130 100       340 return $x -> round(@r) if $y -> is_zero();
3488 122 50       313 return $x -> bzero(@r) if $x -> is_zero();
3489              
3490             # Shifting right by a positive amount might lead to a non-integer result.
3491              
3492 122 100 66     354 return $upgrade -> brsft($x, $y, $b, @r)
3493             if defined($upgrade) && $y -> is_pos();
3494              
3495             # This only works for negative numbers when shifting in base 2.
3496 111 100 66     194 if ($x -> is_neg() && $b -> bcmp("2") == 0) {
3497 57 100       146 return $x -> round(@r) if $x -> is_one('-'); # -1 => -1
3498             # Although this is O(N*N) in Math::BigInt::Calc->_as_bin(), it is O(N)
3499             # in Pari et al., but perhaps there is a better emulation for two's
3500             # complement shift ... if $y != 1, we must simulate it by doing:
3501             # convert to bin, flip all bits, shift, and be done
3502 54         163 $x = $x -> binc(); # -3 => -2
3503 54         158 my $bin = $x -> to_bin(); # convert to string
3504 54         227 $bin =~ s/^-//; # strip leading minus
3505 54         112 $bin =~ tr/10/01/; # flip bits
3506 54         87 my $nbits = CORE::length($bin);
3507 54 100       161 return $x -> bone("-", @r) if $y >= $nbits;
3508 51         171 $bin = substr $bin, 0, $nbits - $y; # keep most significant bits
3509 51         163 $bin = '1' . $bin; # prepend one dummy '1'
3510 51         93 $bin =~ tr/10/01/; # flip bits back
3511 51         172 my $res = $class -> from_bin($bin); # convert back from string
3512 51         186 $res = $res -> binc(); # remember to increment
3513 51         119 $x -> {value} = $res -> {value}; # take over value
3514 51         102 return $x -> round(@r);
3515             }
3516              
3517             # While some of the libraries support an arbitrarily large base, not all of
3518             # them do, so rather than returning an incorrect result in those cases, use
3519             # division.
3520              
3521 54         100 my $uintmax = ~0;
3522 54 50 33     161 if ($x -> bcmp($uintmax) > 0 || $x -> is_neg()) {
3523 0         0 $x = $x -> bdiv($b -> bpow($y));
3524             } else {
3525 54         175 $b = $b -> numify();
3526 54         261 $x -> {value} = $LIB -> _rsft($x -> {value}, $y -> {value}, $b);
3527             }
3528              
3529 54         175 return $x -> round(@r);
3530             }
3531              
3532             ###############################################################################
3533             # Bitwise methods
3534             ###############################################################################
3535              
3536             # Bitwise left shift.
3537              
3538             sub bblsft {
3539             # We don't call objectify(), because the bitwise methods should not
3540             # upgrade/downgrade, even when upgrading/downgrading is enabled.
3541              
3542 35     35 1 90 my ($class, $x, $y, @r);
3543              
3544             # $x -> bblsft($y)
3545              
3546 35 100       123 if (ref($_[0])) {
3547 27         80 ($class, $x, $y, @r) = (ref($_[0]), @_);
3548 27 50 33     186 $y = $y -> as_int()
      33        
3549             if ref($y) && !$y -> isa(__PACKAGE__) && $y -> can('as_int');
3550 27 50       81 $y = $class -> new(int($y)) unless ref($y);
3551             }
3552              
3553             # $class -> bblsft($x, $y)
3554              
3555             else {
3556 8         29 ($class, $x, $y, @r) = @_;
3557 8         20 for ($x, $y) {
3558 16 50 33     78 $_ = $_ -> as_int()
      33        
3559             if ref($_) && !$_ -> isa(__PACKAGE__) && $_ -> can('as_int');
3560 16 50       63 $_ = $class -> new(int($_)) unless ref($_);
3561             }
3562             }
3563              
3564 35 50       139 return $x if $x -> modify('bblsft');
3565              
3566 35 100 66     99 return $x -> bnan(@r) if $x -> is_nan() || $y -> is_nan();
3567              
3568             # bblsft($x, -$y) = bbrsft($x, $y)
3569              
3570 31 100       110 return $x -> bbrsft($y -> copy() -> bneg()) if $y -> is_neg();
3571              
3572             # Shifting infinitely far to the left.
3573              
3574 27 50       90 if ($y -> is_inf("+")) {
3575 0 0       0 return $x -> binf("+", @r) if $x -> is_pos();
3576 0 0       0 return $x -> binf("-", @r) if $x -> is_neg();
3577 0         0 return $x -> bnan(@r);
3578             }
3579              
3580             # These cases change nothing.
3581              
3582 27 50 33     140 return $x -> round(@r) if $x -> is_zero() || $x -> is_inf() ||
      33        
3583             $y -> is_zero();
3584              
3585 27         187 $x -> {value} = $LIB -> _lsft($x -> {value}, $y -> {value}, 2);
3586 27         120 $x -> round(@r);
3587             }
3588              
3589             # Bitwise right shift.
3590              
3591             sub bbrsft {
3592             # We don't call objectify(), because the bitwise methods should not
3593             # upgrade/downgrade, even when upgrading/downgrading is enabled.
3594              
3595 35     35 1 75 my ($class, $x, $y, @r);
3596              
3597             # $x -> bblsft($y)
3598              
3599 35 100       102 if (ref($_[0])) {
3600 27         76 ($class, $x, $y, @r) = (ref($_[0]), @_);
3601 27 50 33     183 $y = $y -> as_int()
      33        
3602             if ref($y) && !$y -> isa(__PACKAGE__) && $y -> can('as_int');
3603 27 50       75 $y = $class -> new(int($y)) unless ref($y);
3604             }
3605              
3606             # $class -> bblsft($x, $y)
3607              
3608             else {
3609 8         24 ($class, $x, $y, @r) = @_;
3610 8         22 for ($x, $y) {
3611 16 50 33     68 $_ = $_ -> as_int()
      33        
3612             if ref($_) && !$_ -> isa(__PACKAGE__) && $_ -> can('as_int');
3613 16 50       71 $_ = $class -> new(int($_)) unless ref($_);
3614             }
3615             }
3616              
3617 35 50       146 return $x if $x -> modify('bbrsft');
3618              
3619 35 100 66     92 return $x -> bnan(@r) if $x -> is_nan() || $y -> is_nan();
3620              
3621             # bbrsft($x, -$y) = bblsft($x, $y)
3622              
3623 31 100       150 return $x -> bblsft($y -> copy() -> bneg()) if $y -> is_neg();
3624              
3625             # Shifting infinitely far to the right.
3626              
3627 27 50       85 if ($y -> is_inf("+")) {
3628 0 0       0 return $x -> bnan(@r) if $x -> is_inf();
3629 0 0       0 return $x -> bone("-", @r) if $x -> is_neg();
3630 0         0 return $x -> bzero(@r);
3631             }
3632              
3633             # These cases change nothing.
3634              
3635 27 50 33     130 return $x -> round(@r) if $x -> is_zero() || $x -> is_inf() ||
      33        
3636             $y -> is_zero();
3637              
3638             # At this point, $x is either positive or negative, not zero.
3639              
3640 27 50       139 if ($x -> is_pos()) {
3641 27         150 $x -> {value} = $LIB -> _rsft($x -> {value}, $y -> {value}, 2);
3642             } else {
3643 0         0 my $n = $x -> {value};
3644 0         0 my $d = $LIB -> _pow($LIB -> _new("2"), $y -> {value});
3645 0         0 my ($p, $q) = $LIB -> _div($n, $d);
3646 0 0       0 $p = $LIB -> _inc($p) unless $LIB -> _is_zero($q);
3647 0         0 $x -> {value} = $p;
3648             }
3649              
3650 27         130 $x -> round(@r);
3651             }
3652              
3653             sub band {
3654             #(BINT or num_str, BINT or num_str) return BINT
3655             # compute x & y
3656              
3657 175 100 66 175 1 1223 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
3658             ? (ref($_[0]), @_) : objectify(2, @_);
3659              
3660 175 50       615 return $x if $x->modify('band');
3661              
3662 175 100 66     552 return $upgrade -> band($x, $y, @r)
      100        
3663             if defined($upgrade) && (!$x -> isa(__PACKAGE__) ||
3664             !$y -> isa(__PACKAGE__));
3665              
3666 174         337 $r[3] = $y; # no push!
3667              
3668 174 100 100     1130 return $x->bnan(@r) if $x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/;
3669              
3670 162 100 100     601 if ($x->{sign} eq '+' && $y->{sign} eq '+') {
3671 129         487 $x->{value} = $LIB->_and($x->{value}, $y->{value});
3672             } else {
3673             ($x->{value}, $x->{sign}) = $LIB->_sand($x->{value}, $x->{sign},
3674 33         171 $y->{value}, $y->{sign});
3675             }
3676 162         453 return $x->round(@r);
3677             }
3678              
3679             sub bior {
3680             #(BINT or num_str, BINT or num_str) return BINT
3681             # compute x | y
3682              
3683 236 100 66 236 1 1585 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
3684             ? (ref($_[0]), @_) : objectify(2, @_);
3685              
3686 236 50       707 return $x if $x->modify('bior');
3687              
3688 236 100 66     777 return $upgrade -> bior($x, $y, @r)
      100        
3689             if defined($upgrade) && (!$x -> isa(__PACKAGE__) ||
3690             !$y -> isa(__PACKAGE__));
3691              
3692 235         415 $r[3] = $y; # no push!
3693              
3694 235 100 100     1368 return $x->bnan() if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/);
3695              
3696 223 100 100     814 if ($x->{sign} eq '+' && $y->{sign} eq '+') {
3697 188         672 $x->{value} = $LIB->_or($x->{value}, $y->{value});
3698             } else {
3699             ($x->{value}, $x->{sign}) = $LIB->_sor($x->{value}, $x->{sign},
3700 35         173 $y->{value}, $y->{sign});
3701             }
3702 223         629 return $x->round(@r);
3703             }
3704              
3705             sub bxor {
3706             #(BINT or num_str, BINT or num_str) return BINT
3707             # compute x ^ y
3708              
3709 246 100 66 246 1 1673 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
3710             ? (ref($_[0]), @_) : objectify(2, @_);
3711              
3712 246 50       824 return $x if $x->modify('bxor');
3713              
3714 246 100 66     792 return $upgrade -> bxor($x, $y, @r)
      100        
3715             if defined($upgrade) && (!$x -> isa(__PACKAGE__) ||
3716             !$y -> isa(__PACKAGE__));
3717              
3718 245         422 $r[3] = $y; # no push!
3719              
3720 245 100 100     1367 return $x->bnan(@r) if $x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/;
3721              
3722 233 100 100     856 if ($x->{sign} eq '+' && $y->{sign} eq '+') {
3723 193         766 $x->{value} = $LIB->_xor($x->{value}, $y->{value});
3724             } else {
3725             ($x->{value}, $x->{sign}) = $LIB->_sxor($x->{value}, $x->{sign},
3726 40         197 $y->{value}, $y->{sign});
3727             }
3728 233         714 return $x->round(@r);
3729             }
3730              
3731             sub bnot {
3732             # (num_str or BINT) return BINT
3733             # represent ~x as twos-complement number
3734 39 50   39 1 408 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
3735              
3736 39 50       146 return $x if $x->modify('bnot');
3737              
3738 39 50 66     123 return $upgrade -> bnot($x, @r)
3739             if defined($upgrade) && !$x -> isa(__PACKAGE__);
3740              
3741 39         113 $x -> binc() -> bneg(@r);
3742             }
3743              
3744             ###############################################################################
3745             # Rounding methods
3746             ###############################################################################
3747              
3748             sub round {
3749             # Round $self according to given parameters, or given second argument's
3750             # parameters or global defaults
3751              
3752 71804 50   71804 1 230953 my ($class, $self, @args) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
3753              
3754             # $x->round(undef, undef) signals no rounding
3755              
3756 71804 100 100     250711 if (@args >= 2 && @args <= 3 && !defined($args[0]) && !defined($args[1])) {
      100        
      100        
3757 3599         6937 $self->{_a} = undef;
3758 3599         6247 $self->{_p} = undef;
3759 3599         9170 return $self;
3760             }
3761              
3762 68205         150739 my ($a, $p, $r) = splice @args, 0, 3;
3763              
3764             # $a accuracy, if given by caller
3765             # $p precision, if given by caller
3766             # $r round_mode, if given by caller
3767             # @args all 'other' arguments (0 for unary, 1 for binary ops)
3768              
3769 68205 100       139128 if (defined $a) {
3770 304 50       1541 croak "accuracy must be a number, not '$a'"
3771             unless $a =~/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[Ee][+-]?\d+)?\z/;
3772             }
3773              
3774 68205 100       125881 if (defined $p) {
3775 92 50       534 croak "precision must be a number, not '$p'"
3776             unless $p =~/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[Ee][+-]?\d+)?\z/;
3777             }
3778              
3779             # now pick $a or $p, but only if we have got "arguments"
3780 68205 100       132460 if (!defined $a) {
3781 67901         123401 foreach ($self, @args) {
3782             # take the defined one, or if both defined, the one that is smaller
3783             $a = $_->{_a}
3784 108121 100 100     313156 if (defined $_->{_a}) && (!defined $a || $_->{_a} < $a);
      100        
3785             }
3786             }
3787 68205 100       126856 if (!defined $p) {
3788             # even if $a is defined, take $p, to signal error for both defined
3789 68113         107449 foreach ($self, @args) {
3790             # take the defined one, or if both defined, the one that is bigger
3791             # -2 > -3, and 3 > 2
3792             $p = $_->{_p}
3793 108356 100 66     227564 if (defined $_->{_p}) && (!defined $p || $_->{_p} > $p);
      66        
3794             }
3795             }
3796              
3797 51     51   654 no strict 'refs';
  51         147  
  51         406425  
3798              
3799             # if still none defined, use globals
3800 68205 100 100     195149 unless (defined $a || defined $p) {
3801 46880         62977 $a = ${"$class\::accuracy"};
  46880         143875  
3802 46880         67875 $p = ${"$class\::precision"};
  46880         96783  
3803             }
3804              
3805             # A == 0 is useless, so undef it to signal no rounding
3806 68205 100 100     168559 $a = undef if defined $a && $a == 0;
3807              
3808             # no rounding today?
3809 68205 100 100     281144 return $self unless defined $a || defined $p; # early out
3810              
3811             # set A and set P is an fatal error
3812 21363 100 100     60872 return $self->bnan() if defined $a && defined $p;
3813              
3814 21305 100       37414 $r = ${"$class\::round_mode"} unless defined $r;
  21244         73488  
3815 21305 50       80180 if ($r !~ /^(even|odd|[+-]inf|zero|trunc|common)$/) {
3816 0         0 croak("Unknown round mode '$r'");
3817             }
3818              
3819             # now round, by calling either bround or bfround:
3820 21305 100       39526 if (defined $a) {
3821             $self = $self->bround(int($a), $r)
3822 21140 100 100     110734 if !defined $self->{_a} || $self->{_a} >= $a;
3823             } else { # both can't be undefined due to early out
3824             $self = $self->bfround(int($p), $r)
3825 165 50 66     879 if !defined $self->{_p} || $self->{_p} <= $p;
3826             }
3827              
3828             # bround() or bfround() already called bnorm() if nec.
3829 21305         65065 $self;
3830             }
3831              
3832             sub bround {
3833             # accuracy: +$n preserve $n digits from left,
3834             # -$n preserve $n digits from right (f.i. for 0.1234 style in MBF)
3835             # no-op for $n == 0
3836             # and overwrite the rest with 0's, return normalized number
3837             # do not return $x->bnorm(), but $x
3838              
3839 26041 50   26041 1 84151 my ($class, $x, @a) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
3840              
3841 26041         54418 my ($scale, $mode) = $x->_scale_a(@a);
3842 26041 100 66     110155 return $x if !defined $scale || $x->modify('bround'); # no-op
3843              
3844 26039 100 100     59058 if ($x->is_zero() || $scale == 0) {
3845 101 100 66     436 $x->{_a} = $scale if !defined $x->{_a} || $x->{_a} > $scale; # 3 > 2
3846 101         369 return $x;
3847             }
3848 25938 100       72357 return $x if $x->{sign} !~ /^[+-]$/; # inf, NaN
3849              
3850             # we have fewer digits than we want to scale to
3851 25926         58327 my $len = $x->length();
3852             # convert $scale to a scalar in case it is an object (put's a limit on the
3853             # number length, but this would already limited by memory constraints),
3854             # makes it faster
3855 25926 50       50725 $scale = $scale->numify() if ref ($scale);
3856              
3857             # scale < 0, but > -len (not >=!)
3858 25926 100 66     100365 if (($scale < 0 && $scale < -$len-1) || ($scale >= $len)) {
      66        
3859 194 100 66     898 $x->{_a} = $scale if !defined $x->{_a} || $x->{_a} > $scale; # 3 > 2
3860 194         644 return $x;
3861             }
3862              
3863             # count of 0's to pad, from left (+) or right (-): 9 - +6 => 3, or |-6| => 6
3864 25732         39795 my ($pad, $digit_round, $digit_after);
3865 25732         35134 $pad = $len - $scale;
3866 25732 100       44757 $pad = abs($scale-1) if $scale < 0;
3867              
3868             # do not use digit(), it is very costly for binary => decimal
3869             # getting the entire string is also costly, but we need to do it only once
3870 25732         65820 my $xs = $LIB->_str($x->{value});
3871 25732         45984 my $pl = -$pad-1;
3872              
3873             # pad: 123: 0 => -1, at 1 => -2, at 2 => -3, at 3 => -4
3874             # pad+1: 123: 0 => 0, at 1 => -1, at 2 => -2, at 3 => -3
3875 25732         38131 $digit_round = '0';
3876 25732 100       58645 $digit_round = substr($xs, $pl, 1) if $pad <= $len;
3877 25732         34969 $pl++;
3878 25732 100       46480 $pl ++ if $pad >= $len;
3879 25732         36112 $digit_after = '0';
3880 25732 50       52774 $digit_after = substr($xs, $pl, 1) if $pad > 0;
3881              
3882             # in case of 01234 we round down, for 6789 up, and only in case 5 we look
3883             # closer at the remaining digits of the original $x, remember decision
3884 25732         36325 my $round_up = 1; # default round up
3885             $round_up -- if
3886             ($mode eq 'trunc') || # trunc by round down
3887             ($digit_after =~ /[01234]/) || # round down anyway,
3888             # 6789 => round up
3889             ($digit_after eq '5') && # not 5000...0000
3890             ($x->_scan_for_nonzero($pad, $xs, $len) == 0) &&
3891             (
3892             ($mode eq 'even') && ($digit_round =~ /[24680]/) ||
3893             ($mode eq 'odd') && ($digit_round =~ /[13579]/) ||
3894             ($mode eq '+inf') && ($x->{sign} eq '-') ||
3895 25732 100 100     140924 ($mode eq '-inf') && ($x->{sign} eq '+') ||
      100        
      100        
      100        
      100        
3896             ($mode eq 'zero') # round down if zero, sign adjusted below
3897             );
3898 25732         40057 my $put_back = 0; # not yet modified
3899              
3900 25732 100 66     75769 if (($pad > 0) && ($pad <= $len)) {
    50          
3901 25610         57049 substr($xs, -$pad, $pad) = '0' x $pad; # replace with '00...'
3902 25610         47411 $xs =~ s/^0+(\d)/$1/; # "00000" -> "0"
3903 25610         36766 $put_back = 1; # need to put back
3904             } elsif ($pad > $len) {
3905 122         352 $x = $x->bzero(); # round to '0'
3906             }
3907              
3908 25732 100       48604 if ($round_up) { # what gave test above?
3909 12381         16941 $put_back = 1; # need to put back
3910 12381 100       22936 $pad = $len, $xs = '0' x $pad if $scale < 0; # tlr: whack 0.51=>1.0
3911              
3912             # we modify directly the string variant instead of creating a number and
3913             # adding it, since that is faster (we already have the string)
3914 12381         16966 my $c = 0;
3915 12381         16835 $pad ++; # for $pad == $len case
3916 12381         23582 while ($pad <= $len) {
3917 13696         25817 $c = substr($xs, -$pad, 1) + 1;
3918 13696 100       26519 $c = '0' if $c eq '10';
3919 13696         20468 substr($xs, -$pad, 1) = $c;
3920 13696         17030 $pad++;
3921 13696 100       28331 last if $c != 0; # no overflow => early out
3922             }
3923 12381 100       24827 $xs = '1'.$xs if $c == 0;
3924             }
3925 25732 100       87929 $x->{value} = $LIB->_new($xs) if $put_back == 1; # put back, if needed
3926              
3927 25732 100       70486 $x->{_a} = $scale if $scale >= 0;
3928 25732 100       48748 if ($scale < 0) {
3929 134         277 $x->{_a} = $len+$scale;
3930 134 100       336 $x->{_a} = 0 if $scale < -$len;
3931             }
3932 25732         73858 $x;
3933             }
3934              
3935             sub bfround {
3936             # precision: round to the $Nth digit left (+$n) or right (-$n) from the '.'
3937             # $n == 0 || $n == 1 => round to integer
3938              
3939 212 50   212 1 708 my ($class, $x, @p) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
3940              
3941 212         509 my ($scale, $mode) = $x->_scale_p(@p);
3942              
3943 212 50 33     1002 return $x if !defined $scale || $x->modify('bfround'); # no-op
3944              
3945             # no-op for Math::BigInt objects if $n <= 0
3946 212 100       576 $x = $x->bround($x->length()-$scale, $mode) if $scale > 0;
3947              
3948 212         398 $x->{_a} = undef;
3949 212         365 $x->{_p} = $scale; # store new _p
3950 212         408 $x;
3951             }
3952              
3953             sub fround {
3954             # Exists to make life easier for switch between MBF and MBI (should we
3955             # autoload fxxx() like MBF does for bxxx()?)
3956 0     0 0 0 my $x = shift;
3957 0 0       0 $x = __PACKAGE__->new($x) unless ref $x;
3958 0         0 $x->bround(@_);
3959             }
3960              
3961             sub bfloor {
3962             # round towards minus infinity; no-op since it's already integer
3963 36 50   36 1 443 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
3964              
3965 36 50 66     131 return $upgrade -> bfloor($x)
3966             if defined($upgrade) && !$x -> isa(__PACKAGE__);
3967              
3968 36         95 $x->round(@r);
3969             }
3970              
3971             sub bceil {
3972             # round towards plus infinity; no-op since it's already int
3973 36 50   36 1 437 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
3974              
3975 36 50 66     128 return $upgrade -> bceil($x)
3976             if defined($upgrade) && !$x -> isa(__PACKAGE__);
3977              
3978 36         99 $x->round(@r);
3979             }
3980              
3981             sub bint {
3982             # round towards zero; no-op since it's already integer
3983 38 50   38 1 428 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
3984              
3985 38 50 66     154 return $upgrade -> bint($x)
3986             if defined($upgrade) && !$x -> isa(__PACKAGE__);
3987              
3988 38         102 $x->round(@r);
3989             }
3990              
3991             ###############################################################################
3992             # Other mathematical methods
3993             ###############################################################################
3994              
3995             sub bgcd {
3996             # (BINT or num_str, BINT or num_str) return BINT
3997             # does not modify arguments, but returns new object
3998             # GCD -- Euclid's algorithm, variant C (Knuth Vol 3, pg 341 ff)
3999              
4000             # Class::method(...) -> Class->method(...)
4001 97 100 100 97 1 1996 unless (@_ && (defined(blessed($_[0])) && $_[0] -> isa(__PACKAGE__) ||
      66        
4002             $_[0] =~ /^[a-z]\w*(?:::[a-z]\w*)*$/i))
4003             {
4004             #carp "Using ", (caller(0))[3], "() as a function is deprecated;",
4005             # " use is as a method instead";
4006 1         5 unshift @_, __PACKAGE__;
4007             }
4008              
4009 97         317 my ($class, @args) = objectify(0, @_);
4010              
4011             # Upgrade?
4012              
4013 97 100       253 if (defined $upgrade) {
4014 15         35 my $do_upgrade = 0;
4015 15         30 for my $arg (@args) {
4016 32 50       83 unless ($arg -> isa(__PACKAGE__)) {
4017 0         0 $do_upgrade = 1;
4018 0         0 last;
4019             }
4020             }
4021 15 50       32 return $upgrade -> bgcd(@args) if $do_upgrade;
4022             }
4023              
4024 97         160 my $x = shift @args;
4025 97 50 33     605 $x = defined(blessed($x)) && $x -> isa(__PACKAGE__) ? $x -> copy()
4026             : $class -> new($x);
4027              
4028 97 100       439 return $class->bnan() if $x->{sign} !~ /^[+-]$/; # x NaN?
4029              
4030 74         192 while (@args) {
4031 84         141 my $y = shift @args;
4032 84 50 33     429 $y = $class->new($y)
4033             unless defined(blessed($y)) && $y -> isa(__PACKAGE__);
4034 84 100       302 return $class->bnan() if $y->{sign} !~ /^[+-]$/; # y NaN?
4035 74         274 $x->{value} = $LIB->_gcd($x->{value}, $y->{value});
4036 74 100       211 last if $LIB->_is_one($x->{value});
4037             }
4038              
4039 64         182 return $x -> babs();
4040             }
4041              
4042             sub blcm {
4043             # (BINT or num_str, BINT or num_str) return BINT
4044             # does not modify arguments, but returns new object
4045             # Least Common Multiple
4046              
4047             # Class::method(...) -> Class->method(...)
4048 35 100 100 35 1 1246 unless (@_ && (defined(blessed($_[0])) && $_[0] -> isa(__PACKAGE__) ||
      66        
4049             $_[0] =~ /^[a-z]\w*(?:::[a-z]\w*)*$/i))
4050             {
4051             #carp "Using ", (caller(0))[3], "() as a function is deprecated;",
4052             # " use is as a method instead";
4053 1         4 unshift @_, __PACKAGE__;
4054             }
4055              
4056 35         110 my ($class, @args) = objectify(0, @_);
4057              
4058             # Upgrade?
4059              
4060 35 100       104 if (defined $upgrade) {
4061 8         13 my $do_upgrade = 0;
4062 8         14 for my $arg (@args) {
4063 16 50       42 unless ($arg -> isa(__PACKAGE__)) {
4064 0         0 $do_upgrade = 1;
4065 0         0 last;
4066             }
4067             }
4068 8 50       17 return $upgrade -> blcm(@args) if $do_upgrade;
4069             }
4070              
4071 35         61 my $x = shift @args;
4072 35 50 33     265 $x = defined(blessed($x)) && $x -> isa(__PACKAGE__) ? $x -> copy()
4073             : $class -> new($x);
4074 35 100       423 return $class->bnan() if $x->{sign} !~ /^[+-]$/; # x NaN?
4075              
4076 27         88 while (@args) {
4077 30         96 my $y = shift @args;
4078 30 50 33     175 $y = $class -> new($y)
4079             unless defined(blessed($y)) && $y -> isa(__PACKAGE__);
4080 30 100       124 return $x->bnan() if $y->{sign} !~ /^[+-]$/; # y not integer
4081 26         129 $x -> {value} = $LIB->_lcm($x -> {value}, $y -> {value});
4082             }
4083              
4084 23         69 return $x -> babs();
4085             }
4086              
4087             ###############################################################################
4088             # Object property methods
4089             ###############################################################################
4090              
4091             sub sign {
4092             # return the sign of the number: +/-/-inf/+inf/NaN
4093 8837 50   8837 1 24733 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4094              
4095 8837 50       18516 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4096              
4097 8837         27745 $x->{sign};
4098             }
4099              
4100             sub digit {
4101             # return the nth decimal digit, negative values count backward, 0 is right
4102 87 100   87 1 1000 my (undef, $x, $n, @r) = ref($_[0]) ? (undef, @_) : objectify(1, @_);
4103              
4104 87 50       228 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4105              
4106 87 100       292 $n = $n->numify() if ref($n);
4107 87   100     397 $LIB->_digit($x->{value}, $n || 0);
4108             }
4109              
4110             sub bdigitsum {
4111             # like digitsum(), but assigns the result to the invocand
4112 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4113              
4114 0 0       0 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4115              
4116 0 0       0 return $x if $x -> is_nan();
4117 0 0       0 return $x -> bnan() if $x -> is_inf();
4118              
4119 0         0 $x -> {value} = $LIB -> _digitsum($x -> {value});
4120 0         0 $x -> {sign} = '+';
4121 0         0 return $x;
4122             }
4123              
4124             sub digitsum {
4125             # compute sum of decimal digits and return it
4126 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4127              
4128 0 0       0 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4129              
4130 0 0       0 return $class -> bnan() if $x -> is_nan();
4131 0 0       0 return $class -> bnan() if $x -> is_inf();
4132              
4133 0         0 my $y = $class -> bzero();
4134 0         0 $y -> {value} = $LIB -> _digitsum($x -> {value});
4135 0         0 $y -> round(@r);
4136             }
4137              
4138             sub length {
4139 26074 50   26074 1 67426 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4140              
4141 26074 50       52649 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4142              
4143 26074         63858 my $e = $LIB->_len($x->{value});
4144 26074 100       59924 wantarray ? ($e, 0) : $e;
4145             }
4146              
4147             sub exponent {
4148             # return a copy of the exponent (here always 0, NaN or 1 for $m == 0)
4149 72 50   72 1 568 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4150              
4151 72 50       173 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4152              
4153             # Upgrade?
4154              
4155 72 50 66     277 return $upgrade -> exponent($x, @r)
4156             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4157              
4158 72 100       246 if ($x->{sign} !~ /^[+-]$/) {
4159 24         47 my $s = $x->{sign};
4160 24         70 $s =~ s/^[+-]//; # NaN, -inf, +inf => NaN or inf
4161 24         66 return $class->new($s, @r);
4162             }
4163 48 100       129 return $class->bzero(@r) if $x->is_zero();
4164              
4165             # 12300 => 2 trailing zeros => exponent is 2
4166 40         134 $class->new($LIB->_zeros($x->{value}), @r);
4167             }
4168              
4169             sub mantissa {
4170             # return the mantissa (compatible to Math::BigFloat, e.g. reduced)
4171 68 50   68 1 463 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4172              
4173 68 50       152 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4174              
4175             # Upgrade?
4176              
4177 68 50 66     201 return $upgrade -> mantissa($x, @r)
4178             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4179              
4180 68 100       239 if ($x->{sign} !~ /^[+-]$/) {
4181             # for NaN, +inf, -inf: keep the sign
4182 24         85 return $class->new($x->{sign}, @r);
4183             }
4184 44         129 my $m = $x->copy();
4185 44         141 $m -> precision(undef);
4186 44         120 $m -> accuracy(undef);
4187              
4188             # that's a bit inefficient:
4189 44         185 my $zeros = $LIB->_zeros($m->{value});
4190 44 100       153 $m = $m->brsft($zeros, 10) if $zeros != 0;
4191 44         116 $m -> round(@r);
4192             }
4193              
4194             sub parts {
4195             # return a copy of both the exponent and the mantissa
4196 36 50   36 1 487 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4197              
4198 36 50       94 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4199              
4200             # Upgrade?
4201              
4202 36 50 66     121 return $upgrade -> parts($x, @r)
4203             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4204              
4205 36         104 ($x->mantissa(@r), $x->exponent(@r));
4206             }
4207              
4208             # Parts used for scientific notation with significand/mantissa and exponent as
4209             # integers. E.g., "12345.6789" is returned as "123456789" (mantissa) and "-4"
4210             # (exponent).
4211              
4212             sub sparts {
4213 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4214              
4215 0 0       0 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4216              
4217             # Not-a-number.
4218              
4219 0 0       0 if ($x -> is_nan()) {
4220 0         0 my $mant = $class -> bnan(@r); # mantissa
4221 0 0       0 return $mant unless wantarray; # scalar context
4222 0         0 my $expo = $class -> bnan(@r); # exponent
4223 0         0 return ($mant, $expo); # list context
4224             }
4225              
4226             # Infinity.
4227              
4228 0 0       0 if ($x -> is_inf()) {
4229 0         0 my $mant = $class -> binf($x->{sign}, @r); # mantissa
4230 0 0       0 return $mant unless wantarray; # scalar context
4231 0         0 my $expo = $class -> binf('+', @r); # exponent
4232 0         0 return ($mant, $expo); # list context
4233             }
4234              
4235             # Upgrade?
4236              
4237 0 0 0     0 return $upgrade -> sparts($x, @r)
4238             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4239              
4240             # Finite number.
4241              
4242 0         0 my $mant = $x -> copy();
4243 0         0 my $nzeros = $LIB -> _zeros($mant -> {value});
4244              
4245             $mant -> {value}
4246 0 0       0 = $LIB -> _rsft($mant -> {value}, $LIB -> _new($nzeros), 10)
4247             if $nzeros != 0;
4248 0 0       0 return $mant unless wantarray;
4249              
4250 0         0 my $expo = $class -> new($nzeros, @r);
4251 0         0 return ($mant, $expo);
4252             }
4253              
4254             # Parts used for normalized notation with significand/mantissa as either 0 or a
4255             # number in the semi-open interval [1,10). E.g., "12345.6789" is returned as
4256             # "1.23456789" and "4".
4257              
4258             sub nparts {
4259 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4260              
4261 0 0       0 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4262              
4263             # Not-a-Number and Infinity.
4264              
4265 0 0 0     0 return $x -> sparts(@r) if $x -> is_nan() || $x -> is_inf();
4266              
4267             # Upgrade?
4268              
4269 0 0 0     0 return $upgrade -> nparts($x, @r)
4270             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4271              
4272             # Finite number.
4273              
4274 0         0 my ($mant, $expo) = $x -> sparts(@r);
4275 0 0       0 if ($mant -> bcmp(0)) {
4276 0         0 my ($ndigtot, $ndigfrac) = $mant -> length();
4277 0         0 my $expo10adj = $ndigtot - $ndigfrac - 1;
4278              
4279 0 0       0 if ($expo10adj > 0) { # if mantissa is not an integer
4280 0 0       0 return $upgrade -> nparts($x, @r) if defined $upgrade;
4281 0         0 $mant = $mant -> bnan(@r);
4282 0 0       0 return $mant unless wantarray;
4283 0         0 $expo = $expo -> badd($expo10adj, @r);
4284 0         0 return ($mant, $expo);
4285             }
4286             }
4287              
4288 0 0       0 return $mant unless wantarray;
4289 0         0 return ($mant, $expo);
4290             }
4291              
4292             # Parts used for engineering notation with significand/mantissa as either 0 or a
4293             # number in the semi-open interval [1,1000) and the exponent is a multiple of 3.
4294             # E.g., "12345.6789" is returned as "12.3456789" and "3".
4295              
4296             sub eparts {
4297 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4298              
4299 0 0       0 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4300              
4301             # Not-a-number and Infinity.
4302              
4303 0 0 0     0 return $x -> sparts(@r) if $x -> is_nan() || $x -> is_inf();
4304              
4305             # Upgrade?
4306              
4307 0 0 0     0 return $upgrade -> eparts($x, @r)
4308             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4309              
4310             # Finite number.
4311              
4312 0         0 my ($mant, $expo) = $x -> sparts(@r);
4313              
4314 0 0       0 if ($mant -> bcmp(0)) {
4315 0         0 my $ndigmant = $mant -> length();
4316 0         0 $expo = $expo -> badd($ndigmant, @r);
4317              
4318             # $c is the number of digits that will be in the integer part of the
4319             # final mantissa.
4320              
4321 0         0 my $c = $expo -> copy() -> bdec() -> bmod(3) -> binc();
4322 0         0 $expo = $expo -> bsub($c);
4323              
4324 0 0       0 if ($ndigmant > $c) {
4325 0 0       0 return $upgrade -> eparts($x, @r) if defined $upgrade;
4326 0         0 $mant = $mant -> bnan(@r);
4327 0 0       0 return $mant unless wantarray;
4328 0         0 return ($mant, $expo);
4329             }
4330              
4331 0         0 $mant = $mant -> blsft($c - $ndigmant, 10, @r);
4332             }
4333              
4334 0 0       0 return $mant unless wantarray;
4335 0         0 return ($mant, $expo);
4336             }
4337              
4338             # Parts used for decimal notation, e.g., "12345.6789" is returned as "12345"
4339             # (integer part) and "0.6789" (fraction part).
4340              
4341             sub dparts {
4342 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4343              
4344 0 0       0 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4345              
4346             # Not-a-number.
4347              
4348 0 0       0 if ($x -> is_nan()) {
4349 0         0 my $int = $class -> bnan(@r);
4350 0 0       0 return $int unless wantarray;
4351 0         0 my $frc = $class -> bzero(@r); # or NaN?
4352 0         0 return ($int, $frc);
4353             }
4354              
4355             # Infinity.
4356              
4357 0 0       0 if ($x -> is_inf()) {
4358 0         0 my $int = $class -> binf($x->{sign}, @r);
4359 0 0       0 return $int unless wantarray;
4360 0         0 my $frc = $class -> bzero(@r);
4361 0         0 return ($int, $frc);
4362             }
4363              
4364             # Upgrade?
4365              
4366 0 0 0     0 return $upgrade -> dparts($x, @r)
4367             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4368              
4369             # Finite number.
4370              
4371 0         0 my $int = $x -> copy() -> round(@r);
4372 0 0       0 return $int unless wantarray;
4373              
4374 0         0 my $frc = $class -> bzero(@r);
4375 0         0 return ($int, $frc);
4376             }
4377              
4378             # Fractional parts with the numerator and denominator as integers. E.g.,
4379             # "123.4375" is returned as "1975" and "16".
4380              
4381             sub fparts {
4382 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4383              
4384 0 0       0 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4385              
4386             # NaN => NaN/NaN
4387              
4388 0 0       0 if ($x -> is_nan()) {
4389 0 0       0 return $class -> bnan(@r) unless wantarray;
4390 0         0 return $class -> bnan(@r), $class -> bnan(@r);
4391             }
4392              
4393             # ±Inf => ±Inf/1
4394              
4395 0 0       0 if ($x -> is_inf()) {
4396 0         0 my $numer = $class -> binf($x->{sign}, @r);
4397 0 0       0 return $numer unless wantarray;
4398 0         0 my $denom = $class -> bone(@r);
4399 0         0 return $numer, $denom;
4400             }
4401              
4402             # Upgrade?
4403              
4404 0 0 0     0 return $upgrade -> fparts($x, @r)
4405             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4406              
4407             # N => N/1
4408              
4409 0         0 my $numer = $x -> copy() -> round(@r);
4410 0 0       0 return $numer unless wantarray;
4411 0         0 my $denom = $class -> bone(@r);
4412 0         0 return $numer, $denom;
4413             }
4414              
4415             sub numerator {
4416 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4417              
4418 0 0       0 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4419              
4420 0 0 0     0 return $upgrade -> numerator($x, @r)
4421             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4422              
4423 0         0 return $x -> copy() -> round(@r);
4424             }
4425              
4426             sub denominator {
4427 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4428              
4429 0 0       0 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4430              
4431 0 0 0     0 return $upgrade -> denominator($x, @r)
4432             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4433              
4434 0 0       0 return $x -> is_nan() ? $class -> bnan(@r) : $class -> bone(@r);
4435             }
4436              
4437             ###############################################################################
4438             # String conversion methods
4439             ###############################################################################
4440              
4441             sub bstr {
4442 12036 100   12036 1 1883180 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4443              
4444 12036 50       29904 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4445              
4446             # Inf and NaN
4447              
4448 12036 100 100     40535 if ($x->{sign} ne '+' && $x->{sign} ne '-') {
4449 2703 100       24693 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN
4450 544         4986 return 'inf'; # +inf
4451             }
4452              
4453             # Upgrade?
4454              
4455 9333 50 66     24256 return $upgrade -> bstr($x, @r)
4456             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4457              
4458             # Finite number
4459              
4460 9333         32793 my $str = $LIB->_str($x->{value});
4461 9333 100       113025 return $x->{sign} eq '-' ? "-$str" : $str;
4462             }
4463              
4464             # Scientific notation with significand/mantissa as an integer, e.g., "12345" is
4465             # written as "1.2345e+4".
4466              
4467             sub bsstr {
4468 66 100   66 1 12994 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4469              
4470 66 50       181 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4471              
4472             # Inf and NaN
4473              
4474 66 100 100     281 if ($x->{sign} ne '+' && $x->{sign} ne '-') {
4475 18 100       145 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN
4476 7         69 return 'inf'; # +inf
4477             }
4478              
4479             # Upgrade?
4480              
4481 48 50 66     161 return $upgrade -> bsstr($x, @r)
4482             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4483              
4484             # Finite number
4485              
4486 48         191 my $expo = $LIB -> _zeros($x->{value});
4487 48         1271 my $mant = $LIB -> _str($x->{value});
4488 48 100       185 $mant = substr($mant, 0, -$expo) if $expo; # strip trailing zeros
4489              
4490 48 100       531 ($x->{sign} eq '-' ? '-' : '') . $mant . 'e+' . $expo;
4491             }
4492              
4493             # Normalized notation, e.g., "12345" is written as "1.2345e+4".
4494              
4495             sub bnstr {
4496 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4497              
4498 0 0       0 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4499              
4500             # Inf and NaN
4501              
4502 0 0 0     0 if ($x->{sign} ne '+' && $x->{sign} ne '-') {
4503 0 0       0 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN
4504 0         0 return 'inf'; # +inf
4505             }
4506              
4507             # Upgrade?
4508              
4509 0 0 0     0 return $upgrade -> bnstr($x, @r)
4510             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4511              
4512             # Finite number
4513              
4514 0         0 my $expo = $LIB -> _zeros($x->{value});
4515 0         0 my $mant = $LIB -> _str($x->{value});
4516 0 0       0 $mant = substr($mant, 0, -$expo) if $expo; # strip trailing zeros
4517              
4518 0         0 my $mantlen = CORE::length($mant);
4519 0 0       0 if ($mantlen > 1) {
4520 0         0 $expo += $mantlen - 1; # adjust exponent
4521 0         0 substr $mant, 1, 0, "."; # insert decimal point
4522             }
4523              
4524 0 0       0 ($x->{sign} eq '-' ? '-' : '') . $mant . 'e+' . $expo;
4525             }
4526              
4527             # Engineering notation, e.g., "12345" is written as "12.345e+3".
4528              
4529             sub bestr {
4530 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4531              
4532 0 0       0 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4533              
4534             # Inf and NaN
4535              
4536 0 0 0     0 if ($x->{sign} ne '+' && $x->{sign} ne '-') {
4537 0 0       0 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN
4538 0         0 return 'inf'; # +inf
4539             }
4540              
4541             # Upgrade?
4542              
4543 0 0 0     0 return $upgrade -> bestr($x, @r)
4544             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4545              
4546             # Finite number
4547              
4548 0         0 my $expo = $LIB -> _zeros($x->{value}); # number of trailing zeros
4549 0         0 my $mant = $LIB -> _str($x->{value}); # mantissa as a string
4550 0 0       0 $mant = substr($mant, 0, -$expo) if $expo; # strip trailing zeros
4551 0         0 my $mantlen = CORE::length($mant); # length of mantissa
4552 0         0 $expo += $mantlen;
4553              
4554 0         0 my $dotpos = ($expo - 1) % 3 + 1; # offset of decimal point
4555 0         0 $expo -= $dotpos;
4556              
4557 0 0       0 if ($dotpos < $mantlen) {
    0          
4558 0         0 substr $mant, $dotpos, 0, "."; # insert decimal point
4559             } elsif ($dotpos > $mantlen) {
4560 0         0 $mant .= "0" x ($dotpos - $mantlen); # append zeros
4561             }
4562              
4563 0 0       0 ($x->{sign} eq '-' ? '-' : '') . $mant . 'e+' . $expo;
4564             }
4565              
4566             # Decimal notation, e.g., "12345" (no exponent).
4567              
4568             sub bdstr {
4569 24 50   24 1 89 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4570              
4571 24 50       57 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4572              
4573             # Inf and NaN
4574              
4575 24 100 100     84 if ($x->{sign} ne '+' && $x->{sign} ne '-') {
4576 8 100       35 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN
4577 1         4 return 'inf'; # +inf
4578             }
4579              
4580             # Upgrade?
4581              
4582 16 50 33     82 return $upgrade -> bdstr($x, @r)
4583             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4584              
4585             # Finite number
4586              
4587 16 100       63 ($x->{sign} eq '-' ? '-' : '') . $LIB->_str($x->{value});
4588             }
4589              
4590             # Fraction notation, e.g., "123.4375" is written as "1975/16", but "123" is
4591             # written as "123", not "123/1".
4592              
4593             sub bfstr {
4594 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4595              
4596 0 0       0 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4597              
4598             # Inf and NaN
4599              
4600 0 0 0     0 if ($x->{sign} ne '+' && $x->{sign} ne '-') {
4601 0 0       0 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN
4602 0         0 return 'inf'; # +inf
4603             }
4604              
4605             # Upgrade?
4606              
4607 0 0 0     0 return $upgrade -> bfstr($x, @r)
4608             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4609              
4610             # Finite number
4611              
4612 0 0       0 ($x->{sign} eq '-' ? '-' : '') . $LIB->_str($x->{value});
4613             }
4614              
4615             sub to_hex {
4616             # return as hex string with no prefix
4617              
4618 36 50   36 1 494 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4619              
4620 36 50       110 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4621              
4622             # Inf and NaN
4623              
4624 36 100 100     150 if ($x->{sign} ne '+' && $x->{sign} ne '-') {
4625 12 100       113 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN
4626 4         71 return 'inf'; # +inf
4627             }
4628              
4629             # Upgrade?
4630              
4631 24 50 66     86 return $upgrade -> to_hex($x, @r)
4632             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4633              
4634             # Finite number
4635              
4636 24         257 my $hex = $LIB->_to_hex($x->{value});
4637 24 100       281 return $x->{sign} eq '-' ? "-$hex" : $hex;
4638             }
4639              
4640             sub to_oct {
4641             # return as octal string with no prefix
4642              
4643 40 50   40 1 524 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4644              
4645 40 50       473 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4646              
4647             # Inf and NaN
4648              
4649 40 100 100     178 if ($x->{sign} ne '+' && $x->{sign} ne '-') {
4650 12 100       101 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN
4651 4         51 return 'inf'; # +inf
4652             }
4653              
4654             # Upgrade?
4655              
4656 28 50 66     97 return $upgrade -> to_oct($x, @r)
4657             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4658              
4659             # Finite number
4660              
4661 28         127 my $oct = $LIB->_to_oct($x->{value});
4662 28 100       301 return $x->{sign} eq '-' ? "-$oct" : $oct;
4663             }
4664              
4665             sub to_bin {
4666             # return as binary string with no prefix
4667              
4668 93 50   93 1 677 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4669              
4670 93 50       216 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4671              
4672             # Inf and NaN
4673              
4674 93 100 100     400 if ($x->{sign} ne '+' && $x->{sign} ne '-') {
4675 12 100       120 return $x->{sign} unless $x->{sign} eq '+inf'; # -inf, NaN
4676 4         44 return 'inf'; # +inf
4677             }
4678              
4679             # Upgrade?
4680              
4681 81 50 66     209 return $upgrade -> to_bin($x, @r)
4682             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4683              
4684             # Finite number
4685              
4686 81         293 my $bin = $LIB->_to_bin($x->{value});
4687 81 100       502 return $x->{sign} eq '-' ? "-$bin" : $bin;
4688             }
4689              
4690             sub to_bytes {
4691             # return a byte string
4692              
4693 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4694              
4695 0 0       0 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4696              
4697 0 0 0     0 croak("to_bytes() requires a finite, non-negative integer")
4698             if $x -> is_neg() || ! $x -> is_int();
4699              
4700 0 0 0     0 return $upgrade -> to_bytes($x, @r)
4701             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4702              
4703 0 0       0 croak("to_bytes() requires a newer version of the $LIB library.")
4704             unless $LIB->can('_to_bytes');
4705              
4706 0         0 return $LIB->_to_bytes($x->{value});
4707             }
4708              
4709             sub to_base {
4710             # return a base anything string
4711              
4712             # $cs is the collation sequence
4713 0 0 0 0 1 0 my ($class, $x, $base, $cs, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
4714             ? (ref($_[0]), @_) : objectify(2, @_);
4715              
4716 0 0       0 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4717              
4718 0 0 0     0 croak("the value to convert must be a finite, non-negative integer")
4719             if $x -> is_neg() || !$x -> is_int();
4720              
4721 0 0 0     0 croak("the base must be a finite integer >= 2")
4722             if $base < 2 || ! $base -> is_int();
4723              
4724             # If no collating sequence is given, pass some of the conversions to
4725             # methods optimized for those cases.
4726              
4727 0 0       0 unless (defined $cs) {
4728 0 0       0 return $x -> to_bin() if $base == 2;
4729 0 0       0 return $x -> to_oct() if $base == 8;
4730 0 0       0 return uc $x -> to_hex() if $base == 16;
4731 0 0       0 return $x -> bstr() if $base == 10;
4732             }
4733              
4734 0 0       0 croak("to_base() requires a newer version of the $LIB library.")
4735             unless $LIB->can('_to_base');
4736              
4737 0 0 0     0 return $upgrade -> to_base($x, $base, $cs, @r)
      0        
4738             if defined($upgrade) && (!$x -> isa(__PACKAGE__) ||
4739             !$base -> isa(__PACKAGE__));
4740              
4741             return $LIB->_to_base($x->{value}, $base -> {value},
4742 0 0       0 defined($cs) ? $cs : ());
4743             }
4744              
4745             sub to_base_num {
4746             # return a base anything array ref, e.g.,
4747             # Math::BigInt -> new(255) -> to_base_num(10) returns [2, 5, 5];
4748              
4749             # $cs is the collation sequence
4750 0 0 0 0 1 0 my ($class, $x, $base, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
4751             ? (ref($_[0]), @_) : objectify(2, @_);
4752              
4753 0 0       0 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4754              
4755 0 0 0     0 croak("the value to convert must be a finite non-negative integer")
4756             if $x -> is_neg() || !$x -> is_int();
4757              
4758 0 0 0     0 croak("the base must be a finite integer >= 2")
4759             if $base < 2 || ! $base -> is_int();
4760              
4761 0 0       0 croak("to_base() requires a newer version of the $LIB library.")
4762             unless $LIB->can('_to_base');
4763              
4764 0 0 0     0 return $upgrade -> to_base_num($x, $base, @r)
      0        
4765             if defined($upgrade) && (!$x -> isa(__PACKAGE__) ||
4766             !$base -> isa(__PACKAGE__));
4767              
4768             # Get a reference to an array of library thingies, and replace each element
4769             # with a Math::BigInt object using that thingy.
4770              
4771 0         0 my $vals = $LIB -> _to_base_num($x->{value}, $base -> {value});
4772              
4773 0         0 for my $i (0 .. $#$vals) {
4774 0         0 my $x = $class -> bzero();
4775 0         0 $x -> {value} = $vals -> [$i];
4776 0         0 $vals -> [$i] = $x;
4777             }
4778              
4779 0         0 return $vals;
4780             }
4781              
4782             sub as_hex {
4783             # return as hex string, with prefixed 0x
4784              
4785 36 50   36 1 527 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4786              
4787 36 50       103 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4788              
4789 36 100       161 return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, nan etc
4790              
4791 24 50 66     122 return $upgrade -> as_hex($x, @r)
4792             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4793              
4794 24         100 my $hex = $LIB->_as_hex($x->{value});
4795 24 100       266 return $x->{sign} eq '-' ? "-$hex" : $hex;
4796             }
4797              
4798             sub as_oct {
4799             # return as octal string, with prefixed 0
4800              
4801 40 50   40 1 496 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4802              
4803 40 50       104 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4804              
4805 40 100       170 return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, nan etc
4806              
4807 28 50 66     100 return $upgrade -> as_oct($x, @r)
4808             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4809              
4810 28         125 my $oct = $LIB->_as_oct($x->{value});
4811 28 100       328 return $x->{sign} eq '-' ? "-$oct" : $oct;
4812             }
4813              
4814             sub as_bin {
4815             # return as binary string, with prefixed 0b
4816              
4817 39 50   39 1 502 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4818              
4819 39 50       98 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4820              
4821 39 100       152 return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, nan etc
4822              
4823 27 50 66     123 return $upgrade -> as_bin($x, @r)
4824             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4825              
4826 27         98 my $bin = $LIB->_as_bin($x->{value});
4827 27 100       299 return $x->{sign} eq '-' ? "-$bin" : $bin;
4828             }
4829              
4830             *as_bytes = \&to_bytes;
4831              
4832             ###############################################################################
4833             # Other conversion methods
4834             ###############################################################################
4835              
4836             sub numify {
4837             # Make a Perl scalar number from a Math::BigInt object.
4838 495 50   495 1 1697 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
4839              
4840 495 50       1031 carp "Rounding is not supported for ", (caller(0))[3], "()" if @r;
4841              
4842 495 50       1161 if ($x -> is_nan()) {
4843 0         0 require Math::Complex;
4844 0         0 my $inf = $Math::Complex::Inf;
4845 0         0 return $inf - $inf;
4846             }
4847              
4848 495 50       1108 if ($x -> is_inf()) {
4849 0         0 require Math::Complex;
4850 0         0 my $inf = $Math::Complex::Inf;
4851 0 0       0 return $x -> is_negative() ? -$inf : $inf;
4852             }
4853              
4854 495 50 66     1339 return $upgrade -> numify($x, @r)
4855             if defined($upgrade) && !$x -> isa(__PACKAGE__);
4856              
4857 495         1523 my $num = 0 + $LIB->_num($x->{value});
4858 495 100       2146 return $x->{sign} eq '-' ? -$num : $num;
4859             }
4860              
4861             ###############################################################################
4862             # Private methods and functions.
4863             ###############################################################################
4864              
4865             sub objectify {
4866             # Convert strings and "foreign objects" to the objects we want.
4867              
4868             # The first argument, $count, is the number of following arguments that
4869             # objectify() looks at and converts to objects. The first is a classname.
4870             # If the given count is 0, all arguments will be used.
4871              
4872             # After the count is read, objectify obtains the name of the class to which
4873             # the following arguments are converted. If the second argument is a
4874             # reference, use the reference type as the class name. Otherwise, if it is
4875             # a string that looks like a class name, use that. Otherwise, use $class.
4876              
4877             # Caller: Gives us:
4878             #
4879             # $x->badd(1); => ref x, scalar y
4880             # Class->badd(1, 2); => classname x (scalar), scalar x, scalar y
4881             # Class->badd(Class->(1), 2); => classname x (scalar), ref x, scalar y
4882             # Math::BigInt::badd(1, 2); => scalar x, scalar y
4883              
4884             # A shortcut for the common case $x->unary_op(), in which case the argument
4885             # list is (0, $x) or (1, $x).
4886              
4887 5151 100 100 5151   28690 return (ref($_[1]), $_[1]) if @_ == 2 && ($_[0] || 0) == 1 && ref($_[1]);
      100        
      66        
4888              
4889             # Check the context.
4890              
4891 5001 50       11000 unless (wantarray) {
4892 0         0 croak(__PACKAGE__ . "::objectify() needs list context");
4893             }
4894              
4895             # Get the number of arguments to objectify.
4896              
4897 5001         8109 my $count = shift;
4898              
4899             # Initialize the output array.
4900              
4901 5001         11456 my @a = @_;
4902              
4903             # If the first argument is a reference, use that reference type as our
4904             # class name. Otherwise, if the first argument looks like a class name,
4905             # then use that as our class name. Otherwise, use the default class name.
4906              
4907 5001         6837 my $class;
4908 5001 100       13649 if (ref($a[0])) { # reference?
    100          
4909 3728         6195 $class = ref($a[0]);
4910             } elsif ($a[0] =~ /^[A-Z].*::/) { # string with class name?
4911 1261         2599 $class = shift @a;
4912             } else {
4913 12         44 $class = __PACKAGE__; # default class name
4914             }
4915              
4916 5001   66     11593 $count ||= @a;
4917 5001         11945 unshift @a, $class;
4918              
4919 51     51   589 no strict 'refs';
  51         147  
  51         80772  
4920              
4921             # What we upgrade to, if anything. Note that we need the whole upgrade
4922             # chain, since there might be multiple levels of upgrading. E.g., class A
4923             # upgrades to class B, which upgrades to class C. Delay getting the chain
4924             # until we actually need it.
4925              
4926 5001         8120 my @upg = ();
4927 5001         7248 my $have_upgrade_chain = 0;
4928              
4929             # Disable downgrading, because Math::BigFloat -> foo('1.0', '2.0') needs
4930             # floats.
4931              
4932 5001         7037 my $down;
4933 5001 100       6811 if (defined ${"$a[0]::downgrade"}) {
  5001         18511  
4934 14         26 $down = ${"$a[0]::downgrade"};
  14         36  
4935 14         34 ${"$a[0]::downgrade"} = undef;
  14         37  
4936             }
4937              
4938 5001         13059 ARG: for my $i (1 .. $count) {
4939              
4940 9136         16962 my $ref = ref $a[$i];
4941              
4942             # Perl scalars are fed to the appropriate constructor.
4943              
4944 9136 100       17337 unless ($ref) {
4945 4214         11939 $a[$i] = $a[0] -> new($a[$i]);
4946 4214         15302 next;
4947             }
4948              
4949             # If it is an object of the right class, all is fine.
4950              
4951 4922 100       16558 next if $ref -> isa($a[0]);
4952              
4953             # Upgrading is OK, so skip further tests if the argument is upgraded,
4954             # but first get the whole upgrade chain if we haven't got it yet.
4955              
4956 404 100       998 unless ($have_upgrade_chain) {
4957 281         478 my $cls = $class;
4958 281         739 my $upg = $cls -> upgrade();
4959 281         911 while (defined $upg) {
4960 17 50       44 last if $upg eq $cls;
4961 17         37 push @upg, $upg;
4962 17         32 $cls = $upg;
4963 17         59 $upg = $cls -> upgrade();
4964             }
4965 281         556 $have_upgrade_chain = 1;
4966             }
4967              
4968 404         803 for my $upg (@upg) {
4969 17 100       48 next ARG if $ref -> isa($upg);
4970             }
4971              
4972             # See if we can call one of the as_xxx() methods. We don't know whether
4973             # the as_xxx() method returns an object or a scalar, so re-check
4974             # afterwards.
4975              
4976 388         584 my $recheck = 0;
4977              
4978 388 100       1775 if ($a[0] -> isa('Math::BigInt')) {
    50          
4979 42 50       205 if ($a[$i] -> can('as_int')) {
    0          
4980 42         130 $a[$i] = $a[$i] -> as_int();
4981 42         105 $recheck = 1;
4982             } elsif ($a[$i] -> can('as_number')) {
4983 0         0 $a[$i] = $a[$i] -> as_number();
4984 0         0 $recheck = 1;
4985             }
4986             }
4987              
4988             elsif ($a[0] -> isa('Math::BigFloat')) {
4989 346 50       1432 if ($a[$i] -> can('as_float')) {
4990 346         802 $a[$i] = $a[$i] -> as_float();
4991 346         831 $recheck = $1;
4992             }
4993             }
4994              
4995             # If we called one of the as_xxx() methods, recheck.
4996              
4997 388 100       1045 if ($recheck) {
4998 44         114 $ref = ref($a[$i]);
4999              
5000             # Perl scalars are fed to the appropriate constructor.
5001              
5002 44 50       101 unless ($ref) {
5003 0         0 $a[$i] = $a[0] -> new($a[$i]);
5004 0         0 next;
5005             }
5006              
5007             # If it is an object of the right class, all is fine.
5008              
5009 44 100       216 next if $ref -> isa($a[0]);
5010             }
5011              
5012             # Last resort.
5013              
5014 345         1054 $a[$i] = $a[0] -> new($a[$i]);
5015             }
5016              
5017             # Reset the downgrading.
5018              
5019 5001         7882 ${"$a[0]::downgrade"} = $down;
  5001         13345  
5020              
5021 5001         18685 return @a;
5022             }
5023              
5024             sub import {
5025 103     103   4328 my $class = shift;
5026 103         214 $IMPORT++; # remember we did import()
5027 103         202 my @a; # unrecognized arguments
5028              
5029 103         427 while (@_) {
5030 91         212 my $param = shift;
5031              
5032             # Enable overloading of constants.
5033              
5034 91 100       351 if ($param eq ':constant') {
5035             overload::constant
5036              
5037             integer => sub {
5038 2     2   11 $class -> new(shift);
5039             },
5040              
5041             float => sub {
5042 0     0   0 $class -> new(shift);
5043             },
5044              
5045             binary => sub {
5046             # E.g., a literal 0377 shall result in an object whose value
5047             # is decimal 255, but new("0377") returns decimal 377.
5048 0 0   0   0 return $class -> from_oct($_[0]) if $_[0] =~ /^0_*[0-7]/;
5049 0         0 $class -> new(shift);
5050 1         7 };
5051 1         55 next;
5052             }
5053              
5054             # Upgrading.
5055              
5056 90 100       336 if ($param eq 'upgrade') {
5057 2         8 $class -> upgrade(shift);
5058 2         7 next;
5059             }
5060              
5061             # Downgrading.
5062              
5063 88 50       306 if ($param eq 'downgrade') {
5064 0         0 $class -> downgrade(shift);
5065 0         0 next;
5066             }
5067              
5068             # Accuracy.
5069              
5070 88 50       303 if ($param eq 'accuracy') {
5071 0         0 $class -> accuracy(shift);
5072 0         0 next;
5073             }
5074              
5075             # Precision.
5076              
5077 88 50       311 if ($param eq 'precision') {
5078 0         0 $class -> precision(shift);
5079 0         0 next;
5080             }
5081              
5082             # Rounding mode.
5083              
5084 88 50       269 if ($param eq 'round_mode') {
5085 0         0 $class -> round_mode(shift);
5086 0         0 next;
5087             }
5088              
5089             # Backend library.
5090              
5091 88 100       665 if ($param =~ /^(lib|try|only)\z/) {
5092             # try => 0 (no warn if unavailable module)
5093             # lib => 1 (warn on fallback)
5094             # only => 2 (die on fallback)
5095              
5096             # Get the list of user-specified libraries.
5097              
5098 29 50       126 croak "Library argument for import parameter '$param' is missing"
5099             unless @_;
5100 29         68 my $libs = shift;
5101 29 50       109 croak "Library argument for import parameter '$param' is undefined"
5102             unless defined($libs);
5103              
5104             # Check and clean up the list of user-specified libraries.
5105              
5106 29         80 my @libs;
5107 29         172 for my $lib (split /,/, $libs) {
5108 29         125 $lib =~ s/^\s+//;
5109 29         98 $lib =~ s/\s+$//;
5110              
5111 29 50       149 if ($lib =~ /[^a-zA-Z0-9_:]/) {
5112 0         0 carp "Library name '$lib' contains invalid characters";
5113 0         0 next;
5114             }
5115              
5116 29 50       119 if (! CORE::length $lib) {
5117 0         0 carp "Library name is empty";
5118 0         0 next;
5119             }
5120              
5121 29 100       145 $lib = "Math::BigInt::$lib" if $lib !~ /^Math::BigInt::/i;
5122              
5123             # If a library has already been loaded, that is OK only if the
5124             # requested library is identical to the loaded one.
5125              
5126 29 100       115 if (defined($LIB)) {
5127 10 100       57 if ($lib ne $LIB) {
5128             #carp "Library '$LIB' has already been loaded, so",
5129             # " ignoring requested library '$lib'";
5130             }
5131 10         41 next;
5132             }
5133              
5134 19         80 push @libs, $lib;
5135             }
5136              
5137 29 100       139 next if defined $LIB;
5138              
5139 19 50       74 croak "Library list contains no valid libraries" unless @libs;
5140              
5141             # Try to load the specified libraries, if any.
5142              
5143 19         93 for (my $i = 0 ; $i <= $#libs ; $i++) {
5144 19         42 my $lib = $libs[$i];
5145 19         1649 eval "require $lib";
5146 19 50       5123 unless ($@) {
5147 19         59 $LIB = $lib;
5148 19         62 last;
5149             }
5150             }
5151              
5152 19 50       150 next if defined $LIB;
5153              
5154             # No library has been loaded, and none of the requested libraries
5155             # could be loaded, and fallback and the user doesn't allow fallback.
5156              
5157 0 0       0 if ($param eq 'only') {
5158 0         0 croak "Couldn't load the specified math lib(s) ",
5159             join(", ", map "'$_'", @libs),
5160             ", and fallback to '$DEFAULT_LIB' is not allowed";
5161             }
5162              
5163             # No library has been loaded, and none of the requested libraries
5164             # could be loaded, but the user accepts the use of a fallback
5165             # library, so try to load it.
5166              
5167 0         0 eval "require $DEFAULT_LIB";
5168 0 0       0 if ($@) {
5169 0         0 croak "Couldn't load the specified math lib(s) ",
5170             join(", ", map "'$_'", @libs),
5171             ", not even the fallback lib '$DEFAULT_LIB'";
5172             }
5173              
5174             # The fallback library was successfully loaded, but the user
5175             # might want to know that we are using the fallback.
5176              
5177 0 0       0 if ($param eq 'lib') {
5178 0         0 carp "Couldn't load the specified math lib(s) ",
5179             join(", ", map "'$_'", @libs),
5180             ", so using fallback lib '$DEFAULT_LIB'";
5181             }
5182              
5183 0         0 next;
5184             }
5185              
5186             # Unrecognized parameter.
5187              
5188 59         254 push @a, $param;
5189             }
5190              
5191             # Any non-':constant' stuff is handled by our parent, Exporter
5192              
5193 103 100       343 if (@a) {
5194 58         3037 $class->SUPER::import(@a); # need it for subclasses
5195 58         5549 $class->export_to_level(1, $class, @a); # need it for Math::BigFloat
5196             }
5197              
5198             # We might not have loaded any backend library yet, either because the user
5199             # didn't specify any, or because the specified libraries failed to load and
5200             # the user allows the use of a fallback library.
5201              
5202 103 100       16701 unless (defined $LIB) {
5203 32         2484 eval "require $DEFAULT_LIB";
5204 32 50       302 if ($@) {
5205 0         0 croak "No lib specified, and couldn't load the default",
5206             " lib '$DEFAULT_LIB'";
5207             }
5208 32         2339 $LIB = $DEFAULT_LIB;
5209             }
5210              
5211             # import done
5212             }
5213              
5214             sub _trailing_zeros {
5215             # return the amount of trailing zeros in $x (as scalar)
5216 0     0   0 my $x = shift;
5217 0 0       0 $x = __PACKAGE__->new($x) unless ref $x;
5218              
5219 0 0       0 return 0 if $x->{sign} !~ /^[+-]$/; # NaN, inf, -inf etc
5220              
5221 0         0 $LIB->_zeros($x->{value}); # must handle odd values, 0 etc
5222             }
5223              
5224             sub _scan_for_nonzero {
5225             # internal, used by bround() to scan for non-zeros after a '5'
5226 2983     2983   7499 my ($x, $pad, $xs, $len) = @_;
5227              
5228 2983 100       6482 return 0 if $len == 1; # "5" is trailed by invisible zeros
5229 2960         4408 my $follow = $pad - 1;
5230 2960 100 66     23357 return 0 if $follow > $len || $follow < 1;
5231              
5232             # use the string form to check whether only '0's follow or not
5233 2307 100       13972 substr ($xs, -$follow) =~ /[^0]/ ? 1 : 0;
5234             }
5235              
5236             sub _find_round_parameters {
5237             # After any operation or when calling round(), the result is rounded by
5238             # regarding the A & P from arguments, local parameters, or globals.
5239              
5240             # !!!!!!! If you change this, remember to change round(), too! !!!!!!!!!!
5241              
5242             # This procedure finds the round parameters, but it is for speed reasons
5243             # duplicated in round. Otherwise, it is tested by the testsuite and used
5244             # by bdiv().
5245              
5246             # returns ($self) or ($self, $a, $p, $r) - sets $self to NaN of both A and P
5247             # were requested/defined (locally or globally or both)
5248              
5249 10202     10202   55049 my ($self, $a, $p, $r, @args) = @_;
5250             # $a accuracy, if given by caller
5251             # $p precision, if given by caller
5252             # $r round_mode, if given by caller
5253             # @args all 'other' arguments (0 for unary, 1 for binary ops)
5254              
5255 10202         19074 my $class = ref($self); # find out class of argument(s)
5256 51     51   539 no strict 'refs';
  51         186  
  51         22212  
5257              
5258             # convert to normal scalar for speed and correctness in inner parts
5259 10202 50 100     35317 $a = $a->can('numify') ? $a->numify() : "$a" if defined $a && ref($a);
    100          
5260 10202 0 66     22789 $p = $p->can('numify') ? $p->numify() : "$p" if defined $p && ref($p);
    50          
5261              
5262             # now pick $a or $p, but only if we have got "arguments"
5263 10202 100       19781 if (!defined $a) {
5264 994         2192 foreach ($self, @args) {
5265             # take the defined one, or if both defined, the one that is smaller
5266             $a = $_->{_a}
5267 1568 50 33     4005 if (defined $_->{_a}) && (!defined $a || $_->{_a} < $a);
      66        
5268             }
5269             }
5270 10202 100       19098 if (!defined $p) {
5271             # even if $a is defined, take $p, to signal error for both defined
5272 10150         18784 foreach ($self, @args) {
5273             # take the defined one, or if both defined, the one that is bigger
5274             # -2 > -3, and 3 > 2
5275             $p = $_->{_p}
5276 18981 50 33     41220 if (defined $_->{_p}) && (!defined $p || $_->{_p} > $p);
      66        
5277             }
5278             }
5279              
5280             # if still none defined, use globals (#2)
5281 10202 100       18238 $a = ${"$class\::accuracy"} unless defined $a;
  962         2978  
5282 10202 100       18298 $p = ${"$class\::precision"} unless defined $p;
  10140         28514  
5283              
5284             # A == 0 is useless, so undef it to signal no rounding
5285 10202 100 100     32010 $a = undef if defined $a && $a == 0;
5286              
5287             # no rounding today?
5288 10202 100 100     25737 return ($self) unless defined $a || defined $p; # early out
5289              
5290             # set A and set P is an fatal error
5291 9291 100 100     28446 return ($self->bnan()) if defined $a && defined $p; # error
5292              
5293 9282 100       16645 $r = ${"$class\::round_mode"} unless defined $r;
  9273         21298  
5294 9282 100       39433 if ($r !~ /^(even|odd|[+-]inf|zero|trunc|common)$/) {
5295 3         412 croak("Unknown round mode '$r'");
5296             }
5297              
5298 9279 100       19728 $a = int($a) if defined $a;
5299 9279 100       17194 $p = int($p) if defined $p;
5300              
5301 9279         39554 ($self, $a, $p, $r);
5302             }
5303              
5304             # Return true if the input is numeric and false if it is a string.
5305              
5306             sub _is_numeric {
5307 0     0   0 shift; # class name
5308 0         0 my $value = shift;
5309 51     51   467 no warnings 'numeric';
  51         114  
  51         144294  
5310             # detect numbers
5311             # string & "" -> ""
5312             # number & "" -> 0 (with warning)
5313             # nan and inf can detect as numbers, so check with * 0
5314 0 0       0 return unless CORE::length((my $dummy = "") & $value);
5315 0 0       0 return unless 0 + $value eq $value;
5316 0 0       0 return 1 if $value * 0 == 0;
5317 0         0 return -1; # Inf/NaN
5318             }
5319              
5320             # Trims the sign of the significand, the (absolute value of the) significand,
5321             # the sign of the exponent, and the (absolute value of the) exponent. The
5322             # returned values have no underscores ("_") or unnecessary leading or trailing
5323             # zeros.
5324              
5325             sub _trim_split_parts {
5326 10064     10064   14298 shift; # class name
5327              
5328 10064   100     37310 my $sig_sgn = shift() || '+';
5329 10064   100     29446 my $sig_str = shift() || '0';
5330 10064   100     30839 my $exp_sgn = shift() || '+';
5331 10064   100     28178 my $exp_str = shift() || '0';
5332              
5333 10064         20924 $sig_str =~ tr/_//d; # "1.0_0_0" -> "1.000"
5334 10064         29830 $sig_str =~ s/^0+//; # "01.000" -> "1.000"
5335 10064 100       29414 $sig_str =~ s/\.0*$// # "1.000" -> "1"
5336             || $sig_str =~ s/(\..*[^0])0+$/$1/; # "1.010" -> "1.01"
5337 10064 100       22723 $sig_str = '0' unless CORE::length($sig_str);
5338              
5339 10064 100       34778 return '+', '0', '+', '0' if $sig_str eq '0';
5340              
5341 5308         8677 $exp_str =~ tr/_//d; # "01_234" -> "01234"
5342 5308         16567 $exp_str =~ s/^0+//; # "01234" -> "1234"
5343 5308 100       13813 $exp_str = '0' unless CORE::length($exp_str);
5344 5308 100       12206 $exp_sgn = '+' if $exp_str eq '0'; # "+3e-0" -> "+3e+0"
5345              
5346 5308         25912 return $sig_sgn, $sig_str, $exp_sgn, $exp_str;
5347             }
5348              
5349             # Takes any string representing a valid decimal number and splits it into four
5350             # strings: the sign of the significand, the absolute value of the significand,
5351             # the sign of the exponent, and the absolute value of the exponent. Both the
5352             # significand and the exponent are in base 10.
5353             #
5354             # Perl accepts literals like the following. The value is 100.1.
5355             #
5356             # 1__0__.__0__1__e+0__1__ (prints "Misplaced _ in number")
5357             # 1_0.0_1e+0_1
5358             #
5359             # Strings representing decimal numbers do not allow underscores, so only the
5360             # following is valid
5361             #
5362             # "10.01e+01"
5363              
5364             sub _dec_str_to_dec_str_parts {
5365 9785     9785   14985 my $class = shift;
5366 9785         15283 my $str = shift;
5367              
5368 9785 100       52732 if ($str =~ /
5369             ^
5370              
5371             # optional leading whitespace
5372             \s*
5373              
5374             # optional sign
5375             ( [+-]? )
5376              
5377             # significand
5378             (
5379             # integer part and optional fraction part ...
5380             \d+ (?: _+ \d+ )* _*
5381             (?:
5382             \.
5383             (?: _* \d+ (?: _+ \d+ )* _* )?
5384             )?
5385             |
5386             # ... or mandatory fraction part
5387             \.
5388             \d+ (?: _+ \d+ )* _*
5389             )
5390              
5391             # optional exponent
5392             (?:
5393             [Ee]
5394             ( [+-]? )
5395             ( \d+ (?: _+ \d+ )* _* )
5396             )?
5397              
5398             # optional trailing whitespace
5399             \s*
5400              
5401             $
5402             /x)
5403             {
5404 8695         26317 return $class -> _trim_split_parts($1, $2, $3, $4);
5405             }
5406              
5407 1090         3297 return;
5408             }
5409              
5410             # Takes any string representing a valid hexadecimal number and splits it into
5411             # four strings: the sign of the significand, the absolute value of the
5412             # significand, the sign of the exponent, and the absolute value of the exponent.
5413             # The significand is in base 16, and the exponent is in base 2.
5414             #
5415             # Perl accepts literals like the following. The "x" might be a capital "X". The
5416             # value is 32.0078125.
5417             #
5418             # 0x__1__0__.0__1__p+0__1__ (prints "Misplaced _ in number")
5419             # 0x1_0.0_1p+0_1
5420             #
5421             # The CORE::hex() function does not accept floating point accepts
5422             #
5423             # "0x_1_0"
5424             # "x_1_0"
5425             # "_1_0"
5426              
5427             sub _hex_str_to_hex_str_parts {
5428 1118     1118   1688 my $class = shift;
5429 1118         1549 my $str = shift;
5430              
5431 1118 100       6200 if ($str =~ /
5432             ^
5433              
5434             # optional leading whitespace
5435             \s*
5436              
5437             # optional sign
5438             ( [+-]? )
5439              
5440             # optional hex prefix
5441             (?: 0? [Xx] _* )?
5442              
5443             # significand using the hex digits 0..9 and a..f
5444             (
5445             # integer part and optional fraction part ...
5446             [0-9a-fA-F]+ (?: _+ [0-9a-fA-F]+ )* _*
5447             (?:
5448             \.
5449             (?: _* [0-9a-fA-F]+ (?: _+ [0-9a-fA-F]+ )* _* )?
5450             )?
5451             |
5452             # ... or mandatory fraction part
5453             \.
5454             [0-9a-fA-F]+ (?: _+ [0-9a-fA-F]+ )* _*
5455             )
5456              
5457             # optional exponent (power of 2) using decimal digits
5458             (?:
5459             [Pp]
5460             ( [+-]? )
5461             ( \d+ (?: _+ \d+ )* _* )
5462             )?
5463              
5464             # optional trailing whitespace
5465             \s*
5466              
5467             $
5468             /x)
5469             {
5470 1114         3073 return $class -> _trim_split_parts($1, $2, $3, $4);
5471             }
5472              
5473 4         22 return;
5474             }
5475              
5476             # Takes any string representing a valid octal number and splits it into four
5477             # strings: the sign of the significand, the absolute value of the significand,
5478             # the sign of the exponent, and the absolute value of the exponent. The
5479             # significand is in base 8, and the exponent is in base 2.
5480              
5481             sub _oct_str_to_oct_str_parts {
5482 3     3   6 my $class = shift;
5483 3         8 my $str = shift;
5484              
5485 3 50       32 if ($str =~ /
5486             ^
5487              
5488             # optional leading whitespace
5489             \s*
5490              
5491             # optional sign
5492             ( [+-]? )
5493              
5494             # optional octal prefix
5495             (?: 0? [Oo] _* )?
5496              
5497             # significand using the octal digits 0..7
5498             (
5499             # integer part and optional fraction part ...
5500             [0-7]+ (?: _+ [0-7]+ )* _*
5501             (?:
5502             \.
5503             (?: _* [0-7]+ (?: _+ [0-7]+ )* _* )?
5504             )?
5505             |
5506             # ... or mandatory fraction part
5507             \.
5508             [0-7]+ (?: _+ [0-7]+ )* _*
5509             )
5510              
5511             # optional exponent (power of 2) using decimal digits
5512             (?:
5513             [Pp]
5514             ( [+-]? )
5515             ( \d+ (?: _+ \d+ )* _* )
5516             )?
5517              
5518             # optional trailing whitespace
5519             \s*
5520              
5521             $
5522             /x)
5523             {
5524 3         12 return $class -> _trim_split_parts($1, $2, $3, $4);
5525             }
5526              
5527 0         0 return;
5528             }
5529              
5530             # Takes any string representing a valid binary number and splits it into four
5531             # strings: the sign of the significand, the absolute value of the significand,
5532             # the sign of the exponent, and the absolute value of the exponent. The
5533             # significand is in base 2, and the exponent is in base 2.
5534              
5535             sub _bin_str_to_bin_str_parts {
5536 275     275   422 my $class = shift;
5537 275         390 my $str = shift;
5538              
5539 275 100       1697 if ($str =~ /
5540             ^
5541              
5542             # optional leading whitespace
5543             \s*
5544              
5545             # optional sign
5546             ( [+-]? )
5547              
5548             # optional binary prefix
5549             (?: 0? [Bb] _* )?
5550              
5551             # significand using the binary digits 0 and 1
5552             (
5553             # integer part and optional fraction part ...
5554             [01]+ (?: _+ [01]+ )* _*
5555             (?:
5556             \.
5557             (?: _* [01]+ (?: _+ [01]+ )* _* )?
5558             )?
5559             |
5560             # ... or mandatory fraction part
5561             \.
5562             [01]+ (?: _+ [01]+ )* _*
5563             )
5564              
5565             # optional exponent (power of 2) using decimal digits
5566             (?:
5567             [Pp]
5568             ( [+-]? )
5569             ( \d+ (?: _+ \d+ )* _* )
5570             )?
5571              
5572             # optional trailing whitespace
5573             \s*
5574              
5575             $
5576             /x)
5577             {
5578 252         766 return $class -> _trim_split_parts($1, $2, $3, $4);
5579             }
5580              
5581 23         83 return;
5582             }
5583              
5584             # Takes any string representing a valid decimal number and splits it into four
5585             # parts: the sign of the significand, the absolute value of the significand as a
5586             # libray thingy, the sign of the exponent, and the absolute value of the
5587             # exponent as a library thingy.
5588              
5589             sub _dec_str_parts_to_flt_lib_parts {
5590 8695     8695   12750 shift; # class name
5591              
5592 8695         19381 my ($sig_sgn, $sig_str, $exp_sgn, $exp_str) = @_;
5593              
5594             # Handle zero.
5595              
5596 8695 100       17828 if ($sig_str eq '0') {
5597 4744         15506 return '+', $LIB -> _zero(), '+', $LIB -> _zero();
5598             }
5599              
5600             # Absolute value of exponent as library "object".
5601              
5602 3951         13685 my $exp_lib = $LIB -> _new($exp_str);
5603              
5604             # If there is a dot in the significand, remove it so the significand
5605             # becomes an integer and adjust the exponent accordingly. Also remove
5606             # leading zeros which might now appear in the significand. E.g.,
5607             #
5608             # 12.345e-2 -> 12345e-5
5609             # 12.345e+2 -> 12345e-1
5610             # 0.0123e+5 -> 00123e+1 -> 123e+1
5611              
5612 3951         9178 my $idx = index $sig_str, '.';
5613 3951 100       9143 if ($idx >= 0) {
5614 2324         5677 substr($sig_str, $idx, 1) = '';
5615              
5616             # delta = length - index
5617 2324         6197 my $delta = $LIB -> _new(CORE::length($sig_str));
5618 2324         7907 $delta = $LIB -> _sub($delta, $LIB -> _new($idx));
5619              
5620             # exponent - delta
5621 2324         10393 ($exp_lib, $exp_sgn) = $LIB -> _ssub($exp_lib, $exp_sgn, $delta, '+');
5622              
5623 2324         7612 $sig_str =~ s/^0+//;
5624             }
5625              
5626             # If there are trailing zeros in the significand, remove them and
5627             # adjust the exponent. E.g.,
5628             #
5629             # 12340e-5 -> 1234e-4
5630             # 12340e-1 -> 1234e0
5631             # 12340e+3 -> 1234e4
5632              
5633 3951 100       12417 if ($sig_str =~ s/(0+)\z//) {
5634 863         2110 my $len = CORE::length($1);
5635 863         2455 ($exp_lib, $exp_sgn) =
5636             $LIB -> _sadd($exp_lib, $exp_sgn, $LIB -> _new($len), '+');
5637             }
5638              
5639             # At this point, the significand is empty or an integer with no trailing
5640             # zeros. The exponent is in base 10.
5641              
5642 3951 50       9319 unless (CORE::length $sig_str) {
5643 0         0 return '+', $LIB -> _zero(), '+', $LIB -> _zero();
5644             }
5645              
5646             # Absolute value of significand as library "object".
5647              
5648 3951         9385 my $sig_lib = $LIB -> _new($sig_str);
5649              
5650 3951         26107 return $sig_sgn, $sig_lib, $exp_sgn, $exp_lib;
5651             }
5652              
5653             # Takes any string representing a valid binary number and splits it into four
5654             # parts: the sign of the significand, the absolute value of the significand as a
5655             # libray thingy, the sign of the exponent, and the absolute value of the
5656             # exponent as a library thingy.
5657              
5658             sub _bin_str_parts_to_flt_lib_parts {
5659 1369     1369   2038 shift; # class name
5660              
5661 1369         3243 my ($sig_sgn, $sig_str, $exp_sgn, $exp_str, $bpc) = @_;
5662 1369         4438 my $bpc_lib = $LIB -> _new($bpc);
5663              
5664             # Handle zero.
5665              
5666 1369 100       3153 if ($sig_str eq '0') {
5667 12         45 return '+', $LIB -> _zero(), '+', $LIB -> _zero();
5668             }
5669              
5670             # Absolute value of exponent as library "object".
5671              
5672 1357         2921 my $exp_lib = $LIB -> _new($exp_str);
5673              
5674             # If there is a dot in the significand, remove it so the significand
5675             # becomes an integer and adjust the exponent accordingly. Also remove
5676             # leading zeros which might now appear in the significand. E.g., with
5677             # hexadecimal numbers
5678             #
5679             # 12.345p-2 -> 12345p-14
5680             # 12.345p+2 -> 12345p-10
5681             # 0.0123p+5 -> 00123p-11 -> 123p-11
5682              
5683 1357         2862 my $idx = index $sig_str, '.';
5684 1357 100       2658 if ($idx >= 0) {
5685 3         10 substr($sig_str, $idx, 1) = '';
5686              
5687             # delta = (length - index) * bpc
5688 3         9 my $delta = $LIB -> _new(CORE::length($sig_str));
5689 3         37 $delta = $LIB -> _sub($delta, $LIB -> _new($idx));
5690 3 100       18 $delta = $LIB -> _mul($delta, $bpc_lib) if $bpc != 1;
5691              
5692             # exponent - delta
5693 3         15 ($exp_lib, $exp_sgn) = $LIB -> _ssub($exp_lib, $exp_sgn, $delta, '+');
5694              
5695 3         10 $sig_str =~ s/^0+//;
5696             }
5697              
5698             # If there are trailing zeros in the significand, remove them and
5699             # adjust the exponent accordingly. E.g., with hexadecimal numbers
5700             #
5701             # 12340p-5 -> 1234p-1
5702             # 12340p-1 -> 1234p+3
5703             # 12340p+3 -> 1234p+7
5704              
5705 1357 100       4581 if ($sig_str =~ s/(0+)\z//) {
5706              
5707             # delta = length * bpc
5708 241         877 my $delta = $LIB -> _new(CORE::length($1));
5709 241 100       967 $delta = $LIB -> _mul($delta, $bpc_lib) if $bpc != 1;
5710              
5711             # exponent + delta
5712 241         848 ($exp_lib, $exp_sgn) = $LIB -> _sadd($exp_lib, $exp_sgn, $delta, '+');
5713             }
5714              
5715             # At this point, the significand is empty or an integer with no leading
5716             # or trailing zeros. The exponent is in base 2.
5717              
5718 1357 50       2794 unless (CORE::length $sig_str) {
5719 0         0 return '+', $LIB -> _zero(), '+', $LIB -> _zero();
5720             }
5721              
5722             # Absolute value of significand as library "object".
5723              
5724 1357 50       6777 my $sig_lib = $bpc == 1 ? $LIB -> _from_bin('0b' . $sig_str)
    100          
    100          
5725             : $bpc == 3 ? $LIB -> _from_oct('0' . $sig_str)
5726             : $bpc == 4 ? $LIB -> _from_hex('0x' . $sig_str)
5727             : die "internal error: invalid exponent multiplier";
5728              
5729             # If the exponent (in base 2) is positive or zero ...
5730              
5731 1357 100       3014 if ($exp_sgn eq '+') {
5732              
5733 1356 100       3541 if (!$LIB -> _is_zero($exp_lib)) {
5734              
5735             # Multiply significand by 2 raised to the exponent.
5736              
5737 242         684 my $p = $LIB -> _pow($LIB -> _two(), $exp_lib);
5738 242         610 $sig_lib = $LIB -> _mul($sig_lib, $p);
5739 242         618 $exp_lib = $LIB -> _zero();
5740             }
5741             }
5742              
5743             # ... else if the exponent is negative ...
5744              
5745             else {
5746              
5747             # Rather than dividing the significand by 2 raised to the absolute
5748             # value of the exponent, multiply the significand by 5 raised to the
5749             # absolute value of the exponent and let the exponent be in base 10:
5750             #
5751             # a * 2^(-b) = a * 5^b * 10^(-b) = c * 10^(-b), where c = a * 5^b
5752              
5753 1         5 my $p = $LIB -> _pow($LIB -> _new("5"), $exp_lib);
5754 1         4 $sig_lib = $LIB -> _mul($sig_lib, $p);
5755             }
5756              
5757             # Adjust for the case when the conversion to decimal introduced trailing
5758             # zeros in the significand.
5759              
5760 1357         3598 my $n = $LIB -> _zeros($sig_lib);
5761 1357 100       2840 if ($n) {
5762 213         654 $n = $LIB -> _new($n);
5763 213         674 $sig_lib = $LIB -> _rsft($sig_lib, $n, 10);
5764 213         670 ($exp_lib, $exp_sgn) = $LIB -> _sadd($exp_lib, $exp_sgn, $n, '+');
5765             }
5766              
5767 1357         8443 return $sig_sgn, $sig_lib, $exp_sgn, $exp_lib;
5768             }
5769              
5770             # Takes any string representing a valid hexadecimal number and splits it into
5771             # four parts: the sign of the significand, the absolute value of the significand
5772             # as a libray thingy, the sign of the exponent, and the absolute value of the
5773             # exponent as a library thingy.
5774              
5775             sub _hex_str_to_flt_lib_parts {
5776 1118     1118   2009 my $class = shift;
5777 1118         1645 my $str = shift;
5778 1118 100       2779 if (my @parts = $class -> _hex_str_to_hex_str_parts($str)) {
5779 1114         3064 return $class -> _bin_str_parts_to_flt_lib_parts(@parts, 4); # 4 bits pr. chr
5780             }
5781 4         43 return;
5782             }
5783              
5784             # Takes any string representing a valid octal number and splits it into four
5785             # parts: the sign of the significand, the absolute value of the significand as a
5786             # libray thingy, the sign of the exponent, and the absolute value of the
5787             # exponent as a library thingy.
5788              
5789             sub _oct_str_to_flt_lib_parts {
5790 3     3   9 my $class = shift;
5791 3         6 my $str = shift;
5792 3 50       14 if (my @parts = $class -> _oct_str_to_oct_str_parts($str)) {
5793 3         11 return $class -> _bin_str_parts_to_flt_lib_parts(@parts, 3); # 3 bits pr. chr
5794             }
5795 0         0 return;
5796             }
5797              
5798             # Takes any string representing a valid binary number and splits it into four
5799             # parts: the sign of the significand, the absolute value of the significand as a
5800             # libray thingy, the sign of the exponent, and the absolute value of the
5801             # exponent as a library thingy.
5802              
5803             sub _bin_str_to_flt_lib_parts {
5804 275     275   521 my $class = shift;
5805 275         402 my $str = shift;
5806 275 100       728 if (my @parts = $class -> _bin_str_to_bin_str_parts($str)) {
5807 252         770 return $class -> _bin_str_parts_to_flt_lib_parts(@parts, 1); # 1 bit pr. chr
5808             }
5809 23         109 return;
5810             }
5811              
5812             # Decimal string is split into the sign of the signficant, the absolute value of
5813             # the significand as library thingy, the sign of the exponent, and the absolute
5814             # value of the exponent as a a library thingy.
5815              
5816             sub _dec_str_to_flt_lib_parts {
5817 9785     9785   18119 my $class = shift;
5818 9785         15238 my $str = shift;
5819 9785 100       24454 if (my @parts = $class -> _dec_str_to_dec_str_parts($str)) {
5820 8695         24666 return $class -> _dec_str_parts_to_flt_lib_parts(@parts);
5821             }
5822 1090         5635 return;
5823             }
5824              
5825             # Hexdecimal string to a string using decimal floating point notation.
5826              
5827             sub hex_str_to_dec_flt_str {
5828 0     0 1   my $class = shift;
5829 0           my $str = shift;
5830 0 0         if (my @parts = $class -> _hex_str_to_flt_lib_parts($str)) {
5831 0           return $class -> _flt_lib_parts_to_flt_str(@parts);
5832             }
5833 0           return;
5834             }
5835              
5836             # Octal string to a string using decimal floating point notation.
5837              
5838             sub oct_str_to_dec_flt_str {
5839 0     0 1   my $class = shift;
5840 0           my $str = shift;
5841 0 0         if (my @parts = $class -> _oct_str_to_flt_lib_parts($str)) {
5842 0           return $class -> _flt_lib_parts_to_flt_str(@parts);
5843             }
5844 0           return;
5845             }
5846              
5847             # Binary string to a string decimal floating point notation.
5848              
5849             sub bin_str_to_dec_flt_str {
5850 0     0 1   my $class = shift;
5851 0           my $str = shift;
5852 0 0         if (my @parts = $class -> _bin_str_to_flt_lib_parts($str)) {
5853 0           return $class -> _flt_lib_parts_to_flt_str(@parts);
5854             }
5855 0           return;
5856             }
5857              
5858             # Decimal string to a string using decimal floating point notation.
5859              
5860             sub dec_str_to_dec_flt_str {
5861 0     0 1   my $class = shift;
5862 0           my $str = shift;
5863 0 0         if (my @parts = $class -> _dec_str_to_flt_lib_parts($str)) {
5864 0           return $class -> _flt_lib_parts_to_flt_str(@parts);
5865             }
5866 0           return;
5867             }
5868              
5869             # Hexdecimal string to decimal notation (no exponent).
5870              
5871             sub hex_str_to_dec_str {
5872 0     0 1   my $class = shift;
5873 0           my $str = shift;
5874 0 0         if (my @parts = $class -> _dec_str_to_flt_lib_parts($str)) {
5875 0           return $class -> _flt_lib_parts_to_dec_str(@parts);
5876             }
5877 0           return;
5878             }
5879              
5880             # Octal string to decimal notation (no exponent).
5881              
5882             sub oct_str_to_dec_str {
5883 0     0 1   my $class = shift;
5884 0           my $str = shift;
5885 0 0         if (my @parts = $class -> _oct_str_to_flt_lib_parts($str)) {
5886 0           return $class -> _flt_lib_parts_to_dec_str(@parts);
5887             }
5888 0           return;
5889             }
5890              
5891             # Binary string to decimal notation (no exponent).
5892              
5893             sub bin_str_to_dec_str {
5894 0     0 1   my $class = shift;
5895 0           my $str = shift;
5896 0 0         if (my @parts = $class -> _bin_str_to_flt_lib_parts($str)) {
5897 0           return $class -> _flt_lib_parts_to_dec_str(@parts);
5898             }
5899 0           return;
5900             }
5901              
5902             # Decimal string to decimal notation (no exponent).
5903              
5904             sub dec_str_to_dec_str {
5905 0     0 1   my $class = shift;
5906 0           my $str = shift;
5907 0 0         if (my @parts = $class -> _dec_str_to_flt_lib_parts($str)) {
5908 0           return $class -> _flt_lib_parts_to_dec_str(@parts);
5909             }
5910 0           return;
5911             }
5912              
5913             sub _flt_lib_parts_to_flt_str {
5914 0     0     my $class = shift;
5915 0           my @parts = @_;
5916 0           return $parts[0] . $LIB -> _str($parts[1])
5917             . 'e' . $parts[2] . $LIB -> _str($parts[3]);
5918             }
5919              
5920             sub _flt_lib_parts_to_dec_str {
5921 0     0     my $class = shift;
5922 0           my @parts = @_;
5923              
5924             # The number is an integer iff the exponent is non-negative.
5925              
5926 0 0         if ($parts[2] eq '+') {
5927 0           my $str = $parts[0]
5928             . $LIB -> _str($LIB -> _lsft($parts[1], $parts[3], 10));
5929 0           return $str;
5930             }
5931              
5932             # If it is not an integer, add a decimal point.
5933              
5934             else {
5935 0           my $mant = $LIB -> _str($parts[1]);
5936 0           my $mant_len = CORE::length($mant);
5937 0           my $expo = $LIB -> _num($parts[3]);
5938 0           my $len_cmp = $mant_len <=> $expo;
5939 0 0         if ($len_cmp <= 0) {
5940 0           return $parts[0] . '0.' . '0' x ($expo - $mant_len) . $mant;
5941             } else {
5942 0           substr $mant, $mant_len - $expo, 0, '.';
5943 0           return $parts[0] . $mant;
5944             }
5945             }
5946             }
5947              
5948             # Takes four arguments, the sign of the significand, the absolute value of the
5949             # significand as a libray thingy, the sign of the exponent, and the absolute
5950             # value of the exponent as a library thingy, and returns three parts: the sign
5951             # of the rational number, the absolute value of the numerator as a libray
5952             # thingy, and the absolute value of the denominator as a library thingy.
5953             #
5954             # For example, to convert data representing the value "+12e-2", then
5955             #
5956             # $sm = "+";
5957             # $m = $LIB -> _new("12");
5958             # $se = "-";
5959             # $e = $LIB -> _new("2");
5960             # ($sr, $n, $d) = $class -> _flt_lib_parts_to_rat_lib_parts($sm, $m, $se, $e);
5961             #
5962             # returns data representing the same value written as the fraction "+3/25"
5963             #
5964             # $sr = "+"
5965             # $n = $LIB -> _new("3");
5966             # $d = $LIB -> _new("12");
5967              
5968             sub _flt_lib_parts_to_rat_lib_parts {
5969 0     0     my $self = shift;
5970 0           my ($msgn, $mabs, $esgn, $eabs) = @_;
5971              
5972 0 0         if ($esgn eq '-') { # "12e-2" -> "12/100" -> "3/25"
    0          
5973 0           my $num_lib = $LIB -> _copy($mabs);
5974 0           my $den_lib = $LIB -> _1ex($LIB -> _num($eabs));
5975 0           my $gcd_lib = $LIB -> _gcd($LIB -> _copy($num_lib), $den_lib);
5976 0           $num_lib = $LIB -> _div($LIB -> _copy($num_lib), $gcd_lib);
5977 0           $den_lib = $LIB -> _div($den_lib, $gcd_lib);
5978 0           return $msgn, $num_lib, $den_lib;
5979             }
5980              
5981             elsif (!$LIB -> _is_zero($eabs)) { # "12e+2" -> "1200" -> "1200/1"
5982 0           return $msgn, $LIB -> _lsft($LIB -> _copy($mabs), $eabs, 10),
5983             $LIB -> _one();
5984             }
5985              
5986             else { # "12e+0" -> "12" -> "12/1"
5987 0           return $msgn, $mabs, $LIB -> _one();
5988             }
5989             }
5990              
5991             # Add the function _register_callback() to Math::BigInt. It is provided for
5992             # backwards compabibility so that old version of Math::BigRat etc. don't
5993             # complain about missing it.
5994              
5995       0     sub _register_callback { }
5996              
5997             ###############################################################################
5998             # this method returns 0 if the object can be modified, or 1 if not.
5999             # We use a fast constant sub() here, to avoid costly calls. Subclasses
6000             # may override it with special code (f.i. Math::BigInt::Constant does so)
6001              
6002             sub modify () { 0; }
6003              
6004             1;
6005              
6006             __END__