File Coverage

blib/lib/Math/BigInt/Lite.pm
Criterion Covered Total %
statement 471 689 68.3
branch 279 556 50.1
condition 97 221 43.8
subroutine 103 121 85.1
pod 91 93 97.8
total 1041 1680 61.9


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   653276 use strict;
  6         12  
  6         207  
10 6     6   36 use warnings;
  6         32  
  6         416  
11              
12             require Exporter;
13 6     6   33 use Scalar::Util qw< blessed >;
  6         9  
  6         333  
14              
15 6     6   8885 use Math::BigInt;
  6         266534  
  6         33  
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.30';
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   205970 my $e0 = 1;
47 6         17 my $e1 = $e0 + 1;
48 6         12 my $num;
49             {
50 6         11 $num = '9' x $e1; # maximum value in base 10**$e1
  54         101  
51 54         123 $num = $num * $num # multiply by itself
52             + ($num - 1); # largest possible carry
53 54 100       934 last if $num !~ /^9{$e0}89{$e1}$/; # check digit pattern
54 48         90 $e0 = $e1;
55 48         70 $e1++;
56 48         88 redo;
57             }
58 6         22 my $e = $e0; # $e1 is one too large
59              
60             # the limits below brush the problems with the test above under the rug:
61              
62             # the test should be able to find the proper $e automatically
63 6 50       37 $e = 5 if $^O =~ /^uts/; # UTS get's some special treatment
64 6 50       24 $e = 5 if $^O =~ /^unicos/; # unicos is also problematic (6 seems to work
65             # there, but we play safe)
66 6 50       2303 $e = 8 if $e > 8; # cap, for VMS, OS/390 and other 64 bit systems
67              
68 6         2129 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         12 $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         1792 $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         3053 $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   1650 no strict 'refs';
  6         28  
  6         4418  
