File Coverage

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