File Coverage

blib/lib/Math/BigInt.pm
Criterion Covered Total %
statement 1550 2179 71.1
branch 1215 2038 59.6
condition 632 1044 60.5
subroutine 181 235 77.0
pod 135 136 99.2
total 3713 5632 65.9


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