107             # make Class->round_mode() work
108 77     77 1 460 my $self = shift;
109 77   50     358 my $class = ref($self) || $self || __PACKAGE__;
110 77 50       177 if (defined $_[0]) {
111 77         109 my $m = shift;
112 77 50       333 die "Unknown round mode $m"
113             if $m !~ /^(even|odd|\+inf|\-inf|zero|trunc|common)$/;
114             # set in BigInt, too
115 77         293 Math::BigInt->round_mode($m);
116 77         1224 return ${"${class}::round_mode"} = $m;
  77         1003  
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   48 no strict 'refs';
  6         18  
  6         1361  
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   71 no strict 'refs';
  6         13  
  6         4419  
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   528 my $x = $_[0];
194 9         17 my $y = $_[1];
195 9         21 my $class = ref $x;
196 9 100       49 $y = $class->new($y) unless ref($y);
197 9 50       24 if ($y->isa($class)) {
198 9         20 $x = \($$x + $$y);
199 9         18 bless $x, $class;
200 9 50       55 $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   448 my $x = $_[0];
209 2         6 my $y = $_[1];
210 2         6 my $class = ref $x;
211 2 100       12 $y = $class->new($y) unless ref($y);
212 2 50       9 if ($y->isa($class)) {
213 2         7 $x = \($$x * $$y);
214 2 50       11 $$x = 0 if $$x eq '-0'; # correct 5.x.x bug
215 2         17 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 343     343   42088 '""' => sub { "${$_[0]}"; },
  343         2517  
238              
239 21     21   22 '0+' => sub { ${$_[0]}; },
  21         254  
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 19 100   19   2708 sign => ($_[0] < 0) ? '-' : '+',
256             };
257             },
258 6     6   49 ;
  6         11  
  6         163  
259              
260             BEGIN {
261 6     6   38277 *objectify = \&Math::BigInt::objectify;
262             }
263              
264             sub config {
265 2     2 1 504063 my $class = shift;
266              
267             # config({a => b, ...}) -> config(a => b, ...)
268 2 50 33     54 @_ = %{ $_[0] } if @_ == 1 && ref($_[0]) eq 'HASH';
  0         0  
269              
270             # Getter/accessor.
271              
272 2 50       11 if (@_ == 1) {
273 2         6 my $param = shift;
274              
275             # We don't use a math backend library.
276 2 100 66     17 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 1062 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         103 my ($class, @args) = objectify(0, @_);
310              
311             # If bgcd() is called as a function, the class might be anything.
312              
313 26 50       872 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 26         36 my $do_upgrade = 0;
322 26         43 for my $arg (@args) {
323 47 100       132 unless ($arg -> isa($class)) {
324 10         13 $do_upgrade = 1;
325 10         16 last;
326             }
327             }
328 26 100       76 return $upgrade -> bgcd(@args) if $do_upgrade;
329              
330             # Now compute the GCD.
331              
332 16         21 my ($a, $b, $c);
333 16         24 $a = shift @args;
334 16         45 $a = abs($$a);
335 16   100     52 while (@args && $a != 1) {
336 16         17 $b = shift @args;
337 16 100       33 next if $$b == 0;
338 15         18 $b = abs($$b);
339 15         15 do {
340 44         47 $c = $a % $b;
341 44         41 $a = $b;
342 44         66 $b = $c;
343             } while $c;
344             }
345              
346 16         242 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 319 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         29 my ($class, @args) = objectify(0, @_);
364              
365 8         199 my @a = ();
366 8         13 for my $arg (@args) {
367 16 100 66     72 $arg = $upgrade -> new("$arg")
368             unless defined(blessed($arg)) && $arg -> isa($upgrade);
369 16         789 push @a, $arg;
370             }
371              
372 8         22 $upgrade -> blcm(@a);
373             }
374              
375             sub isa {
376             # we aren't a BigInt nor BigRat/BigFloat
377 25388 100   25388 0 477554 $_[1] =~ /^Math::BigInt::Lite/ ? 1 : 0;
378             }
379              
380             sub new {
381 14379     14379 1 37271755 my ($class, $wanted, @r) = @_;
382              
383 14379 50       43912 return $upgrade->new($wanted) if !defined $wanted;
384              
385             # 1e12, NaN, inf, 0x12, 0b11, 1.2e2, "12345678901234567890" etc all upgrade
386 14379 50       33626 if (!ref($wanted)) {
387 14379 100 100     146242 if ((length($wanted) <= $MAX_NEW_LEN) &&
388             ($wanted =~ /^[+-]?[0-9]{1,$MAX_NEW_LEN}(\.0*)?\z/)) {
389 12716         36063 my $a = \($wanted+0); # +0 to make a copy and force it numeric
390 12716         153247 return bless $a, $class;
391             }
392             # TODO: 1e10 style constants that are still below MAX_NEW
393 1663 100       8454 if ($wanted =~ /^([+-])?([0-9]+)[eE][+]?([0-9]+)$/) {
394 37 100       236 if ((length($2) + $3) < $MAX_NEW_LEN) {
395 28         166 my $a = \($wanted+0); # +0 to make a copy and force it numeric
396 28         173 return bless $a, $class;
397             }
398             }
399             # print "new '$$a' $BASE_LEN ($wanted)\n";
400             }
401 1635         8057 $upgrade->new($wanted, @r);
402             }
403              
404             ###############################################################################
405             # String conversion methods
406             ###############################################################################
407              
408             sub bstr {
409 2960 50   2960 1 8455405 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
410              
411 2960 50 33     20455 return $upgrade -> exponent($x)
412             if defined($upgrade) && !$x -> isa($class);
413              
414 2960         20059 "$$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 627 50   627 1 1880 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
422              
423 627 50 33     2236 return $upgrade -> exponent($x)
424             if defined($upgrade) && !$x -> isa($class);
425              
426 627 50       4555 if ($$x =~ / ^
427             (
428             [+-]?
429             (?: 0 | [1-9] (?: \d* [1-9] )? )
430             )
431             ( 0* )
432             $
433             /x)
434             {
435 627         1580 my $mant = $1;
436 627         1213 my $expo = CORE::length($2);
437 627         2690 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 2 50   2 1 15 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
538              
539 2 50 33     11 return $upgrade -> exponent($x)
540             if defined($upgrade) && !$x -> isa($class);
541              
542 2         129 "$$x";
543             }
544              
545             ###############################################################################
546              
547             sub bnorm {
548             # no-op
549 211 50   211 1 320745 my $x = ref($_[0]) ? $_[0] : $_[0]->new($_[1]);
550              
551 211         49902 $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 398 100 66 398   1671 shift if !ref($_[0]) && $_[0] =~ /^Math::BigInt::Lite/;
565              
566 398         1002 my ($x, $y, @r) = @_;
567              
568 398         723 my $up = 0; # default: don't upgrade
569              
570 398 50 33     3203 $up = 1
      33        
      33        
571             if (defined $r[0] || defined $r[1] || defined $accuracy || defined $precision);
572 398 100       961 $x = __PACKAGE__->new($x) unless ref $x; # upgrade literals
573 398 100       847 $y = __PACKAGE__->new($y) unless ref $y; # upgrade literals
574 398 100 66     1077 $up = 1 unless $x->isa($class) && $y->isa($class);
575             # no need to check for overflow for add/sub/div/mod math
576 398 100       1049 if ($up == 1) {
577 45 50       144 $x = $upgrade->new($$x) if $x->isa($class);
578 45 50       4916 $y = $upgrade->new($$y) if $y->isa($class);
579             }
580              
581 398         1410 ($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 37 100 66 37   178 shift if !ref($_[0]) && $_[0] =~ /^Math::BigInt::Lite/;
596              
597 37         103 my ($x, $y, @r) = @_;
598              
599 37         71 my $up = 0; # default: don't upgrade
600              
601 37 50 33     332 $up = 1
      33        
      33        
602             if (defined $r[0] || defined $r[1] || defined $accuracy || defined $precision);
603 37 100       95 $x = __PACKAGE__->new($x) unless ref $x; # upgrade literals
604 37 100       97 $y = __PACKAGE__->new($y) unless ref $y; # upgrade literals
605 37 100 66     131 $up = 1 unless $x->isa($class) && $y->isa($class);
606 37 50 33     261 $up = 1 if ($up == 0 && (abs($$x) >= $MAX_MUL || abs($$y) >= $MAX_MUL) );
      66        
607 37 100       99 if ($up == 1) {
608 3 50       13 $x = $upgrade->new($$x) if $x->isa($class);
609 3 50       354 $y = $upgrade->new($$y) if $y->isa($class);
610             }
611 37         146 ($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   19 my ($x, @r) = @_;
622              
623 6         26 my $up = 0; # default: don't upgrade
624              
625 6 50 33     122 $up = 1
      33        
      33        
626             if (defined $r[0] || defined $r[1] || defined $accuracy || defined $precision);
627 6 50       15 $x = __PACKAGE__->new($x) unless ref $x; # upgrade literals
628 6 50       29 $up = 1 unless $x->isa($class);
629 6 50       16 if ($up == 1) {
630 0 0       0 $x = $upgrade->new($$x) if $x->isa($class);
631             }
632 6         22 ($up, $x, @r);
633             }
634              
635             ##############################################################################
636             # rounding functions
637              
638             sub bround {
639 9 50   9 1 70 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       23 $x = $upgrade->new($$x) if $x->isa($class);
645 9         833 $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         119 $x->bfround(@p);
656              
657             }
658              
659             sub round {
660 2 50   2 1 29 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
661              
662 2 50       8 $x = $upgrade->new($$x) if $x->isa($class);
663 2         447 $x->round(@r);
664             }
665              
666             ##############################################################################
667             # special values
668              
669             sub bnan {
670             # return a NaN
671 5     5 1 2031 shift;
672 5         35 $upgrade -> bnan(@_);
673             }
674              
675             sub binf {
676             # return a +/-Inf
677 17     17 1 11058 shift;
678 17         91 $upgrade -> binf(@_);
679             }
680              
681             sub bone {
682             # return a +/-1
683 12     12 1 3004 my $x = shift;
684              
685 12         56 my ($sign, @r) = @_;
686              
687             # Get the sign.
688              
689 12 100 100     110 if (defined($_[0]) && $_[0] =~ /^\s*([+-])\s*$/) {
690 8         27 $sign = $1;
691 8         13 shift;
692             } else {
693 4         12 $sign = '+';
694             }
695              
696 12 100       35 my $num = $sign eq "-" ? -1 : 1;
697 12 100       48 return $x -> new($num) unless ref $x; # $class->bone();
698 6         15 $$x = $num;
699 6         47 $x;
700             }
701              
702             sub bzero {
703             # return a one
704 3     3 1 405 my $x = shift;
705              
706 3 100       17 return $x->new(0) unless ref $x; # $class->bone();
707 1         3 $$x = 0;
708 1         3 $x;
709             }
710              
711             sub bcmp {
712             # compare the value of two objects
713 95 100 66 95 1 2499 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
714             ? (ref($_[0]), @_)
715             : objectify(2, @_);
716              
717 95 100 66     818 return $upgrade->bcmp($x, $y)
      66        
718             if defined($upgrade) && (!$x->isa($class) || !$y->isa($class));
719              
720 90         485 $$x <=> $$y;
721             }
722              
723             sub bacmp {
724             # compare the absolute value of two objects
725 12 100 66 12 1 901 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
726             ? (ref($_[0]), @_)
727             : objectify(2, @_);
728              
729 12 100 66     456 return $upgrade->bacmp($x, $y)
      66        
730             if defined($upgrade) && (!$x->isa($class) || !$y->isa($class));
731              
732 7         105 abs($$x) <=> abs($$y);
733             }
734              
735             ##############################################################################
736             # copy/conversion
737              
738             sub copy {
739 289     289 1 28032 my ($x, $class);
740 289 50       771 if (ref($_[0])) { # $y = $x -> copy()
741 289         417 $x = shift;
742 289         483 $class = ref($x);
743             } else { # $y = $class -> copy($y)
744 0         0 $class = shift;
745 0         0 $x = shift;
746             }
747              
748 289         536 my $val = $$x;
749 289         1172 bless \$val, $class;
750             }
751              
752             sub as_int {
753 624 50   624 1 19890 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
754              
755 624 50       1462 return $x -> copy() if $x -> isa("Math::BigInt");
756              
757             # disable upgrading and downgrading
758              
759 624         1441 my $upg = Math::BigInt -> upgrade();
760 624         6202 my $dng = Math::BigInt -> downgrade();
761 624         6416 Math::BigInt -> upgrade(undef);
762 624         6968 Math::BigInt -> downgrade(undef);
763              
764 624         6752 my $y = Math::BigInt -> new($x -> bsstr());
765              
766             # reset upgrading and downgrading
767              
768 624         54602 Math::BigInt -> upgrade($upg);
769 624         6892 Math::BigInt -> downgrade($dng);
770              
771 624         7285 return $y;
772             }
773              
774             sub as_number {
775 1 50   1 0 450 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
776              
777 1 50       5 return $upgrade->new($x) unless ref($x);
778             # as_number needs to return a BigInt
779 1 50       5 return $upgrade->new($$x) if $x->isa($class);
780 0         0 $x->copy();
781             }
782              
783             sub numify {
784 81 50   81 1 2733 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
785              
786 81 50       240 return $$x if $x->isa($class);
787 0         0 $x->numify();
788             }
789              
790             sub as_hex {
791 5 50   5 1 34 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
792              
793 5 50       28 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 50 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
799              
800 5 50       21 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 35 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
806              
807 5 50       12 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 25 my ($up, $x, $y, @r) = _upgrade_1(@_);
958              
959 3 50       11 return $x->binc(@r) if $up;
960 3         10 $$x++;
961 3 50       10 return $upgrade->new($$x) if abs($$x) > $MAX_ADD;
962 3         33 $x;
963             }
964              
965             sub bdec {
966             # decrement by one
967 3     3 1 87 my ($up, $x, $y, @r) = _upgrade_1(@_);
968              
969 3 50       11 return $x->bdec(@r) if $up;
970 3         9 $$x--;
971 3 50       10 return $upgrade->new($$x) if abs($$x) > $MAX_ADD;
972 3         34 $x;
973             }
974              
975             ##############################################################################
976             # shifting
977              
978             sub brsft {
979             # shift right
980 26     26 1 282 my ($class, $x, $y, $b, @r) = objectify(2, @_);
981              
982 26 50       607 $x = $class->new($x) unless ref($x);
983 26 50       74 $y = $class->new($y) unless ref($y);
984 26 50 33     82 $b = $$b if ref $b && $b->isa($class);
985              
986 26 50       63 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       57 return $upgrade->new($$x)->brsft($y, $b, @r)
991             unless $y->isa($class);
992              
993 26 100       74 $b = 2 if !defined $b;
994             # can't do this
995 26 100 66     261 return $upgrade->new($$x)->brsft($upgrade->new($$y), $b, @r)
996             if $b != 2 || $$y < 0;
997 6     6   64 use integer;
  6         13  
  6         47  
998 18         46 $$x >>= $$y; # only base 2 for now
999 18         260 $x;
1000             }
1001              
1002             sub blsft {
1003             # shift left
1004 12     12 1 91 my ($class, $x, $y, $b, @r) = objectify(2, @_);
1005              
1006 12 50       274 $x = $class->new($x) unless ref($x);
1007 12 50       37 $y = $class->new($x) unless ref($y);
1008              
1009 12 50       33 return $x->blsft($upgrade->new($$y), $b, @r) unless $x->isa($class);
1010 12 50       29 return $upgrade->new($$x)->blsft($y, $b, @r)
1011             unless $y->isa($class);
1012              
1013             # overflow: can't do this
1014 12 50       43 return $upgrade->new($$x)->blsft($upgrade->new($$y), $b, @r)
1015             if $$y > 31;
1016 12 100       35 $b = 2 if !defined $b;
1017             # can't do this
1018 12 100 66     85 return $upgrade->new($$x)->blsft($upgrade->new($$y), $b, @r)
1019             if $b != 2 || $$y < 0;
1020 6     6   1510 use integer;
  6         9  
  6         25  
1021 6         16 $$x <<= $$y; # only base 2 for now
1022 6         71 $x;
1023             }
1024              
1025             ###############################################################################
1026             # Bitwise methods
1027             ###############################################################################
1028              
1029             # Bitwise left shift.
1030              
1031             sub bblsft {
1032 5 50   5 1 34 my ($class, $x, $y, @r) = ref($_[0]) ? (ref($_[0]), @_) : @_;
1033             # For now, upgrade, but we should handle simple cases here. Fixme!
1034 5         27 $upgrade -> bblsft($x, $y, @r);
1035             }
1036              
1037             # Bitwise right shift.
1038              
1039             sub bbrsft {
1040 2 50   2 1 10 my ($class, $x, $y, @r) = ref($_[0]) ? (ref($_[0]), @_) : @_;
1041             # For now, upgrade, but we should handle simple cases here. Fixme!
1042 2         12 $upgrade -> bbrsft($x, $y, @r);
1043             }
1044              
1045             sub band {
1046             # AND two objects
1047 15 100 66 15 1 163 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
1048             ? (ref($_[0]), @_) : objectify(2, @_);
1049              
1050 15 100 66     86 return $upgrade -> band($x, $y, @r)
1051             unless $x -> isa($class) && $y -> isa($class);
1052              
1053 6     6   2032 use integer;
  6         27  
  6         35  
1054 14         53 $$x = ($$x+0) & ($$y+0); # +0 to avoid string-context
1055 14         174 $x;
1056             }
1057              
1058             sub bxor {
1059             # XOR two objects
1060 22 100 66 22 1 150 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
1061             ? (ref($_[0]), @_) : objectify(2, @_);
1062              
1063 22 100 66     305 return $upgrade -> bxor($x, $y, @r)
1064             unless $x -> isa($class) && $y -> isa($class);
1065              
1066 6     6   1070 use integer;
  6         13  
  6         32  
1067 16         39 $$x = ($$x+0) ^ ($$y+0); # +0 to avoid string-context
1068 16         140 $x;
1069             }
1070              
1071             sub bior {
1072             # OR two objects
1073 21 100 66 21 1 216 my ($class, $x, $y, @r) = ref($_[0]) && ref($_[0]) eq ref($_[1])
1074             ? (ref($_[0]), @_) : objectify(2, @_);
1075              
1076 21 100 66     301 return $upgrade -> bior($x, $y, @r)
1077             unless $x -> isa($class) && $y -> isa($class);
1078              
1079 6     6   968 use integer;
  6         12  
  6         32  
1080 15         51 $$x = ($$x+0) | ($$y+0); # +0 to avoid string-context
1081 15         187 $x;
1082             }
1083              
1084             ##############################################################################
1085             # mul/add/div etc
1086              
1087             sub badd {
1088             # add two objects
1089 60     60 1 6266 my ($up, $x, $y, @r) = _upgrade_2(@_);
1090              
1091 60 100       188 return $x->badd($y, @r) if $up;
1092              
1093 46         168 $$x = $$x + $$y;
1094 46 50       140 return $upgrade->new($$x) if abs($$x) > $MAX_ADD;
1095 46         513 $x;
1096             }
1097              
1098             sub bsub {
1099             # subtract two objects
1100 65     65 1 543 my ($up, $x, $y, @r) = _upgrade_2(@_);
1101 65 100       183 return $x->bsub($y, @r) if $up;
1102 64         177 $$x = $$x - $$y;
1103 64 50       162 return $upgrade->new($$x) if abs($$x) > $MAX_ADD;
1104 64         530 $x;
1105             }
1106              
1107             sub bmul {
1108             # multiply two objects
1109 37     37 1 813 my ($up, $x, $y, @r) = _upgrade_2_mul(@_);
1110 37 100       119 return $x->bmul($y, @r) if $up;
1111 34         94 $$x = $$x * $$y;
1112 34 50       111 $$x = 0 if $$x eq '-0'; # for some Perls leave '-0' here
1113             #return $upgrade->new($$x) if abs($$x) > $MAX_ADD;
1114 34         378 $x;
1115             }
1116              
1117             sub bmod {
1118             # remainder of div
1119 63     63 1 231 my ($up, $x, $y, @r) = _upgrade_2(@_);
1120 63 100       162 return $x->bmod($y, @r) if $up;
1121 57 100       151 return $upgrade->new($$x)->bmod($y, @r) if $$y == 0;
1122 54         138 $$x = $$x % $$y;
1123 54         501 $x;
1124             }
1125              
1126             sub bdiv {
1127             # divide two objects
1128 108     108 1 2411 my ($up, $x, $y, @r) = _upgrade_2(@_);
1129              
1130 108 100       360 return $x->bdiv($y, @r) if $up;
1131              
1132 96 100       338 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       220 return $upgrade->new($$x)->bdiv($$y, @r)
1136             if defined $Math::BigInt::upgrade;
1137              
1138 90         142 my ($quo, $rem);
1139              
1140 90         204 $rem = \($$x % $$y);
1141 90         257 $quo = int($$x / $$y);
1142 90 100 100     342 $quo-- if $$rem != 0 && ($$x <=> 0) != ($$y <=> 0);
1143              
1144 90         163 $$x = $quo;
1145              
1146 90 100       213 if (wantarray) {
1147 42         82 bless $rem, $class;
1148 42         185 return $x, $rem;
1149             }
1150              
1151 48         625 return $x;
1152             }
1153              
1154             sub btdiv {
1155             # divide two objects
1156 102     102 1 2438 my ($up, $x, $y, @r) = _upgrade_2(@_);
1157              
1158 102 100       335 return $x->btdiv($y, @r) if $up;
1159              
1160 90 100       338 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       261 return $upgrade->new($$x)->btdiv($$y, @r)
1164             if defined $Math::BigInt::upgrade;
1165              
1166 84         187 my ($quo, $rem);
1167              
1168 84 100       195 if (wantarray) {
1169 42         116 $rem = \($$x % $$y);
1170 42 100 100     214 $$rem -= $$y if $$rem != 0 && ($$x <=> 0) != ($$y <=> 0);
1171 42         104 bless $rem, $class;
1172             }
1173              
1174 84         274 $quo = int($$x / $$y);
1175              
1176 84         162 $$x = $quo;
1177 84 100       323 return $x, $rem if wantarray;
1178 42         551 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 3 50   3 1 94 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1187              
1188 3 50       13 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 7 50   7 1 132 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1195              
1196 7 50       23 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 4 50   4 1 33 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1203              
1204 4 50       13 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 202 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1211              
1212 11 50       70 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 51 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1219              
1220 3 50       12 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 28 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1227              
1228 3 50       10 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 73 my ($class, $x, $s) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1235              
1236 9         14 my $one = 1;
1237 9 100 100     49 $one = -1 if ($s || '+') eq '-';
1238 9 50       28 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 110 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1245              
1246 10 50       29 return $x->is_odd() unless $x->isa($class);
1247 10 100       172 $$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 94 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1253              
1254 10 50       31 return $x->is_even() unless $x->isa($class);
1255 10 100       161 $$x & 1 == 1 ? 0 : 1;
1256             }
1257              
1258             ##############################################################################
1259             # parts() and friends
1260              
1261             sub sign {
1262 0 0   0 1 0 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1263              
1264 0 0       0 $$x >= 0 ? '+' : '-';
1265             }
1266              
1267             sub parts {
1268 6 50   6 1 37 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1269              
1270 6 50 33     21 return $upgrade -> exponent($x)
1271             if defined($upgrade) && !$x -> isa($class);
1272              
1273 6 50       31 if ($$x =~ / ^
1274             (
1275             [+-]?
1276             (?: 0 | [1-9] (?: \d* [1-9] )? )
1277             )
1278             ( 0* )
1279             $
1280             /x)
1281             {
1282 6         7 my $mant = $1;
1283 6         9 my $expo = CORE::length($2);
1284 6         13 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 36 my ($class, $x) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1293              
1294 6 50 33     29 return $upgrade -> exponent($x)
1295             if defined($upgrade) && !$x -> isa($class);
1296              
1297 6         10 my $expo;
1298 6 50       27 if ($$x =~ / (?: ^ 0 | [1-9] ) ( 0* ) $/x) {
1299 6         7 $expo = CORE::length($1);
1300 6         9 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 33 my ($class, $x) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1309              
1310 5 50 33     43 return $upgrade -> exponent($x)
1311             if defined($upgrade) && !$x -> isa($class);
1312              
1313 5 50       23 if ($$x =~ / ^
1314             (
1315             [+-]?
1316             (?: 0 | [1-9] (?: \d* [1-9] )? )
1317             )
1318             /x)
1319             {
1320 5         11 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 893 my ($class, $x, $n) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1445              
1446 22 50       63 return $x->digit($n) unless $x->isa($class);
1447              
1448 22 50       38 $n = 0 if !defined $n;
1449 22         61 my $len = length("$$x");
1450              
1451 22 100       66 $n = $len+$n if $n < 0; # -1 last, -2 second-to-last
1452 22         100 $n = abs($n); # if negative was too big
1453 22         31 $len--;
1454 22 50       43 $n = $len if $n > $len; # n to big?
1455              
1456 22         109 substr($$x, -$n-1, 1);
1457             }
1458              
1459             sub length {
1460 6 50   6 1 65 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1461              
1462 6 50       34 return $x->length() unless $x->isa($class);
1463 6         26 my $l = length($$x);
1464 6 100       24 $l-- if $$x < 0; # -123 => 123
1465 6         99 $l;
1466             }
1467              
1468             ##############################################################################
1469             # sign based methods
1470              
1471             sub babs {
1472 25 50   25 1 99 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1473              
1474 25         48 $$x = abs($$x);
1475 25         76 $x;
1476             }
1477              
1478             sub bneg {
1479 29 50   29 1 113 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1480              
1481 29 100       93 $$x = -$$x if $$x != 0;
1482 29         166 $x;
1483             }
1484              
1485             sub bnot {
1486 5 50   5 1 34 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1487              
1488 5         39 $$x = -$$x - 1;
1489 5         46 $x;
1490             }
1491              
1492             ##############################################################################
1493             # special calc routines
1494              
1495             sub bceil {
1496 5 50   5 1 51 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1497 5         95 $x; # no-op
1498             }
1499              
1500             sub bfloor {
1501 5 50   5 1 139 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1502 5         70 $x; # no-op
1503             }
1504              
1505             sub bint {
1506 5 50   5 1 49 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1507 5         61 $x; # no-op
1508             }
1509              
1510             sub bfac {
1511 17 50   17 1 164 my ($self, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) :
1512             ($class, $class->new($_[0]), $_[1], $_[2], $_[3], $_[4]);
1513              
1514 17 50       49 $x = $upgrade->new($$x) if $x->isa($class);
1515 17         1834 $upgrade->bfac($x, @r);
1516             }
1517              
1518             sub bdfac {
1519 15 50   15 1 117 my ($self, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) :
1520             ($class, $class->new($_[0]), $_[1], $_[2], $_[3], $_[4]);
1521              
1522 15 50       52 $x = $upgrade->new($$x) if $x->isa($class);
1523 15         1319 $upgrade->bdfac($x, @r);
1524             }
1525              
1526             sub btfac {
1527 16 50   16 1 105 my ($self, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) :
1528             ($class, $class->new($_[0]), $_[1], $_[2], $_[3], $_[4]);
1529              
1530 16 50       34 $x = $upgrade->new($$x) if $x->isa($class);
1531 16         1279 $upgrade->btfac($x, @r);
1532             }
1533              
1534             sub bmfac {
1535 75     75 1 886 my ($class, $x, $k, @r) = objectify(2, @_);
1536              
1537 75 50       1214 $x = $upgrade->new($$x) if $x->isa($class);
1538 75         5940 $upgrade->bmfac($x, $k, @r);
1539             }
1540              
1541             sub bpow {
1542 97     97 1 1645 my ($class, $x, $y, @r) = objectify(2, @_);
1543              
1544 97 50       2445 $x = $upgrade->new($$x) if $x->isa($class);
1545 97 100       8150 $y = $upgrade->new($$y) if $y->isa($class);
1546              
1547 97         4988 $x->bpow($y, @r);
1548             }
1549              
1550             sub blog {
1551 38     38 1 1199 my ($class, $x, $base, @r);
1552              
1553             # Don't objectify the base, since an undefined base, as in $x->blog() or
1554             # $x->blog(undef) signals that the base is Euler's number.
1555              
1556 38 50 33     171 if (!ref($_[0]) && $_[0] =~ /^[A-Za-z]|::/) {
1557             # E.g., Math::BigInt::Lite->blog(256, 2)
1558 0 0       0 ($class, $x, $base, @r) =
1559             defined $_[2] ? objectify(2, @_) : objectify(1, @_);
1560             } else {
1561             # E.g., Math::BigInt::Lite::blog(256, 2) or $x->blog(2)
1562 38 100       268 ($class, $x, $base, @r) =
1563             defined $_[1] ? objectify(2, @_) : objectify(1, @_);
1564             }
1565              
1566 38 50       1165 $x = $upgrade->new($$x) if $x->isa($class);
1567 38 100 100     4351 $base = $upgrade->new($$base) if defined $base && $base->isa($class);
1568              
1569 38         2900 $x->blog($base, @r);
1570             }
1571              
1572             sub bexp {
1573 2     2 1 27 my ($class, $x, @r) = objectify(1, @_);
1574              
1575 2 50       25 $x = $upgrade->new($$x) if $x->isa($class);
1576              
1577 2         203 $x->bexp(@r);
1578             }
1579              
1580             sub batan2 {
1581 20     20 1 604 my ($class, $x, $y, @r) = objectify(2, @_);
1582              
1583 20 50       465 $x = $upgrade->new($$x) if $x->isa($class);
1584              
1585 20         1635 $x->batan2($y, @r);
1586             }
1587              
1588             sub bnok {
1589 4880     4880 1 57679 my ($class, $x, $y, @r) = objectify(2, @_);
1590              
1591 4880 50       100291 $x = $upgrade->new($$x) if $x->isa($class);
1592 4880 100       542510 $y = $upgrade->new($$y) if $y->isa($class);
1593              
1594 4880         405361 $x->bnok($y, @r);
1595             }
1596              
1597             sub broot {
1598 31     31 1 715 my ($class, $x, $base, @r) = objectify(2, @_);
1599              
1600 31 50       691 $x = $upgrade->new($$x) if $x->isa($class);
1601 31 100 66     2681 $base = $upgrade->new($$base) if defined $base && $base->isa($class);
1602              
1603 31         1902 $x->broot($base, @r);
1604             }
1605              
1606             sub bmuladd {
1607 27     27 1 518 my ($class, $x, $y, $z, @r) = objectify(2, @_);
1608              
1609 27 50       745 $x = $upgrade->new($$x) if $x->isa($class);
1610 27 100 66     3237 $y = $upgrade->new($$y) if defined $y && $y->isa($class);
1611 27 100 66     3113 $z = $upgrade->new($$z) if defined $z && $z->isa($class);
1612              
1613 27         2816 $x->bmuladd($y, $z, @r);
1614             }
1615              
1616             sub bmodpow {
1617 160     160 1 1445 my ($class, $x, $y, @r) = objectify(2, @_);
1618              
1619 160 50       2660 $x = $upgrade->new($$x) if $x->isa($class);
1620 160 100 66     14630 $y = $upgrade->new($$y) if defined $y && $y->isa($class);
1621              
1622 160         11349 $x->bmodpow($y, @r);
1623             }
1624              
1625             sub bmodinv {
1626 29     29 1 432 my ($class, $x, $y, @r) = objectify(2, @_);
1627              
1628 29 50       508 $x = $upgrade->new($$x) if $x->isa($class);
1629 29 100 66     2170 $y = $upgrade->new($$y) if defined $y && $y->isa($class);
1630              
1631 29         1531 $x->bmodinv($y, @r);
1632             }
1633              
1634             sub bsqrt {
1635 17 50   17 1 138 my ($class, $x, @r) =
1636             ref($_[0]) ? (ref($_[0]), @_)
1637             : ($class, $class->new($_[0]), $_[1], $_[2], $_[3]);
1638              
1639 17 50       39 return $x->bsqrt(@r) unless $x->isa($class);
1640              
1641 17 100       88 return $upgrade->new($$x)->bsqrt() if $$x < 0; # NaN
1642 15         30 my $s = sqrt($$x);
1643             # If MBI's upgrade is defined, and result is non-integer, we need to hand
1644             # up. If upgrade is undef, result would be the same, anyway
1645 15 100       44 if (int($s) != $s) {
1646 7         31 return $upgrade->new($$x)->bsqrt();
1647             }
1648 8         18 $$x = $s;
1649 8         74 $x;
1650             }
1651              
1652             sub bpi {
1653 3     3 1 24 my $self = shift;
1654 3   33     17 my $class = ref($self) || $self;
1655 3         10 $class -> new("3");
1656             }
1657              
1658             sub to_bin {
1659 5     5 1 38 my $self = shift;
1660 5         34 $upgrade -> new($$self) -> to_bin();
1661             }
1662              
1663             sub to_oct {
1664 5     5 1 65 my $self = shift;
1665 5         31 $upgrade -> new($$self) -> to_oct();
1666             }
1667              
1668             sub to_hex {
1669 5     5 1 34 my $self = shift;
1670 5         28 $upgrade -> new($$self) -> to_hex();
1671             }
1672              
1673             ##############################################################################
1674              
1675             sub import {
1676 6     6   63 my $self = shift;
1677              
1678 6         18 my @a = @_;
1679 6         14 my $l = scalar @_;
1680 6         13 my $j = 0;
1681 6         13 my $lib = '';
1682 6         31 for (my $i = 0; $i < $l ; $i++, $j++) {
1683 0 0       0 if ($_[$i] eq ':constant') {
    0          
    0          
1684             # this causes overlord er load to step in
1685 0     0   0 overload::constant integer => sub { $self->new(shift) };
  0         0  
1686 0         0 splice @a, $j, 1;
1687 0         0 $j --;
1688             } elsif ($_[$i] eq 'upgrade') {
1689             # this causes upgrading
1690 0         0 $upgrade = $_[$i+1]; # or undef to disable
1691 0         0 my $s = 2;
1692 0 0       0 $s = 1 if @a-$j < 2; # no "can not modify non-existant..."
1693 0         0 splice @a, $j, $s;
1694 0         0 $j -= $s;
1695             } elsif ($_[$i] eq 'lib') {
1696 0         0 $lib = $_[$i+1]; # or undef to disable
1697 0         0 my $s = 2;
1698 0 0       0 $s = 1 if @a-$j < 2; # no "can not modify non-existant..."
1699 0         0 splice @a, $j, $s;
1700 0         0 $j -= $s;
1701             }
1702             }
1703             # any non :constant stuff is handled by our parent,
1704             # even if @_ is empty, to give it a chance
1705 6         93 $self->SUPER::import(@a); # need it for subclasses
1706 6         7990 $self->export_to_level(1, $self, @a); # need it for MBF
1707             }
1708              
1709             1;
1710              
1711             __END__