File Coverage

blib/lib/Math/BigInt/Calc.pm
Criterion Covered Total %
statement 875 1220 71.7
branch 343 578 59.3
condition 151 259 58.3
subroutine 63 71 88.7
pod 0 2 0.0
total 1432 2130 67.2


line stmt bran cond sub pod time code
1             package Math::BigInt::Calc;
2              
3 50     50   273644 use 5.006001;
  50         190  
4 50     50   302 use strict;
  50         87  
  50         1376  
5 50     50   245 use warnings;
  50         104  
  50         3795  
6              
7 50     50   348 use Carp qw< carp croak >;
  50         105  
  50         3928  
8 50     50   37881 use Math::BigInt::Lib;
  50         191  
  50         367  
9              
10             our $VERSION = '2.005003';
11             $VERSION =~ tr/_//d;
12              
13             our @ISA = ('Math::BigInt::Lib');
14              
15             # Package to store unsigned big integers in decimal and do math with them
16             #
17             # Internally the numbers are stored in an array with at least 1 element, no
18             # leading zero parts (except the first) and in base 1eX where X is determined
19             # automatically at loading time to be the maximum possible value
20             #
21             # todo:
22             # - fully remove funky $# stuff in div() (maybe - that code scares me...)
23              
24             ##############################################################################
25             # global constants, flags and accessory
26              
27             # constants for easier life
28              
29             my $MAX_EXP_F; # the maximum possible base 10 exponent with "no integer"
30             my $MAX_EXP_I; # the maximum possible base 10 exponent with "use integer"
31              
32             my $MAX_BITS; # the maximum possible number of bits for $AND_BITS etc.
33              
34             my $BASE_LEN; # the current base exponent in use
35             my $USE_INT; # whether "use integer" is used in the computations
36              
37             my $BASE; # the current base, e.g., 10000 if $BASE_LEN is 5
38             my $MAX_VAL; # maximum value for an element, i.e., $BASE - 1
39              
40             my $AND_BITS; # maximum value used in binary and, e.g., 0xffff
41             my $OR_BITS; # ditto for binary or
42             my $XOR_BITS; # ditto for binary xor
43              
44             my $AND_MASK; # $AND_BITS + 1, e.g., 0x10000 if $AND_BITS is 0xffff
45             my $OR_MASK; # ditto for binary or
46             my $XOR_MASK; # ditto for binary xor
47              
48             sub config {
49 0     0 0 0 my $self = shift;
50              
51 0 0       0 croak "Missing input argument" unless @_;
52              
53             # Called as a getter.
54              
55 0 0       0 if (@_ == 1) {
56 0         0 my $param = shift;
57 0 0 0     0 croak "Parameter name must be a non-empty string"
58             unless defined $param && length $param;
59 0 0       0 return $BASE_LEN if $param eq 'base_len';
60 0 0       0 return $USE_INT if $param eq 'use_int';
61 0         0 croak "Unknown parameter '$param'";
62             }
63              
64             # Called as a setter.
65              
66 0         0 my $opts;
67 0         0 while (@_) {
68 0         0 my $param = shift;
69 0 0 0     0 croak "Parameter name must be a non-empty string"
70             unless defined $param && length $param;
71 0 0       0 croak "Missing value for parameter '$param'"
72             unless @_;
73 0         0 my $value = shift;
74              
75 0 0 0     0 if ($param eq 'base_len' || $param eq 'use_int') {
76 0         0 $opts -> {$param} = $value;
77 0         0 next;
78             }
79              
80 0         0 croak "Unknown parameter '$param'";
81             }
82              
83 0 0       0 $BASE_LEN = $opts -> {base_len} if exists $opts -> {base_len};
84 0 0       0 $USE_INT = $opts -> {use_int} if exists $opts -> {use_int};
85 0         0 __PACKAGE__ -> _base_len($BASE_LEN, $USE_INT);
86              
87 0         0 return $self;
88             }
89              
90             sub _base_len {
91             #my $class = shift; # $class is not used
92 68     68   434912 shift;
93              
94 68 100       268 if (@_) { # if called as setter ...
95 57         413 my ($base_len, $use_int) = @_;
96              
97 57 50 33     668 croak "The base length must be a positive integer"
      33        
98             unless defined($base_len) && $base_len == int($base_len)
99             && $base_len > 0;
100              
101 57 50 66     673 if ( $use_int && ($base_len > $MAX_EXP_I) ||
      66        
      33        
102             !$use_int && ($base_len > $MAX_EXP_F))
103             {
104 0 0       0 croak "The maximum base length (exponent) is $MAX_EXP_I with",
105             " 'use integer' and $MAX_EXP_F without 'use integer'. The",
106             " requested settings, a base length of $base_len ",
107             $use_int ? "with" : "without", " 'use integer', is invalid.";
108             }
109              
110 57         151 $BASE_LEN = $base_len;
111 57         281 $BASE = 0 + ("1" . ("0" x $BASE_LEN));
112 57         133 $MAX_VAL = $BASE - 1;
113 57 100       199 $USE_INT = $use_int ? 1 : 0;
114              
115             {
116 50     50   519 no warnings "redefine";
  50         168  
  50         53067  
  57         136  
117 57 100       222 if ($use_int) {
118 56         282 *_mul = \&_mul_use_int;
119 56         200 *_div = \&_div_use_int;
120             } else {
121 1         5 *_mul = \&_mul_no_int;
122 1         3 *_div = \&_div_no_int;
123             }
124             }
125             }
126              
127             # Find max bits. This is the largest power of two that is both no larger
128             # than $BASE and no larger than the maximum integer (i.e., ~0). We need
129             # this limitation because _and(), _or(), and _xor() only work on one
130             # element at a time.
131              
132 68         161 my $umax = ~0; # largest unsigned integer
133 68 50       271 my $tmp = $umax < $BASE ? $umax : $BASE;
134              
135 68         152 $MAX_BITS = 0;
136 68         541 while ($tmp >>= 1) {
137 1920         3362 $MAX_BITS++;
138             }
139              
140             # Limit to 32 bits for portability. Is this really necessary? XXX
141              
142 68 50       289 $MAX_BITS = 32 if $MAX_BITS > 32;
143              
144             # Find out how many bits _and, _or and _xor can take (old default = 16).
145             # Are these tests really necessary? Can't we just use $MAX_BITS? XXX
146              
147 68         314 for ($AND_BITS = $MAX_BITS ; $AND_BITS > 0 ; $AND_BITS--) {
148 68         787 my $x = CORE::oct('0b' . '1' x $AND_BITS);
149 68         167 my $y = $x & $x;
150 68         254 my $z = 2 * (2 ** ($AND_BITS - 1)) + 1;
151 68 0 33     373 last unless $AND_BITS < $MAX_BITS && $x == $z && $y == $x;
      33        
152             }
153              
154 68         219 for ($XOR_BITS = $MAX_BITS ; $XOR_BITS > 0 ; $XOR_BITS--) {
155 68         249 my $x = CORE::oct('0b' . '1' x $XOR_BITS);
156 68         194 my $y = $x ^ $x;
157 68         170 my $z = 2 * (2 ** ($XOR_BITS - 1)) + 1;
158 68 0 33     281 last unless $XOR_BITS < $MAX_BITS && $x == $z && $y == $x;
      33        
159             }
160              
161 68         238 for ($OR_BITS = $MAX_BITS ; $OR_BITS > 0 ; $OR_BITS--) {
162 68         287 my $x = CORE::oct('0b' . '1' x $OR_BITS);
163 68         153 my $y = $x | $x;
164 68         210 my $z = 2 * (2 ** ($OR_BITS - 1)) + 1;
165 68 0 33     296 last unless $OR_BITS < $MAX_BITS && $x == $z && $y == $x;
      33        
166             }
167              
168 68         454 $AND_MASK = __PACKAGE__->_new(( 2 ** $AND_BITS ));
169 68         302 $XOR_MASK = __PACKAGE__->_new(( 2 ** $XOR_BITS ));
170 68         253 $OR_MASK = __PACKAGE__->_new(( 2 ** $OR_BITS ));
171              
172 68 100       65136 return $BASE_LEN unless wantarray;
173 6         42 return ($BASE_LEN, $BASE, $AND_BITS, $XOR_BITS, $OR_BITS, $BASE_LEN, $MAX_VAL,
174             $MAX_BITS, $MAX_EXP_F, $MAX_EXP_I, $USE_INT);
175             }
176              
177             sub _new {
178             # Given a string representing an integer, returns a reference to an array
179             # of integers, where each integer represents a chunk of the original input
180             # integer.
181              
182 225682     225682   620849 my ($class, $str) = @_;
183             #unless ($str =~ /^([1-9]\d*|0)\z/) {
184             # croak("Invalid input string '$str'");
185             #}
186              
187 225682         415429 my $input_len = length($str) - 1;
188              
189             # Shortcut for small numbers.
190 225682 100       919381 return bless [ $str ], $class if $input_len < $BASE_LEN;
191              
192 31058         79634 my $format = "a" . (($input_len % $BASE_LEN) + 1);
193 31058 50       91818 $format .= $] < 5.008 ? "a$BASE_LEN" x int($input_len / $BASE_LEN)
194             : "(a$BASE_LEN)*";
195              
196 31058         206689 my $self = [ reverse(map { 0 + $_ } unpack($format, $str)) ];
  241939         558425  
