File Coverage

blib/lib/Math/BigInt/Lite.pm
Criterion Covered Total %
statement 467 686 68.0
branch 279 556 50.1
condition 86 203 42.3
subroutine 98 116 84.4
pod 87 88 98.8
total 1017 1649 61.6


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   308891 use strict;
  6         55  
  6         144  
10 6     6   24 use warnings;
  6         7  
  6         231  
11              
12             require Exporter;
13 6     6   30 use Scalar::Util qw< blessed >;
  6         8  
  6         206  
14              
15 6     6   5938 use Math::BigInt;
  6         161541  
  6         30  
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.26';
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   117345 my $e0 = 1;
47 6         16 my $e1 = $e0 + 1;
48 6         9 my $num;
49             {
50 6         11 $num = '9' x $e1; # maximum value in base 10**$e1
  54         76  
51 54         98 $num = $num * $num # multiply by itself
52             + ($num - 1); # largest possible carry
53 54 100       579 last if $num !~ /^9{$e0}89{$e1}$/; # check digit pattern
54 48         74 $e0 = $e1;
55 48         48 $e1++;
56 48         56 redo;
57             }
58 6         23 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       38 $e = 5 if $^O =~ /^uts/; # UTS get's some special treatment
64 6 50       35 $e = 5 if $^O =~ /^unicos/; # unicos is also problematic (6 seems to work
65             # there, but we play safe)
66 6 50       34 $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         10 $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         27 $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         171 $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   56 no strict 'refs';
  6         10  
  6         1133  
107             # make Class->round_mode() work
108 77     77 1 272 my $self = shift;
109 77   50     212 my $class = ref($self) || $self || __PACKAGE__;
110 77 50       117 if (defined $_[0]) {
111 77         79 my $m = shift;
112 77 50       208 die "Unknown round mode $m"
113             if $m !~ /^(even|odd|\+inf|\-inf|zero|trunc|common)$/;
114             # set in BigInt, too
115 77         175 Math::BigInt->round_mode($m);
116 77         817 return ${"${class}::round_mode"} = $m;
  77         662  
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   33 no strict 'refs';
  6         10  
  6         964  
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   33 no strict 'refs';
  6         15  
  6         2884  
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   256 my $x = $_[0];
194 9         11 my $y = $_[1];
195 9         13 my $class = ref $x;
196 9 100       18 $y = $class->new($y) unless ref($y);
197 9 50       20 if ($y->isa($class)) {
198 9         16 $x = \($$x + $$y);
199 9         13 bless $x, $class;
200 9 50       16 $x = $upgrade->new($$x) if abs($$x) >= $MAX_ADD;
201             } else {
202 0         0 $x = $upgrade->new($$x)->badd($y);
203             }
204 9         25 $x;
205             },
206              
207             '*' => sub {
208 2     2   220 my $x = $_[0];
209 2         3 my $y = $_[1];
210 2         4 my $class = ref $x;
211 2 100       8 $y = $class->new($y) unless ref($y);
212 2 50       4 if ($y->isa($class)) {
213 2         5 $x = \($$x * $$y);
214 2 50       8 $$x = 0 if $$x eq '-0'; # correct 5.x.x bug
215 2         24 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   20062 '""' => sub { "${$_[0]}"; },
  342         1912  
238              
239 21     21   24 '0+' => sub { ${$_[0]}; },
  21         182  
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   2253 sign => ($_[0] < 0) ? '-' : '+',
256             };
257             },
258 6     6   36 ;
  6         11  
  6         116  
