File Coverage

blib/lib/Math/BigInt/Lite.pm
Criterion Covered Total %
statement 458 677 67.6
branch 276 544 50.7
condition 98 221 44.3
subroutine 98 116 84.4
pod 87 88 98.8
total 1017 1646 61.7


line stmt bran cond sub pod time code
1             # For speed and simplicity, a Math::BigInt::Lite object is a reference to a
2             # scalar. When something more complex needs to happen (like +inf,-inf, NaN or
3             # rounding), Math::BigInt::Lite objects are upgraded.
4              
5             package Math::BigInt::Lite;
6              
7             require 5.006001;
8              
9 6     6   330801 use strict;
  6         62  
  6         146  
10 6     6   26 use warnings;
  6         11  
  6         219  
11              
12             require Exporter;
13 6     6   30 use Scalar::Util qw< blessed >;
  6         9  
  6         216  
14              
15 6     6   6665 use Math::BigInt;
  6         180236  
  6         26  
16              
17             our ($_trap_inf, $_trap_nan);
18              
19             our @ISA = qw(Math::BigInt Exporter);
20             our @EXPORT_OK = qw/objectify/;
21             my $class = 'Math::BigInt::Lite';
22              
23             our $VERSION = '0.27';
24              
25             ##############################################################################
26             # global constants, flags and accessory
27              
28             our $accuracy = undef;
29             our $precision = undef;
30             our $round_mode = 'even';
31             our $div_scale = 40;
32             our $upgrade = 'Math::BigInt';
33             our $downgrade = undef;
34              
35             my $nan = 'NaN';
36              
37             my $MAX_NEW_LEN;
38             my $MAX_MUL;
39             my $MAX_ADD;
40              
41             my $MAX_BIN_LEN = 31;
42             my $MAX_OCT_LEN = 10;
43             my $MAX_HEX_LEN = 7;
44              
45             BEGIN {
46 6     6   127658 my $e0 = 1;
47 6         37 my $e1 = $e0 + 1;
48 6         12 my $num;
49             {
50 6         10 $num = '9' x $e1; # maximum value in base 10**$e1
  54         80  
51 54         146 $num = $num * $num # multiply by itself
52             + ($num - 1); # largest possible carry
53 54 100       617 last if $num !~ /^9{$e0}89{$e1}$/; # check digit pattern
54 48         86 $e0 = $e1;
55 48         54 $e1++;
56 48         60 redo;
57             }
58 6         22 my $e = $e0; # $e1 is one too large
59              
60             # the limits below brush the problems with the test above under the rug:
61              
62             # the test should be able to find the proper $e automatically
63 6 50       43 $e = 5 if $^O =~ /^uts/; # UTS get's some special treatment
64 6 50       42 $e = 5 if $^O =~ /^unicos/; # unicos is also problematic (6 seems to work
65             # there, but we play safe)
66 6 50       27 $e = 8 if $e > 8; # cap, for VMS, OS/390 and other 64 bit systems
67              
68 6         20 my $bi = $e;
69              
70             # # determine how many digits fit into an integer and can be safely added
71             # # together plus carry w/o causing an overflow
72             #
73             # # this below detects 15 on a 64 bit system, because after that it becomes
74             # # 1e16 and not 1000000 :/ I can make it detect 18, but then I get a lot of
75             # # test failures. Ugh! (Tomake detect 18: uncomment lines marked with *)
76             # use integer;
77             # my $bi = 5; # approx. 16 bit
78             # $num = int('9' x $bi);
79             # # $num = 99999; # *
80             # # while ( ($num+$num+1) eq '1' . '9' x $bi) # *
81             # while ( int($num+$num+1) eq '1' . '9' x $bi)
82             # {
83             # $bi++; $num = int('9' x $bi);
84             # # $bi++; $num *= 10; $num += 9; # *
85             # }
86             # $bi--; # back off one step
87              
88             # we ensure that every number created is below the length for the add, so
89             # that it is always safe to add two objects together
90 6         11 $MAX_NEW_LEN = $bi;
91             # The constant below is used to check the result of any add, if above, we
92             # need to upgrade.
93 6         25 $MAX_ADD = int("1E$bi");
94             # For mul, we need to check *before* the operation that both operands are
95             # below the number benlow, since otherwise it could overflow.
96 6         227 $MAX_MUL = int("1E$e");
97              
98             # print "MAX_NEW_LEN $MAX_NEW_LEN MAX_ADD $MAX_ADD MAX_MUL $MAX_MUL\n\n";
99             }
100              
101             ##############################################################################
102             # we tie our accuracy/precision/round_mode to BigInt, so that setting it here
103             # will do it in BigInt, too. You can't use Lite w/o BigInt, anyway.
104              
105             sub round_mode {
106 6     6   50 no strict 'refs';
  6         12  
  6         1169  
107             # make Class->round_mode() work
108 77     77 1 304 my $self = shift;
109 77   50     239 my $class = ref($self) || $self || __PACKAGE__;
110 77 50       131 if (defined $_[0]) {
111 77         100 my $m = shift;
112 77 50       237 die "Unknown round mode $m"
113             if $m !~ /^(even|odd|\+inf|\-inf|zero|trunc|common)$/;
114             # set in BigInt, too
115 77         219 Math::BigInt->round_mode($m);
116 77         980 return ${"${class}::round_mode"} = $m;
  77         770  
117             }
118 0         0 return ${"${class}::round_mode"};
  0         0  
119             }
120              
121             sub accuracy {
122             # $x->accuracy($a); ref($x) $a
123             # $x->accuracy(); ref($x)
124             # Class->accuracy(); class
125             # Class->accuracy($a); class $a
126              
127 0     0 1 0 my $x = shift;
128 0   0     0 my $class = ref($x) || $x || __PACKAGE__;
129              
130 6     6   39 no strict 'refs';
  6         8  
  6         1090  
131             # need to set new value?
132 0 0       0 if (@_ > 0) {
133 0         0 my $a = shift;
134 0 0 0     0 die ('accuracy must not be zero') if defined $a && $a == 0;
135 0 0       0 if (ref($x)) {
136             # $object->accuracy() or fallback to global
137 0 0       0 $x->bround($a) if defined $a;
138 0         0 $x->{_a} = $a; # set/overwrite, even if not rounded
139 0         0 $x->{_p} = undef; # clear P
140             } else {
141             # set global
142 0         0 Math::BigInt->accuracy($a);
143             # and locally here
144 0         0 $accuracy = $a;
145 0         0 $precision = undef; # clear P
146             }
147 0         0 return $a; # shortcut
148             }
149              
150 0 0       0 if (ref($x)) {
151             # $object->accuracy() or fallback to global
152 0   0     0 return $x->{_a} || ${"${class}::accuracy"};
153             }
154 0         0 return ${"${class}::accuracy"};
  0         0  
155             }
156              
157             sub precision {
158             # $x->precision($p); ref($x) $p
159             # $x->precision(); ref($x)
160             # Class->precision(); class
161             # Class->precision($p); class $p
162              
163 0     0 1 0 my $x = shift;
164 0   0     0 my $class = ref($x) || $x || __PACKAGE__;
165              
166 6     6   40 no strict 'refs';
  6         11  
  6         3261  
167             # need to set new value?
168 0 0       0 if (@_ > 0) {
169 0         0 my $p = shift;
170 0 0       0 if (ref($x)) {
171             # $object->precision() or fallback to global
172 0 0       0 $x->bfround($p) if defined $p;
173 0         0 $x->{_p} = $p; # set/overwrite, even if not rounded
174 0         0 $x->{_a} = undef; # clear A
175             } else {
176 0         0 Math::BigInt->precision($p);
177             # and locally here
178 0         0 $accuracy = undef; # clear A
179 0         0 $precision = $p;
180             }
181 0         0 return $p; # shortcut
182             }
183              
184 0 0       0 if (ref($x)) {
185             # $object->precision() or fallback to global
186 0   0     0 return $x->{_p} || ${"${class}::precision"};
187             }
188 0         0 return ${"${class}::precision"};
  0         0  
189             }
190              
191             use overload
192             '+' => sub {
193 9     9   293 my $x = $_[0];
194 9         13 my $y = $_[1];
195 9         16 my $class = ref $x;
196 9 100       34 $y = $class->new($y) unless ref($y);
197 9 50       21 if ($y->isa($class)) {
198 9         20 $x = \($$x + $$y);
199 9         15 bless $x, $class;
200 9 50       22 $x = $upgrade->new($$x) if abs($$x) >= $MAX_ADD;
201             } else {
202 0         0 $x = $upgrade->new($$x)->badd($y);
203             }
204 9         27 $x;
205             },
206              
207             '*' => sub {
208 2     2   247 my $x = $_[0];
209 2         5 my $y = $_[1];
210 2         5 my $class = ref $x;
211 2 100       9 $y = $class->new($y) unless ref($y);
212 2 50       6 if ($y->isa($class)) {
213 2         8 $x = \($$x * $$y);
214 2 50       8 $$x = 0 if $$x eq '-0'; # correct 5.x.x bug
215 2         30 bless $x, $class; # inline copy
216             } else {
217 0         0 $x = $upgrade->new(${$_[0]})->bmul($y);
  0         0  
218             }
219             },
220              
221             # some shortcuts for speed (assumes that reversed order of arguments is routed
222             # to normal '+' and we thus can always modify first arg. If this is changed,
223             # this breaks and must be adjusted.)
224             #'/=' => sub { scalar $_[0]->bdiv($_[1]); },
225             #'*=' => sub { $_[0]->bmul($_[1]); },
226             #'+=' => sub { $_[0]->badd($_[1]); },
227             #'-=' => sub { $_[0]->bsub($_[1]); },
228             #'%=' => sub { $_[0]->bmod($_[1]); },
229             #'&=' => sub { $_[0]->band($_[1]); },
230             #'^=' => sub { $_[0]->bxor($_[1]); },
231             #'|=' => sub { $_[0]->bior($_[1]); },
232             #'**=' => sub { $upgrade->bpow($_[0], $_[1]); },
233              
234 0     0   0 '<=>' => sub { my $cmp = $_[0] -> bcmp($_[1]);
235 0 0 0     0 defined($cmp) && $_[2] ? -$cmp : $cmp; },
236              
237 342     342   24013 '""' => sub { "${$_[0]}"; },
  342         2216  