197 31058         153648 return bless $self, $class;
198             }
199              
200             BEGIN {
201              
202             # Compute $MAX_EXP_F, the maximum usable base 10 exponent.
203              
204             # The largest element in base 10**$BASE_LEN is 10**$BASE_LEN-1. For instance,
205             # with $BASE_LEN = 5, the largest element is 99_999, and the largest carry is
206             #
207             # int( 99_999 * 99_999 / 100_000 ) = 99_998
208             #
209             # so make sure that 99_999 * 99_999 + 99_998 is within the range of integers
210             # that can be represented accuratly.
211             #
212             # Note that on some systems with quadmath support, the following is within
213             # the range of numbers that can be represented exactly, but it still gives
214             # the incorrect value $r = 2 (even though POSIX::fmod($x, $y) gives the
215             # correct value of 1:
216             #
217             # $x = 99999999999999999;
218             # $y = 100000000000000000;
219             # $r = $x * $x % $y; # should be 1
220             #
221             # so also check for this.
222              
223 50     50   310 for ($MAX_EXP_F = 1 ; ; $MAX_EXP_F++) { # when $MAX_EXP_F = 5
224 500         803 my $MAX_EXP_FM1 = $MAX_EXP_F - 1; # = 4
225 500         882 my $bs = "1" . ("0" x $MAX_EXP_F); # = "100000"
226 500         803 my $xs = "9" x $MAX_EXP_F; # = "99999"
227 500         832 my $cs = ("9" x $MAX_EXP_FM1) . "8"; # = "99998"
228 500         862 my $ys = $cs . ("0" x $MAX_EXP_FM1) . "1"; # = "9999800001"
229              
230             # Compute and check the product.
231 500         877 my $yn = $xs * $xs; # = 9999800001
232 500 50       1243 last if $yn != $ys;
233              
234             # Compute and check the remainder.
235 500         789 my $rn = $yn % $bs; # = 1
236 500 100       1077 last if $rn != 1;
237              
238             # Compute and check the carry. The division here is exact.
239 450         1094 my $cn = ($yn - $rn) / $bs; # = 99998
240 450 50       1159 last if $cn != $cs;
241              
242             # Compute and check product plus carry.
243 450         837 my $zs = $cs . ("9" x $MAX_EXP_F); # = "9999899999"
244 450         707 my $zn = $yn + $cn; # = 99998999999
245 450 50       838 last if $zn != $zs;
246 450 50       1005 last if $zn - ($zn - 1) != 1;
247             }
248 50         214 $MAX_EXP_F--; # last test failed, so retract one step
249              
250             # Compute $MAX_EXP_I, the maximum usable base 10 exponent within the range
251             # of what is available with "use integer". On older versions of Perl,
252             # integers are converted to floating point numbers, even though they are
253             # within the range of what can be represented as integers. For example, on
254             # some 64 bit Perls, 999999999 * 999999999 becomes 999999998000000000, not
255             # 999999998000000001, even though the latter is less than the maximum value
256             # for a 64 bit integer, 18446744073709551615.
257              
258 50         100 my $umax = ~0; # largest unsigned integer
259 50         317 for ($MAX_EXP_I = int(0.5 * log($umax) / log(10));
260             $MAX_EXP_I > 0;
261             $MAX_EXP_I--)
262             { # when $MAX_EXP_I = 5
263 50         209 my $MAX_EXP_IM1 = $MAX_EXP_I - 1; # = 4
264 50         161 my $bs = "1" . ("0" x $MAX_EXP_I); # = "100000"
265 50         139 my $xs = "9" x $MAX_EXP_I; # = "99999"
266 50         254 my $cs = ("9" x $MAX_EXP_IM1) . "8"; # = "99998"
267 50         161 my $ys = $cs . ("0" x $MAX_EXP_IM1) . "1"; # = "9999800001"
268              
269             # Compute and check the product.
270 50         124 my $yn = $xs * $xs; # = 9999800001
271 50 50       230 next if $yn != $ys;
272              
273             # Compute and check the remainder.
274 50         106 my $rn = $yn % $bs; # = 1
275 50 50       200 next if $rn != 1;
276              
277             # Compute and check the carry. The division here is exact.
278 50         108 my $cn = ($yn - $rn) / $bs; # = 99998
279 50 50       200 next if $cn != $cs;
280              
281             # Compute and check product plus carry.
282 50         159 my $zs = $cs . ("9" x $MAX_EXP_I); # = "9999899999"
283 50         107 my $zn = $yn + $cn; # = 99998999999
284 50 50       258 next if $zn != $zs;
285 50 50       175 next if $zn - ($zn - 1) != 1;
286 50         116 last;
287             }
288              
289 50 50       267 ($BASE_LEN, $USE_INT) = $MAX_EXP_F > $MAX_EXP_I
290             ? ($MAX_EXP_F, 0) : ($MAX_EXP_I, 1);
291              
292 50         416 __PACKAGE__ -> _base_len($BASE_LEN, $USE_INT);
293             }
294              
295             ###############################################################################
296              
297             sub _zero {
298             # create a zero
299 49190     49190   83352 my $class = shift;
300 49190         175218 return bless [ 0 ], $class;
301             }
302              
303             sub _one {
304             # create a one
305 15062     15062   26425 my $class = shift;
306 15062         46109 return bless [ 1 ], $class;
307             }
308              
309             sub _two {
310             # create a two
311 1946     1946   3599 my $class = shift;
312 1946         7459 return bless [ 2 ], $class;
313             }
314              
315             sub _ten {
316             # create a 10
317 34034     34034   58742 my $class = shift;
318 34034 50       83576 my $self = $BASE_LEN == 1 ? [ 0, 1 ] : [ 10 ];
319 34034         116265 bless $self, $class;
320             }
321              
322             sub _1ex {
323             # create a 1Ex
324 1035     1035   1704 my $class = shift;
325              
326 1035         2041 my $rem = $_[0] % $BASE_LEN; # remainder
327 1035         2279 my $div = ($_[0] - $rem) / $BASE_LEN; # parts
328              
329             # With a $BASE_LEN of 6, 1e14 becomes
330             # [ 000000, 000000, 100 ] -> [ 0, 0, 100 ]
331 1035         4792 bless [ (0) x $div, 0 + ("1" . ("0" x $rem)) ], $class;
332             }
333              
334             sub _copy {
335             # make a true copy
336 146683     146683   229130 my $class = shift;
337 146683         202832 return bless [ @{ $_[0] } ], $class;
  146683         488314  
338             }
339              
340             sub import {
341 7     7   247 my $self = shift;
342              
343 7         19 my $opts;
344 7         18 my ($base_len, $use_int);
345 7         34 while (@_) {
346 2         24 my $param = shift;
347 2 50 33     15 croak "Parameter name must be a non-empty string"
348             unless defined $param && length $param;
349 2 50       5 croak "Missing value for parameter '$param'"
350             unless @_;
351 2         5 my $value = shift;
352              
353 2 50 66     13 if ($param eq 'base_len' || $param eq 'use_int') {
354 2         6 $opts -> {$param} = $value;
355 2         8 next;
356             }
357              
358 0         0 croak "Unknown parameter '$param'";
359             }
360              
361 7 100       38 $base_len = exists $opts -> {base_len} ? $opts -> {base_len} : $BASE_LEN;
362 7 100       24 $use_int = exists $opts -> {use_int} ? $opts -> {use_int} : $USE_INT;
363 7         37 __PACKAGE__ -> _base_len($base_len, $use_int);
364              
365 7         7459 return $self;
366             }
367              
368             ##############################################################################
369             # convert back to string and number
370              
371             sub _str {
372             # Convert number from internal base 1eN format to string format. Internal
373             # format is always normalized, i.e., no leading zeros.
374              
375 80619     80619   149231 my $ary = $_[1];
376 80619         149249 my $idx = $#$ary; # index of last element
377              
378 80619 50       190573 if ($idx < 0) { # should not happen
379 0         0 croak("$_[1] has no elements");
380             }
381              
382             # Handle first one differently, since it should not have any leading zeros.
383 80619         157918 my $ret = int($ary->[$idx]);
384 80619 100       176471 if ($idx > 0) {
385             # Interestingly, the pre-padd method uses more time.
386             # The old grep variant takes longer (14 vs. 10 sec).
387 31085         84700 my $z = '0' x ($BASE_LEN - 1);
388 31085         74444 while (--$idx >= 0) {
389 212019         633490 $ret .= substr($z . $ary->[$idx], -$BASE_LEN);
390             }
391             }
392 80619         218169 $ret;
393             }
394              
395             sub _num {
396             # Make a Perl scalar number (int/float) from a BigInt object.
397 82108     82108   142680 my $x = $_[1];
398              
399 82108 100       276414 return $x->[0] if @$x == 1; # below $BASE
400              
401             # Start with the most significant element and work towards the least
402             # significant element. Avoid multiplying "inf" (which happens if the number
403             # overflows) with "0" (if there are zero elements in $x) since this gives
404             # "nan" which propagates to the output.
405              
406 16         40 my $num = 0;
407 16         78 for (my $i = $#$x ; $i >= 0 ; --$i) {
408 41         73 $num *= $BASE;
409 41         103 $num += $x -> [$i];
410             }
411 16         48 return $num;
412             }
413              
414             ##############################################################################
415             # actual math code
416              
417             sub _add {
418             # (ref to int_num_array, ref to int_num_array)
419             #
420             # Routine to add two base 1eX numbers stolen from Knuth Vol 2 Algorithm A
421             # pg 231. There are separate routines to add and sub as per Knuth pg 233.
422             # This routine modifies array x, but not y.
423              
424 61736     61736   124374 my ($c, $x, $y) = @_;
425              
426             # $x + 0 => $x
427              
428 61736 100 100     237615 return $x if @$y == 1 && $y->[0] == 0;
429              
430             # 0 + $y => $y->copy
431              
432 54410 100 100     177570 if (@$x == 1 && $x->[0] == 0) {
433 8892         23974 @$x = @$y;
434 8892         22127 return $x;
435             }
436              
437             # For each in Y, add Y to X and carry. If after that, something is left in
438             # X, foreach in X add carry to X and then return X, carry. Trades one
439             # "$j++" for having to shift arrays.
440              
441 45518         70899 my $car = 0;
442 45518         66254 my $j = 0;
443 45518         85198 for my $i (@$y) {
444 84477 100       230174 $x->[$j] -= $BASE if $car = (($x->[$j] += $i + $car) >= $BASE) ? 1 : 0;
    100          
445 84477         135566 $j++;
446             }
447 45518         107226 while ($car != 0) {
448 394 100       2177 $x->[$j] -= $BASE if $car = (($x->[$j] += $car) >= $BASE) ? 1 : 0;
    100          
449 394         1050 $j++;
450             }
451 45518         130699 $x;
452             }
453              
454             sub _inc {
455             # (ref to int_num_array, ref to int_num_array)
456             # Add 1 to $x, modify $x in place
457 5396     5396   12629 my ($c, $x) = @_;
458              
459 5396         11376 for my $i (@$x) {
460 5409 100       20203 return $x if ($i += 1) < $BASE; # early out
461 18         39 $i = 0; # overflow, next
462             }
463 5 50       67 push @$x, 1 if $x->[-1] == 0; # last overflowed, so extend
464 5         19 $x;
465             }
466              
467             sub _dec {
468             # (ref to int_num_array, ref to int_num_array)
469             # Sub 1 from $x, modify $x in place
470 730     730   2088 my ($c, $x) = @_;
471              
472 730         1529 my $MAX = $BASE - 1; # since MAX_VAL based on BASE
473 730         1832 for my $i (@$x) {
474 746 100       2643 last if ($i -= 1) >= 0; # early out
475 16         25 $i = $MAX; # underflow, next
476             }
477 730 100 100     2690 pop @$x if $x->[-1] == 0 && @$x > 1; # last underflowed (but leave 0)
478 730         1724 $x;
479             }
480              
481             sub _sub {
482             # (ref to int_num_array, ref to int_num_array, swap)
483             #
484             # Subtract base 1eX numbers -- stolen from Knuth Vol 2 pg 232, $x > $y
485             # subtract Y from X by modifying x in place
486 62881     62881   147236 my ($c, $sx, $sy, $s) = @_;
487              
488 62881         104528 my $car = 0;
489 62881         93113 my $j = 0;
490 62881 100       154178 if (!$s) {
491 55276         122459 for my $i (@$sx) {
492 73032 100 100     199933 last unless defined $sy->[$j] || $car;
493 71486 100 100     254041 $i += $BASE if $car = (($i -= ($sy->[$j] || 0) + $car) < 0);
494 71486         123897 $j++;
495             }
496             # might leave leading zeros, so fix that
497 55276         129101 return __strip_zeros($sx);
498             }
499 7605         17516 for my $i (@$sx) {
500             # We can't do an early out if $x < $y, since we need to copy the high
501             # chunks from $y. Found by Bob Mathews.
502             #last unless defined $sy->[$j] || $car;
503 7711 100 100     38195 $sy->[$j] += $BASE
504             if $car = ($sy->[$j] = $i - ($sy->[$j] || 0) - $car) < 0;
505 7711         15555 $j++;
506             }
507             # might leave leading zeros, so fix that
508 7605         18696 __strip_zeros($sy);
509             }
510              
511             sub _mul_use_int {
512             # (ref to int_num_array, ref to int_num_array)
513             # multiply two numbers in internal representation
514             # modifies first arg, second need not be different from first
515             # works for 64 bit integer with "use integer"
516 61453     61453   135412 my ($c, $xv, $yv) = @_;
517 50     50   33355 use integer;
  50         817  
  50         295  
518              
519 61453 100       147967 if (@$yv == 1) {
520             # shortcut for two very short numbers (improved by Nathan Zook) works
521             # also if xv and yv are the same reference, and handles also $x == 0
522 48506 100       103010 if (@$xv == 1) {
523 37661 100       101017 if (($xv->[0] *= $yv->[0]) >= $BASE) {
524 1339         5194 $xv->[0] =
525             $xv->[0] - ($xv->[1] = $xv->[0] / $BASE) * $BASE;
526             }
527 37661         95481 return $xv;
528             }
529             # $x * 0 => 0
530 10845 100       29963 if ($yv->[0] == 0) {
531 15         61 @$xv = (0);
532 15         62 return $xv;
533             }
534              
535             # multiply a large number a by a single element one, so speed up
536 10830         23315 my $y = $yv->[0];
537 10830         16996 my $car = 0;
538 10830         24495 foreach my $i (@$xv) {
539             #$i = $i * $y + $car; $car = $i / $BASE; $i -= $car * $BASE;
540 59824         86254 $i = $i * $y + $car;
541 59824         100319 $i -= ($car = $i / $BASE) * $BASE;
542             }
543 10830 100       26830 push @$xv, $car if $car != 0;
544 10830         34318 return $xv;
545             }
546              
547             # shortcut for result $x == 0 => result = 0
548 12947 100 100     40238 return $xv if @$xv == 1 && $xv->[0] == 0;
549              
550             # since multiplying $x with $x fails, make copy in this case
551 12678 100       50271 $yv = $c->_copy($xv) if $xv == $yv; # same references?
552              
553 12678         26165 my @prod = ();
554 12678         21537 my ($prod, $car, $cty);
555 12678         26850 for my $xi (@$xv) {
556 58564         82061 $car = 0;
557 58564         78746 $cty = 0;
558             # looping through this if $xi == 0 is silly - so optimize it away!
559 58564 100 100     131323 $xi = (shift(@prod) || 0), next if $xi == 0;
560 56972         91447 for my $yi (@$yv) {
561 803888   100     1543512 $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
562 803888         1311375 $prod[$cty++] = $prod - ($car = $prod / $BASE) * $BASE;
563             }
564 56972 100       113262 $prod[$cty] += $car if $car; # need really to check for 0?
565 56972   100     134949 $xi = shift(@prod) || 0; # || 0 makes v5.005_3 happy
566             }
567 12678         33484 push @$xv, @prod;
568 12678         47785 $xv;
569             }
570              
571             sub _mul_no_int {
572             # (ref to int_num_array, ref to int_num_array)
573             # multiply two numbers in internal representation
574             # modifies first arg, second need not be different from first
575 0     0   0 my ($c, $xv, $yv) = @_;
576              
577 0 0       0 if (@$yv == 1) {
578             # shortcut for two very short numbers (improved by Nathan Zook) works
579             # also if xv and yv are the same reference, and handles also $x == 0
580 0 0       0 if (@$xv == 1) {
581 0 0       0 if (($xv->[0] *= $yv->[0]) >= $BASE) {
582 0         0 my $rem = $xv->[0] % $BASE;
583 0         0 $xv->[1] = ($xv->[0] - $rem) / $BASE;
584 0         0 $xv->[0] = $rem;
585             }
586 0         0 return $xv;
587             }
588             # $x * 0 => 0
589 0 0       0 if ($yv->[0] == 0) {
590 0         0 @$xv = (0);
591 0         0 return $xv;
592             }
593              
594             # multiply a large number a by a single element one, so speed up
595 0         0 my $y = $yv->[0];
596 0         0 my $car = 0;
597 0         0 my $rem;
598 0         0 foreach my $i (@$xv) {
599 0         0 $i = $i * $y + $car;
600 0         0 $rem = $i % $BASE;
601 0         0 $car = ($i - $rem) / $BASE;
602 0         0 $i = $rem;
603             }
604 0 0       0 push @$xv, $car if $car != 0;
605 0         0 return $xv;
606             }
607              
608             # shortcut for result $x == 0 => result = 0
609 0 0 0     0 return $xv if @$xv == 1 && $xv->[0] == 0;
610              
611             # since multiplying $x with $x fails, make copy in this case
612 0 0       0 $yv = $c->_copy($xv) if $xv == $yv; # same references?
613              
614 0         0 my @prod = ();
615 0         0 my ($prod, $rem, $car, $cty);
616 0         0 for my $xi (@$xv) {
617 0         0 $car = 0;
618 0         0 $cty = 0;
619             # looping through this if $xi == 0 is silly - so optimize it away!
620 0 0 0     0 $xi = (shift(@prod) || 0), next if $xi == 0;
621 0         0 for my $yi (@$yv) {
622 0   0     0 $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
623 0         0 $rem = $prod % $BASE;
624 0         0 $car = ($prod - $rem) / $BASE;
625 0         0 $prod[$cty++] = $rem;
626             }
627 0 0       0 $prod[$cty] += $car if $car; # need really to check for 0?
628 0   0     0 $xi = shift(@prod) || 0; # || 0 makes v5.005_3 happy
629             }
630 0         0 push @$xv, @prod;
631 0         0 $xv;
632             }
633              
634             sub _div_use_int {
635             # ref to array, ref to array, modify first array and return remainder if
636             # in list context
637              
638             # This version works on integers
639 50     50   36847 use integer;
  50         103  
  50         260  
640              
641 24404     24404   56134 my ($c, $x, $yorg) = @_;
642              
643             # the general div algorithm here is about O(N*N) and thus quite slow, so
644             # we first check for some special cases and use shortcuts to handle them.
645              
646             # if both numbers have only one element:
647 24404 100 100     77746 if (@$x == 1 && @$yorg == 1) {
648             # shortcut, $yorg and $x are two small numbers
649 9003 100       17297 if (wantarray) {
650 3918         10640 my $rem = [ $x->[0] % $yorg->[0] ];
651 3918         7690 bless $rem, $c;
652 3918         10331 $x->[0] = $x->[0] / $yorg->[0];
653 3918         12437 return ($x, $rem);
654             } else {
655 5085         10337 $x->[0] = $x->[0] / $yorg->[0];
656 5085         12342 return $x;
657             }
658             }
659              
660             # if x has more than one, but y has only one element:
661 15401 100       36662 if (@$yorg == 1) {
662 4201         6675 my $rem;
663 4201 100       21869 $rem = $c->_mod($c->_copy($x), $yorg) if wantarray;
664              
665             # shortcut, $y is < $BASE
666 4201         7623 my $j = @$x;
667 4201         6965 my $r = 0;
668 4201         8960 my $y = $yorg->[0];
669 4201         6527 my $b;
670 4201         11947 while ($j-- > 0) {
671 28892         42839 $b = $r * $BASE + $x->[$j];
672 28892         42142 $r = $b % $y;
673 28892         56641 $x->[$j] = $b / $y;
674             }
675 4201 100 66     20042 pop(@$x) if @$x > 1 && $x->[-1] == 0; # remove any trailing zero
676 4201 100       10771 return ($x, $rem) if wantarray;
677 3827         12591 return $x;
678             }
679              
680             # now x and y have more than one element
681              
682             # check whether y has more elements than x, if so, the result is 0
683 11200 100       29648 if (@$yorg > @$x) {
684 261         368 my $rem;
685 261 100       1002 $rem = $c->_copy($x) if wantarray; # make copy
686 261         753 @$x = 0; # set to 0
687 261 100       10541 return ($x, $rem) if wantarray; # including remainder?
688 1         4 return $x; # only x, which is [0] now
689             }
690              
691             # check whether the numbers have the same number of elements, in that case
692             # the result will fit into one element and can be computed efficiently
693 10939 100       28694 if (@$yorg == @$x) {
694 1962         3005 my $cmp = 0;
695 1962         5291 for (my $j = $#$x ; $j >= 0 ; --$j) {
696 2146 100       5758 last if $cmp = $x->[$j] - $yorg->[$j];
697             }
698              
699 1962 100       4053 if ($cmp == 0) { # x = y
700 20         67 @$x = 1;
701 20 100       102 return $x, $c->_zero() if wantarray;
702 8         44 return $x;
703             }
704              
705 1942 100       4716 if ($cmp < 0) { # x < y
706 407 100       1321 if (wantarray) {
707 86         296 my $rem = $c->_copy($x);
708 86         291 @$x = 0;
709 86         307 return $x, $rem;
710             }
711 321         965 @$x = 0;
712 321         863 return $x;
713             }
714             }
715              
716             # all other cases:
717              
718 10512         27290 my $y = $c->_copy($yorg); # always make copy to preserve
719              
720 10512         17151 my $tmp;
721 10512         23670 my $dd = $BASE / ($y->[-1] + 1);
722 10512 100       22565 if ($dd != 1) {
723 10326         15930 my $car = 0;
724 10326         33159 for my $xi (@$x) {
725 108683         145951 $xi = $xi * $dd + $car;
726 108683         167910 $xi -= ($car = $xi / $BASE) * $BASE;
727             }
728 10326         21594 push(@$x, $car);
729 10326         15527 $car = 0;
730 10326         18528 for my $yi (@$y) {
731 52695         71711 $yi = $yi * $dd + $car;
732 52695         82526 $yi -= ($car = $yi / $BASE) * $BASE;
733             }
734             } else {
735 186         570 push(@$x, 0);
736             }
737              
738             # @q will accumulate the final result, $q contains the current computed
739             # part of the final result
740              
741 10512         19347 my @q = ();
742 10512         27617 my ($v2, $v1) = @$y[-2, -1];
743 10512 100       24332 $v2 = 0 unless $v2;
744 10512         28723 while ($#$x > $#$y) {
745 68010         151954 my ($u2, $u1, $u0) = @$x[-3 .. -1];
746 68010 100       126798 $u2 = 0 unless $u2;
747             #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"
748             # if $v1 == 0;
749 68010         101037 my $tmp = $u0 * $BASE + $u1;
750 68010         99126 my $rem = $tmp % $v1;
751 68010 100       129255 my $q = $u0 == $v1 ? $MAX_VAL : (($tmp - $rem) / $v1);
752 68010         165456 --$q while $v2 * $q > ($u0 * $BASE + $u1 - $q * $v1) * $BASE + $u2;
753 68010 100       130336 if ($q) {
754 62311         83016 my $prd;
755 62311         102650 my ($car, $bar) = (0, 0);
756 62311         156770 for (my $yi = 0, my $xi = $#$x - $#$y - 1; $yi <= $#$y; ++$yi, ++$xi) {
757 1108759         1622919 $prd = $q * $y->[$yi] + $car;
758 1108759         1605697 $prd -= ($car = int($prd / $BASE)) * $BASE;
759 1108759 100       3126586 $x->[$xi] += $BASE if $bar = (($x->[$xi] -= $prd + $bar) < 0);
760             }
761 62311 100       143274 if ($x->[-1] < $car + $bar) {
762 24         53 $car = 0;
763 24         43 --$q;
764 24         205 for (my $yi = 0, my $xi = $#$x - $#$y - 1; $yi <= $#$y; ++$yi, ++$xi) {
765 121 100       400 $x->[$xi] -= $BASE
766             if $car = (($x->[$xi] += $y->[$yi] + $car) >= $BASE);
767             }
768             }
769             }
770 68010         100785 pop(@$x);
771 68010         184661 unshift(@q, $q);
772             }
773              
774 10512 100       23941 if (wantarray) {
775 3619         8065 my $d = bless [], $c;
776 3619 100       6809 if ($dd != 1) {
777 3577         4998 my $car = 0;
778 3577         4710 my $prd;
779 3577         6168 for my $xi (reverse @$x) {
780 11911         15698 $prd = $car * $BASE + $xi;
781 11911         15731 $car = $prd - ($tmp = $prd / $dd) * $dd;
782 11911         20326 unshift @$d, $tmp;
783             }
784             } else {
785 42         146 @$d = @$x;
786             }
787 3619         8203 @$x = @q;
788 3619         8995 __strip_zeros($x);
789 3619         7234 __strip_zeros($d);
790 3619         13548 return ($x, $d);
791             }
792 6893         25725 @$x = @q;
793 6893         24022 __strip_zeros($x);
794 6893         37685 $x;
795             }
796              
797             sub _div_no_int {
798             # ref to array, ref to array, modify first array and return remainder if
799             # in list context
800              
801 0     0   0 my ($c, $x, $yorg) = @_;
802              
803             # the general div algorithm here is about O(N*N) and thus quite slow, so
804             # we first check for some special cases and use shortcuts to handle them.
805              
806             # if both numbers have only one element:
807 0 0 0     0 if (@$x == 1 && @$yorg == 1) {
808             # shortcut, $yorg and $x are two small numbers
809 0         0 my $rem = [ $x->[0] % $yorg->[0] ];
810 0         0 bless $rem, $c;
811 0         0 $x->[0] = ($x->[0] - $rem->[0]) / $yorg->[0];
812 0 0       0 return ($x, $rem) if wantarray;
813 0         0 return $x;
814             }
815              
816             # if x has more than one, but y has only one element:
817 0 0       0 if (@$yorg == 1) {
818 0         0 my $rem;
819 0 0       0 $rem = $c->_mod($c->_copy($x), $yorg) if wantarray;
820              
821             # shortcut, $y is < $BASE
822 0         0 my $j = @$x;
823 0         0 my $r = 0;
824 0         0 my $y = $yorg->[0];
825 0         0 my $b;
826 0         0 while ($j-- > 0) {
827 0         0 $b = $r * $BASE + $x->[$j];
828 0         0 $r = $b % $y;
829 0         0 $x->[$j] = ($b - $r) / $y;
830             }
831 0 0 0     0 pop(@$x) if @$x > 1 && $x->[-1] == 0; # remove any trailing zero
832 0 0       0 return ($x, $rem) if wantarray;
833 0         0 return $x;
834             }
835              
836             # now x and y have more than one element
837              
838             # check whether y has more elements than x, if so, the result is 0
839 0 0       0 if (@$yorg > @$x) {
840 0         0 my $rem;
841 0 0       0 $rem = $c->_copy($x) if wantarray; # make copy
842 0         0 @$x = 0; # set to 0
843 0 0       0 return ($x, $rem) if wantarray; # including remainder?
844 0         0 return $x; # only x, which is [0] now
845             }
846              
847             # check whether the numbers have the same number of elements, in that case
848             # the result will fit into one element and can be computed efficiently
849 0 0       0 if (@$yorg == @$x) {
850 0         0 my $cmp = 0;
851 0         0 for (my $j = $#$x ; $j >= 0 ; --$j) {
852 0 0       0 last if $cmp = $x->[$j] - $yorg->[$j];
853             }
854              
855 0 0       0 if ($cmp == 0) { # x = y
856 0         0 @$x = 1;
857 0 0       0 return $x, $c->_zero() if wantarray;
858 0         0 return $x;
859             }
860              
861 0 0       0 if ($cmp < 0) { # x < y
862 0 0       0 if (wantarray) {
863 0         0 my $rem = $c->_copy($x);
864 0         0 @$x = 0;
865 0         0 return $x, $rem;
866             }
867 0         0 @$x = 0;
868 0         0 return $x;
869             }
870             }
871              
872             # all other cases:
873              
874 0         0 my $y = $c->_copy($yorg); # always make copy to preserve
875              
876 0         0 my $tmp = $y->[-1] + 1;
877 0         0 my $rem = $BASE % $tmp;
878 0         0 my $dd = ($BASE - $rem) / $tmp;
879 0 0       0 if ($dd != 1) {
880 0         0 my $car = 0;
881 0         0 for my $xi (@$x) {
882 0         0 $xi = $xi * $dd + $car;
883 0         0 $rem = $xi % $BASE;
884 0         0 $car = ($xi - $rem) / $BASE;
885 0         0 $xi = $rem;
886             }
887 0         0 push(@$x, $car);
888 0         0 $car = 0;
889 0         0 for my $yi (@$y) {
890 0         0 $yi = $yi * $dd + $car;
891 0         0 $rem = $yi % $BASE;
892 0         0 $car = ($yi - $rem) / $BASE;
893 0         0 $yi = $rem;
894             }
895             } else {
896 0         0 push(@$x, 0);
897             }
898              
899             # @q will accumulate the final result, $q contains the current computed
900             # part of the final result
901              
902 0         0 my @q = ();
903 0         0 my ($v2, $v1) = @$y[-2, -1];
904 0 0       0 $v2 = 0 unless $v2;
905 0         0 while ($#$x > $#$y) {
906 0         0 my ($u2, $u1, $u0) = @$x[-3 .. -1];
907 0 0       0 $u2 = 0 unless $u2;
908             #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"
909             # if $v1 == 0;
910 0         0 my $tmp = $u0 * $BASE + $u1;
911 0         0 my $rem = $tmp % $v1;
912 0 0       0 my $q = $u0 == $v1 ? $MAX_VAL : (($tmp - $rem) / $v1);
913 0         0 --$q while $v2 * $q > ($u0 * $BASE + $u1 - $q * $v1) * $BASE + $u2;
914 0 0       0 if ($q) {
915 0         0 my $prd;
916 0         0 my ($car, $bar) = (0, 0);
917 0         0 for (my $yi = 0, my $xi = $#$x - $#$y - 1; $yi <= $#$y; ++$yi, ++$xi) {
918 0         0 $prd = $q * $y->[$yi] + $car;
919 0         0 $rem = $prd % $BASE;
920 0         0 $car = ($prd - $rem) / $BASE;
921 0         0 $prd -= $car * $BASE;
922 0 0       0 $x->[$xi] += $BASE if $bar = (($x->[$xi] -= $prd + $bar) < 0);
923             }
924 0 0       0 if ($x->[-1] < $car + $bar) {
925 0         0 $car = 0;
926 0         0 --$q;
927 0         0 for (my $yi = 0, my $xi = $#$x - $#$y - 1; $yi <= $#$y; ++$yi, ++$xi) {
928 0 0       0 $x->[$xi] -= $BASE
929             if $car = (($x->[$xi] += $y->[$yi] + $car) >= $BASE);
930             }
931             }
932             }
933 0         0 pop(@$x);
934 0         0 unshift(@q, $q);
935             }
936              
937 0 0       0 if (wantarray) {
938 0         0 my $d = bless [], $c;
939 0 0       0 if ($dd != 1) {
940 0         0 my $car = 0;
941 0         0 my ($prd, $rem);
942 0         0 for my $xi (reverse @$x) {
943 0         0 $prd = $car * $BASE + $xi;
944 0         0 $rem = $prd % $dd;
945 0         0 $tmp = ($prd - $rem) / $dd;
946 0         0 $car = $rem;
947 0         0 unshift @$d, $tmp;
948             }
949             } else {
950 0         0 @$d = @$x;
951             }
952 0         0 @$x = @q;
953 0         0 __strip_zeros($x);
954 0         0 __strip_zeros($d);
955 0         0 return ($x, $d);
956             }
957 0         0 @$x = @q;
958 0         0 __strip_zeros($x);
959 0         0 $x;
960             }
961              
962             ##############################################################################
963             # testing
964              
965             sub _acmp {
966             # Internal absolute post-normalized compare (ignore signs)
967             # ref to array, ref to array, return <0, 0, >0
968             # Arrays must have at least one entry; this is not checked for.
969 126859     126859   282819 my ($c, $cx, $cy) = @_;
970              
971             # shortcut for short numbers
972 126859 100 100     615402 return (($cx->[0] <=> $cy->[0]) <=> 0)
973             if @$cx == 1 && @$cy == 1;
974              
975             # fast comp based on number of array elements (aka pseudo-length)
976 19821   100     86651 my $lxy = (@$cx - @$cy)
977             # or length of first element if same number of elements (aka difference 0)
978             ||
979             # need int() here because sometimes the last element is '00018' vs '18'
980             (length(int($cx->[-1])) - length(int($cy->[-1])));
981              
982 19821 100       53211 return -1 if $lxy < 0; # already differs, ret
983 16996 100       47663 return 1 if $lxy > 0; # ditto
984              
985             # manual way (abort if unequal, good for early ne)
986 13311         20412 my $a;
987 13311         22418 my $j = @$cx;
988 13311         31638 while (--$j >= 0) {
989 39937 100       111866 last if $a = $cx->[$j] - $cy->[$j];
990             }
991 13311         64869 $a <=> 0;
992             }
993              
994             sub _len {
995             # compute number of digits in base 10
996              
997             # int() because add/sub sometimes leaves strings (like '00005') instead of
998             # '5' in this place, thus causing length() to report wrong length
999 115243     115243   188193 my $cx = $_[1];
1000              
1001 115243         415211 (@$cx - 1) * $BASE_LEN + length(int($cx->[-1]));
1002             }
1003              
1004             sub _digit {
1005             # Return the nth digit. Zero is rightmost, so _digit(123, 0) gives 3.
1006             # Negative values count from the left, so _digit(123, -1) gives 1.
1007 141     141   339 my ($c, $x, $n) = @_;
1008              
1009 141         398 my $len = _len('', $x);
1010              
1011 141 100       378 $n += $len if $n < 0; # -1 last, -2 second-to-last
1012              
1013             # Math::BigInt::Calc returns 0 if N is out of range, but this is not done
1014             # by the other backend libraries.
1015              
1016 141 100 100     608 return "0" if $n < 0 || $n >= $len; # return 0 for digits out of range
1017              
1018 135         326 my $elem = int($n / $BASE_LEN); # index of array element
1019 135         237 my $digit = $n % $BASE_LEN; # index of digit within the element
1020 135         1962 substr("0" x $BASE_LEN . "$x->[$elem]", -1 - $digit, 1);
1021             }
1022              
1023             sub _zeros {
1024             # Return number of trailing zeros in decimal.
1025             # Check each array element for having 0 at end as long as elem == 0
1026             # Upon finding a elem != 0, stop.
1027              
1028 85176     85176   2483134 my $x = $_[1];
1029              
1030 85176 100 100     286159 return 0 if @$x == 1 && $x->[0] == 0;
1031              
1032 82700         135748 my $zeros = 0;
1033 82700         166529 foreach my $elem (@$x) {
1034 151125 100       302624 if ($elem != 0) {
1035 82700         523937 $elem =~ /[^0](0*)\z/;
1036 82700         250439 $zeros += length($1); # count trailing zeros
1037 82700         178056 last; # early out
1038             }
1039 68425         112468 $zeros += $BASE_LEN;
1040             }
1041 82700         204775 $zeros;
1042             }
1043              
1044             ##############################################################################
1045             # _is_* routines
1046              
1047             sub _is_zero {
1048             # return true if arg is zero
1049 400112 100 100 400112   588341 @{$_[1]} == 1 && $_[1]->[0] == 0 ? 1 : 0;
1050             }
1051              
1052             sub _is_even {
1053             # return true if arg is even
1054 210 100   210   2546 $_[1]->[0] % 2 ? 0 : 1;
1055             }
1056              
1057             sub _is_odd {
1058             # return true if arg is odd
1059 833 100   833   7574 $_[1]->[0] % 2 ? 1 : 0;
1060             }
1061              
1062             sub _is_one {
1063             # return true if arg is one
1064 30693 100 100 30693   45585 @{$_[1]} == 1 && $_[1]->[0] == 1 ? 1 : 0;
1065             }
1066              
1067             sub _is_two {
1068             # return true if arg is two
1069 169 100 100 169   317 @{$_[1]} == 1 && $_[1]->[0] == 2 ? 1 : 0;
1070             }
1071              
1072             sub _is_ten {
1073             # return true if arg is ten
1074 2 50   2   7 if ($BASE_LEN == 1) {
1075 0 0 0     0 @{$_[1]} == 2 && $_[1]->[0] == 0 && $_[1]->[1] == 1 ? 1 : 0;
1076             } else {
1077 2 100 66     5 @{$_[1]} == 1 && $_[1]->[0] == 10 ? 1 : 0;
1078             }
1079             }
1080              
1081             sub __strip_zeros {
1082             # Internal normalization function that strips leading zeros from the array.
1083             # Args: ref to array
1084 77021     77021   139284 my $x = shift;
1085              
1086 77021 100       171808 push @$x, 0 if @$x == 0; # div might return empty results, so fix it
1087 77021 100       259574 return $x if @$x == 1; # early out
1088              
1089             #print "strip: cnt $cnt i $i\n";
1090             # '0', '3', '4', '0', '0',
1091             # 0 1 2 3 4
1092             # cnt = 5, i = 4
1093             # i = 4
1094             # i = 3
1095             # => fcnt = cnt - i (5-2 => 3, cnt => 5-1 = 4, throw away from 4th pos)
1096             # >= 1: skip first part (this can be zero)
1097              
1098 16063         27580 my $i = $#$x;
1099 16063         37588 while ($i > 0) {
1100 25193 100       58310 last if $x->[$i] != 0;
1101 9638         19192 $i--;
1102             }
1103 16063         24762 $i++;
1104 16063 100       56254 splice(@$x, $i) if $i < @$x;
1105 16063         34011 $x;
1106             }
1107              
1108             ###############################################################################
1109             # check routine to test internal state for corruptions
1110              
1111             sub _check {
1112             # used by the test suite
1113 8106     8106   2798185 my ($class, $x) = @_;
1114              
1115 8106         39325 my $msg = $class -> SUPER::_check($x);
1116 8106 100       21281 return $msg if $msg;
1117              
1118 8105         13386 my $n;
1119 8105         16899 eval { $n = @$x };
  8105         15895  
1120 8105 50       20023 return "Not an array reference" unless $@ eq '';
1121              
1122 8105 50       20179 return "Reference to an empty array" unless $n > 0;
1123              
1124             # The following fails with Math::BigInt::FastCalc because a
1125             # Math::BigInt::FastCalc "object" is an unblessed array ref.
1126             #
1127             #return 0 unless ref($x) eq $class;
1128              
1129 8105         28908 for (my $i = 0 ; $i <= $#$x ; ++ $i) {
1130 9134         18428 my $e = $x -> [$i];
1131              
1132 9134 50       19628 return "Element at index $i is undefined"
1133             unless defined $e;
1134              
1135 9134 50       23578 return "Element at index $i is a '" . ref($e) .
1136             "', which is not a scalar"
1137             unless ref($e) eq "";
1138              
1139             # It would be better to use the regex /^([1-9]\d*|0)\z/, but that fails
1140             # in Math::BigInt::FastCalc, because it sometimes creates array
1141             # elements like "000000".
1142 9134 50       40230 return "Element at index $i is '$e', which does not look like an" .
1143             " normal integer" unless $e =~ /^\d+\z/;
1144              
1145 9134 50       22470 return "Element at index $i is '$e', which is not smaller than" .
1146             " the base '$BASE'" if $e >= $BASE;
1147              
1148 9134 50 100     43886 return "Element at index $i (last element) is zero"
      66        
1149             if $#$x > 0 && $i == $#$x && $e == 0;
1150             }
1151              
1152 8105         24306 return 0;
1153             }
1154              
1155             ###############################################################################
1156              
1157             sub _mod {
1158             # if possible, use mod shortcut
1159 14929     14929   27078 my ($c, $x, $yo) = @_;
1160              
1161             # slow way since $y too big
1162 14929 100       30386 if (@$yo > 1) {
1163 3229         7595 my ($xo, $rem) = $c->_div($x, $yo);
1164 3229         6952 @$x = @$rem;
1165 3229         8627 return $x;
1166             }
1167              
1168 11700         19303 my $y = $yo->[0];
1169              
1170             # if both are single element arrays
1171 11700 100       23532 if (@$x == 1) {
1172 10964         17989 $x->[0] %= $y;
1173 10964         20470 return $x;
1174             }
1175              
1176             # if @$x has more than one element, but @$y is a single element
1177 736         1876 my $b = $BASE % $y;
1178 736 100       2669 if ($b == 0) {
    100          
1179             # when BASE % Y == 0 then (B * BASE) % Y == 0
1180             # (B * BASE) % $y + A % Y => A % Y
1181             # so need to consider only last element: O(1)
1182 88         191 $x->[0] %= $y;
1183             } elsif ($b == 1) {
1184             # else need to go through all elements in @$x: O(N), but loop is a bit
1185             # simplified
1186 205         420 my $r = 0;
1187 205         554 foreach (@$x) {
1188 412         870 $r = ($r + $_) % $y; # not much faster, but heh...
1189             #$r += $_ % $y; $r %= $y;
1190             }
1191 205 50       686 $r = 0 if $r == $y;
1192 205         452 $x->[0] = $r;
1193             } else {
1194             # else need to go through all elements in @$x: O(N)
1195 443         777 my $r = 0;
1196 443         754 my $bm = 1;
1197 443         1096 foreach (@$x) {
1198 2847         3871 $r = ($_ * $bm + $r) % $y;
1199 2847         3882 $bm = ($bm * $b) % $y;
1200              
1201             #$r += ($_ % $y) * $bm;
1202             #$bm *= $b;
1203             #$bm %= $y;
1204             #$r %= $y;
1205             }
1206 443 50       1146 $r = 0 if $r == $y;
1207 443         1040 $x->[0] = $r;
1208             }
1209 736         2410 @$x = $x->[0]; # keep one element of @$x
1210 736         1787 return $x;
1211             }
1212              
1213             ##############################################################################
1214             # shifts
1215              
1216             sub _rsft {
1217 34030     34030   81466 my ($c, $x, $n, $b) = @_;
1218 34030 50 33     84580 return $x if $c->_is_zero($x) || $c->_is_zero($n);
1219              
1220             # For backwards compatibility, allow the base $b to be a scalar.
1221              
1222 34030 50       103431 $b = $c->_new($b) unless ref $b;
1223              
1224 34030 100       107827 if ($c -> _acmp($b, $c -> _ten())) {
1225 49         174 return scalar $c->_div($x, $c->_pow($c->_copy($b), $n));
1226             }
1227              
1228             # shortcut (faster) for shifting by 10)
1229             # multiples of $BASE_LEN
1230 33981         86891 my $dst = 0; # destination
1231 33981         91971 my $src = $c->_num($n); # as normal int
1232 33981         94885 my $xlen = (@$x - 1) * $BASE_LEN + length(int($x->[-1]));
1233 33981 100 33     124446 if ($src >= $xlen or ($src == $xlen and !defined $x->[1])) {
      66        
1234             # 12345 67890 shifted right by more than 10 digits => 0
1235 164         491 splice(@$x, 1); # leave only one element
1236 164         381 $x->[0] = 0; # set to zero
1237 164         705 return $x;
1238             }
1239 33817         60519 my $rem = $src % $BASE_LEN; # remainder to shift
1240 33817         84673 $src = int($src / $BASE_LEN); # source
1241 33817 100       68420 if ($rem == 0) {
1242 1965         5393 splice(@$x, 0, $src); # even faster, 38.4 => 39.3
1243             } else {
1244 31852         56113 my $len = @$x - $src; # elems to go
1245 31852         47570 my $vd;
1246 31852         76141 my $z = '0' x $BASE_LEN;
1247 31852         90610 $x->[ @$x ] = 0; # avoid || 0 test inside loop
1248 31852         72431 while ($dst < $len) {
1249 185195         296629 $vd = $z . $x->[$src];
1250 185195         339623 $vd = substr($vd, -$BASE_LEN, $BASE_LEN - $rem);
1251 185195         250668 $src++;
1252 185195         409399 $vd = substr($z . $x->[$src], -$rem, $rem) . $vd;
1253 185195 50       342777 $vd = substr($vd, -$BASE_LEN, $BASE_LEN) if length($vd) > $BASE_LEN;
1254 185195         305435 $x->[$dst] = int($vd);
1255 185195         371749 $dst++;
1256             }
1257 31852 50       103195 splice(@$x, $dst) if $dst > 0; # kill left-over array elems
1258 31852 100 66     141744 pop(@$x) if $x->[-1] == 0 && @$x > 1; # kill last element if 0
1259             } # else rem == 0
1260 33817         141308 $x;
1261             }
1262              
1263             sub _lsft {
1264 21934     21934   53588 my ($c, $x, $n, $b) = @_;
1265              
1266 21934 100 100     56771 return $x if $c->_is_zero($x) || $c->_is_zero($n);
1267              
1268             # For backwards compatibility, allow the base $b to be a scalar.
1269              
1270 20692 100       70871 $b = $c->_new($b) unless ref $b;
1271              
1272             # If the base is a power of 10, use shifting, since the internal
1273             # representation is in base 10eX.
1274              
1275 20692         58247 my $bstr = $c->_str($b);
1276 20692 100       114375 if ($bstr =~ /^1(0+)\z/) {
1277              
1278             # Adjust $n so that we're shifting in base 10. Do this by multiplying
1279             # $n by the base 10 logarithm of $b: $b ** $n = 10 ** (log10($b) * $n).
1280              
1281 20634         59421 my $log10b = length($1);
1282 20634         52706 $n = $c->_mul($c->_new($log10b), $n);
1283 20634         55216 $n = $c->_num($n); # shift-len as normal int
1284              
1285             # $q is the number of places to shift the elements within the array,
1286             # and $r is the number of places to shift the values within the
1287             # elements.
1288              
1289 20634         64951 my $r = $n % $BASE_LEN;
1290 20634         47677 my $q = ($n - $r) / $BASE_LEN;
1291              
1292             # If we must shift the values within the elements ...
1293              
1294 20634 100       44579 if ($r) {
1295 18991         32928 my $i = @$x; # index
1296 18991         45828 $x->[$i] = 0; # initialize most significant element
1297 18991         46208 my $z = '0' x $BASE_LEN;
1298 18991         29057 my $vd;
1299 18991         46718 while ($i >= 0) {
1300 102538         173682 $vd = $x->[$i];
1301 102538         164516 $vd = $z . $vd;
1302 102538         177415 $vd = substr($vd, $r - $BASE_LEN, $BASE_LEN - $r);
1303 102538 100       268867 $vd .= $i > 0 ? substr($z . $x->[$i - 1], -$BASE_LEN, $r)
1304             : '0' x $r;
1305 102538 50       193517 $vd = substr($vd, -$BASE_LEN, $BASE_LEN) if length($vd) > $BASE_LEN;
1306 102538         169326 $x->[$i] = int($vd); # e.g., "0...048" -> 48 etc.
1307 102538         194143 $i--;
1308             }
1309              
1310 18991 100       56035 pop(@$x) if $x->[-1] == 0; # if most significant element is zero
1311             }
1312              
1313             # If we must shift the elements within the array ...
1314              
1315 20634 100       48346 if ($q) {
1316 16804         72791 unshift @$x, (0) x $q;
1317             }
1318              
1319             } else {
1320 58         250 $x = $c->_mul($x, $c->_pow($b, $n));
1321             }
1322              
1323 20692         89277 return $x;
1324             }
1325              
1326             sub _pow {
1327             # power of $x to $y
1328             # ref to array, ref to array, return ref to array
1329 1340     1340   4040 my ($c, $cx, $cy) = @_;
1330              
1331 1340 100 66     7008 if (@$cy == 1 && $cy->[0] == 0) {
1332 120         316 splice(@$cx, 1);
1333 120         302 $cx->[0] = 1; # y == 0 => x => 1
1334 120         367 return $cx;
1335             }
1336              
1337 1220 100 100     9500 if ((@$cx == 1 && $cx->[0] == 1) || # x == 1
      66        
      100        
1338             (@$cy == 1 && $cy->[0] == 1)) # or y == 1
1339             {
1340 244         1071 return $cx;
1341             }
1342              
1343 976 100 100     4455 if (@$cx == 1 && $cx->[0] == 0) {
1344 1         4 splice (@$cx, 1);
1345 1         3 $cx->[0] = 0; # 0 ** y => 0 (if not y <= 0)
1346 1         5 return $cx;
1347             }
1348              
1349 975         3503 my $pow2 = $c->_one();
1350              
1351 975         4190 my $y_bin = $c->_as_bin($cy);
1352 975         3441 $y_bin =~ s/^0b//;
1353 975         2104 my $len = length($y_bin);
1354 975         3060 while (--$len > 0) {
1355 2053 100       6850 $c->_mul($pow2, $cx) if substr($y_bin, $len, 1) eq '1'; # is odd?
1356 2053         5373 $c->_mul($cx, $cx);
1357             }
1358              
1359 975         3145 $c->_mul($cx, $pow2);
1360 975         3898 $cx;
1361             }
1362              
1363             sub _nok {
1364             # Return binomial coefficient (n over k).
1365             # Given refs to arrays, return ref to array.
1366             # First input argument is modified.
1367              
1368 56     56   167 my ($c, $n, $k) = @_;
1369              
1370             # If k > n/2, or, equivalently, 2*k > n, compute nok(n, k) as
1371             # nok(n, n-k), to minimize the number if iterations in the loop.
1372              
1373             {
1374 56         86 my $twok = $c->_mul($c->_two(), $c->_copy($k)); # 2 * k
  56         142  
1375 56 50       182 if ($c->_acmp($twok, $n) > 0) { # if 2*k > n
1376 0         0 $k = $c->_sub($c->_copy($n), $k); # k = n - k
1377             }
1378             }
1379              
1380             # Example:
1381             #
1382             # / 7 \ 7! 1*2*3*4 * 5*6*7 5 * 6 * 7 6 7
1383             # | | = --------- = --------------- = --------- = 5 * - * -
1384             # \ 3 / (7-3)! 3! 1*2*3*4 * 1*2*3 1 * 2 * 3 2 3
1385              
1386 56 100       251 if ($c->_is_zero($k)) {
1387 21         65 @$n = 1;
1388             } else {
1389              
1390             # Make a copy of the original n, since we'll be modifying n in-place.
1391              
1392 35         107 my $n_orig = $c->_copy($n);
1393              
1394             # n = 5, f = 6, d = 2 (cf. example above)
1395              
1396 35         144 $c->_sub($n, $k);
1397 35         152 $c->_inc($n);
1398              
1399 35         83 my $f = $c->_copy($n);
1400 35         114 $c->_inc($f);
1401              
1402 35         88 my $d = $c->_two();
1403              
1404             # while f <= n (the original n, that is) ...
1405              
1406 35         103 while ($c->_acmp($f, $n_orig) <= 0) {
1407              
1408             # n = (n * f / d) == 5 * 6 / 2 (cf. example above)
1409              
1410 105         335 $c->_mul($n, $f);
1411 105         294 $c->_div($n, $d);
1412              
1413             # f = 7, d = 3 (cf. example above)
1414              
1415 105         275 $c->_inc($f);
1416 105         203 $c->_inc($d);
1417             }
1418              
1419             }
1420              
1421 56         212 return $n;
1422             }
1423              
1424             sub _fac {
1425             # factorial of $x
1426             # ref to array, return ref to array
1427 146     146   485 my ($c, $cx) = @_;
1428              
1429             # We cache the smallest values. Don't assume that a single element has a
1430             # value larger than 9 or else it won't work with a $BASE_LEN of 1.
1431              
1432 146 50       467 if (@$cx == 1) {
1433 146         711 my @factorials =
1434             (
1435             '1',
1436             '1',
1437             '2',
1438             '6',
1439             '24',
1440             '120',
1441             '720',
1442             '5040',
1443             '40320',
1444             '362880',
1445             );
1446 146 100       550 if ($cx->[0] <= $#factorials) {
1447 75         329 my $tmp = $c -> _new($factorials[ $cx->[0] ]);
1448 75         249 @$cx = @$tmp;
1449 75         378 return $cx;
1450             }
1451             }
1452              
1453             # The old code further below doesn't work for small values of $BASE_LEN.
1454             # Alas, I have not been able to (or taken the time to) decipher it, so for
1455             # the case when $BASE_LEN is small, we call the parent class. This code
1456             # works in for every value of $x and $BASE_LEN. We could use this code for
1457             # all cases, but it is a little slower than the code further below, so at
1458             # least for now we keep the code below.
1459              
1460 71 50       230 if ($BASE_LEN <= 2) {
1461 0         0 my $tmp = $c -> SUPER::_fac($cx);
1462 0         0 @$cx = @$tmp;
1463 0         0 return $cx;
1464             }
1465              
1466             # This code does not work for small values of $BASE_LEN.
1467              
1468 71 100 66     517 if ((@$cx == 1) && # we do this only if $x >= 12 and $x <= 7000
      33        
1469             ($cx->[0] >= 12 && $cx->[0] < 7000)) {
1470              
1471             # Calculate (k-j) * (k-j+1) ... k .. (k+j-1) * (k + j)
1472             # See http://blogten.blogspot.com/2007/01/calculating-n.html
1473             # The above series can be expressed as factors:
1474             # k * k - (j - i) * 2
1475             # We cache k*k, and calculate (j * j) as the sum of the first j odd integers
1476              
1477             # This will not work when N exceeds the storage of a Perl scalar, however,
1478             # in this case the algorithm would be way too slow to terminate, anyway.
1479              
1480             # As soon as the last element of $cx is 0, we split it up and remember
1481             # how many zeors we got so far. The reason is that n! will accumulate
1482             # zeros at the end rather fast.
1483 55         110 my $zero_elements = 0;
1484              
1485             # If n is even, set n = n -1
1486 55         207 my $k = $c->_num($cx);
1487 55         159 my $even = 1;
1488 55 100       200 if (($k & 1) == 0) {
1489 35         81 $even = $k;
1490 35         79 $k --;
1491             }
1492             # set k to the center point
1493 55         156 $k = ($k + 1) / 2;
1494             # print "k $k even: $even\n";
1495             # now calculate k * k
1496 55         115 my $k2 = $k * $k;
1497 55         94 my $odd = 1;
1498 55         96 my $sum = 1;
1499 55         125 my $i = $k - 1;
1500             # keep reference to x
1501 55         234 my $new_x = $c->_new($k * $even);
1502 55         195 @$cx = @$new_x;
1503 55 50       173 if ($cx->[0] == 0) {
1504 0         0 $zero_elements ++;
1505 0         0 shift @$cx;
1506             }
1507             # print STDERR "x = ", $c->_str($cx), "\n";
1508 55         160 my $BASE2 = int(sqrt($BASE))-1;
1509 55         129 my $j = 1;
1510 55         155 while ($j <= $i) {
1511 282         428 my $m = ($k2 - $sum);
1512 282         462 $odd += 2;
1513 282         461 $sum += $odd;
1514 282         394 $j++;
1515 282   100     1370 while ($j <= $i && ($m < $BASE2) && (($k2 - $sum) < $BASE2)) {
      66        
1516 366         624 $m *= ($k2 - $sum);
1517 366         547 $odd += 2;
1518 366         488 $sum += $odd;
1519 366         1213 $j++;
1520             # print STDERR "\n k2 $k2 m $m sum $sum odd $odd\n"; sleep(1);
1521             }
1522 282 50       544 if ($m < $BASE) {
1523 282         816 $c->_mul($cx, [$m]);
1524             } else {
1525 0         0 $c->_mul($cx, $c->_new($m));
1526             }
1527 282 100       923 if ($cx->[0] == 0) {
1528 10         33 $zero_elements ++;
1529 10         38 shift @$cx;
1530             }
1531             # print STDERR "Calculate $k2 - $sum = $m (x = ", $c->_str($cx), ")\n";
1532             }
1533             # multiply in the zeros again
1534 55         160 unshift @$cx, (0) x $zero_elements;
1535 55         378 return $cx;
1536             }
1537              
1538             # go forward until $base is exceeded limit is either $x steps (steps == 100
1539             # means a result always too high) or $base.
1540 16         40 my $steps = 100;
1541 16 50       74 $steps = $cx->[0] if @$cx == 1;
1542 16         35 my $r = 2;
1543 16         37 my $cf = 3;
1544 16         32 my $step = 2;
1545 16         33 my $last = $r;
1546 16   66     129 while ($r * $cf < $BASE && $step < $steps) {
1547 136         208 $last = $r;
1548 136         199 $r *= $cf++;
1549 136         441 $step++;
1550             }
1551 16 50 33     110 if ((@$cx == 1) && $step == $cx->[0]) {
1552             # completely done, so keep reference to $x and return
1553 16         44 $cx->[0] = $r;
1554 16         95 return $cx;
1555             }
1556              
1557             # now we must do the left over steps
1558 0         0 my $n; # steps still to do
1559 0 0       0 if (@$cx == 1) {
1560 0         0 $n = $cx->[0];
1561             } else {
1562 0         0 $n = $c->_copy($cx);
1563             }
1564              
1565             # Set $cx to the last result below $BASE (but keep ref to $x)
1566 0         0 $cx->[0] = $last;
1567 0         0 splice (@$cx, 1);
1568             # As soon as the last element of $cx is 0, we split it up and remember
1569             # how many zeors we got so far. The reason is that n! will accumulate
1570             # zeros at the end rather fast.
1571 0         0 my $zero_elements = 0;
1572              
1573             # do left-over steps fit into a scalar?
1574 0 0       0 if (ref $n eq 'ARRAY') {
1575             # No, so use slower inc() & cmp()
1576             # ($n is at least $BASE here)
1577 0         0 my $base_2 = int(sqrt($BASE)) - 1;
1578             #print STDERR "base_2: $base_2\n";
1579 0         0 while ($step < $base_2) {
1580 0 0       0 if ($cx->[0] == 0) {
1581 0         0 $zero_elements ++;
1582 0         0 shift @$cx;
1583             }
1584 0         0 my $b = $step * ($step + 1);
1585 0         0 $step += 2;
1586 0         0 $c->_mul($cx, [$b]);
1587             }
1588 0         0 $step = [$step];
1589 0         0 while ($c->_acmp($step, $n) <= 0) {
1590 0 0       0 if ($cx->[0] == 0) {
1591 0         0 $zero_elements ++;
1592 0         0 shift @$cx;
1593             }
1594 0         0 $c->_mul($cx, $step);
1595 0         0 $c->_inc($step);
1596             }
1597             } else {
1598             # Yes, so we can speed it up slightly
1599              
1600             # print "# left over steps $n\n";
1601              
1602 0         0 my $base_4 = int(sqrt(sqrt($BASE))) - 2;
1603             #print STDERR "base_4: $base_4\n";
1604 0         0 my $n4 = $n - 4;
1605 0   0     0 while ($step < $n4 && $step < $base_4) {
1606 0 0       0 if ($cx->[0] == 0) {
1607 0         0 $zero_elements ++;
1608 0         0 shift @$cx;
1609             }
1610 0         0 my $b = $step * ($step + 1);
1611 0         0 $step += 2;
1612 0         0 $b *= $step * ($step + 1);
1613 0         0 $step += 2;
1614 0         0 $c->_mul($cx, [$b]);
1615             }
1616 0         0 my $base_2 = int(sqrt($BASE)) - 1;
1617 0         0 my $n2 = $n - 2;
1618             #print STDERR "base_2: $base_2\n";
1619 0   0     0 while ($step < $n2 && $step < $base_2) {
1620 0 0       0 if ($cx->[0] == 0) {
1621 0         0 $zero_elements ++;
1622 0         0 shift @$cx;
1623             }
1624 0         0 my $b = $step * ($step + 1);
1625 0         0 $step += 2;
1626 0         0 $c->_mul($cx, [$b]);
1627             }
1628             # do what's left over
1629 0         0 while ($step <= $n) {
1630 0         0 $c->_mul($cx, [$step]);
1631 0         0 $step++;
1632 0 0       0 if ($cx->[0] == 0) {
1633 0         0 $zero_elements ++;
1634 0         0 shift @$cx;
1635             }
1636             }
1637             }
1638             # multiply in the zeros again
1639 0         0 unshift @$cx, (0) x $zero_elements;
1640 0         0 $cx; # return result
1641             }
1642              
1643             sub _log_int {
1644             # calculate integer log of $x to base $base
1645             # ref to array, ref to array - return ref to array
1646 85     85   200 my ($c, $x, $base) = @_;
1647              
1648             # X == 0 => NaN
1649 85 50 66     334 return if @$x == 1 && $x->[0] == 0;
1650              
1651             # BASE 0 or 1 => NaN
1652 85 50 66     447 return if @$base == 1 && $base->[0] < 2;
1653              
1654             # X == 1 => 0 (is exact)
1655 85 50 66     303 if (@$x == 1 && $x->[0] == 1) {
1656 0         0 @$x = 0;
1657 0         0 return $x, 1;
1658             }
1659              
1660 85         257 my $cmp = $c->_acmp($x, $base);
1661              
1662             # X == BASE => 1 (is exact)
1663 85 50       206 if ($cmp == 0) {
1664 0         0 @$x = 1;
1665 0         0 return $x, 1;
1666             }
1667              
1668             # 1 < X < BASE => 0 (is truncated)
1669 85 100       235 if ($cmp < 0) {
1670 4         18 @$x = 0;
1671 4         18 return $x, 0;
1672             }
1673              
1674 81         260 my $x_org = $c->_copy($x); # preserve x
1675              
1676             # Compute a guess for the result based on:
1677             # $guess = int ( length_in_base_10(X) / ( log(base) / log(10) ) )
1678 81         244 my $len = $c->_len($x_org);
1679 81         300 my $log = log($base->[-1]) / log(10);
1680              
1681             # for each additional element in $base, we add $BASE_LEN to the result,
1682             # based on the observation that log($BASE, 10) is BASE_LEN and
1683             # log(x*y) == log(x) + log(y):
1684 81         187 $log += (@$base - 1) * $BASE_LEN;
1685              
1686             # calculate now a guess based on the values obtained above:
1687 81         293 my $res = $c->_new(int($len / $log));
1688              
1689 81         287 @$x = @$res;
1690 81         212 my $trial = $c->_pow($c->_copy($base), $x);
1691 81         245 my $acmp = $c->_acmp($trial, $x_org);
1692              
1693             # Did we get the exact result?
1694              
1695 81 100       272 return $x, 1 if $acmp == 0;
1696              
1697             # Too small?
1698              
1699 64         164 while ($acmp < 0) {
1700 7         27 $c->_mul($trial, $base);
1701 7         41 $c->_inc($x);
1702 7         22 $acmp = $c->_acmp($trial, $x_org);
1703             }
1704              
1705             # Too big?
1706              
1707 64         172 while ($acmp > 0) {
1708 81         311 $c->_div($trial, $base);
1709 81         300 $c->_dec($x);
1710 81         201 $acmp = $c->_acmp($trial, $x_org);
1711             }
1712              
1713 64 100       314 return $x, 1 if $acmp == 0; # result is exact
1714 19         119 return $x, 0; # result is too small
1715             }
1716              
1717             sub _ilog2 {
1718             # calculate int(log2($x))
1719              
1720             # There is virtually nothing to gain from computing this any differently
1721             # than _log_int(), but it is important that we don't use the method
1722             # inherited from the parent, because that method is very slow for backend
1723             # libraries whose internal representation uses base 10.
1724              
1725 0     0   0 my ($c, $x) = @_;
1726 0         0 ($x, my $is_exact) = $c -> _log_int($x, $c -> _two());
1727 0 0       0 return wantarray ? ($x, $is_exact) : $x;
1728             }
1729              
1730             sub _ilog10 {
1731             # calculate int(log10($x))
1732              
1733 0     0   0 my ($c, $x) = @_;
1734              
1735             # X == 0 => NaN
1736 0 0 0     0 return if @$x == 1 && $x->[0] == 0;
1737              
1738             # X == 1 => 0 (is exact)
1739 0 0 0     0 if (@$x == 1 && $x->[0] == 1) {
1740 0         0 @$x = 0;
1741 0 0       0 return wantarray ? ($x, 1) : $x;
1742             }
1743              
1744 0         0 my $x_orig = $c -> _copy($x);
1745 0         0 my $nm1 = $c -> _len($x) - 1;
1746              
1747 0         0 my $xtmp = $c -> _new($nm1);
1748 0         0 @$x = @$xtmp;
1749              
1750 0 0       0 return $x unless wantarray;
1751              
1752             # See if the original $x is an exact power of 10, in which case all but the
1753             # most significan chunks are 0, and the most significant chunk is a power
1754             # of 10.
1755              
1756 0         0 my $is_pow10 = 1;
1757 0         0 for my $i (0 .. $#$x_orig - 1) {
1758 0 0       0 last unless $is_pow10 = $x_orig->[$i] == 0;
1759             }
1760 0   0     0 $is_pow10 &&= $x_orig->[-1] == 10**int(0.5 + log($x_orig->[-1]) / log(10));
1761              
1762 0 0       0 return wantarray ? ($x, 1) : $x if $is_pow10;
    0          
1763 0 0       0 return wantarray ? ($x, 0) : $x;
1764             }
1765              
1766             sub _clog2 {
1767             # calculate ceil(log2($x))
1768              
1769 0     0   0 my ($c, $x) = @_;
1770              
1771             # X == 0 => NaN
1772              
1773 0 0 0     0 return if @$x == 1 && $x->[0] == 0;
1774              
1775             # X == 1 => 0 (is exact)
1776              
1777 0 0 0     0 if (@$x == 1 && $x->[0] == 1) {
1778 0         0 @$x = 0;
1779 0 0       0 return wantarray ? ($x, 1) : $x;
1780             }
1781              
1782 0         0 my $base = $c -> _two();
1783 0         0 my $acmp = $c -> _acmp($x, $base);
1784              
1785             # X == BASE => 1 (is exact)
1786              
1787 0 0       0 if ($acmp == 0) {
1788 0         0 @$x = 1;
1789 0 0       0 return wantarray ? ($x, 1) : $x;
1790             }
1791              
1792             # 1 < X < BASE => 0 (is truncated)
1793              
1794 0 0       0 if ($acmp < 0) {
1795 0         0 @$x = 0;
1796 0 0       0 return wantarray ? ($x, 0) : $x;
1797             }
1798              
1799             # Compute a guess for the result based on:
1800             # $guess = int( length_in_base_10(X) / (log(base) / log(10)) )
1801              
1802 0         0 my $len = $c -> _len($x);
1803 0         0 my $log = log(2) / log(10);
1804 0         0 my $guess = $c -> _new(int($len / $log));
1805 0         0 my $x_orig = $c -> _copy($x);
1806 0         0 @$x = @$guess;
1807              
1808 0         0 my $trial = $c -> _pow($c -> _copy($base), $x);
1809 0         0 $acmp = $c -> _acmp($trial, $x_orig);
1810              
1811             # Too big?
1812              
1813 0         0 while ($acmp > 0) {
1814 0         0 $c -> _div($trial, $base);
1815 0         0 $c -> _dec($x);
1816 0         0 $acmp = $c -> _acmp($trial, $x_orig);
1817             }
1818              
1819             # Too small?
1820              
1821 0         0 while ($acmp < 0) {
1822 0         0 $c -> _mul($trial, $base);
1823 0         0 $c -> _inc($x);
1824 0         0 $acmp = $c -> _acmp($trial, $x_orig);
1825             }
1826              
1827 0 0       0 return wantarray ? ($x, 1) : $x if $acmp == 0; # result is exact
    0          
1828 0 0       0 return wantarray ? ($x, 0) : $x; # result is too small
1829             }
1830              
1831             sub _clog10 {
1832             # calculate ceil(log2($x))
1833 0     0   0 my ($c, $x) = @_;
1834              
1835             # X == 0 => NaN
1836 0 0 0     0 return if @$x == 1 && $x->[0] == 0;
1837              
1838             # X == 1 => 0 (is exact)
1839 0 0 0     0 if (@$x == 1 && $x->[0] == 1) {
1840 0         0 @$x = 0;
1841 0 0       0 return wantarray ? ($x, 1) : $x;
1842             }
1843              
1844             # Get the number of base 10 digits. $n is the desired output, except when
1845             # $x is an exact power of 10, in which case $n is 1 too big.
1846              
1847 0         0 my $n = $c -> _len($x);
1848              
1849             # See if $x is an exact power of 10, in which case all but the most
1850             # significan chunks are 0, and the most significant chunk is a power of 10.
1851              
1852 0         0 my $is_pow10 = 1;
1853 0         0 for my $i (0 .. $#$x - 1) {
1854 0 0       0 last unless $is_pow10 = $x->[$i] == 0;
1855             }
1856 0   0     0 $is_pow10 &&= $x->[-1] == 10**int(0.5 + log($x->[-1]) / log(10));
1857              
1858 0 0       0 $n-- if $is_pow10;
1859              
1860 0         0 my $xtmp = $c ->_new($n);
1861 0         0 @$x = @$xtmp;
1862              
1863 0 0       0 return wantarray ? ($x, 1) : $x if $is_pow10; # result is exact
    0          
1864 0 0       0 return wantarray ? ($x, 0) : $x; # result is too small
1865             }
1866              
1867             # for debugging:
1868 50     50   330255 use constant DEBUG => 0;
  50         120  
  50         84803  