259              
260             BEGIN {
261 6     6   21077 *objectify = \&Math::BigInt::objectify;
262             }
263              
264             sub config {
265 2     2 1 5563 my $class = shift;
266              
267             # config({a => b, ...}) -> config(a => b, ...)
268 2 50 33     20 @_ = %{ $_[0] } if @_ == 1 && ref($_[0]) eq 'HASH';
  0         0  
269              
270             # Getter/accessor.
271              
272 2 50       6 if (@_ == 1) {
273 2         4 my $param = shift;
274              
275             # We don't use a math backend library.
276 2 100 66     13 return if ($param eq 'lib' ||
277             $param eq 'lib_version');
278              
279 1         6 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 607 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       380 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         23 my $do_upgrade = 0;
322 19         22 for my $arg (@args) {
323 40 100       54 unless ($arg -> isa($class)) {
324 3         4 $do_upgrade = 1;
325 3         4 last;
326             }
327             }
328 19 100       32 return $upgrade -> bgcd(@args) if $do_upgrade;
329              
330             # Now compute the GCD.
331              
332 16         17 my ($a, $b, $c);
333 16         22 $a = shift @args;
334 16         28 $a = abs($$a);
335 16   100     40 while (@args && $a != 1) {
336 16         20 $b = shift @args;
337 16 100       25 next if $$b == 0;
338 15         17 $b = abs($$b);
339 15         14 do {
340 44         41 $c = $a % $b;
341 44         41 $a = $b;
342 44         64 $b = $c;
343             } while $c;
344             }
345              
346 16         125 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 183 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         19 my ($class, @args) = objectify(0, @_);
364              
365 8         112 my @a = ();
366 8         9 for my $arg (@args) {
367 16 100 66     52 $arg = $upgrade -> new("$arg")
368             unless defined(blessed($arg)) && $arg -> isa($upgrade);
369 16         708 push @a, $arg;
370             }
371              
372 8         16 $upgrade -> blcm(@a);
373             }
374              
375             sub isa {
376             # we aren't a BigInt nor BigRat/BigFloat
377 26722 100   26722 0 224739 $_[1] =~ /^Math::BigInt::Lite/ ? 1 : 0;
378             }
379              
380             sub new {
381 14638     14638 1 16256917 my ($class, $wanted, @r) = @_;
382              
383 14638 50       25375 return $upgrade->new($wanted) if !defined $wanted;
384              
385             # 1e12, NaN, inf, 0x12, 0b11, 1.2e2, "12345678901234567890" etc all upgrade
386 14638 50       20062 if (!ref($wanted)) {
387 14638 100 100     76927 if ((length($wanted) <= $MAX_NEW_LEN) &&
388             ($wanted =~ /^[+-]?[0-9]{1,$MAX_NEW_LEN}(\.0*)?\z/)) {
389 12975         24851 my $a = \($wanted+0); # +0 to make a copy and force it numeric
390 12975         93302 return bless $a, $class;
391             }
392             # TODO: 1e10 style constants that are still below MAX_NEW
393 1663 100       5200 if ($wanted =~ /^([+-])?([0-9]+)[eE][+]?([0-9]+)$/) {
394 37 100       117 if ((length($2) + $3) < $MAX_NEW_LEN) {
395 28         78 my $a = \($wanted+0); # +0 to make a copy and force it numeric
396 28         124 return bless $a, $class;
397             }
398             }
399             # print "new '$$a' $BASE_LEN ($wanted)\n";
400             }
401 1635         4279 $upgrade->new($wanted, @r);
402             }
403              
404             ###############################################################################
405             # String conversion methods
406             ###############################################################################
407              
408             sub bstr {
409 2984 50   2984 1 3956780 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
410              
411 2984 50 33     8311 return $upgrade -> exponent($x)
412             if defined($upgrade) && !$x -> isa($class);
413              
414 2984         16714 "$$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 1057 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
422              
423 543 50 33     1133 return $upgrade -> exponent($x)
424             if defined($upgrade) && !$x -> isa($class);
425              
426 543 50       2352 if ($$x =~ / ^
427             (
428             [+-]?
429             (?: 0 | [1-9] (?: \d* [1-9] )? )
430             )
431             ( 0* )
432             $
433             /x)
434             {
435 543         901 my $mant = $1;
436 543         757 my $expo = CORE::length($2);
437 543         1568 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 137015 my $x = ref($_[0]) ? $_[0] : $_[0]->new($_[1]);
550              
551 211         25571 $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   1148 shift if !ref($_[0]) && $_[0] =~ /^Math::BigInt::Lite/;
565              
566 541         825 my ($x, $y, @r) = @_;
567              
568 541         554 my $up = 0; # default: don't upgrade
569              
570 541 50 33     2309 $up = 1
      33        
      33        
571             if (defined $r[0] || defined $r[1] || defined $accuracy || defined $precision);
572 541 100       933 $x = __PACKAGE__->new($x) unless ref $x; # upgrade literals
573 541 100       816 $y = __PACKAGE__->new($y) unless ref $y; # upgrade literals
574 541 100 66     794 $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       860 if ($up == 1) {
577 46 50       64 $x = $upgrade->new($$x) if $x->isa($class);
578 46 50       2656 $y = $upgrade->new($$y) if $y->isa($class);
579             }
580              
581 541         1100 ($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   252 shift if !ref($_[0]) && $_[0] =~ /^Math::BigInt::Lite/;
596              
597 123         159 my ($x, $y, @r) = @_;
598              
599 123         123 my $up = 0; # default: don't upgrade
600              
601 123 50 33     464 $up = 1
      33        
      33        
602             if (defined $r[0] || defined $r[1] || defined $accuracy || defined $precision);
603 123 100       172 $x = __PACKAGE__->new($x) unless ref $x; # upgrade literals
604 123 100       163 $y = __PACKAGE__->new($y) unless ref $y; # upgrade literals
605 123 100 66     154 $up = 1 unless $x->isa($class) && $y->isa($class);
606 123 50 33     488 $up = 1 if ($up == 0 && (abs($$x) >= $MAX_MUL || abs($$y) >= $MAX_MUL) );
      66        
607 123 100       164 if ($up == 1) {
608 3 50       6 $x = $upgrade->new($$x) if $x->isa($class);
609 3 50       237 $y = $upgrade->new($$y) if $y->isa($class);
610             }
611 123         257 ($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         8 my $up = 0; # default: don't upgrade
624              
625 6 50 33     30 $up = 1
      33        
      33        
626             if (defined $r[0] || defined $r[1] || defined $accuracy || defined $precision);
627 6 50       12 $x = __PACKAGE__->new($x) unless ref $x; # upgrade literals
628 6 50       8 $up = 1 unless $x->isa($class);
629 6 50       13 if ($up == 1) {
630 0 0       0 $x = $upgrade->new($$x) if $x->isa($class);
631             }
632 6         12 ($up, $x, @r);
633             }
634              
635             ##############################################################################
636             # rounding functions
637              
638             sub bround {
639 9 50   9 1 44 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         496 $x->bround(@a);
646             }
647              
648             sub bfround {
649 1 50   1 1 5 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       2 $x = $upgrade->new($$x) if $x->isa($class);
655 1         51 $x->bfround(@p);
656              
657             }
658              
659             sub round {
660 64 50   64 1 410 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
661              
662 64 50       105 $x = $upgrade->new($$x) if $x->isa($class);
663 64         3265 $x->round(@r);
664             }
665              
666             ##############################################################################
667             # special values
668              
669             sub bnan {
670             # return a NaN
671 15     15 1 919 shift;
672 15         40 $upgrade -> bnan(@_);
673             }
674              
675             sub binf {
676             # return a +/-Inf
677 17     17 1 5006 shift;
678 17         47 $upgrade -> binf(@_);
679             }
680              
681             sub bone {
682             # return a +/-1
683 117     117 1 1794 my $x = shift;
684              
685 117         139 my ($sign, @r) = @_;
686              
687             # Get the sign.
688              
689 117 100 100     255 if (defined($_[0]) && $_[0] =~ /^\s*([+-])\s*$/) {
690 8         18 $sign = $1;
691 8         9 shift;
692             } else {
693 109         145 $sign = '+';
694             }
695              
696 117 100       152 my $num = $sign eq "-" ? -1 : 1;
697 117 100       232 return $x -> new($num) unless ref $x; # $class->bone();
698 30         37 $$x = $num;
699 30         227 $x;
700             }
701              
702             sub bzero {
703             # return a one
704 3     3 1 216 my $x = shift;
705              
706 3 100       11 return $x->new(0) unless ref $x; # $class->bone();
707 1         1 $$x = 0;
708 1         2 $x;
709             }
710              
711             sub bcmp {
712             # compare the value of two objects
713 567 100 66 567 1 5985 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
714             ? (ref($_[0]), @_)
715             : objectify(2, @_);
716              
717 567 100 66     1208 return $upgrade->bcmp($x, $y)
      66        
718             if defined($upgrade) && (!$x->isa($class) || !$y->isa($class));
719              
720 561         1198 $$x <=> $$y;
721             }
722              
723             sub bacmp {
724             # compare the absolute value of two objects
725 12 100 66 12 1 411 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
726             ? (ref($_[0]), @_)
727             : objectify(2, @_);
728              
729 12 100 66     185 return $upgrade->bacmp($x, $y)
      66        
730             if defined($upgrade) && (!$x->isa($class) || !$y->isa($class));
731              
732 7         51 abs($$x) <=> abs($$y);
733             }
734              
735             ##############################################################################
736             # copy/conversion
737              
738             sub copy {
739 432     432 1 14668 my ($x, $class);
740 432 50       684 if (ref($_[0])) { # $y = $x -> copy()
741 432         473 $x = shift;
742 432         491 $class = ref($x);
743             } else { # $y = $class -> copy($y)
744 0         0 $class = shift;
745 0         0 $x = shift;
746             }
747              
748 432         543 my $val = $$x;
749 432         886 bless \$val, $class;
750             }
751              
752             sub as_int {
753 540 50   540 1 10411 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
754              
755 540 50       737 return $x -> copy() if $x -> isa("Math::BigInt");
756              
757             # disable upgrading and downgrading
758              
759 540         1006 my $upg = Math::BigInt -> upgrade();
760 540         3605 my $dng = Math::BigInt -> downgrade();
761 540         3680 Math::BigInt -> upgrade(undef);
762 540         3631 Math::BigInt -> downgrade(undef);
763              
764 540         3535 my $y = Math::BigInt -> new($x -> bsstr());
765              
766             # reset upgrading and downgrading
767              
768 540         30191 Math::BigInt -> upgrade($upg);
769 540         3798 Math::BigInt -> downgrade($dng);
770              
771 540         3577 return $y;
772             }
773              
774             sub as_number {
775 3 50   3 1 227 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
776              
777 3 50       9 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 1313 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
785              
786 81 50       129 return $$x if $x->isa($class);
787 0         0 $x->numify();
788             }
789              
790             sub as_hex {
791 5 50   5 1 25 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
792              
793 5 50       6 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 27 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 28 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
806              
807 5 50       9 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 14 my ($up, $x, $y, @r) = _upgrade_1(@_);
958              
959 3 50       5 return $x->binc(@r) if $up;
960 3         6 $$x++;
961 3 50       5 return $upgrade->new($$x) if abs($$x) > $MAX_ADD;
962 3         20 $x;
963             }
964              
965             sub bdec {
966             # decrement by one
967 3     3 1 13 my ($up, $x, $y, @r) = _upgrade_1(@_);
968              
969 3 50       7 return $x->bdec(@r) if $up;
970 3         5 $$x--;
971 3 50       5 return $upgrade->new($$x) if abs($$x) > $MAX_ADD;
972 3         18 $x;
973             }
974              
975             ##############################################################################
976             # shifting
977              
978             sub brsft {
979             # shift right
980 29     29 1 119 my ($class, $x, $y, $b, @r) = objectify(2, @_);
981              
982 29 50       221 $x = $class->new($x) unless ref($x);
983 29 50       46 $y = $class->new($y) unless ref($y);
984 29 50 33     50 $b = $$b if ref $b && $b->isa($class);
985              
986 29 50       42 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       43 return $upgrade->new($$x)->brsft($y, $b, @r)
991             unless $y->isa($class);
992              
993 29 100       40 $b = 2 if !defined $b;
994             # can't do this
995 29 100 100     96 return $upgrade->new($$x)->brsft($upgrade->new($$y), $b, @r)
996             if $b != 2 || $$y < 0;
997 6     6   90 use integer;
  6         14  
  6         43  
998 20         21 $$x >>= $$y; # only base 2 for now
999 20         131 $x;
1000             }
1001              
1002             sub blsft {
1003             # shift left
1004 17     17 1 69 my ($class, $x, $y, $b, @r) = objectify(2, @_);
1005              
1006 17 50       133 $x = $class->new($x) unless ref($x);
1007 17 50       29 $y = $class->new($x) unless ref($y);
1008              
1009 17 50       27 return $x->blsft($upgrade->new($$y), $b, @r) unless $x->isa($class);
1010 17 50       26 return $upgrade->new($$x)->blsft($y, $b, @r)
1011             unless $y->isa($class);
1012              
1013             # overflow: can't do this
1014 17 100       42 return $upgrade->new($$x)->blsft($upgrade->new($$y), $b, @r)
1015             if $$y > 31;
1016 15 100       25 $b = 2 if !defined $b;
1017             # can't do this
1018 15 100 100     50 return $upgrade->new($$x)->blsft($upgrade->new($$y), $b, @r)
1019             if $b != 2 || $$y < 0;
1020 6     6   930 use integer;
  6         11  
  6         25  
1021 8         13 $$x <<= $$y; # only base 2 for now
1022 8         46 $x;
1023             }
1024              
1025             ##############################################################################
1026             # bitwise logical operators
1027              
1028             sub band {
1029             # AND two objects
1030 15     15 1 32 my ($x, $y, @r) = @_; #objectify(2, @_);
1031              
1032 15 50       29 $x = $class->new($x) unless ref($x);
1033 15 50       25 $y = $class->new($x) unless ref($y);
1034              
1035 15 50       25 return $x->band($y, @r) unless $x->isa($class);
1036 15 100       27 return $upgrade->band($x, $y, @r) unless $y->isa($class);
1037 6     6   584 use integer;
  6         11  
  6         17  
1038 14         29 $$x = ($$x+0) & ($$y+0); # +0 to avoid string-context
1039 14         91 $x;
1040             }
1041              
1042             sub bxor {
1043             # XOR two objects
1044 22     22 1 35 my ($x, $y, @r) = @_; #objectify(2, @_);
1045              
1046 22 50       45 $x = $class->new($x) unless ref($x);
1047 22 50       29 $y = $class->new($x) unless ref($y);
1048              
1049 22 50       41 return $x->bxor($y, @r) unless $x->isa($class);
1050 22 100       54 return $upgrade->bxor($x, $y, @r) unless $y->isa($class);
1051 6     6   587 use integer;
  6         12  
  6         73  
1052 16         32 $$x = ($$x+0) ^ ($$y+0); # +0 to avoid string-context
1053 16         106 $x;
1054             }
1055              
1056             sub bior {
1057             # OR two objects
1058 21     21 1 46 my ($x, $y, @r) = @_; #objectify(2, @_);
1059              
1060 21 50       40 $x = $class->new($x) unless ref($x);
1061 21 50       33 $y = $class->new($x) unless ref($y);
1062              
1063 21 50       37 return $x->bior($y, @r) unless $x->isa($class);
1064 21 100       55 return $upgrade->bior($x, $y, @r) unless $y->isa($class);
1065 6     6   621 use integer;
  6         10  
  6         18  
1066 15         31 $$x = ($$x+0) | ($$y+0); # +0 to avoid string-context
1067 15         106 $x;
1068             }
1069              
1070             ##############################################################################
1071             # mul/add/div etc
1072              
1073             sub badd {
1074             # add two objects
1075 60     60 1 2755 my ($up, $x, $y, @r) = _upgrade_2(@_);
1076              
1077 60 100       108 return $x->badd($y, @r) if $up;
1078              
1079 46         82 $$x = $$x + $$y;
1080 46 50       75 return $upgrade->new($$x) if abs($$x) > $MAX_ADD;
1081 46         254 $x;
1082             }
1083              
1084             sub bsub {
1085             # subtract two objects
1086 208     208 1 626 my ($up, $x, $y, @r) = _upgrade_2(@_);
1087 208 100       332 return $x->bsub($y, @r) if $up;
1088 206         294 $$x = $$x - $$y;
1089 206 50       307 return $upgrade->new($$x) if abs($$x) > $MAX_ADD;
1090 206         562 $x;
1091             }
1092              
1093             sub bmul {
1094             # multiply two objects
1095 123     123 1 768 my ($up, $x, $y, @r) = _upgrade_2_mul(@_);
1096 123 100       208 return $x->bmul($y, @r) if $up;
1097 120         164 $$x = $$x * $$y;
1098 120 50       200 $$x = 0 if $$x eq '-0'; # for some Perls leave '-0' here
1099             #return $upgrade->new($$x) if abs($$x) > $MAX_ADD;
1100 120         344 $x;
1101             }
1102              
1103             sub bmod {
1104             # remainder of div
1105 63     63 1 149 my ($up, $x, $y, @r) = _upgrade_2(@_);
1106 63 100       128 return $x->bmod($y, @r) if $up;
1107 57 100       96 return $upgrade->new($$x)->bmod($y, @r) if $$y == 0;
1108 54         81 $$x = $$x % $$y;
1109 54         338 $x;
1110             }
1111              
1112             sub bdiv {
1113             # divide two objects
1114 108     108 1 1191 my ($up, $x, $y, @r) = _upgrade_2(@_);
1115              
1116 108 100       193 return $x->bdiv($y, @r) if $up;
1117              
1118 96 100       185 return $upgrade->new($$x)->bdiv($$y, @r) if $$y == 0;
1119              
1120             # need to give Math::BigInt a chance to upgrade further
1121 90 50       126 return $upgrade->new($$x)->bdiv($$y, @r)
1122             if defined $Math::BigInt::upgrade;
1123              
1124 90         109 my ($quo, $rem);
1125              
1126 90         145 $rem = \($$x % $$y);
1127 90         156 $quo = int($$x / $$y);
1128 90 100 100     188 $quo-- if $$rem != 0 && ($$x <=> 0) != ($$y <=> 0);
1129              
1130 90         107 $$x = $quo;
1131              
1132 90 100       120 if (wantarray) {
1133 42         53 bless $rem, $class;
1134 42         104 return $x, $rem;
1135             }
1136              
1137 48         310 return $x;
1138             }
1139              
1140             sub btdiv {
1141             # divide two objects
1142 102     102 1 1204 my ($up, $x, $y, @r) = _upgrade_2(@_);
1143              
1144 102 100       176 return $x->btdiv($y, @r) if $up;
1145              
1146 90 100       176 return $upgrade->new($$x)->btdiv($$y, @r) if $$y == 0;
1147              
1148             # need to give Math::BigInt a chance to upgrade further
1149 84 50       135 return $upgrade->new($$x)->btdiv($$y, @r)
1150             if defined $Math::BigInt::upgrade;
1151              
1152 84         90 my ($quo, $rem);
1153              
1154 84 100       119 if (wantarray) {
1155 42         59 $rem = \($$x % $$y);
1156 42 100 100     90 $$rem -= $$y if $$rem != 0 && ($$x <=> 0) != ($$y <=> 0);
1157 42         53 bless $rem, $class;
1158             }
1159              
1160 84         146 $quo = int($$x / $$y);
1161              
1162 84         96 $$x = $quo;
1163 84 100       173 return $x, $rem if wantarray;
1164 42         320 return $x;
1165             }
1166              
1167             ##############################################################################
1168             # is_foo methods (the rest is inherited)
1169              
1170             sub is_int {
1171             # return true if arg (BLite or num_str) is an integer
1172 2 50   2 1 14 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1173              
1174 2 50       5 return 1 if $x->isa($class); # Lite objects are always int
1175 0         0 $x->is_int();
1176             }
1177              
1178             sub is_inf {
1179             # return true if arg (BLite or num_str) is an infinity
1180 2 50   2 1 13 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1181              
1182 2 50       6 return 0 if $x->isa($class); # Lite objects are never inf
1183 0         0 $x->is_inf();
1184             }
1185              
1186             sub is_nan {
1187             # return true if arg (BLite or num_str) is an NaN
1188 165 50   165 1 928 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1189              
1190 165 50       192 return 0 if $x->isa($class); # Lite objects are never NaN
1191 0         0 $x->is_nan();
1192             }
1193              
1194             sub is_zero {
1195             # return true if arg (BLite or num_str) is zero
1196 11 50   11 1 84 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1197              
1198 11 50       24 return ($$x == 0) <=> 0 if $x->isa($class);
1199 0         0 $x->is_zero();
1200             }
1201              
1202             sub is_positive {
1203             # return true if arg (BLite or num_str) is positive
1204 3 50   3 1 17 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1205              
1206 3 50       7 return ($$x > 0) <=> 0 if $x->isa($class);
1207 0         0 $x->is_positive();
1208             }
1209              
1210             sub is_negative {
1211             # return true if arg (BLite or num_str) is negative
1212 3 50   3 1 19 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1213              
1214 3 50       5 return ($$x < 0) <=> 0 if $x->isa($class);
1215 0         0 $x->is_positive();
1216             }
1217              
1218             sub is_one {
1219             # return true if arg (BLite or num_str) is one
1220 9 50   9 1 47 my ($class, $x, $s) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1221              
1222 9         12 my $one = 1;
1223 9 100 100     30 $one = -1 if ($s || '+') eq '-';
1224 9 50       16 return ($$x == $one) <=> 0 if $x->isa($class);
1225 0         0 $x->is_one();
1226             }
1227              
1228             sub is_odd {
1229             # return true if arg (BLite or num_str) is odd
1230 10 50   10 1 48 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1231              
1232 10 50       16 return $x->is_odd() unless $x->isa($class);
1233 10 100       86 $$x & 1 == 1 ? 1 : 0;
1234             }
1235              
1236             sub is_even {
1237             # return true if arg (BLite or num_str) is even
1238 10 50   10 1 45 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1239              
1240 10 50       20 return $x->is_even() unless $x->isa($class);
1241 10 100       87 $$x & 1 == 1 ? 0 : 1;
1242             }
1243              
1244             ##############################################################################
1245             # parts() and friends
1246              
1247             sub sign {
1248 2 50   2 1 31 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1249              
1250 2 100       84 $$x >= 0 ? '+' : '-';
1251             }
1252              
1253             sub parts {
1254 6 50   6 1 31 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1255              
1256 6 50 33     17 return $upgrade -> exponent($x)
1257             if defined($upgrade) && !$x -> isa($class);
1258              
1259 6 50       29 if ($$x =~ / ^
1260             (
1261             [+-]?
1262             (?: 0 | [1-9] (?: \d* [1-9] )? )
1263             )
1264             ( 0* )
1265             $
1266             /x)
1267             {
1268 6         10 my $mant = $1;
1269 6         9 my $expo = CORE::length($2);
1270 6         9 return $class -> new($mant), $class -> new($expo);
1271             }
1272              
1273 0         0 die "Internal error: ", (caller(0))[3], "() couldn't handle",
1274             " the value '", $$x, "', which is likely a bug";
1275             }
1276              
1277             sub exponent {
1278 6 50   6 1 28 my ($class, $x) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1279              
1280 6 50 33     18 return $upgrade -> exponent($x)
1281             if defined($upgrade) && !$x -> isa($class);
1282              
1283 6         7 my $expo;
1284 6 50       25 if ($$x =~ / (?: ^ 0 | [1-9] ) ( 0* ) $/x) {
1285 6         10 $expo = CORE::length($1);
1286 6         54 return $class -> new($expo);
1287             }
1288              
1289 0         0 die "Internal error: ", (caller(0))[3], "() couldn't handle",
1290             " the value '", $$x, "', which is likely a bug";
1291             }
1292              
1293             sub mantissa {
1294 5 50   5 1 24 my ($class, $x) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1295              
1296 5 50 33     16 return $upgrade -> exponent($x)
1297             if defined($upgrade) && !$x -> isa($class);
1298              
1299 5 50       21 if ($$x =~ / ^
1300             (
1301             [+-]?
1302             (?: 0 | [1-9] (?: \d* [1-9] )? )
1303             )
1304             /x)
1305             {
1306 5         9 return $class -> new($1);
1307             }
1308              
1309 0         0 die "Internal error: ", (caller(0))[3], "() couldn't handle",
1310             " the value '", $$x, "', which is likely a bug";
1311             }
1312              
1313             sub sparts {
1314 0 0   0 1 0 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1315              
1316 0 0 0     0 return $upgrade -> exponent($x)
1317             if defined($upgrade) && !$x -> isa($class);
1318              
1319 0 0       0 if ($$x =~ / ^
1320             (
1321             [+-]?
1322             (?: 0 | [1-9] (?: \d* [1-9] )? )
1323             )
1324             ( 0* )
1325             $
1326             /x)
1327             {
1328 0         0 my $mant = $1;
1329 0         0 my $expo = CORE::length($2);
1330 0 0       0 return $class -> new($mant) unless wantarray;
1331 0         0 return $class -> new($mant), $class -> new($expo);
1332             }
1333              
1334 0         0 die "Internal error: ", (caller(0))[3], "() couldn't handle",
1335             " the value '", $$x, "', which is likely a bug";
1336             }
1337              
1338             sub nparts {
1339 0 0   0 1 0 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1340              
1341 0 0 0     0 return $upgrade -> exponent($x)
1342             if defined($upgrade) && !$x -> isa($class);
1343              
1344 0         0 my ($mant, $expo);
1345 0 0       0 if ($$x =~ / ^
    0          
1346             ( [+-]? \d )
1347             ( 0* )
1348             $
1349             /x)
1350             {
1351 0         0 $mant = $class -> new($1);
1352 0         0 $expo = $class -> new(CORE::length($2));
1353             } elsif ($$x =~
1354             / ^
1355             ( [+-]? [1-9] )
1356             ( \d+ )
1357             $
1358             /x)
1359             {
1360 0         0 $mant = $upgrade -> new($1 . "." . $2);
1361 0         0 $expo = $class -> new(CORE::length($2));
1362             } else {
1363 0         0 die "Internal error: ", (caller(0))[3], "() couldn't handle",
1364             " the value '", $$x, "', which is likely a bug";
1365             }
1366              
1367 0 0       0 return $mant unless wantarray;
1368 0         0 return $mant, $expo;
1369             }
1370              
1371             sub eparts {
1372 0 0   0 1 0 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1373              
1374 0 0 0     0 return $upgrade -> exponent($x)
1375             if defined($upgrade) && !$x -> isa($class);
1376              
1377             # Finite number.
1378              
1379 0         0 my ($mant, $expo) = $x -> sparts();
1380              
1381 0 0       0 if ($mant -> bcmp(0)) {
1382 0         0 my $ndigmant = $mant -> length();
1383 0         0 $expo = $expo -> badd($ndigmant);
1384              
1385             # $c is the number of digits that will be in the integer part of the
1386             # final mantissa.
1387              
1388 0         0 my $c = $expo -> copy() -> bdec() -> bmod(3) -> binc();
1389 0         0 $expo = $expo -> bsub($c);
1390              
1391 0 0       0 if ($ndigmant > $c) {
1392 0 0       0 return $upgrade -> eparts($x) if defined $upgrade;
1393 0         0 $mant = $mant -> bnan();
1394 0 0       0 return $mant unless wantarray;
1395 0         0 return ($mant, $expo);
1396             }
1397              
1398 0         0 $mant = $mant -> blsft($c - $ndigmant, 10);
1399             }
1400              
1401 0 0       0 return $mant unless wantarray;
1402 0         0 return ($mant, $expo);
1403             }
1404              
1405             sub dparts {
1406 0 0   0 1 0 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1407              
1408 0 0 0     0 return $upgrade -> exponent($x)
1409             if defined($upgrade) && !$x -> isa($class);
1410              
1411 0         0 my $int = $x -> copy();
1412 0         0 my $frc = $class -> bzero();
1413 0 0       0 return $int unless wantarray;
1414 0         0 return $int, $frc;
1415             }
1416              
1417             sub fparts {
1418 0 0   0 1 0 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1419              
1420 0 0 0     0 return $upgrade -> exponent($x)
1421             if defined($upgrade) && !$x -> isa($class);
1422              
1423 0         0 my $num = $x -> copy();
1424 0         0 my $den = $class -> bone();
1425 0 0       0 return $num unless wantarray;
1426 0         0 return $num, $den;
1427             }
1428              
1429             sub digit {
1430 22 100   22 1 528 my ($class, $x, $n) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1431              
1432 22 50       44 return $x->digit($n) unless $x->isa($class);
1433              
1434 22 50       38 $n = 0 if !defined $n;
1435 22         43 my $len = length("$$x");
1436              
1437 22 100       49 $n = $len+$n if $n < 0; # -1 last, -2 second-to-last
1438 22         86 $n = abs($n); # if negative was too big
1439 22         27 $len--;
1440 22 50       38 $n = $len if $n > $len; # n to big?
1441              
1442 22         128 substr($$x, -$n-1, 1);
1443             }
1444              
1445             sub length {
1446 6 50   6 1 33 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1447              
1448 6 50       12 return $x->length() unless $x->isa($class);
1449 6         15 my $l = length($$x);
1450 6 100       10 $l-- if $$x < 0; # -123 => 123
1451 6         37 $l;
1452             }
1453              
1454             ##############################################################################
1455             # sign based methods
1456              
1457             sub babs {
1458 25 50   25 1 59 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1459              
1460 25         38 $$x = abs($$x);
1461 25         46 $x;
1462             }
1463              
1464             sub bneg {
1465 115 50   115 1 261 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1466              
1467 115 100       228 $$x = -$$x if $$x != 0;
1468 115         241 $x;
1469             }
1470              
1471             sub bnot {
1472 5 50   5 1 25 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1473              
1474 5         12 $$x = -$$x - 1;
1475 5         31 $x;
1476             }
1477              
1478             ##############################################################################
1479             # special calc routines
1480              
1481             sub bceil {
1482 5 50   5 1 24 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1483 5         30 $x; # no-op
1484             }
1485              
1486             sub bfloor {
1487 5 50   5 1 24 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1488 5         29 $x; # no-op
1489             }
1490              
1491             sub bfac {
1492 17 50   17 1 83 my ($self, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) :
1493             ($class, $class->new($_[0]), $_[1], $_[2], $_[3], $_[4]);
1494              
1495 17 50       28 $x = $upgrade->new($$x) if $x->isa($class);
1496 17         904 $upgrade->bfac($x, @r);
1497             }
1498              
1499             sub bdfac {
1500 15 50   15 1 67 my ($self, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) :
1501             ($class, $class->new($_[0]), $_[1], $_[2], $_[3], $_[4]);
1502              
1503 15 50       28 $x = $upgrade->new($$x) if $x->isa($class);
1504 15         811 $upgrade->bdfac($x, @r);
1505             }
1506              
1507             sub bpow {
1508 97     97 1 838 my ($class, $x, $y, @r) = objectify(2, @_);
1509              
1510 97 50       1323 $x = $upgrade->new($$x) if $x->isa($class);
1511 97 100       5246 $y = $upgrade->new($$y) if $y->isa($class);
1512              
1513 97         3769 $x->bpow($y, @r);
1514             }
1515              
1516             sub blog {
1517 38     38 1 733 my ($class, $x, $base, @r);
1518              
1519             # Don't objectify the base, since an undefined base, as in $x->blog() or
1520             # $x->blog(undef) signals that the base is Euler's number.
1521              
1522 38 50 33     94 if (!ref($_[0]) && $_[0] =~ /^[A-Za-z]|::/) {
1523             # E.g., Math::BigInt::Lite->blog(256, 2)
1524 0 0       0 ($class, $x, $base, @r) =
1525             defined $_[2] ? objectify(2, @_) : objectify(1, @_);
1526             } else {
1527             # E.g., Math::BigInt::Lite::blog(256, 2) or $x->blog(2)
1528 38 100       108 ($class, $x, $base, @r) =
1529             defined $_[1] ? objectify(2, @_) : objectify(1, @_);
1530             }
1531              
1532 38 50       446 $x = $upgrade->new($$x) if $x->isa($class);
1533 38 100 100     2154 $base = $upgrade->new($$base) if defined $base && $base->isa($class);
1534              
1535 38         1227 $x->blog($base, @r);
1536             }
1537              
1538             sub bexp {
1539 2     2 1 12 my ($class, $x, @r) = objectify(1, @_);
1540              
1541 2 50       14 $x = $upgrade->new($$x) if $x->isa($class);
1542              
1543 2         102 $x->bexp(@r);
1544             }
1545              
1546             sub batan2 {
1547 20     20 1 426 my ($class, $x, $y, @r) = objectify(2, @_);
1548              
1549 20 50       278 $x = $upgrade->new($$x) if $x->isa($class);
1550              
1551 20         1193 $x->batan2($y, @r);
1552             }
1553              
1554             sub bnok {
1555 4880     4880 1 25178 my ($class, $x, $y, @r) = objectify(2, @_);
1556              
1557 4880 50       41100 $x = $upgrade->new($$x) if $x->isa($class);
1558 4880 100       241458 $y = $upgrade->new($$y) if $y->isa($class);
1559              
1560 4880         209632 $x->bnok($y, @r);
1561             }
1562              
1563             sub broot {
1564 31     31 1 458 my ($class, $x, $base, @r) = objectify(2, @_);
1565              
1566 31 50       348 $x = $upgrade->new($$x) if $x->isa($class);
1567 31 100 66     1652 $base = $upgrade->new($$base) if defined $base && $base->isa($class);
1568              
1569 31         1271 $x->broot($base, @r);
1570             }
1571              
1572             sub bmuladd {
1573 27     27 1 253 my ($class, $x, $y, $z, @r) = objectify(2, @_);
1574              
1575 27 50       274 $x = $upgrade->new($$x) if $x->isa($class);
1576 27 100 66     1529 $y = $upgrade->new($$y) if defined $y && $y->isa($class);
1577 27 100 66     1243 $z = $upgrade->new($$z) if defined $z && $z->isa($class);
1578              
1579 27         1802 $x->bmuladd($y, $z, @r);
1580             }
1581              
1582             sub bmodpow {
1583 160     160 1 796 my ($class, $x, $y, @r) = objectify(2, @_);
1584              
1585 160 50       1293 $x = $upgrade->new($$x) if $x->isa($class);
1586 160 100 66     9041 $y = $upgrade->new($$y) if defined $y && $y->isa($class);
1587              
1588 160         7925 $x->bmodpow($y, @r);
1589             }
1590              
1591             sub bmodinv {
1592 29     29 1 326 my ($class, $x, $y, @r) = objectify(2, @_);
1593              
1594 29 50       313 $x = $upgrade->new($$x) if $x->isa($class);
1595 29 100 66     1589 $y = $upgrade->new($$y) if defined $y && $y->isa($class);
1596              
1597 29         1177 $x->bmodinv($y, @r);
1598             }
1599              
1600             sub bsqrt {
1601 17 50   17 1 79 my ($class, $x, @r) =
1602             ref($_[0]) ? (ref($_[0]), @_)
1603             : ($class, $class->new($_[0]), $_[1], $_[2], $_[3]);
1604              
1605 17 50       31 return $x->bsqrt(@r) unless $x->isa($class);
1606              
1607 17 100       44 return $upgrade->new($$x)->bsqrt() if $$x < 0; # NaN
1608 15         23 my $s = sqrt($$x);
1609             # If MBI's upgrade is defined, and result is non-integer, we need to hand
1610             # up. If upgrade is undef, result would be the same, anyway
1611 15 100       26 if (int($s) != $s) {
1612 7         18 return $upgrade->new($$x)->bsqrt();
1613             }
1614 8         10 $$x = $s;
1615 8         58 $x;
1616             }
1617              
1618             sub bpi {
1619 3     3 1 12 my $self = shift;
1620 3   33     11 my $class = ref($self) || $self;
1621 3         5 $class -> new("3");
1622             }
1623              
1624             sub to_bin {
1625 5     5 1 22 my $self = shift;
1626 5         14 $upgrade -> new($$self) -> to_bin();
1627             }
1628              
1629             sub to_oct {
1630 5     5 1 22 my $self = shift;
1631 5         16 $upgrade -> new($$self) -> to_oct();
1632             }
1633              
1634             sub to_hex {
1635 5     5 1 20 my $self = shift;
1636 5         15 $upgrade -> new($$self) -> to_hex();
1637             }
1638              
1639             ##############################################################################
1640              
1641             sub import {
1642 6     6   50 my $self = shift;
1643              
1644 6         11 my @a = @_;
1645 6         11 my $l = scalar @_;
1646 6         9 my $j = 0;
1647 6         8 my $lib = '';
1648 6         27 for (my $i = 0; $i < $l ; $i++, $j++) {
1649 0 0       0 if ($_[$i] eq ':constant') {
    0          
    0          
1650             # this causes overlord er load to step in
1651 0     0   0 overload::constant integer => sub { $self->new(shift) };
  0         0  
1652 0         0 splice @a, $j, 1;
1653 0         0 $j --;
1654             } elsif ($_[$i] eq 'upgrade') {
1655             # this causes upgrading
1656 0         0 $upgrade = $_[$i+1]; # or undef to disable
1657 0         0 my $s = 2;
1658 0 0       0 $s = 1 if @a-$j < 2; # no "can not modify non-existant..."
1659 0         0 splice @a, $j, $s;
1660 0         0 $j -= $s;
1661             } elsif ($_[$i] eq 'lib') {
1662 0         0 $lib = $_[$i+1]; # or undef to disable
1663 0         0 my $s = 2;
1664 0 0       0 $s = 1 if @a-$j < 2; # no "can not modify non-existant..."
1665 0         0 splice @a, $j, $s;
1666 0         0 $j -= $s;
1667             }
1668             }
1669             # any non :constant stuff is handled by our parent,
1670             # even if @_ is empty, to give it a chance
1671 6         54 $self->SUPER::import(@a); # need it for subclasses
1672 6         5045 $self->export_to_level(1, $self, @a); # need it for MBF
1673             }
1674              
1675             1;
1676              
1677             __END__