238              
239 21     21   28 '0+' => sub { ${$_[0]}; },
  21         208  
240              
241             '++' => sub {
242 0     0   0 ${$_[0]}++;
  0         0  
243 0 0       0 return $upgrade->new(${$_[0]}) if ${$_[0]} >= $MAX_ADD;
  0         0  
  0         0  
244 0         0 $_[0];
245             },
246              
247             '--' => sub {
248 0     0   0 ${$_[0]}--;
  0         0  
249 0 0       0 return $upgrade->new(${$_[0]}) if ${$_[0]} <= -$MAX_ADD;
  0         0  
  0         0  
250 0         0 $_[0];
251             },
252             # fake HASH reference, so that Math::BigInt::Lite->new(123)->{sign} works
253             '%{}' => sub {
254             {
255 109 100   109   2762 sign => ($_[0] < 0) ? '-' : '+',
256             };
257             },
258 6     6   46 ;
  6         8  
  6         77  
259              
260             BEGIN {
261 6     6   23628 *objectify = \&Math::BigInt::objectify;
262             }
263              
264             sub config {
265 2     2 1 6241 my $class = shift;
266              
267             # config({a => b, ...}) -> config(a => b, ...)
268 2 50 33     23 @_ = %{ $_[0] } if @_ == 1 && ref($_[0]) eq 'HASH';
  0         0  
269              
270             # Getter/accessor.
271              
272 2 50       7 if (@_ == 1) {
273 2         5 my $param = shift;
274              
275             # We don't use a math backend library.
276 2 100 66     15 return if ($param eq 'lib' ||
277             $param eq 'lib_version');
278              
279 1         9 return $class -> SUPER::config($param);
280             }
281              
282             # Setter.
283              
284 0 0       0 $class -> SUPER::config(@_) if @_;
285              
286             # For backwards compatibility.
287              
288 0         0 my $cfg = Math::BigInt -> config();
289 0         0 $cfg->{version} = $VERSION;
290 0         0 $cfg->{lib} = undef;
291 0         0 $cfg->{lib_version} = undef;
292 0         0 $cfg;
293             }
294              
295             sub bgcd {
296              
297             # Convert calls like Class::method(2) into Class->method(2). It ignores
298             # cases like Class::method($x), where $x is an object, because this is
299             # indistinguishable from $x->method().
300              
301 26 50 33 26 1 679 unless (@_ && (ref($_[0]) || $_[0] =~ /^[a-z]\w*(?:::[a-z]\w*)*$/i)) {
      33        
302             #carp "Using ", (caller(0))[3], "() as a function is deprecated;",
303             # " use is as a method instead" if warnings::warnif("deprecated");
304 0         0 unshift @_, __PACKAGE__;
305             }
306              
307             # Make sure each argument is an object.
308              
309 26         58 my ($class, @args) = objectify(0, @_);
310              
311             # If bgcd() is called as a function, the class might be anything.
312              
313 26 100       446 return $class -> bgcd(@args) unless $class -> isa(__PACKAGE__);
314              
315             # Upgrade if one of the operands are upgraded. This is for cases like
316             #
317             # $x = Math::BigInt::Lite::bgcd("1e50");
318             # $gcd = Math::BigInt::Lite::bgcd(5, $x);
319             # $gcd = Math::BigInt::Lite->bgcd(5, $x);
320              
321 19         24 my $do_upgrade = 0;
322 19         31 for my $arg (@args) {
323 40 100       62 unless ($arg -> isa($class)) {
324 3         4 $do_upgrade = 1;
325 3         5 last;
326             }
327             }
328 19 100       39 return $upgrade -> bgcd(@args) if $do_upgrade;
329              
330             # Now compute the GCD.
331              
332 16         24 my ($a, $b, $c);
333 16         23 $a = shift @args;
334 16         30 $a = abs($$a);
335 16   100     52 while (@args && $a != 1) {
336 16         19 $b = shift @args;
337 16 100       32 next if $$b == 0;
338 15         20 $b = abs($$b);
339 15         16 do {
340 44         50 $c = $a % $b;
341 44         44 $a = $b;
342 44         76 $b = $c;
343             } while $c;
344             }
345              
346 16         136 return bless \( $a ), $class;
347             }
348              
349             sub blcm {
350              
351             # Convert calls like Class::method(2) into Class->method(2). It ignores
352             # cases like Class::method($x), where $x is an object, because this is
353             # indistinguishable from $x->method().
354              
355 8 50 33 8 1 220 unless (@_ && (ref($_[0]) || $_[0] =~ /^[a-z]\w*(?:::[a-z]\w*)*$/i)) {
      33        
356             #carp "Using ", (caller(0))[3], "() as a function is deprecated;",
357             # " use is as a method instead" if warnings::warnif("deprecated");
358 0         0 unshift @_, __PACKAGE__;
359             }
360              
361             # Make sure each argument is an object.
362              
363 8         18 my ($class, @args) = objectify(0, @_);
364              
365 8         137 my @a = ();
366 8         15 for my $arg (@args) {
367 16 100 66     61 $arg = $upgrade -> new("$arg")
368             unless defined(blessed($arg)) && $arg -> isa($upgrade);
369 16         836 push @a, $arg;
370             }
371              
372 8         20 $upgrade -> blcm(@a);
373             }
374              
375             sub isa {
376             # we aren't a BigInt nor BigRat/BigFloat
377 26735 100   26735 0 279782 $_[1] =~ /^Math::BigInt::Lite/ ? 1 : 0;
378             }
379              
380             sub new {
381 14638     14638 1 19928504 my ($class, $wanted, @r) = @_;
382              
383 14638 50       32232 return $upgrade->new($wanted) if !defined $wanted;
384              
385             # 1e12, NaN, inf, 0x12, 0b11, 1.2e2, "12345678901234567890" etc all upgrade
386 14638 50       25559 if (!ref($wanted)) {
387 14638 100 100     98271 if ((length($wanted) <= $MAX_NEW_LEN) &&
388             ($wanted =~ /^[+-]?[0-9]{1,$MAX_NEW_LEN}(\.0*)?\z/)) {
389 12975         30847 my $a = \($wanted+0); # +0 to make a copy and force it numeric
390 12975         113183 return bless $a, $class;
391             }
392             # TODO: 1e10 style constants that are still below MAX_NEW
393 1663 100       6003 if ($wanted =~ /^([+-])?([0-9]+)[eE][+]?([0-9]+)$/) {
394 37 100       142 if ((length($2) + $3) < $MAX_NEW_LEN) {
395 28         84 my $a = \($wanted+0); # +0 to make a copy and force it numeric
396 28         144 return bless $a, $class;
397             }
398             }
399             # print "new '$$a' $BASE_LEN ($wanted)\n";
400             }
401 1635         5061 $upgrade->new($wanted, @r);
402             }
403              
404             ###############################################################################
405             # String conversion methods
406             ###############################################################################
407              
408             sub bstr {
409 2984 50   2984 1 4860872 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
410              
411 2984 50 33     11580 return $upgrade -> exponent($x)
412             if defined($upgrade) && !$x -> isa($class);
413              
414 2984         20656 "$$x";
415             }
416              
417             # Scientific notation with significand/mantissa as an integer, e.g., "12345" is
418             # written as "1.2345e+4".
419              
420             sub bsstr {
421 543 50   543 1 1194 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
422              
423 543 50 33     1226 return $upgrade -> exponent($x)
424             if defined($upgrade) && !$x -> isa($class);
425              
426 543 50       2640 if ($$x =~ / ^
427             (
428             [+-]?
429             (?: 0 | [1-9] (?: \d* [1-9] )? )
430             )
431             ( 0* )
432             $
433             /x)
434             {
435 543         1026 my $mant = $1;
436 543         836 my $expo = CORE::length($2);
437 543         1795 return $mant . "e+" . $expo;
438             }
439              
440 0         0 die "Internal error: ", (caller(0))[3], "() couldn't handle",
441             " the value '", $$x, "', which is likely a bug";
442             }
443              
444             # Normalized notation, e.g., "12345" is written as "1.2345e+4".
445              
446             sub bnstr {
447 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
448              
449 0 0 0     0 return $upgrade -> exponent($x)
450             if defined($upgrade) && !$x -> isa($class);
451              
452 0         0 my ($mant, $expo);
453              
454 0 0       0 if ($$x =~ / ^
455             (
456             [+-]?
457             \d
458             )
459             ( 0* )
460             $
461             /x)
462             {
463 0         0 return $1 . "e+" . CORE::length($2);
464             }
465              
466 0 0       0 if ($$x =~
467             / ^
468             ( [+-]? [1-9] )
469             (
470             ( \d* [1-9] )
471             0*
472             )
473             $
474             /x)
475             {
476 0         0 return $1 . "." . $3 . "e+" . CORE::length($2);
477             }
478              
479 0         0 die "Internal error: ", (caller(0))[3], "() couldn't handle",
480             " the value '", $$x, "', which is likely a bug";
481             }
482              
483             # Engineering notation, e.g., "12345" is written as "12.345e+3".
484              
485             sub bestr {
486 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
487              
488 0 0 0     0 return $upgrade -> exponent($x)
489             if defined($upgrade) && !$x -> isa($class);
490              
491 0 0       0 if ($$x =~ / ^
492             ( [+-]? )
493             (
494             0 | [1-9] (?: \d* [1-9] )?
495             )
496             ( 0* )
497             $
498             /x)
499             {
500 0         0 my $sign = $1;
501 0         0 my $mant = $2;
502 0         0 my $expo = CORE::length($3);
503 0         0 my $mantlen = CORE::length($mant); # length of mantissa
504 0         0 $expo += $mantlen;
505              
506 0         0 my $dotpos = ($expo - 1) % 3 + 1; # offset of decimal point
507 0         0 $expo -= $dotpos;
508              
509 0 0       0 if ($dotpos < $mantlen) {
    0          
510 0         0 substr $mant, $dotpos, 0, "."; # insert decimal point
511             } elsif ($dotpos > $mantlen) {
512 0         0 $mant .= "0" x ($dotpos - $mantlen); # append zeros
513             }
514              
515 0 0       0 return ($sign eq '-' ? '-' : '') . $mant . 'e+' . $expo;
516             }
517              
518 0         0 die "Internal error: ", (caller(0))[3], "() couldn't handle",
519             " the value '", $$x, "', which is likely a bug";
520             }
521              
522             # Decimal notation, e.g., "12345" (no exponent).
523              
524             sub bdstr {
525 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
526              
527 0 0 0     0 return $upgrade -> exponent($x)
528             if defined($upgrade) && !$x -> isa($class);
529              
530 0         0 "$$x";
531             }
532              
533             # Fraction notation, e.g., "123.4375" is written as "1975/16", but "123" is
534             # written as "123", not "123/1".
535              
536             sub bfstr {
537 0 0   0 1 0 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
538              
539 0 0 0     0 return $upgrade -> exponent($x)
540             if defined($upgrade) && !$x -> isa($class);
541              
542 0         0 "$$x";
543             }
544              
545             ###############################################################################
546              
547             sub bnorm {
548             # no-op
549 211 50   211 1 159630 my $x = ref($_[0]) ? $_[0] : $_[0]->new($_[1]);
550              
551 211         29152 $x;
552             }
553              
554             sub _upgrade_2 {
555             # This takes the two possible arguments, and checks them. It uses new() to
556             # convert literals to objects first. Then it upgrades the operation
557             # when it detects that:
558             # * one or both of the argument(s) is/are BigInt,
559             # * global A or P are set
560             # Input arguments: x, y, a, p, r
561             # Output: flag (1: need to upgrade, 0: need not), x, y, $a, $p, $r
562              
563             # Math::BigInt::Lite->badd(1, 2) style calls
564 541 100 66 541   1211 shift if !ref($_[0]) && $_[0] =~ /^Math::BigInt::Lite/;
565              
566 541         827 my ($x, $y, @r) = @_;
567              
568 541         621 my $up = 0; # default: don't upgrade
569              
570 541 50 33     2572 $up = 1
      33        
      33        
571             if (defined $r[0] || defined $r[1] || defined $accuracy || defined $precision);
572 541 100       899 $x = __PACKAGE__->new($x) unless ref $x; # upgrade literals
573 541 100       916 $y = __PACKAGE__->new($y) unless ref $y; # upgrade literals
574 541 100 66     873 $up = 1 unless $x->isa($class) && $y->isa($class);
575             # no need to check for overflow for add/sub/div/mod math
576 541 100       1216 if ($up == 1) {
577 46 50       74 $x = $upgrade->new($$x) if $x->isa($class);
578 46 50       3074 $y = $upgrade->new($$y) if $y->isa($class);
579             }
580              
581 541         1321 ($up, $x, $y, @r);
582             }
583              
584             sub _upgrade_2_mul {
585             # This takes the two possible arguments, and checks them. It uses new() to
586             # convert literals to objects first. Then it upgrades the operation
587             # when it detects that:
588             # * one or both of the argument(s) is/are BigInt,
589             # * global A or P are set
590             # * One of the arguments is too large for the operation
591             # Input arguments: x, y, a, p, r
592             # Output: flag (1: need to upgrade, 0: need not), x, y, $a, $p, $r
593              
594             # Math::BigInt::Lite->badd(1, 2) style calls
595 123 100 66 123   271 shift if !ref($_[0]) && $_[0] =~ /^Math::BigInt::Lite/;
596              
597 123         207 my ($x, $y, @r) = @_;
598              
599 123         140 my $up = 0; # default: don't upgrade
600              
601 123 50 33     534 $up = 1
      33        
      33        
602             if (defined $r[0] || defined $r[1] || defined $accuracy || defined $precision);
603 123 100       209 $x = __PACKAGE__->new($x) unless ref $x; # upgrade literals
604 123 100       175 $y = __PACKAGE__->new($y) unless ref $y; # upgrade literals
605 123 100 66     191 $up = 1 unless $x->isa($class) && $y->isa($class);
606 123 50 33     482 $up = 1 if ($up == 0 && (abs($$x) >= $MAX_MUL || abs($$y) >= $MAX_MUL) );
      66        
607 123 100       202 if ($up == 1) {
608 3 50       7 $x = $upgrade->new($$x) if $x->isa($class);
609 3 50       254 $y = $upgrade->new($$y) if $y->isa($class);
610             }
611 123         291 ($up, $x, $y, @r);
612             }
613              
614             sub _upgrade_1 {
615             # This takes the one possible argument, and checks it. It uses new() to
616             # convert a literal to an object first. Then it checks for a necc. upgrade:
617             # * the argument is a BigInt
618             # * global A or P are set
619             # Input arguments: x, a, p, r
620             # Output: flag (1: need to upgrade, 0: need not), x, $a, $p, $r
621 6     6   11 my ($x, @r) = @_;
622              
623 6         9 my $up = 0; # default: don't upgrade
624              
625 6 50 33     44 $up = 1
      33        
      33        
626             if (defined $r[0] || defined $r[1] || defined $accuracy || defined $precision);
627 6 50       14 $x = __PACKAGE__->new($x) unless ref $x; # upgrade literals
628 6 50       12 $up = 1 unless $x->isa($class);
629 6 50       12 if ($up == 1) {
630 0 0       0 $x = $upgrade->new($$x) if $x->isa($class);
631             }
632 6         17 ($up, $x, @r);
633             }
634              
635             ##############################################################################
636             # rounding functions
637              
638             sub bround {
639 9 50   9 1 58 my ($class, $x, @a) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
640              
641             #$m = $self->round_mode() if !defined $m;
642             #$a = $self->accuracy() if !defined $a;
643              
644 9 50       18 $x = $upgrade->new($$x) if $x->isa($class);
645 9         565 $x->bround(@a);
646             }
647              
648             sub bfround {
649 1 50   1 1 7 my ($class, $x, @p) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
650              
651             #$m = $self->round_mode() if !defined $m;
652             #$p = $self->precision() if !defined $p;
653              
654 1 50       3 $x = $upgrade->new($$x) if $x->isa($class);
655 1         68 $x->bfround(@p);
656              
657             }
658              
659             sub round {
660 64 50   64 1 469 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
661              
662 64 50       108 $x = $upgrade->new($$x) if $x->isa($class);
663 64         3735 $x->round(@r);
664             }
665              
666             ##############################################################################
667             # special values
668              
669             sub bnan {
670             # return a NaN
671 15     15 1 1047 shift;
672 15         52 $upgrade -> bnan(@_);
673             }
674              
675             sub binf {
676             # return a +/-Inf
677 17     17 1 6038 shift;
678 17         56 $upgrade -> binf(@_);
679             }
680              
681             sub bone {
682             # return a +/-1
683 117     117 1 2070 my $x = shift;
684              
685 117         177 my ($sign, @r) = @_;
686              
687             # Get the sign.
688              
689 117 100 100     285 if (defined($_[0]) && $_[0] =~ /^\s*([+-])\s*$/) {
690 8         19 $sign = $1;
691 8         11 shift;
692             } else {
693 109         159 $sign = '+';
694             }
695              
696 117 100       182 my $num = $sign eq "-" ? -1 : 1;
697 117 100       246 return $x -> new($num) unless ref $x; # $class->bone();
698 30         47 $$x = $num;
699 30         234 $x;
700             }
701              
702             sub bzero {
703             # return a one
704 3     3 1 245 my $x = shift;
705              
706 3 100       15 return $x->new(0) unless ref $x; # $class->bone();
707 1         3 $$x = 0;
708 1         2 $x;
709             }
710              
711             sub bcmp {
712             # compare the value of two objects
713 567 100 66 567 1 6531 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
714             ? (ref($_[0]), @_)
715             : objectify(2, @_);
716              
717 567 100 66     1393 return $upgrade->bcmp($x, $y)
      66        
718             if defined($upgrade) && (!$x->isa($class) || !$y->isa($class));
719              
720 561         1279 $$x <=> $$y;
721             }
722              
723             sub bacmp {
724             # compare the absolute value of two objects
725 12 100 66 12 1 475 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
726             ? (ref($_[0]), @_)
727             : objectify(2, @_);
728              
729 12 100 66     239 return $upgrade->bacmp($x, $y)
      66        
730             if defined($upgrade) && (!$x->isa($class) || !$y->isa($class));
731              
732 7         54 abs($$x) <=> abs($$y);
733             }
734              
735             ##############################################################################
736             # copy/conversion
737              
738             sub copy {
739 432     432 1 16530 my ($x, $class);
740 432 50       775 if (ref($_[0])) { # $y = $x -> copy()
741 432         542 $x = shift;
742 432         540 $class = ref($x);
743             } else { # $y = $class -> copy($y)
744 0         0 $class = shift;
745 0         0 $x = shift;
746             }
747              
748 432         596 my $val = $$x;
749 432         1088 bless \$val, $class;
750             }
751              
752             sub as_int {
753 540 50   540 1 12253 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
754              
755 540 50       897 return $x -> copy() if $x -> isa("Math::BigInt");
756              
757             # disable upgrading and downgrading
758              
759 540         974 my $upg = Math::BigInt -> upgrade();
760 540         4166 my $dng = Math::BigInt -> downgrade();
761 540         4262 Math::BigInt -> upgrade(undef);
762 540         4119 Math::BigInt -> downgrade(undef);
763              
764 540         4059 my $y = Math::BigInt -> new($x -> bsstr());
765              
766             # reset upgrading and downgrading
767              
768 540         34948 Math::BigInt -> upgrade($upg);
769 540         4357 Math::BigInt -> downgrade($dng);
770              
771 540         4012 return $y;
772             }
773              
774             sub as_number {
775 3 50   3 1 324 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
776              
777 3 50       10 return $upgrade->new($x) unless ref($x);
778             # as_number needs to return a BigInt
779 3 50       6 return $upgrade->new($$x) if $x->isa($class);
780 0         0 $x->copy();
781             }
782              
783             sub numify {
784 81 50   81 1 1510 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
785              
786 81 50       145 return $$x if $x->isa($class);
787 0         0 $x->numify();
788             }
789              
790             sub as_hex {
791 5 50   5 1 31 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
792              
793 5 50       12 return $upgrade->new($$x)->as_hex() if $x->isa($class);
794 0         0 $x->as_hex();
795             }
796              
797             sub as_oct {
798 5 50   5 1 34 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
799              
800 5 50       10 return $upgrade->new($$x)->as_oct() if $x->isa($class);
801 0         0 $x->as_hex();
802             }
803              
804             sub as_bin {
805 5 50   5 1 30 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
806              
807 5 50       11 return $upgrade->new($$x)->as_bin() if $x->isa($class);
808 0         0 $x->as_bin();
809             }
810              
811             sub from_hex {
812 0     0 1 0 my $self = shift;
813 0         0 my $selfref = ref $self;
814 0   0     0 my $class = $selfref || $self;
815              
816 0         0 my $str = shift;
817              
818             # If called as a class method, initialize a new object.
819              
820 0 0       0 $self = $class -> bzero() unless $selfref;
821              
822 0 0       0 if ($str =~ s/
823             ^
824             \s*
825             ( [+-]? )
826             ( 0? [Xx] )?
827             (
828             [0-9a-fA-F]*
829             ( _ [0-9a-fA-F]+ )*
830             )
831             \s*
832             $
833             //x)
834             {
835             # Get a "clean" version of the string, i.e., non-emtpy and with no
836             # underscores or invalid characters.
837              
838 0         0 my $sign = $1;
839 0         0 my $chrs = $3;
840 0         0 $chrs =~ tr/_//d;
841 0 0       0 $chrs = '0' unless CORE::length $chrs;
842              
843 0 0       0 return $upgrade -> from_hex($sign . $chrs)
844             if length($chrs) > $MAX_HEX_LEN;
845              
846 0         0 $$self = oct('0x' . $chrs);
847 0 0       0 $$self = -$$self if $sign eq '-';
848              
849 0         0 return $self;
850             }
851              
852             # For consistency with from_hex() and from_oct(), we return NaN when the
853             # input is invalid.
854              
855 0         0 return $self->bnan();
856             }
857              
858             sub from_oct {
859 0     0 1 0 my $self = shift;
860 0         0 my $selfref = ref $self;
861 0   0     0 my $class = $selfref || $self;
862              
863 0         0 my $str = shift;
864              
865             # If called as a class method, initialize a new object.
866              
867 0 0       0 $self = $class -> bzero() unless $selfref;
868              
869 0 0       0 if ($str =~ s/
870             ^
871             \s*
872             ( [+-]? )
873             ( 0? [Oo] )?
874             (
875             [0-7]*
876             ( _ [0-7]+ )*
877             )
878             \s*
879             $
880             //x)
881             {
882             # Get a "clean" version of the string, i.e., non-emtpy and with no
883             # underscores or invalid characters.
884              
885 0         0 my $sign = $1;
886 0         0 my $chrs = $3;
887 0         0 $chrs =~ tr/_//d;
888 0 0       0 $chrs = '0' unless CORE::length $chrs;
889              
890 0 0       0 return $upgrade -> from_oct($sign . $chrs)
891             if length($chrs) > $MAX_OCT_LEN;
892              
893 0         0 $$self = oct($chrs);
894 0 0       0 $$self = -$$self if $sign eq '-';
895              
896 0         0 return $self;
897             }
898              
899             # For consistency with from_hex() and from_oct(), we return NaN when the
900             # input is invalid.
901              
902 0         0 return $self->bnan();
903             }
904              
905             sub from_bin {
906 0     0 1 0 my $self = shift;
907 0         0 my $selfref = ref $self;
908 0   0     0 my $class = $selfref || $self;
909              
910 0         0 my $str = shift;
911              
912             # If called as a class method, initialize a new object.
913              
914 0 0       0 $self = $class -> bzero() unless $selfref;
915              
916 0 0       0 if ($str =~ s/
917             ^
918             \s*
919             ( [+-]? )
920             ( 0? [Bb] )?
921             (
922             [01]*
923             ( _ [01]+ )*
924             )
925             \s*
926             $
927             //x)
928             {
929             # Get a "clean" version of the string, i.e., non-emtpy and with no
930             # underscores or invalid characters.
931              
932 0         0 my $sign = $1;
933 0         0 my $chrs = $3;
934 0         0 $chrs =~ tr/_//d;
935 0 0       0 $chrs = '0' unless CORE::length $chrs;
936              
937 0 0       0 return $upgrade -> from_bin($sign . $chrs)
938             if length($chrs) > $MAX_BIN_LEN;
939              
940 0         0 $$self = oct('0b' . $chrs);
941 0 0       0 $$self = -$$self if $sign eq '-';
942              
943 0         0 return $self;
944             }
945              
946             # For consistency with from_hex() and from_oct(), we return NaN when the
947             # input is invalid.
948              
949 0         0 return $self->bnan();
950             }
951              
952             ##############################################################################
953             # binc/bdec
954              
955             sub binc {
956             # increment by one
957 3     3 1 18 my ($up, $x, $y, @r) = _upgrade_1(@_);
958              
959 3 50       6 return $x->binc(@r) if $up;
960 3         7 $$x++;
961 3 50       7 return $upgrade->new($$x) if abs($$x) > $MAX_ADD;
962 3         22 $x;
963             }
964              
965             sub bdec {
966             # decrement by one
967 3     3 1 14 my ($up, $x, $y, @r) = _upgrade_1(@_);
968              
969 3 50       7 return $x->bdec(@r) if $up;
970 3         7 $$x--;
971 3 50       9 return $upgrade->new($$x) if abs($$x) > $MAX_ADD;
972 3         21 $x;
973             }
974              
975             ##############################################################################
976             # shifting
977              
978             sub brsft {
979             # shift right
980 29     29 1 133 my ($class, $x, $y, $b, @r) = objectify(2, @_);
981              
982 29 50       251 $x = $class->new($x) unless ref($x);
983 29 50       53 $y = $class->new($y) unless ref($y);
984 29 50 33     62 $b = $$b if ref $b && $b->isa($class);
985              
986 29 50       45 if (!$x->isa($class)) {
987 0 0       0 $y = $upgrade->new($$y) if $y->isa($class);
988 0         0 return $x->brsft($y, $b, @r);
989             }
990 29 50       48 return $upgrade->new($$x)->brsft($y, $b, @r)
991             unless $y->isa($class);
992              
993 29 100       52 $b = 2 if !defined $b;
994             # can't do this
995 29 100 100     107 return $upgrade->new($$x)->brsft($upgrade->new($$y), $b, @r)
996             if $b != 2 || $$y < 0;
997 6     6   54 use integer;
  6         10  
  6         38  
998 20         32 $$x >>= $$y; # only base 2 for now
999 20         145 $x;
1000             }
1001              
1002             sub blsft {
1003             # shift left
1004 17     17 1 79 my ($class, $x, $y, $b, @r) = objectify(2, @_);
1005              
1006 17 50       156 $x = $class->new($x) unless ref($x);
1007 17 50       35 $y = $class->new($x) unless ref($y);
1008              
1009 17 50       32 return $x->blsft($upgrade->new($$y), $b, @r) unless $x->isa($class);
1010 17 50       31 return $upgrade->new($$x)->blsft($y, $b, @r)
1011             unless $y->isa($class);
1012              
1013             # overflow: can't do this
1014 17 100       61 return $upgrade->new($$x)->blsft($upgrade->new($$y), $b, @r)
1015             if $$y > 31;
1016 15 100       32 $b = 2 if !defined $b;
1017             # can't do this
1018 15 100 100     59 return $upgrade->new($$x)->blsft($upgrade->new($$y), $b, @r)
1019             if $b != 2 || $$y < 0;
1020 6     6   1029 use integer;
  6         12  
  6         19  
1021 8         17 $$x <<= $$y; # only base 2 for now
1022 8         60 $x;
1023             }
1024              
1025             ##############################################################################
1026             # bitwise logical operators
1027              
1028             sub band {
1029             # AND two objects
1030 15 100 66 15 1 84 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
1031             ? (ref($_[0]), @_) : objectify(2, @_);
1032              
1033 15 100 66     71 return $upgrade -> band($x, $y, @r)
1034             unless $x -> isa($class) && $y -> isa($class);
1035              
1036 6     6   697 use integer;
  6         11  
  6         18  
1037 14         35 $$x = ($$x+0) & ($$y+0); # +0 to avoid string-context
1038 14         107 $x;
1039             }
1040              
1041             sub bxor {
1042             # XOR two objects
1043 22 100 66 22 1 120 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
1044             ? (ref($_[0]), @_) : objectify(2, @_);
1045              
1046 22 100 66     274 return $upgrade -> bxor($x, $y, @r)
1047             unless $x -> isa($class) && $y -> isa($class);
1048              
1049 6     6   694 use integer;
  6         13  
  6         65  
1050 16         38 $$x = ($$x+0) ^ ($$y+0); # +0 to avoid string-context
1051 16         123 $x;
1052             }
1053              
1054             sub bior {
1055             # OR two objects
1056 21 100 66 21 1 119 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
1057             ? (ref($_[0]), @_) : objectify(2, @_);
1058              
1059 21 100 66     260 return $upgrade -> bior($x, $y, @r)
1060             unless $x -> isa($class) && $y -> isa($class);
1061              
1062 6     6   784 use integer;
  6         11  
  6         19  
1063 15         38 $$x = ($$x+0) | ($$y+0); # +0 to avoid string-context
1064 15         119 $x;
1065             }
1066              
1067             ##############################################################################
1068             # mul/add/div etc
1069              
1070             sub badd {
1071             # add two objects
1072 60     60 1 3191 my ($up, $x, $y, @r) = _upgrade_2(@_);
1073              
1074 60 100       129 return $x->badd($y, @r) if $up;
1075              
1076 46         99 $$x = $$x + $$y;
1077 46 50       103 return $upgrade->new($$x) if abs($$x) > $MAX_ADD;
1078 46         340 $x;
1079             }
1080              
1081             sub bsub {
1082             # subtract two objects
1083 208     208 1 697 my ($up, $x, $y, @r) = _upgrade_2(@_);
1084 208 100       358 return $x->bsub($y, @r) if $up;
1085 206         357 $$x = $$x - $$y;
1086 206 50       374 return $upgrade->new($$x) if abs($$x) > $MAX_ADD;
1087 206         642 $x;
1088             }
1089              
1090             sub bmul {
1091             # multiply two objects
1092 123     123 1 873 my ($up, $x, $y, @r) = _upgrade_2_mul(@_);
1093 123 100       219 return $x->bmul($y, @r) if $up;
1094 120         181 $$x = $$x * $$y;
1095 120 50       250 $$x = 0 if $$x eq '-0'; # for some Perls leave '-0' here
1096             #return $upgrade->new($$x) if abs($$x) > $MAX_ADD;
1097 120         397 $x;
1098             }
1099              
1100             sub bmod {
1101             # remainder of div
1102 63     63 1 229 my ($up, $x, $y, @r) = _upgrade_2(@_);
1103 63 100       149 return $x->bmod($y, @r) if $up;
1104 57 100       126 return $upgrade->new($$x)->bmod($y, @r) if $$y == 0;
1105 54         110 $$x = $$x % $$y;
1106 54         416 $x;
1107             }
1108              
1109             sub bdiv {
1110             # divide two objects
1111 108     108 1 1415 my ($up, $x, $y, @r) = _upgrade_2(@_);
1112              
1113 108 100       237 return $x->bdiv($y, @r) if $up;
1114              
1115 96 100       219 return $upgrade->new($$x)->bdiv($$y, @r) if $$y == 0;
1116              
1117             # need to give Math::BigInt a chance to upgrade further
1118 90 50       187 return $upgrade->new($$x)->bdiv($$y, @r)
1119             if defined $Math::BigInt::upgrade;
1120              
1121 90         122 my ($quo, $rem);
1122              
1123 90         183 $rem = \($$x % $$y);
1124 90         192 $quo = int($$x / $$y);
1125 90 100 100     258 $quo-- if $$rem != 0 && ($$x <=> 0) != ($$y <=> 0);
1126              
1127 90         134 $$x = $quo;
1128              
1129 90 100       159 if (wantarray) {
1130 42         60 bless $rem, $class;
1131 42         125 return $x, $rem;
1132             }
1133              
1134 48         372 return $x;
1135             }
1136              
1137             sub btdiv {
1138             # divide two objects
1139 102     102 1 1370 my ($up, $x, $y, @r) = _upgrade_2(@_);
1140              
1141 102 100       213 return $x->btdiv($y, @r) if $up;
1142              
1143 90 100       194 return $upgrade->new($$x)->btdiv($$y, @r) if $$y == 0;
1144              
1145             # need to give Math::BigInt a chance to upgrade further
1146 84 50       156 return $upgrade->new($$x)->btdiv($$y, @r)
1147             if defined $Math::BigInt::upgrade;
1148              
1149 84         99 my ($quo, $rem);
1150              
1151 84 100       132 if (wantarray) {
1152 42         78 $rem = \($$x % $$y);
1153 42 100 100     107 $$rem -= $$y if $$rem != 0 && ($$x <=> 0) != ($$y <=> 0);
1154 42         61 bless $rem, $class;
1155             }
1156              
1157 84         162 $quo = int($$x / $$y);
1158              
1159 84         105 $$x = $quo;
1160 84 100       206 return $x, $rem if wantarray;
1161 42         328 return $x;
1162             }
1163              
1164             ##############################################################################
1165             # is_foo methods (the rest is inherited)
1166              
1167             sub is_int {
1168             # return true if arg (BLite or num_str) is an integer
1169 2 50   2 1 15 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1170              
1171 2 50       6 return 1 if $x->isa($class); # Lite objects are always int
1172 0         0 $x->is_int();
1173             }
1174              
1175             sub is_inf {
1176             # return true if arg (BLite or num_str) is an infinity
1177 2 50   2 1 16 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1178              
1179 2 50       6 return 0 if $x->isa($class); # Lite objects are never inf
1180 0         0 $x->is_inf();
1181             }
1182              
1183             sub is_nan {
1184             # return true if arg (BLite or num_str) is an NaN
1185 165 50   165 1 1038 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1186              
1187 165 50       244 return 0 if $x->isa($class); # Lite objects are never NaN
1188 0         0 $x->is_nan();
1189             }
1190              
1191             sub is_zero {
1192             # return true if arg (BLite or num_str) is zero
1193 11 50   11 1 96 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1194              
1195 11 50       24 return ($$x == 0) <=> 0 if $x->isa($class);
1196 0         0 $x->is_zero();
1197             }
1198              
1199             sub is_positive {
1200             # return true if arg (BLite or num_str) is positive
1201 3 50   3 1 21 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1202              
1203 3 50       8 return ($$x > 0) <=> 0 if $x->isa($class);
1204 0         0 $x->is_positive();
1205             }
1206              
1207             sub is_negative {
1208             # return true if arg (BLite or num_str) is negative
1209 3 50   3 1 19 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1210              
1211 3 50       7 return ($$x < 0) <=> 0 if $x->isa($class);
1212 0         0 $x->is_positive();
1213             }
1214              
1215             sub is_one {
1216             # return true if arg (BLite or num_str) is one
1217 9 50   9 1 48 my ($class, $x, $s) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1218              
1219 9         33 my $one = 1;
1220 9 100 100     38 $one = -1 if ($s || '+') eq '-';
1221 9 50       19 return ($$x == $one) <=> 0 if $x->isa($class);
1222 0         0 $x->is_one();
1223             }
1224              
1225             sub is_odd {
1226             # return true if arg (BLite or num_str) is odd
1227 10 50   10 1 53 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1228              
1229 10 50       19 return $x->is_odd() unless $x->isa($class);
1230 10 100       97 $$x & 1 == 1 ? 1 : 0;
1231             }
1232              
1233             sub is_even {
1234             # return true if arg (BLite or num_str) is even
1235 10 50   10 1 79 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1236              
1237 10 50       18 return $x->is_even() unless $x->isa($class);
1238 10 100       99 $$x & 1 == 1 ? 0 : 1;
1239             }
1240              
1241             ##############################################################################
1242             # parts() and friends
1243              
1244             sub sign {
1245 2 50   2 1 19 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1246              
1247 2 100       66 $$x >= 0 ? '+' : '-';
1248             }
1249              
1250             sub parts {
1251 6 50   6 1 35 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1252              
1253 6 50 33     20 return $upgrade -> exponent($x)
1254             if defined($upgrade) && !$x -> isa($class);
1255              
1256 6 50       29 if ($$x =~ / ^
1257             (
1258             [+-]?
1259             (?: 0 | [1-9] (?: \d* [1-9] )? )
1260             )
1261             ( 0* )
1262             $
1263             /x)
1264             {
1265 6         13 my $mant = $1;
1266 6         10 my $expo = CORE::length($2);
1267 6         11 return $class -> new($mant), $class -> new($expo);
1268             }
1269              
1270 0         0 die "Internal error: ", (caller(0))[3], "() couldn't handle",
1271             " the value '", $$x, "', which is likely a bug";
1272             }
1273              
1274             sub exponent {
1275 6 50   6 1 31 my ($class, $x) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1276              
1277 6 50 33     21 return $upgrade -> exponent($x)
1278             if defined($upgrade) && !$x -> isa($class);
1279              
1280 6         11 my $expo;
1281 6 50       25 if ($$x =~ / (?: ^ 0 | [1-9] ) ( 0* ) $/x) {
1282 6         11 $expo = CORE::length($1);
1283 6         11 return $class -> new($expo);
1284             }
1285              
1286 0         0 die "Internal error: ", (caller(0))[3], "() couldn't handle",
1287             " the value '", $$x, "', which is likely a bug";
1288             }
1289              
1290             sub mantissa {
1291 5 50   5 1 29 my ($class, $x) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1292              
1293 5 50 33     16 return $upgrade -> exponent($x)
1294             if defined($upgrade) && !$x -> isa($class);
1295              
1296 5 50       24 if ($$x =~ / ^
1297             (
1298             [+-]?
1299             (?: 0 | [1-9] (?: \d* [1-9] )? )
1300             )
1301             /x)
1302             {
1303 5         10 return $class -> new($1);
1304             }
1305              
1306 0         0 die "Internal error: ", (caller(0))[3], "() couldn't handle",
1307             " the value '", $$x, "', which is likely a bug";
1308             }
1309              
1310             sub sparts {
1311 0 0   0 1 0 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1312              
1313 0 0 0     0 return $upgrade -> exponent($x)
1314             if defined($upgrade) && !$x -> isa($class);
1315              
1316 0 0       0 if ($$x =~ / ^
1317             (
1318             [+-]?
1319             (?: 0 | [1-9] (?: \d* [1-9] )? )
1320             )
1321             ( 0* )
1322             $
1323             /x)
1324             {
1325 0         0 my $mant = $1;
1326 0         0 my $expo = CORE::length($2);
1327 0 0       0 return $class -> new($mant) unless wantarray;
1328 0         0 return $class -> new($mant), $class -> new($expo);
1329             }
1330              
1331 0         0 die "Internal error: ", (caller(0))[3], "() couldn't handle",
1332             " the value '", $$x, "', which is likely a bug";
1333             }
1334              
1335             sub nparts {
1336 0 0   0 1 0 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1337              
1338 0 0 0     0 return $upgrade -> exponent($x)
1339             if defined($upgrade) && !$x -> isa($class);
1340              
1341 0         0 my ($mant, $expo);
1342 0 0       0 if ($$x =~ / ^
    0          
1343             ( [+-]? \d )
1344             ( 0* )
1345             $
1346             /x)
1347             {
1348 0         0 $mant = $class -> new($1);
1349 0         0 $expo = $class -> new(CORE::length($2));
1350             } elsif ($$x =~
1351             / ^
1352             ( [+-]? [1-9] )
1353             ( \d+ )
1354             $
1355             /x)
1356             {
1357 0         0 $mant = $upgrade -> new($1 . "." . $2);
1358 0         0 $expo = $class -> new(CORE::length($2));
1359             } else {
1360 0         0 die "Internal error: ", (caller(0))[3], "() couldn't handle",
1361             " the value '", $$x, "', which is likely a bug";
1362             }
1363              
1364 0 0       0 return $mant unless wantarray;
1365 0         0 return $mant, $expo;
1366             }
1367              
1368             sub eparts {
1369 0 0   0 1 0 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1370              
1371 0 0 0     0 return $upgrade -> exponent($x)
1372             if defined($upgrade) && !$x -> isa($class);
1373              
1374             # Finite number.
1375              
1376 0         0 my ($mant, $expo) = $x -> sparts();
1377              
1378 0 0       0 if ($mant -> bcmp(0)) {
1379 0         0 my $ndigmant = $mant -> length();
1380 0         0 $expo = $expo -> badd($ndigmant);
1381              
1382             # $c is the number of digits that will be in the integer part of the
1383             # final mantissa.
1384              
1385 0         0 my $c = $expo -> copy() -> bdec() -> bmod(3) -> binc();
1386 0         0 $expo = $expo -> bsub($c);
1387              
1388 0 0       0 if ($ndigmant > $c) {
1389 0 0       0 return $upgrade -> eparts($x) if defined $upgrade;
1390 0         0 $mant = $mant -> bnan();
1391 0 0       0 return $mant unless wantarray;
1392 0         0 return ($mant, $expo);
1393             }
1394              
1395 0         0 $mant = $mant -> blsft($c - $ndigmant, 10);
1396             }
1397              
1398 0 0       0 return $mant unless wantarray;
1399 0         0 return ($mant, $expo);
1400             }
1401              
1402             sub dparts {
1403 0 0   0 1 0 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1404              
1405 0 0 0     0 return $upgrade -> exponent($x)
1406             if defined($upgrade) && !$x -> isa($class);
1407              
1408 0         0 my $int = $x -> copy();
1409 0         0 my $frc = $class -> bzero();
1410 0 0       0 return $int unless wantarray;
1411 0         0 return $int, $frc;
1412             }
1413              
1414             sub fparts {
1415 0 0   0 1 0 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1416              
1417 0 0 0     0 return $upgrade -> exponent($x)
1418             if defined($upgrade) && !$x -> isa($class);
1419              
1420 0         0 my $num = $x -> copy();
1421 0         0 my $den = $class -> bone();
1422 0 0       0 return $num unless wantarray;
1423 0         0 return $num, $den;
1424             }
1425              
1426             sub digit {
1427 22 100   22 1 693 my ($class, $x, $n) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1428              
1429 22 50       58 return $x->digit($n) unless $x->isa($class);
1430              
1431 22 50       49 $n = 0 if !defined $n;
1432 22         48 my $len = length("$$x");
1433              
1434 22 100       50 $n = $len+$n if $n < 0; # -1 last, -2 second-to-last
1435 22         92 $n = abs($n); # if negative was too big
1436 22         32 $len--;
1437 22 50       39 $n = $len if $n > $len; # n to big?
1438              
1439 22         115 substr($$x, -$n-1, 1);
1440             }
1441              
1442             sub length {
1443 6 50   6 1 44 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1444              
1445 6 50       13 return $x->length() unless $x->isa($class);
1446 6         15 my $l = length($$x);
1447 6 100       14 $l-- if $$x < 0; # -123 => 123
1448 6         40 $l;
1449             }
1450              
1451             ##############################################################################
1452             # sign based methods
1453              
1454             sub babs {
1455 25 50   25 1 67 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1456              
1457 25         41 $$x = abs($$x);
1458 25         57 $x;
1459             }
1460              
1461             sub bneg {
1462 115 50   115 1 283 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1463              
1464 115 100       261 $$x = -$$x if $$x != 0;
1465 115         268 $x;
1466             }
1467              
1468             sub bnot {
1469 5 50   5 1 29 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1470              
1471 5         12 $$x = -$$x - 1;
1472 5         33 $x;
1473             }
1474              
1475             ##############################################################################
1476             # special calc routines
1477              
1478             sub bceil {
1479 5 50   5 1 28 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1480 5         33 $x; # no-op
1481             }
1482              
1483             sub bfloor {
1484 5 50   5 1 29 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1485 5         37 $x; # no-op
1486             }
1487              
1488             sub bfac {
1489 17 50   17 1 92 my ($self, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) :
1490             ($class, $class->new($_[0]), $_[1], $_[2], $_[3], $_[4]);
1491              
1492 17 50       35 $x = $upgrade->new($$x) if $x->isa($class);
1493 17         1088 $upgrade->bfac($x, @r);
1494             }
1495              
1496             sub bdfac {
1497 15 50   15 1 81 my ($self, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) :
1498             ($class, $class->new($_[0]), $_[1], $_[2], $_[3], $_[4]);
1499              
1500 15 50       29 $x = $upgrade->new($$x) if $x->isa($class);
1501 15         906 $upgrade->bdfac($x, @r);
1502             }
1503              
1504             sub bpow {
1505 97     97 1 1051 my ($class, $x, $y, @r) = objectify(2, @_);
1506              
1507 97 50       1461 $x = $upgrade->new($$x) if $x->isa($class);
1508 97 100       6023 $y = $upgrade->new($$y) if $y->isa($class);
1509              
1510 97         4091 $x->bpow($y, @r);
1511             }
1512              
1513             sub blog {
1514 38     38 1 706 my ($class, $x, $base, @r);
1515              
1516             # Don't objectify the base, since an undefined base, as in $x->blog() or
1517             # $x->blog(undef) signals that the base is Euler's number.
1518              
1519 38 50 33     106 if (!ref($_[0]) && $_[0] =~ /^[A-Za-z]|::/) {
1520             # E.g., Math::BigInt::Lite->blog(256, 2)
1521 0 0       0 ($class, $x, $base, @r) =
1522             defined $_[2] ? objectify(2, @_) : objectify(1, @_);
1523             } else {
1524             # E.g., Math::BigInt::Lite::blog(256, 2) or $x->blog(2)
1525 38 100       115 ($class, $x, $base, @r) =
1526             defined $_[1] ? objectify(2, @_) : objectify(1, @_);
1527             }
1528              
1529 38 50       498 $x = $upgrade->new($$x) if $x->isa($class);
1530 38 100 100     2433 $base = $upgrade->new($$base) if defined $base && $base->isa($class);
1531              
1532 38         1376 $x->blog($base, @r);
1533             }
1534              
1535             sub bexp {
1536 2     2 1 15 my ($class, $x, @r) = objectify(1, @_);
1537              
1538 2 50       16 $x = $upgrade->new($$x) if $x->isa($class);
1539              
1540 2         116 $x->bexp(@r);
1541             }
1542              
1543             sub batan2 {
1544 20     20 1 511 my ($class, $x, $y, @r) = objectify(2, @_);
1545              
1546 20 50       322 $x = $upgrade->new($$x) if $x->isa($class);
1547              
1548 20         1442 $x->batan2($y, @r);
1549             }
1550              
1551             sub bnok {
1552 4880     4880 1 36465 my ($class, $x, $y, @r) = objectify(2, @_);
1553              
1554 4880 50       51111 $x = $upgrade->new($$x) if $x->isa($class);
1555 4880 100       313928 $y = $upgrade->new($$y) if $y->isa($class);
1556              
1557 4880         249953 $x->bnok($y, @r);
1558             }
1559              
1560             sub broot {
1561 31     31 1 532 my ($class, $x, $base, @r) = objectify(2, @_);
1562              
1563 31 50       454 $x = $upgrade->new($$x) if $x->isa($class);
1564 31 100 66     1896 $base = $upgrade->new($$base) if defined $base && $base->isa($class);
1565              
1566 31         1504 $x->broot($base, @r);
1567             }
1568              
1569             sub bmuladd {
1570 27     27 1 316 my ($class, $x, $y, $z, @r) = objectify(2, @_);
1571              
1572 27 50       316 $x = $upgrade->new($$x) if $x->isa($class);
1573 27 100 66     1764 $y = $upgrade->new($$y) if defined $y && $y->isa($class);
1574 27 100 66     1423 $z = $upgrade->new($$z) if defined $z && $z->isa($class);
1575              
1576 27         2086 $x->bmuladd($y, $z, @r);
1577             }
1578              
1579             sub bmodpow {
1580 160     160 1 1087 my ($class, $x, $y, @r) = objectify(2, @_);
1581              
1582 160 50       1467 $x = $upgrade->new($$x) if $x->isa($class);
1583 160 100 66     10087 $y = $upgrade->new($$y) if defined $y && $y->isa($class);
1584              
1585 160         8769 $x->bmodpow($y, @r);
1586             }
1587              
1588             sub bmodinv {
1589 29     29 1 402 my ($class, $x, $y, @r) = objectify(2, @_);
1590              
1591 29 50       328 $x = $upgrade->new($$x) if $x->isa($class);
1592 29 100 66     1753 $y = $upgrade->new($$y) if defined $y && $y->isa($class);
1593              
1594 29         1288 $x->bmodinv($y, @r);
1595             }
1596              
1597             sub bsqrt {
1598 17 50   17 1 85 my ($class, $x, @r) =
1599             ref($_[0]) ? (ref($_[0]), @_)
1600             : ($class, $class->new($_[0]), $_[1], $_[2], $_[3]);
1601              
1602 17 50       34 return $x->bsqrt(@r) unless $x->isa($class);
1603              
1604 17 100       52 return $upgrade->new($$x)->bsqrt() if $$x < 0; # NaN
1605 15         26 my $s = sqrt($$x);
1606             # If MBI's upgrade is defined, and result is non-integer, we need to hand
1607             # up. If upgrade is undef, result would be the same, anyway
1608 15 100       33 if (int($s) != $s) {
1609 7         20 return $upgrade->new($$x)->bsqrt();
1610             }
1611 8         11 $$x = $s;
1612 8         55 $x;
1613             }
1614              
1615             sub bpi {
1616 3     3 1 16 my $self = shift;
1617 3   33     10 my $class = ref($self) || $self;
1618 3         7 $class -> new("3");
1619             }
1620              
1621             sub to_bin {
1622 5     5 1 20 my $self = shift;
1623 5         16 $upgrade -> new($$self) -> to_bin();
1624             }
1625              
1626             sub to_oct {
1627 5     5 1 22 my $self = shift;
1628 5         16 $upgrade -> new($$self) -> to_oct();
1629             }
1630              
1631             sub to_hex {
1632 5     5 1 21 my $self = shift;
1633 5         17 $upgrade -> new($$self) -> to_hex();
1634             }
1635              
1636             ##############################################################################
1637              
1638             sub import {
1639 6     6   46 my $self = shift;
1640              
1641 6         13 my @a = @_;
1642 6         11 my $l = scalar @_;
1643 6         10 my $j = 0;
1644 6         10 my $lib = '';
1645 6         21 for (my $i = 0; $i < $l ; $i++, $j++) {
1646 0 0       0 if ($_[$i] eq ':constant') {
    0          
    0          
1647             # this causes overlord er load to step in
1648 0     0   0 overload::constant integer => sub { $self->new(shift) };
  0         0  
1649 0         0 splice @a, $j, 1;
1650 0         0 $j --;
1651             } elsif ($_[$i] eq 'upgrade') {
1652             # this causes upgrading
1653 0         0 $upgrade = $_[$i+1]; # or undef to disable
1654 0         0 my $s = 2;
1655 0 0       0 $s = 1 if @a-$j < 2; # no "can not modify non-existant..."
1656 0         0 splice @a, $j, $s;
1657 0         0 $j -= $s;
1658             } elsif ($_[$i] eq 'lib') {
1659 0         0 $lib = $_[$i+1]; # or undef to disable
1660 0         0 my $s = 2;
1661 0 0       0 $s = 1 if @a-$j < 2; # no "can not modify non-existant..."
1662 0         0 splice @a, $j, $s;
1663 0         0 $j -= $s;
1664             }
1665             }
1666             # any non :constant stuff is handled by our parent,
1667             # even if @_ is empty, to give it a chance
1668 6         52 $self->SUPER::import(@a); # need it for subclasses
1669 6         5220 $self->export_to_level(1, $self, @a); # need it for MBF
1670             }
1671              
1672             1;
1673              
1674             __END__