1869             my $steps = 0;
1870 0     0 0 0 sub steps { $steps };
1871              
1872             sub _sqrt {
1873             # square-root of $x in-place
1874              
1875 651     651   1733 my ($c, $x) = @_;
1876              
1877 651 100       1971 if (@$x == 1) {
1878             # fits into one Perl scalar, so result can be computed directly
1879 128         397 $x->[0] = int(sqrt($x->[0]));
1880 128         341 return $x;
1881             }
1882              
1883             # Create an initial guess for the square root.
1884              
1885 523         1027 my $s;
1886 523 100       1650 if (@$x % 2) {
1887 208         1176 $s = [ (0) x ((@$x - 1) / 2), int(sqrt($x->[-1])) ];
1888             } else {
1889 315         1740 $s = [ (0) x ((@$x - 2) / 2), int(sqrt($x->[-2] + $x->[-1] * $BASE)) ];
1890             }
1891              
1892             # Newton's method for the square root of y:
1893             #
1894             # x(n) * x(n) - y
1895             # x(n+1) = x(n) - -----------------
1896             # 2 * x(n)
1897              
1898 523         1141 my $cmp;
1899 523         951 while (1) {
1900 1621         4815 my $sq = $c -> _mul($c -> _copy($s), $s);
1901 1621         5289 $cmp = $c -> _acmp($sq, $x);
1902              
1903             # If x(n)*x(n) > y, compute
1904             #
1905             # x(n) * x(n) - y
1906             # x(n+1) = x(n) - -----------------
1907             # 2 * x(n)
1908              
1909 1621 100       4778 if ($cmp > 0) {
    100          
1910 1095         3028 my $num = $c -> _sub($c -> _copy($sq), $x);
1911 1095         3474 my $den = $c -> _mul($c -> _two(), $s);
1912 1095         3633 my $delta = $c -> _div($num, $den);
1913 1095 100       3684 last if $c -> _is_zero($delta);
1914 777         2369 $s = $c -> _sub($s, $delta);
1915             }
1916              
1917             # If x(n)*x(n) < y, compute
1918             #
1919             # y - x(n) * x(n)
1920             # x(n+1) = x(n) + -----------------
1921             # 2 * x(n)
1922              
1923             elsif ($cmp < 0) {
1924 362         1194 my $num = $c -> _sub($c -> _copy($x), $sq);
1925 362         1577 my $den = $c -> _mul($c -> _two(), $s);
1926 362         1619 my $delta = $c -> _div($num, $den);
1927 362 100       1427 last if $c -> _is_zero($delta);
1928 321         1260 $s = $c -> _add($s, $delta);
1929             }
1930              
1931             # If x(n)*x(n) = y, we have the exact result.
1932              
1933             else {
1934 164         575 last;
1935             }
1936             }
1937              
1938 523 100       2440 $s = $c -> _dec($s) if $cmp > 0; # never overshoot
1939 523         1792 @$x = @$s;
1940 523         2477 return $x;
1941             }
1942              
1943             sub _root {
1944             # Take n'th root of $x in place.
1945              
1946 112     112   2228 my ($c, $x, $n) = @_;
1947              
1948             # Small numbers.
1949              
1950 112 100       406 if (@$x == 1) {
1951 69 50 33     469 return $x if $x -> [0] == 0 || $x -> [0] == 1;
1952              
1953 69 50       254 if (@$n == 1) {
1954             # Result can be computed directly. Adjust initial result for
1955             # numerical errors, e.g., int(1000**(1/3)) is 2, not 3.
1956 69         433 my $y = int($x->[0] ** (1 / $n->[0]));
1957 69         273 my $yp1 = $y + 1;
1958 69 100       271 $y = $yp1 if $yp1 ** $n->[0] == $x->[0];
1959 69         144 $x->[0] = $y;
1960 69         260 return $x;
1961             }
1962             }
1963              
1964             # If x <= n, the result is always (truncated to) 1.
1965              
1966 43 50 33     377 if ((@$x > 1 || $x -> [0] > 0) && # if x is non-zero ...
      33        
1967             $c -> _acmp($x, $n) <= 0) # ... and x <= n
1968             {
1969 0         0 my $one = $c -> _one();
1970 0         0 @$x = @$one;
1971 0         0 return $x;
1972             }
1973              
1974             # If $n is a power of two, take sqrt($x) repeatedly, e.g., root($x, 4) =
1975             # sqrt(sqrt($x)), root($x, 8) = sqrt(sqrt(sqrt($x))).
1976              
1977 43         260 my $b = $c -> _as_bin($n);
1978 43 100       326 if ($b =~ /0b1(0+)$/) {
1979 26         102 my $count = length($1); # 0b100 => len('00') => 2
1980 26         58 my $cnt = $count; # counter for loop
1981 26         110 unshift @$x, 0; # add one element, together with one
1982             # more below in the loop this makes 2
1983 26         86 while ($cnt-- > 0) {
1984             # 'Inflate' $x by adding one element, basically computing
1985             # $x * $BASE * $BASE. This gives us more $BASE_LEN digits for
1986             # result since len(sqrt($X)) approx == len($x) / 2.
1987 103         212 unshift @$x, 0;
1988             # Calculate sqrt($x), $x is now one element to big, again. In the
1989             # next round we make that two, again.
1990 103         429 $c -> _sqrt($x);
1991             }
1992              
1993             # $x is now one element too big, so truncate result by removing it.
1994 26         74 shift @$x;
1995              
1996 26         191 return $x;
1997             }
1998              
1999 17         40 my $DEBUG = 0;
2000              
2001             # Now the general case. This works by finding an initial guess. If this
2002             # guess is incorrect, a relatively small delta is chosen. This delta is
2003             # used to find a lower and upper limit for the correct value. The delta is
2004             # doubled in each iteration. When a lower and upper limit is found,
2005             # bisection is applied to narrow down the region until we have the correct
2006             # value.
2007              
2008             # Split x into mantissa and exponent in base 10, so that
2009             #
2010             # x = xm * 10^xe, where 0 < xm < 1 and xe is an integer
2011              
2012 17         70 my $x_str = $c -> _str($x);
2013 17         45 my $xm = "." . $x_str;
2014 17         42 my $xe = length($x_str);
2015              
2016             # From this we compute the base 10 logarithm of x
2017             #
2018             # log_10(x) = log_10(xm) + log_10(xe^10)
2019             # = log(xm)/log(10) + xe
2020             #
2021             # and then the base 10 logarithm of y, where y = x^(1/n)
2022             #
2023             # log_10(y) = log_10(x)/n
2024              
2025 17         162 my $log10x = log($xm) / log(10) + $xe;
2026 17         74 my $log10y = $log10x / $c -> _num($n);
2027              
2028             # And from this we compute ym and ye, the mantissa and exponent (in
2029             # base 10) of y, where 1 < ym <= 10 and ye is an integer.
2030              
2031 17         49 my $ye = int $log10y;
2032 17         73 my $ym = 10 ** ($log10y - $ye);
2033              
2034             # Finally, we scale the mantissa and exponent to incraese the integer
2035             # part of ym, before building the string representing our guess of y.
2036              
2037 17 50       61 if ($DEBUG) {
2038 0         0 print "\n";
2039 0         0 print "xm = $xm\n";
2040 0         0 print "xe = $xe\n";
2041 0         0 print "log10x = $log10x\n";
2042 0         0 print "log10y = $log10y\n";
2043 0         0 print "ym = $ym\n";
2044 0         0 print "ye = $ye\n";
2045 0         0 print "\n";
2046             }
2047              
2048 17 50       62 my $d = $ye < 15 ? $ye : 15;
2049 17         51 $ym *= 10 ** $d;
2050 17         33 $ye -= $d;
2051              
2052 17         80 my $y_str = sprintf('%.0f', $ym) . "0" x $ye;
2053 17         65 my $y = $c -> _new($y_str);
2054              
2055 17 50       54 if ($DEBUG) {
2056 0         0 print "ym = $ym\n";
2057 0         0 print "ye = $ye\n";
2058 0         0 print "\n";
2059 0         0 print "y_str = $y_str (initial guess)\n";
2060 0         0 print "\n";
2061             }
2062              
2063             # See if our guess y is correct.
2064              
2065 17         57 my $trial = $c -> _pow($c -> _copy($y), $n);
2066 17         63 my $acmp = $c -> _acmp($trial, $x);
2067              
2068 17 100       85 if ($acmp == 0) {
2069 5         43 @$x = @$y;
2070 5         31 return $x;
2071             }
2072              
2073             # Find a lower and upper limit for the correct value of y. Start off with a
2074             # delta value that is approximately the size of the accuracy of the guess.
2075              
2076 12         31 my $lower;
2077             my $upper;
2078              
2079 12         61 my $delta = $c -> _new("1" . ("0" x $ye));
2080 12         42 my $two = $c -> _two();
2081              
2082 12 100       69 if ($acmp < 0) {
    50          
2083 7         17 $lower = $y;
2084 7         21 while ($acmp < 0) {
2085 7         25 $upper = $c -> _add($c -> _copy($lower), $delta);
2086              
2087 7 50       20 if ($DEBUG) {
2088 0         0 print "lower = $lower\n";
2089 0         0 print "upper = $upper\n";
2090 0         0 print "delta = $delta\n";
2091 0         0 print "\n";
2092             }
2093 7         24 $acmp = $c -> _acmp($c -> _pow($c -> _copy($upper), $n), $x);
2094 7 50       52 if ($acmp == 0) {
2095 0         0 @$x = @$upper;
2096 0         0 return $x;
2097             }
2098 7         37 $delta = $c -> _mul($delta, $two);
2099             }
2100             }
2101              
2102             elsif ($acmp > 0) {
2103 5         10 $upper = $y;
2104 5         16 while ($acmp > 0) {
2105 5 50       16 if ($c -> _acmp($upper, $delta) <= 0) {
2106 0         0 $lower = $c -> _zero();
2107 0         0 last;
2108             }
2109 5         17 $lower = $c -> _sub($c -> _copy($upper), $delta);
2110              
2111 5 50       19 if ($DEBUG) {
2112 0         0 print "lower = $lower\n";
2113 0         0 print "upper = $upper\n";
2114 0         0 print "delta = $delta\n";
2115 0         0 print "\n";
2116             }
2117 5         15 $acmp = $c -> _acmp($c -> _pow($c -> _copy($lower), $n), $x);
2118 5 50       22 if ($acmp == 0) {
2119 0         0 @$x = @$lower;
2120 0         0 return $x;
2121             }
2122 5         16 $delta = $c -> _mul($delta, $two);
2123             }
2124             }
2125              
2126             # Use bisection to narrow down the interval.
2127              
2128 12         35 my $one = $c -> _one();
2129             {
2130              
2131 12         25 $delta = $c -> _sub($c -> _copy($upper), $lower);
  12         32  
2132 12 50       37 if ($c -> _acmp($delta, $one) <= 0) {
2133 12         46 @$x = @$lower;
2134 12         122 return $x;
2135             }
2136              
2137 0 0       0 if ($DEBUG) {
2138 0         0 print "lower = $lower\n";
2139 0         0 print "upper = $upper\n";
2140 0         0 print "delta = $delta\n";
2141 0         0 print "\n";
2142             }
2143              
2144 0         0 $delta = $c -> _div($delta, $two);
2145 0         0 my $middle = $c -> _add($c -> _copy($lower), $delta);
2146              
2147 0         0 $acmp = $c -> _acmp($c -> _pow($c -> _copy($middle), $n), $x);
2148 0 0       0 if ($acmp < 0) {
    0          
2149 0         0 $lower = $middle;
2150             } elsif ($acmp > 0) {
2151 0         0 $upper = $middle;
2152             } else {
2153 0         0 @$x = @$middle;
2154 0         0 return $x;
2155             }
2156              
2157 0         0 redo;
2158             }
2159              
2160 0         0 $x;
2161             }
2162              
2163             ##############################################################################
2164             # binary stuff
2165              
2166             sub _and {
2167 419     419   985 my ($c, $x, $y) = @_;
2168              
2169             # the shortcut makes equal, large numbers _really_ fast, and makes only a
2170             # very small performance drop for small numbers (e.g. something with less
2171             # than 32 bit) Since we optimize for large numbers, this is enabled.
2172 419 100       1379 return $x if $c->_acmp($x, $y) == 0; # shortcut
2173              
2174 322         881 my $m = $c->_one();
2175 322         650 my ($xr, $yr);
2176 322         492 my $mask = $AND_MASK;
2177              
2178 322         831 my $x1 = $c->_copy($x);
2179 322         729 my $y1 = $c->_copy($y);
2180 322         911 my $z = $c->_zero();
2181              
2182 50     50   461 use integer;
  50         123  
  50         383  
2183 322   100     950 until ($c->_is_zero($x1) || $c->_is_zero($y1)) {
2184 249         866 ($x1, $xr) = $c->_div($x1, $mask);
2185 249         600 ($y1, $yr) = $c->_div($y1, $mask);
2186              
2187 249         1269 $c->_add($z, $c->_mul([ 0 + $xr->[0] & 0 + $yr->[0] ], $m));
2188 249         749 $c->_mul($m, $mask);
2189             }
2190              
2191 322         1006 @$x = @$z;
2192 322         1746 return $x;
2193             }
2194              
2195             sub _xor {
2196 483     483   1178 my ($c, $x, $y) = @_;
2197              
2198 483 100       1659 return $c->_zero() if $c->_acmp($x, $y) == 0; # shortcut (see -and)
2199              
2200 386         1095 my $m = $c->_one();
2201 386         712 my ($xr, $yr);
2202 386         645 my $mask = $XOR_MASK;
2203              
2204 386         952 my $x1 = $c->_copy($x);
2205 386         816 my $y1 = $c->_copy($y); # make copy
2206 386         1076 my $z = $c->_zero();
2207              
2208 50     50   12273 use integer;
  50         147  
  50         286  
2209 386   100     1322 until ($c->_is_zero($x1) || $c->_is_zero($y1)) {
2210 277         948 ($x1, $xr) = $c->_div($x1, $mask);
2211 277         749 ($y1, $yr) = $c->_div($y1, $mask);
2212             # make ints() from $xr, $yr (see _and())
2213             #$b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }
2214             #$b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }
2215             #$c->_add($x, $c->_mul($c->_new($xrr ^ $yrr)), $m) );
2216              
2217 277         1630 $c->_add($z, $c->_mul([ 0 + $xr->[0] ^ 0 + $yr->[0] ], $m));
2218 277         790 $c->_mul($m, $mask);
2219             }
2220             # the loop stops when the shorter of the two numbers is exhausted
2221             # the remainder of the longer one will survive bit-by-bit, so we simple
2222             # multiply-add it in
2223 386 100       957 $c->_add($z, $c->_mul($x1, $m) ) if !$c->_is_zero($x1);
2224 386 100       877 $c->_add($z, $c->_mul($y1, $m) ) if !$c->_is_zero($y1);
2225              
2226 386         964 @$x = @$z;
2227 386         1811 return $x;
2228             }
2229              
2230             sub _or {
2231 478     478   1040 my ($c, $x, $y) = @_;
2232              
2233 478 100       1505 return $x if $c->_acmp($x, $y) == 0; # shortcut (see _and)
2234              
2235 381         1113 my $m = $c->_one();
2236 381         688 my ($xr, $yr);
2237 381         626 my $mask = $OR_MASK;
2238              
2239 381         993 my $x1 = $c->_copy($x);
2240 381         793 my $y1 = $c->_copy($y); # make copy
2241 381         956 my $z = $c->_zero();
2242              
2243 50     50   13883 use integer;
  50         127  
  50         298  
2244 381   100     1096 until ($c->_is_zero($x1) || $c->_is_zero($y1)) {
2245 276         858 ($x1, $xr) = $c->_div($x1, $mask);
2246 276         719 ($y1, $yr) = $c->_div($y1, $mask);
2247             # make ints() from $xr, $yr (see _and())
2248             # $b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }
2249             # $b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }
2250             # $c->_add($x, $c->_mul(_new( $c, ($xrr | $yrr) ), $m) );
2251 276         1232 $c->_add($z, $c->_mul([ 0 + $xr->[0] | 0 + $yr->[0] ], $m));
2252 276         777 $c->_mul($m, $mask);
2253             }
2254             # the loop stops when the shorter of the two numbers is exhausted
2255             # the remainder of the longer one will survive bit-by-bit, so we simple
2256             # multiply-add it in
2257 381 100       835 $c->_add($z, $c->_mul($x1, $m) ) if !$c->_is_zero($x1);
2258 381 100       813 $c->_add($z, $c->_mul($y1, $m) ) if !$c->_is_zero($y1);
2259              
2260 381         884 @$x = @$z;
2261 381         1807 return $x;
2262             }
2263              
2264             sub _as_hex {
2265             # convert a decimal number to hex (ref to array, return ref to string)
2266 263     263   565 my ($c, $x) = @_;
2267              
2268 263 100 100     1088 return "0x0" if @$x == 1 && $x->[0] == 0;
2269              
2270 220         550 my $x1 = $c->_copy($x);
2271              
2272 220         431 my $x10000 = [ 0x10000 ];
2273              
2274 220         381 my $es = '';
2275 220         333 my $xr;
2276 220   100     895 until (@$x1 == 1 && $x1->[0] == 0) { # _is_zero()
2277 276         814 ($x1, $xr) = $c->_div($x1, $x10000);
2278 276         1643 $es = sprintf('%04x', $xr->[0]) . $es;
2279             }
2280             #$es = reverse $es;
2281 220         1119 $es =~ s/^0*/0x/;
2282 220         1852 return $es;
2283             }
2284              
2285             sub _as_bin {
2286             # convert a decimal number to bin (ref to array, return ref to string)
2287 1072     1072   2742 my ($c, $x) = @_;
2288              
2289 1072 100 100     5033 return "0b0" if @$x == 1 && $x->[0] == 0;
2290              
2291 1062         3349 my $x1 = $c->_copy($x);
2292              
2293 1062         2496 my $x10000 = [ 0x10000 ];
2294              
2295 1062         2101 my $es = '';
2296 1062         1685 my $xr;
2297              
2298 1062   100     4825 until (@$x1 == 1 && $x1->[0] == 0) { # _is_zero()
2299 1112         4770 ($x1, $xr) = $c->_div($x1, $x10000);
2300 1112         8380 $es = sprintf('%016b', $xr->[0]) . $es;
2301             }
2302 1062         6666 $es =~ s/^0*/0b/;
2303 1062         4798 return $es;
2304             }
2305              
2306             sub _as_oct {
2307             # convert a decimal number to octal (ref to array, return ref to string)
2308 58     58   155 my ($c, $x) = @_;
2309              
2310 58 100 100     291 return "00" if @$x == 1 && $x->[0] == 0;
2311              
2312 48         265 my $x1 = $c->_copy($x);
2313              
2314 48         100 my $x1000 = [ 1 << 15 ]; # 15 bits = 32768 = 0100000
2315              
2316 48         95 my $es = '';
2317 48         80 my $xr;
2318 48   100     231 until (@$x1 == 1 && $x1->[0] == 0) { # _is_zero()
2319 106         311 ($x1, $xr) = $c->_div($x1, $x1000);
2320 106         692 $es = sprintf("%05o", $xr->[0]) . $es;
2321             }
2322 48         302 $es =~ s/^0*/0/; # excactly one leading zero
2323 48         234 return $es;
2324             }
2325              
2326             sub _from_oct {
2327             # convert a octal number to decimal (string, return ref to array)
2328 16     16   43 my ($c, $os) = @_;
2329              
2330 16         43 my $m = $c->_new(1 << 30); # 30 bits at a time (<32 bits!)
2331 16         32 my $d = 10; # 10 octal digits at a time
2332              
2333 16         39 my $mul = $c->_one();
2334 16         43 my $x = $c->_zero();
2335              
2336 16         67 my $len = int((length($os) - 1) / $d); # $d digit parts, w/o the '0'
2337 16         27 my $val;
2338 16         28 my $i = -$d;
2339 16         44 while ($len >= 0) {
2340 23         57 $val = substr($os, $i, $d); # get oct digits
2341 23         47 $val = CORE::oct($val);
2342 23         35 $i -= $d;
2343 23         32 $len --;
2344 23         52 my $adder = $c -> _new($val);
2345 23 100       98 $c->_add($x, $c->_mul($adder, $mul)) if $val != 0;
2346 23 100       86 $c->_mul($mul, $m) if $len >= 0; # skip last mul
2347             }
2348 16         59 $x;
2349             }
2350              
2351             sub _from_hex {
2352             # convert a hex number to decimal (string, return ref to array)
2353 1478     1478   3343 my ($c, $hs) = @_;
2354              
2355 1478         3563 my $m = $c->_new(0x10000000); # 28 bit at a time (<32 bit!)
2356 1478         2567 my $d = 7; # 7 hexadecimal digits at a time
2357 1478         4276 my $mul = $c->_one();
2358 1478         4374 my $x = $c->_zero();
2359              
2360 1478         4583 my $len = int((length($hs) - 2) / $d); # $d digit parts, w/o the '0x'
2361 1478         2231 my $val;
2362 1478         2564 my $i = -$d;
2363 1478         3755 while ($len >= 0) {
2364 2235         4930 $val = substr($hs, $i, $d); # get hex digits
2365 2235 100       7539 $val =~ s/^0x// if $len == 0; # for last part only because
2366 2235         4569 $val = CORE::hex($val); # hex does not like wrong chars
2367 2235         3175 $i -= $d;
2368 2235         3434 $len --;
2369 2235         4662 my $adder = $c->_new($val);
2370             # if the resulting number was to big to fit into one element, create a
2371             # two-element version (bug found by Mark Lakata - Thanx!)
2372 2235 50       5637 if (CORE::length($val) > $BASE_LEN) {
2373 0         0 $adder = $c->_new($val);
2374             }
2375 2235 100       7862 $c->_add($x, $c->_mul($adder, $mul)) if $val != 0;
2376 2235 100       8193 $c->_mul($mul, $m) if $len >= 0; # skip last mul
2377             }
2378 1478         5628 $x;
2379             }
2380              
2381             sub _from_bin {
2382             # convert a hex number to decimal (string, return ref to array)
2383 251     251   663 my ($c, $bs) = @_;
2384              
2385             # instead of converting X (8) bit at a time, it is faster to "convert" the
2386             # number to hex, and then call _from_hex.
2387              
2388 251         616 my $hs = $bs;
2389 251         1472 $hs =~ s/^[+-]?0b//; # remove sign and 0b
2390 251         621 my $l = length($hs); # bits
2391 251 100       1306 $hs = '0' x (8 - ($l % 8)) . $hs if ($l % 8) != 0; # padd left side w/ 0
2392 251         1578 my $h = '0x' . unpack('H*', pack ('B*', $hs)); # repack as hex
2393              
2394 251         1152 $c->_from_hex($h);
2395             }
2396              
2397             ##############################################################################
2398             # special modulus functions
2399              
2400             sub _modinv {
2401              
2402             # modular multiplicative inverse
2403 166     166   436 my ($c, $x, $y) = @_;
2404              
2405             # modulo zero
2406 166 50       431 if ($c->_is_zero($y)) {
2407 0         0 return;
2408             }
2409              
2410             # modulo one
2411 166 50       435 if ($c->_is_one($y)) {
2412 0         0 return $c->_zero(), '+';
2413             }
2414              
2415 166         577 my $u = $c->_zero();
2416 166         533 my $v = $c->_one();
2417 166         502 my $a = $c->_copy($y);
2418 166         699 my $b = $c->_copy($x);
2419              
2420             # Euclid's Algorithm for bgcd(), only that we calc bgcd() ($a) and the result
2421             # ($u) at the same time. See comments in BigInt for why this works.
2422 166         313 my $q;
2423 166         337 my $sign = 1;
2424             {
2425 166         246 ($a, $q, $b) = ($b, $c->_div($a, $b)); # step 1
  453         1283  
2426 453 100       1315 last if $c->_is_zero($b);
2427              
2428 287         750 my $t = $c->_add( # step 2:
2429             $c->_mul($c->_copy($v), $q), # t = v * q
2430             $u); # + u
2431 287         517 $u = $v; # u = v
2432 287         511 $v = $t; # v = t
2433 287         447 $sign = -$sign;
2434 287         463 redo;
2435             }
2436              
2437             # if the gcd is not 1, then return NaN
2438 166 100       442 return unless $c->_is_one($a);
2439              
2440 141 100       971 ($v, $sign == 1 ? '+' : '-');
2441             }
2442              
2443             sub _modpow {
2444             # modulus of power ($x ** $y) % $z
2445 462     462   1247 my ($c, $num, $exp, $mod) = @_;
2446              
2447             # a^b (mod 1) = 0 for all a and b
2448 462 100       1551 if ($c->_is_one($mod)) {
2449 154         544 @$num = 0;
2450 154         924 return $num;
2451             }
2452              
2453             # 0^a (mod m) = 0 if m != 0, a != 0
2454             # 0^0 (mod m) = 1 if m != 0
2455 308 100       1010 if ($c->_is_zero($num)) {
2456 40 100       116 if ($c->_is_zero($exp)) {
2457 13         44 @$num = 1;
2458             } else {
2459 27         576 @$num = 0;
2460             }
2461 40         157 return $num;
2462             }
2463              
2464             # We could do the following, but it doesn't actually save any time. The
2465             # _copy() is needed in case $num and $mod are the same object.
2466             #$num = $c->_mod($c->_copy($num), $mod);
2467              
2468 268         833 my $acc = $c->_copy($num);
2469 268         889 my $t = $c->_one();
2470              
2471 268         1348 my $expbin = $c->_to_bin($exp);
2472 268         565 my $len = length($expbin);
2473 268         778 while ($len--) {
2474 1693 100       4717 if (substr($expbin, $len, 1) eq '1') { # if odd
2475 877         2734 $t = $c->_mul($t, $acc);
2476 877         2655 $t = $c->_mod($t, $mod);
2477             }
2478 1693         4722 $acc = $c->_mul($acc, $acc);
2479 1693         4581 $acc = $c->_mod($acc, $mod);
2480             }
2481 268         775 @$num = @$t;
2482 268         1035 $num;
2483             }
2484              
2485             sub _gcd {
2486             # Greatest common divisor.
2487              
2488 4107     4107   9082 my ($c, $x, $y) = @_;
2489              
2490             # gcd(0, 0) = 0
2491             # gcd(0, a) = a, if a != 0
2492              
2493 4107 100 100     18308 if (@$x == 1 && $x->[0] == 0) {
2494 17 100 66     152 if (@$y == 1 && $y->[0] == 0) {
2495 4         19 @$x = 0;
2496             } else {
2497 13         74 @$x = @$y;
2498             }
2499 17         62 return $x;
2500             }
2501              
2502             # Until $y is zero ...
2503              
2504 4090   100     28085 until (@$y == 1 && $y->[0] == 0) {
2505              
2506             # Compute remainder.
2507              
2508 10855         29780 $c->_mod($x, $y);
2509              
2510             # Swap $x and $y.
2511              
2512 10855         21516 my $tmp = $c->_copy($x);
2513 10855         22757 @$x = @$y;
2514 10855         36667 $y = $tmp; # no deref here; that would modify input $y
2515             }
2516              
2517 4090         10637 return $x;
2518             }
2519              
2520             1;
2521              
2522             =pod
2523              
2524             =head1 NAME
2525              
2526             Math::BigInt::Calc - pure Perl module to support Math::BigInt
2527              
2528             =head1 SYNOPSIS
2529              
2530             # to use it with Math::BigInt
2531             use Math::BigInt lib => 'Calc';
2532              
2533             # to use it with Math::BigFloat
2534             use Math::BigFloat lib => 'Calc';
2535              
2536             # to use it with Math::BigRat
2537             use Math::BigRat lib => 'Calc';
2538              
2539             # explicitly set base length and whether to "use integer"
2540             use Math::BigInt::Calc base_len => 4, use_int => 1;
2541             use Math::BigInt lib => 'Calc';
2542              
2543             =head1 DESCRIPTION
2544              
2545             Math::BigInt::Calc inherits from Math::BigInt::Lib.
2546              
2547             In this library, the numbers are represented interenally in base B = 10**N,
2548             where N is the largest possible integer that does not cause overflow in the
2549             intermediate computations. The base B elements are stored in an array, with the
2550             least significant element stored in array element zero. There are no leading
2551             zero elements, except a single zero element when the number is zero. For
2552             instance, if B = 10000, the number 1234567890 is represented internally as
2553             [7890, 3456, 12].
2554              
2555             =head1 OPTIONS
2556              
2557             When the module is loaded, it computes the maximum exponent, i.e., power of 10,
2558             that can be used with and without "use integer" in the computations. The default
2559             is to use this maximum exponent. If the combination of the 'base_len' value and
2560             the 'use_int' value exceeds the maximum value, an error is thrown.
2561              
2562             =over 4
2563              
2564             =item base_len
2565              
2566             The base length can be specified explicitly with the 'base_len' option. The
2567             value must be a positive integer.
2568              
2569             use Math::BigInt::Calc base_len => 4; # use 10000 as internal base
2570              
2571             =item use_int
2572              
2573             This option is used to specify whether "use integer" should be used in the
2574             internal computations. The value is interpreted as a boolean value, so use 0 or
2575             "" for false and anything else for true. If the 'base_len' is not specified
2576             together with 'use_int', the current value for the base length is used.
2577              
2578             use Math::BigInt::Calc use_int => 1; # use "use integer" internally
2579              
2580             =back
2581              
2582             =head1 METHODS
2583              
2584             This overview constains only the methods that are specific to
2585             C. For the other methods, see L.
2586              
2587             =over 4
2588              
2589             =item _base_len()
2590              
2591             Specify the desired base length and whether to enable "use integer" in the
2592             computations.
2593              
2594             Math::BigInt::Calc -> _base_len($base_len, $use_int);
2595              
2596             Note that it is better to specify the base length and whether to use integers as
2597             options when the module is loaded, for example like this
2598              
2599             use Math::BigInt::Calc base_len => 6, use_int => 1;
2600              
2601             =back
2602              
2603             =head1 SEE ALSO
2604              
2605             L for a description of the API.
2606              
2607             Alternative libraries L, L,
2608             L, L, and L.
2609              
2610             Some of the modules that use these libraries L,
2611             L, and L.
2612              
2613             =cut