xref: /openbsd-src/gnu/usr.bin/perl/cpan/Math-BigInt/lib/Math/BigInt/Calc.pm (revision 3d61058aa5c692477b6d18acfbbdb653a9930ff9)
1package Math::BigInt::Calc;
2
3use 5.006001;
4use strict;
5use warnings;
6
7use Carp qw< carp croak >;
8use Math::BigInt::Lib;
9
10our $VERSION = '2.003002';
11$VERSION =~ tr/_//d;
12
13our @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
29my $MAX_EXP_F;      # the maximum possible base 10 exponent with "no integer"
30my $MAX_EXP_I;      # the maximum possible base 10 exponent with "use integer"
31
32my $MAX_BITS;       # the maximum possible number of bits for $AND_BITS etc.
33
34my $BASE_LEN;       # the current base exponent in use
35my $USE_INT;        # whether "use integer" is used in the computations
36
37my $BASE;           # the current base, e.g., 10000 if $BASE_LEN is 5
38my $MAX_VAL;        # maximum value for an element, i.e., $BASE - 1
39
40my $AND_BITS;       # maximum value used in binary and, e.g., 0xffff
41my $OR_BITS;        # ditto for binary or
42my $XOR_BITS;       # ditto for binary xor
43
44my $AND_MASK;       # $AND_BITS + 1, e.g., 0x10000 if $AND_BITS is 0xffff
45my $OR_MASK;        # ditto for binary or
46my $XOR_MASK;       # ditto for binary xor
47
48sub config {
49    my $self = shift;
50
51    croak "Missing input argument" unless @_;
52
53    # Called as a getter.
54
55    if (@_ == 1) {
56        my $param = shift;
57        croak "Parameter name must be a non-empty string"
58          unless defined $param && length $param;
59        return $BASE_LEN if $param eq 'base_len';
60        return $USE_INT  if $param eq 'use_int';
61        croak "Unknown parameter '$param'";
62    }
63
64    # Called as a setter.
65
66    my $opts;
67    while (@_) {
68        my $param = shift;
69        croak "Parameter name must be a non-empty string"
70          unless defined $param && length $param;
71        croak "Missing value for parameter '$param'"
72          unless @_;
73        my $value = shift;
74
75        if ($param eq 'base_len' || $param eq 'use_int') {
76            $opts -> {$param} = $value;
77            next;
78        }
79
80        croak "Unknown parameter '$param'";
81    }
82
83    $BASE_LEN = $opts -> {base_len} if exists $opts -> {base_len};
84    $USE_INT  = $opts -> {use_int}  if exists $opts -> {use_int};
85    __PACKAGE__ -> _base_len($BASE_LEN, $USE_INT);
86
87    return $self;
88}
89
90sub _base_len {
91    #my $class = shift;                  # $class is not used
92    shift;
93
94    if (@_) {                           # if called as setter ...
95        my ($base_len, $use_int) = @_;
96
97        croak "The base length must be a positive integer"
98          unless defined($base_len) && $base_len == int($base_len)
99                 && $base_len > 0;
100
101        if ( $use_int && ($base_len > $MAX_EXP_I) ||
102            !$use_int && ($base_len > $MAX_EXP_F))
103        {
104            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        $BASE_LEN = $base_len;
111        $BASE = 0 + ("1" . ("0" x $BASE_LEN));
112        $MAX_VAL = $BASE - 1;
113        $USE_INT = $use_int ? 1 : 0;
114
115        {
116            no warnings "redefine";
117            if ($use_int) {
118                *_mul = \&_mul_use_int;
119                *_div = \&_div_use_int;
120            } else {
121                *_mul = \&_mul_no_int;
122                *_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    my $umax = ~0;                      # largest unsigned integer
133    my $tmp  = $umax < $BASE ? $umax : $BASE;
134
135    $MAX_BITS = 0;
136    while ($tmp >>= 1) {
137        $MAX_BITS++;
138    }
139
140    # Limit to 32 bits for portability. Is this really necessary? XXX
141
142    $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    for ($AND_BITS = $MAX_BITS ; $AND_BITS > 0 ; $AND_BITS--) {
148        my $x = CORE::oct('0b' . '1' x $AND_BITS);
149        my $y = $x & $x;
150        my $z = 2 * (2 ** ($AND_BITS - 1)) + 1;
151        last unless $AND_BITS < $MAX_BITS && $x == $z && $y == $x;
152    }
153
154    for ($XOR_BITS = $MAX_BITS ; $XOR_BITS > 0 ; $XOR_BITS--) {
155        my $x = CORE::oct('0b' . '1' x $XOR_BITS);
156        my $y = $x ^ $x;
157        my $z = 2 * (2 ** ($XOR_BITS - 1)) + 1;
158        last unless $XOR_BITS < $MAX_BITS && $x == $z && $y == $x;
159    }
160
161    for ($OR_BITS = $MAX_BITS ; $OR_BITS > 0 ; $OR_BITS--) {
162        my $x = CORE::oct('0b' . '1' x $OR_BITS);
163        my $y = $x | $x;
164        my $z = 2 * (2 ** ($OR_BITS - 1)) + 1;
165        last unless $OR_BITS < $MAX_BITS && $x == $z && $y == $x;
166    }
167
168    $AND_MASK = __PACKAGE__->_new(( 2 ** $AND_BITS ));
169    $XOR_MASK = __PACKAGE__->_new(( 2 ** $XOR_BITS ));
170    $OR_MASK  = __PACKAGE__->_new(( 2 ** $OR_BITS  ));
171
172    return $BASE_LEN unless wantarray;
173    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
177sub _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    my ($class, $str) = @_;
183    #unless ($str =~ /^([1-9]\d*|0)\z/) {
184    #    croak("Invalid input string '$str'");
185    #}
186
187    my $input_len = length($str) - 1;
188
189    # Shortcut for small numbers.
190    return bless [ $str ], $class if $input_len < $BASE_LEN;
191
192    my $format = "a" . (($input_len % $BASE_LEN) + 1);
193    $format .= $] < 5.008 ? "a$BASE_LEN" x int($input_len / $BASE_LEN)
194                          : "(a$BASE_LEN)*";
195
196    my $self = [ reverse(map { 0 + $_ } unpack($format, $str)) ];
197    return bless $self, $class;
198}
199
200BEGIN {
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    for ($MAX_EXP_F = 1 ; ; $MAX_EXP_F++) {         # when $MAX_EXP_F = 5
224        my $MAX_EXP_FM1 = $MAX_EXP_F - 1;           #   = 4
225        my $bs = "1" . ("0" x $MAX_EXP_F);          #   = "100000"
226        my $xs = "9" x $MAX_EXP_F;                  #   =  "99999"
227        my $cs = ("9" x $MAX_EXP_FM1) . "8";        #   =  "99998"
228        my $ys = $cs . ("0" x $MAX_EXP_FM1) . "1";  #   = "9999800001"
229
230        # Compute and check the product.
231        my $yn = $xs * $xs;                         #   = 9999800001
232        last if $yn != $ys;
233
234        # Compute and check the remainder.
235        my $rn = $yn % $bs;                         #   = 1
236        last if $rn != 1;
237
238        # Compute and check the carry. The division here is exact.
239        my $cn = ($yn - $rn) / $bs;                 #   = 99998
240        last if $cn != $cs;
241
242        # Compute and check product plus carry.
243        my $zs = $cs . ("9" x $MAX_EXP_F);          #   = "9999899999"
244        my $zn = $yn + $cn;                         #   = 99998999999
245        last if $zn != $zs;
246        last if $zn - ($zn - 1) != 1;
247    }
248    $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    my $umax = ~0;                      # largest unsigned integer
259    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        my $MAX_EXP_IM1 = $MAX_EXP_I - 1;           #   = 4
264        my $bs = "1" . ("0" x $MAX_EXP_I);          #   = "100000"
265        my $xs = "9" x $MAX_EXP_I;                  #   =  "99999"
266        my $cs = ("9" x $MAX_EXP_IM1) . "8";        #   =  "99998"
267        my $ys = $cs . ("0" x $MAX_EXP_IM1) . "1";  #   = "9999800001"
268
269        # Compute and check the product.
270        my $yn = $xs * $xs;                         #   = 9999800001
271        next if $yn != $ys;
272
273        # Compute and check the remainder.
274        my $rn = $yn % $bs;                         #   = 1
275        next if $rn != 1;
276
277        # Compute and check the carry. The division here is exact.
278        my $cn = ($yn - $rn) / $bs;                 #   = 99998
279        next if $cn != $cs;
280
281        # Compute and check product plus carry.
282        my $zs = $cs . ("9" x $MAX_EXP_I);          #   = "9999899999"
283        my $zn = $yn + $cn;                         #   = 99998999999
284        next if $zn != $zs;
285        next if $zn - ($zn - 1) != 1;
286        last;
287    }
288
289    ($BASE_LEN, $USE_INT) = $MAX_EXP_F > $MAX_EXP_I
290                          ? ($MAX_EXP_F, 0) : ($MAX_EXP_I, 1);
291
292    __PACKAGE__ -> _base_len($BASE_LEN, $USE_INT);
293}
294
295###############################################################################
296
297sub _zero {
298    # create a zero
299    my $class = shift;
300    return bless [ 0 ], $class;
301}
302
303sub _one {
304    # create a one
305    my $class = shift;
306    return bless [ 1 ], $class;
307}
308
309sub _two {
310    # create a two
311    my $class = shift;
312    return bless [ 2 ], $class;
313}
314
315sub _ten {
316    # create a 10
317    my $class = shift;
318    my $self = $BASE_LEN == 1 ? [ 0, 1 ] : [ 10 ];
319    bless $self, $class;
320}
321
322sub _1ex {
323    # create a 1Ex
324    my $class = shift;
325
326    my $rem = $_[0] % $BASE_LEN;                # remainder
327    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    bless [ (0) x $div,  0 + ("1" . ("0" x $rem)) ], $class;
332}
333
334sub _copy {
335    # make a true copy
336    my $class = shift;
337    return bless [ @{ $_[0] } ], $class;
338}
339
340sub import {
341    my $self = shift;
342
343    my $opts;
344    my ($base_len, $use_int);
345    while (@_) {
346        my $param = shift;
347        croak "Parameter name must be a non-empty string"
348          unless defined $param && length $param;
349        croak "Missing value for parameter '$param'"
350          unless @_;
351        my $value = shift;
352
353        if ($param eq 'base_len' || $param eq 'use_int') {
354            $opts -> {$param} = $value;
355            next;
356        }
357
358        croak "Unknown parameter '$param'";
359    }
360
361    $base_len = exists $opts -> {base_len} ? $opts -> {base_len} : $BASE_LEN;
362    $use_int  = exists $opts -> {use_int}  ? $opts -> {use_int}  : $USE_INT;
363    __PACKAGE__ -> _base_len($base_len, $use_int);
364
365    return $self;
366}
367
368##############################################################################
369# convert back to string and number
370
371sub _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    my $ary = $_[1];
376    my $idx = $#$ary;           # index of last element
377
378    if ($idx < 0) {             # should not happen
379        croak("$_[1] has no elements");
380    }
381
382    # Handle first one differently, since it should not have any leading zeros.
383    my $ret = int($ary->[$idx]);
384    if ($idx > 0) {
385        # Interestingly, the pre-padd method uses more time.
386        # The old grep variant takes longer (14 vs. 10 sec).
387        my $z = '0' x ($BASE_LEN - 1);
388        while (--$idx >= 0) {
389            $ret .= substr($z . $ary->[$idx], -$BASE_LEN);
390        }
391    }
392    $ret;
393}
394
395sub _num {
396    # Make a Perl scalar number (int/float) from a BigInt object.
397    my $x = $_[1];
398
399    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    my $num = 0;
407    for (my $i = $#$x ; $i >= 0 ; --$i) {
408        $num *= $BASE;
409        $num += $x -> [$i];
410    }
411    return $num;
412}
413
414##############################################################################
415# actual math code
416
417sub _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    my ($c, $x, $y) = @_;
425
426    # $x + 0 => $x
427
428    return $x if @$y == 1 && $y->[0] == 0;
429
430    # 0 + $y => $y->copy
431
432    if (@$x == 1 && $x->[0] == 0) {
433        @$x = @$y;
434        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    my $car = 0;
442    my $j = 0;
443    for my $i (@$y) {
444        $x->[$j] -= $BASE if $car = (($x->[$j] += $i + $car) >= $BASE) ? 1 : 0;
445        $j++;
446    }
447    while ($car != 0) {
448        $x->[$j] -= $BASE if $car = (($x->[$j] += $car) >= $BASE) ? 1 : 0;
449        $j++;
450    }
451    $x;
452}
453
454sub _inc {
455    # (ref to int_num_array, ref to int_num_array)
456    # Add 1 to $x, modify $x in place
457    my ($c, $x) = @_;
458
459    for my $i (@$x) {
460        return $x if ($i += 1) < $BASE; # early out
461        $i = 0;                         # overflow, next
462    }
463    push @$x, 1 if $x->[-1] == 0;       # last overflowed, so extend
464    $x;
465}
466
467sub _dec {
468    # (ref to int_num_array, ref to int_num_array)
469    # Sub 1 from $x, modify $x in place
470    my ($c, $x) = @_;
471
472    my $MAX = $BASE - 1;                # since MAX_VAL based on BASE
473    for my $i (@$x) {
474        last if ($i -= 1) >= 0;         # early out
475        $i = $MAX;                      # underflow, next
476    }
477    pop @$x if $x->[-1] == 0 && @$x > 1; # last underflowed (but leave 0)
478    $x;
479}
480
481sub _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    my ($c, $sx, $sy, $s) = @_;
487
488    my $car = 0;
489    my $j = 0;
490    if (!$s) {
491        for my $i (@$sx) {
492            last unless defined $sy->[$j] || $car;
493            $i += $BASE if $car = (($i -= ($sy->[$j] || 0) + $car) < 0);
494            $j++;
495        }
496        # might leave leading zeros, so fix that
497        return __strip_zeros($sx);
498    }
499    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        $sy->[$j] += $BASE
504          if $car = ($sy->[$j] = $i - ($sy->[$j] || 0) - $car) < 0;
505        $j++;
506    }
507    # might leave leading zeros, so fix that
508    __strip_zeros($sy);
509}
510
511sub _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    my ($c, $xv, $yv) = @_;
517    use integer;
518
519    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        if (@$xv == 1) {
523            if (($xv->[0] *= $yv->[0]) >= $BASE) {
524                $xv->[0] =
525                  $xv->[0] - ($xv->[1] = $xv->[0] / $BASE) * $BASE;
526            }
527            return $xv;
528        }
529        # $x * 0 => 0
530        if ($yv->[0] == 0) {
531            @$xv = (0);
532            return $xv;
533        }
534
535        # multiply a large number a by a single element one, so speed up
536        my $y = $yv->[0];
537        my $car = 0;
538        foreach my $i (@$xv) {
539            #$i = $i * $y + $car; $car = $i / $BASE; $i -= $car * $BASE;
540            $i = $i * $y + $car;
541            $i -= ($car = $i / $BASE) * $BASE;
542        }
543        push @$xv, $car if $car != 0;
544        return $xv;
545    }
546
547    # shortcut for result $x == 0 => result = 0
548    return $xv if @$xv == 1 && $xv->[0] == 0;
549
550    # since multiplying $x with $x fails, make copy in this case
551    $yv = $c->_copy($xv) if $xv == $yv;         # same references?
552
553    my @prod = ();
554    my ($prod, $car, $cty);
555    for my $xi (@$xv) {
556        $car = 0;
557        $cty = 0;
558        # looping through this if $xi == 0 is silly - so optimize it away!
559        $xi = (shift(@prod) || 0), next if $xi == 0;
560        for my $yi (@$yv) {
561            $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
562            $prod[$cty++] = $prod - ($car = $prod / $BASE) * $BASE;
563        }
564        $prod[$cty] += $car if $car;    # need really to check for 0?
565        $xi = shift(@prod) || 0;        # || 0 makes v5.005_3 happy
566    }
567    push @$xv, @prod;
568    $xv;
569}
570
571sub _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    my ($c, $xv, $yv) = @_;
576
577    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        if (@$xv == 1) {
581            if (($xv->[0] *= $yv->[0]) >= $BASE) {
582                my $rem = $xv->[0] % $BASE;
583                $xv->[1] = ($xv->[0] - $rem) / $BASE;
584                $xv->[0] = $rem;
585            }
586            return $xv;
587        }
588        # $x * 0 => 0
589        if ($yv->[0] == 0) {
590            @$xv = (0);
591            return $xv;
592        }
593
594        # multiply a large number a by a single element one, so speed up
595        my $y = $yv->[0];
596        my $car = 0;
597        my $rem;
598        foreach my $i (@$xv) {
599            $i = $i * $y + $car;
600            $rem = $i % $BASE;
601            $car = ($i - $rem) / $BASE;
602            $i = $rem;
603        }
604        push @$xv, $car if $car != 0;
605        return $xv;
606    }
607
608    # shortcut for result $x == 0 => result = 0
609    return $xv if @$xv == 1 && $xv->[0] == 0;
610
611    # since multiplying $x with $x fails, make copy in this case
612    $yv = $c->_copy($xv) if $xv == $yv;         # same references?
613
614    my @prod = ();
615    my ($prod, $rem, $car, $cty);
616    for my $xi (@$xv) {
617        $car = 0;
618        $cty = 0;
619        # looping through this if $xi == 0 is silly - so optimize it away!
620        $xi = (shift(@prod) || 0), next if $xi == 0;
621        for my $yi (@$yv) {
622            $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
623            $rem = $prod % $BASE;
624            $car = ($prod - $rem) / $BASE;
625            $prod[$cty++] = $rem;
626        }
627        $prod[$cty] += $car if $car;    # need really to check for 0?
628        $xi = shift(@prod) || 0;        # || 0 makes v5.005_3 happy
629    }
630    push @$xv, @prod;
631    $xv;
632}
633
634sub _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    use integer;
640
641    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    if (@$x == 1 && @$yorg == 1) {
648        # shortcut, $yorg and $x are two small numbers
649        if (wantarray) {
650            my $rem = [ $x->[0] % $yorg->[0] ];
651            bless $rem, $c;
652            $x->[0] = $x->[0] / $yorg->[0];
653            return ($x, $rem);
654        } else {
655            $x->[0] = $x->[0] / $yorg->[0];
656            return $x;
657        }
658    }
659
660    # if x has more than one, but y has only one element:
661    if (@$yorg == 1) {
662        my $rem;
663        $rem = $c->_mod($c->_copy($x), $yorg) if wantarray;
664
665        # shortcut, $y is < $BASE
666        my $j = @$x;
667        my $r = 0;
668        my $y = $yorg->[0];
669        my $b;
670        while ($j-- > 0) {
671            $b = $r * $BASE + $x->[$j];
672            $r = $b % $y;
673            $x->[$j] = $b / $y;
674        }
675        pop(@$x) if @$x > 1 && $x->[-1] == 0;   # remove any trailing zero
676        return ($x, $rem) if wantarray;
677        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    if (@$yorg > @$x) {
684        my $rem;
685        $rem = $c->_copy($x) if wantarray;      # make copy
686        @$x = 0;                                # set to 0
687        return ($x, $rem) if wantarray;         # including remainder?
688        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    if (@$yorg == @$x) {
694        my $cmp = 0;
695        for (my $j = $#$x ; $j >= 0 ; --$j) {
696            last if $cmp = $x->[$j] - $yorg->[$j];
697        }
698
699        if ($cmp == 0) {        # x = y
700            @$x = 1;
701            return $x, $c->_zero() if wantarray;
702            return $x;
703        }
704
705        if ($cmp < 0) {         # x < y
706            if (wantarray) {
707                my $rem = $c->_copy($x);
708                @$x = 0;
709                return $x, $rem;
710            }
711            @$x = 0;
712            return $x;
713        }
714    }
715
716    # all other cases:
717
718    my $y = $c->_copy($yorg);           # always make copy to preserve
719
720    my $tmp;
721    my $dd = $BASE / ($y->[-1] + 1);
722    if ($dd != 1) {
723        my $car = 0;
724        for my $xi (@$x) {
725            $xi = $xi * $dd + $car;
726            $xi -= ($car = $xi / $BASE) * $BASE;
727        }
728        push(@$x, $car);
729        $car = 0;
730        for my $yi (@$y) {
731            $yi = $yi * $dd + $car;
732            $yi -= ($car = $yi / $BASE) * $BASE;
733        }
734    } else {
735        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    my @q = ();
742    my ($v2, $v1) = @$y[-2, -1];
743    $v2 = 0 unless $v2;
744    while ($#$x > $#$y) {
745        my ($u2, $u1, $u0) = @$x[-3 .. -1];
746        $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        my $tmp = $u0 * $BASE + $u1;
750        my $rem = $tmp % $v1;
751        my $q = $u0 == $v1 ? $MAX_VAL : (($tmp - $rem) / $v1);
752        --$q while $v2 * $q > ($u0 * $BASE + $u1 - $q * $v1) * $BASE + $u2;
753        if ($q) {
754            my $prd;
755            my ($car, $bar) = (0, 0);
756            for (my $yi = 0, my $xi = $#$x - $#$y - 1; $yi <= $#$y; ++$yi, ++$xi) {
757                $prd = $q * $y->[$yi] + $car;
758                $prd -= ($car = int($prd / $BASE)) * $BASE;
759                $x->[$xi] += $BASE if $bar = (($x->[$xi] -= $prd + $bar) < 0);
760            }
761            if ($x->[-1] < $car + $bar) {
762                $car = 0;
763                --$q;
764                for (my $yi = 0, my $xi = $#$x - $#$y - 1; $yi <= $#$y; ++$yi, ++$xi) {
765                    $x->[$xi] -= $BASE
766                      if $car = (($x->[$xi] += $y->[$yi] + $car) >= $BASE);
767                }
768            }
769        }
770        pop(@$x);
771        unshift(@q, $q);
772    }
773
774    if (wantarray) {
775        my $d = bless [], $c;
776        if ($dd != 1) {
777            my $car = 0;
778            my $prd;
779            for my $xi (reverse @$x) {
780                $prd = $car * $BASE + $xi;
781                $car = $prd - ($tmp = $prd / $dd) * $dd;
782                unshift @$d, $tmp;
783            }
784        } else {
785            @$d = @$x;
786        }
787        @$x = @q;
788        __strip_zeros($x);
789        __strip_zeros($d);
790        return ($x, $d);
791    }
792    @$x = @q;
793    __strip_zeros($x);
794    $x;
795}
796
797sub _div_no_int {
798    # ref to array, ref to array, modify first array and return remainder if
799    # in list context
800
801    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    if (@$x == 1 && @$yorg == 1) {
808        # shortcut, $yorg and $x are two small numbers
809        my $rem = [ $x->[0] % $yorg->[0] ];
810        bless $rem, $c;
811        $x->[0] = ($x->[0] - $rem->[0]) / $yorg->[0];
812        return ($x, $rem) if wantarray;
813        return $x;
814    }
815
816    # if x has more than one, but y has only one element:
817    if (@$yorg == 1) {
818        my $rem;
819        $rem = $c->_mod($c->_copy($x), $yorg) if wantarray;
820
821        # shortcut, $y is < $BASE
822        my $j = @$x;
823        my $r = 0;
824        my $y = $yorg->[0];
825        my $b;
826        while ($j-- > 0) {
827            $b = $r * $BASE + $x->[$j];
828            $r = $b % $y;
829            $x->[$j] = ($b - $r) / $y;
830        }
831        pop(@$x) if @$x > 1 && $x->[-1] == 0;   # remove any trailing zero
832        return ($x, $rem) if wantarray;
833        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    if (@$yorg > @$x) {
840        my $rem;
841        $rem = $c->_copy($x) if wantarray;      # make copy
842        @$x = 0;                                # set to 0
843        return ($x, $rem) if wantarray;         # including remainder?
844        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    if (@$yorg == @$x) {
850        my $cmp = 0;
851        for (my $j = $#$x ; $j >= 0 ; --$j) {
852            last if $cmp = $x->[$j] - $yorg->[$j];
853        }
854
855        if ($cmp == 0) {        # x = y
856            @$x = 1;
857            return $x, $c->_zero() if wantarray;
858            return $x;
859        }
860
861        if ($cmp < 0) {         # x < y
862            if (wantarray) {
863                my $rem = $c->_copy($x);
864                @$x = 0;
865                return $x, $rem;
866            }
867            @$x = 0;
868            return $x;
869        }
870    }
871
872    # all other cases:
873
874    my $y = $c->_copy($yorg);           # always make copy to preserve
875
876    my $tmp = $y->[-1] + 1;
877    my $rem = $BASE % $tmp;
878    my $dd  = ($BASE - $rem) / $tmp;
879    if ($dd != 1) {
880        my $car = 0;
881        for my $xi (@$x) {
882            $xi = $xi * $dd + $car;
883            $rem = $xi % $BASE;
884            $car = ($xi - $rem) / $BASE;
885            $xi = $rem;
886        }
887        push(@$x, $car);
888        $car = 0;
889        for my $yi (@$y) {
890            $yi = $yi * $dd + $car;
891            $rem = $yi % $BASE;
892            $car = ($yi - $rem) / $BASE;
893            $yi = $rem;
894        }
895    } else {
896        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    my @q = ();
903    my ($v2, $v1) = @$y[-2, -1];
904    $v2 = 0 unless $v2;
905    while ($#$x > $#$y) {
906        my ($u2, $u1, $u0) = @$x[-3 .. -1];
907        $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        my $tmp = $u0 * $BASE + $u1;
911        my $rem = $tmp % $v1;
912        my $q = $u0 == $v1 ? $MAX_VAL : (($tmp - $rem) / $v1);
913        --$q while $v2 * $q > ($u0 * $BASE + $u1 - $q * $v1) * $BASE + $u2;
914        if ($q) {
915            my $prd;
916            my ($car, $bar) = (0, 0);
917            for (my $yi = 0, my $xi = $#$x - $#$y - 1; $yi <= $#$y; ++$yi, ++$xi) {
918                $prd = $q * $y->[$yi] + $car;
919                $rem = $prd % $BASE;
920                $car = ($prd - $rem) / $BASE;
921                $prd -= $car * $BASE;
922                $x->[$xi] += $BASE if $bar = (($x->[$xi] -= $prd + $bar) < 0);
923            }
924            if ($x->[-1] < $car + $bar) {
925                $car = 0;
926                --$q;
927                for (my $yi = 0, my $xi = $#$x - $#$y - 1; $yi <= $#$y; ++$yi, ++$xi) {
928                    $x->[$xi] -= $BASE
929                      if $car = (($x->[$xi] += $y->[$yi] + $car) >= $BASE);
930                }
931            }
932        }
933        pop(@$x);
934        unshift(@q, $q);
935    }
936
937    if (wantarray) {
938        my $d = bless [], $c;
939        if ($dd != 1) {
940            my $car = 0;
941            my ($prd, $rem);
942            for my $xi (reverse @$x) {
943                $prd = $car * $BASE + $xi;
944                $rem = $prd % $dd;
945                $tmp = ($prd - $rem) / $dd;
946                $car = $rem;
947                unshift @$d, $tmp;
948            }
949        } else {
950            @$d = @$x;
951        }
952        @$x = @q;
953        __strip_zeros($x);
954        __strip_zeros($d);
955        return ($x, $d);
956    }
957    @$x = @q;
958    __strip_zeros($x);
959    $x;
960}
961
962##############################################################################
963# testing
964
965sub _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    my ($c, $cx, $cy) = @_;
970
971    # shortcut for short numbers
972    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    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    return -1 if $lxy < 0;      # already differs, ret
983    return  1 if $lxy > 0;      # ditto
984
985    # manual way (abort if unequal, good for early ne)
986    my $a;
987    my $j = @$cx;
988    while (--$j >= 0) {
989        last if $a = $cx->[$j] - $cy->[$j];
990    }
991    $a <=> 0;
992}
993
994sub _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    my $cx = $_[1];
1000
1001    (@$cx - 1) * $BASE_LEN + length(int($cx->[-1]));
1002}
1003
1004sub _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    my ($c, $x, $n) = @_;
1008
1009    my $len = _len('', $x);
1010
1011    $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    return "0" if $n < 0 || $n >= $len; # return 0 for digits out of range
1017
1018    my $elem = int($n / $BASE_LEN);     # index of array element
1019    my $digit = $n % $BASE_LEN;         # index of digit within the element
1020    substr("0" x $BASE_LEN . "$x->[$elem]", -1 - $digit, 1);
1021}
1022
1023sub _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    my $x = $_[1];
1029
1030    return 0 if @$x == 1 && $x->[0] == 0;
1031
1032    my $zeros = 0;
1033    foreach my $elem (@$x) {
1034        if ($elem != 0) {
1035            $elem =~ /[^0](0*)\z/;
1036            $zeros += length($1);       # count trailing zeros
1037            last;                       # early out
1038        }
1039        $zeros += $BASE_LEN;
1040    }
1041    $zeros;
1042}
1043
1044##############################################################################
1045# _is_* routines
1046
1047sub _is_zero {
1048    # return true if arg is zero
1049    @{$_[1]} == 1 && $_[1]->[0] == 0 ? 1 : 0;
1050}
1051
1052sub _is_even {
1053    # return true if arg is even
1054    $_[1]->[0] % 2 ? 0 : 1;
1055}
1056
1057sub _is_odd {
1058    # return true if arg is odd
1059    $_[1]->[0] % 2 ? 1 : 0;
1060}
1061
1062sub _is_one {
1063    # return true if arg is one
1064    @{$_[1]} == 1 && $_[1]->[0] == 1 ? 1 : 0;
1065}
1066
1067sub _is_two {
1068    # return true if arg is two
1069    @{$_[1]} == 1 && $_[1]->[0] == 2 ? 1 : 0;
1070}
1071
1072sub _is_ten {
1073    # return true if arg is ten
1074    if ($BASE_LEN == 1) {
1075        @{$_[1]} == 2 && $_[1]->[0] == 0 && $_[1]->[1] == 1 ? 1 : 0;
1076    } else {
1077        @{$_[1]} == 1 && $_[1]->[0] == 10 ? 1 : 0;
1078    }
1079}
1080
1081sub __strip_zeros {
1082    # Internal normalization function that strips leading zeros from the array.
1083    # Args: ref to array
1084    my $x = shift;
1085
1086    push @$x, 0 if @$x == 0;    # div might return empty results, so fix it
1087    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    my $i = $#$x;
1099    while ($i > 0) {
1100        last if $x->[$i] != 0;
1101        $i--;
1102    }
1103    $i++;
1104    splice(@$x, $i) if $i < @$x;
1105    $x;
1106}
1107
1108###############################################################################
1109# check routine to test internal state for corruptions
1110
1111sub _check {
1112    # used by the test suite
1113    my ($class, $x) = @_;
1114
1115    my $msg = $class -> SUPER::_check($x);
1116    return $msg if $msg;
1117
1118    my $n;
1119    eval { $n = @$x };
1120    return "Not an array reference" unless $@ eq '';
1121
1122    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    for (my $i = 0 ; $i <= $#$x ; ++ $i) {
1130        my $e = $x -> [$i];
1131
1132        return "Element at index $i is undefined"
1133          unless defined $e;
1134
1135        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        return "Element at index $i is '$e', which does not look like an" .
1143          " normal integer" unless $e =~ /^\d+\z/;
1144
1145        return "Element at index $i is '$e', which is not smaller than" .
1146          " the base '$BASE'" if $e >= $BASE;
1147
1148        return "Element at index $i (last element) is zero"
1149          if $#$x > 0 && $i == $#$x && $e == 0;
1150    }
1151
1152    return 0;
1153}
1154
1155###############################################################################
1156
1157sub _mod {
1158    # if possible, use mod shortcut
1159    my ($c, $x, $yo) = @_;
1160
1161    # slow way since $y too big
1162    if (@$yo > 1) {
1163        my ($xo, $rem) = $c->_div($x, $yo);
1164        @$x = @$rem;
1165        return $x;
1166    }
1167
1168    my $y = $yo->[0];
1169
1170    # if both are single element arrays
1171    if (@$x == 1) {
1172        $x->[0] %= $y;
1173        return $x;
1174    }
1175
1176    # if @$x has more than one element, but @$y is a single element
1177    my $b = $BASE % $y;
1178    if ($b == 0) {
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        $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        my $r = 0;
1187        foreach (@$x) {
1188            $r = ($r + $_) % $y; # not much faster, but heh...
1189            #$r += $_ % $y; $r %= $y;
1190        }
1191        $r = 0 if $r == $y;
1192        $x->[0] = $r;
1193    } else {
1194        # else need to go through all elements in @$x: O(N)
1195        my $r = 0;
1196        my $bm = 1;
1197        foreach (@$x) {
1198            $r = ($_ * $bm + $r) % $y;
1199            $bm = ($bm * $b) % $y;
1200
1201            #$r += ($_ % $y) * $bm;
1202            #$bm *= $b;
1203            #$bm %= $y;
1204            #$r %= $y;
1205        }
1206        $r = 0 if $r == $y;
1207        $x->[0] = $r;
1208    }
1209    @$x = $x->[0];              # keep one element of @$x
1210    return $x;
1211}
1212
1213##############################################################################
1214# shifts
1215
1216sub _rsft {
1217    my ($c, $x, $n, $b) = @_;
1218    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    $b = $c->_new($b) unless ref $b;
1223
1224    if ($c -> _acmp($b, $c -> _ten())) {
1225        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    my $dst = 0;                # destination
1231    my $src = $c->_num($n);     # as normal int
1232    my $xlen = (@$x - 1) * $BASE_LEN + length(int($x->[-1]));
1233    if ($src >= $xlen or ($src == $xlen and !defined $x->[1])) {
1234        # 12345 67890 shifted right by more than 10 digits => 0
1235        splice(@$x, 1);         # leave only one element
1236        $x->[0] = 0;            # set to zero
1237        return $x;
1238    }
1239    my $rem = $src % $BASE_LEN;   # remainder to shift
1240    $src = int($src / $BASE_LEN); # source
1241    if ($rem == 0) {
1242        splice(@$x, 0, $src);   # even faster, 38.4 => 39.3
1243    } else {
1244        my $len = @$x - $src;   # elems to go
1245        my $vd;
1246        my $z = '0' x $BASE_LEN;
1247        $x->[ @$x ] = 0;          # avoid || 0 test inside loop
1248        while ($dst < $len) {
1249            $vd = $z . $x->[$src];
1250            $vd = substr($vd, -$BASE_LEN, $BASE_LEN - $rem);
1251            $src++;
1252            $vd = substr($z . $x->[$src], -$rem, $rem) . $vd;
1253            $vd = substr($vd, -$BASE_LEN, $BASE_LEN) if length($vd) > $BASE_LEN;
1254            $x->[$dst] = int($vd);
1255            $dst++;
1256        }
1257        splice(@$x, $dst) if $dst > 0;       # kill left-over array elems
1258        pop(@$x) if $x->[-1] == 0 && @$x > 1; # kill last element if 0
1259    }                                        # else rem == 0
1260    $x;
1261}
1262
1263sub _lsft {
1264    my ($c, $x, $n, $b) = @_;
1265
1266    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    $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    my $bstr = $c->_str($b);
1276    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        my $log10b = length($1);
1282        $n = $c->_mul($c->_new($log10b), $n);
1283        $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        my $r = $n % $BASE_LEN;
1290        my $q = ($n - $r) / $BASE_LEN;
1291
1292        # If we must shift the values within the elements ...
1293
1294        if ($r) {
1295            my $i = @$x;                # index
1296            $x->[$i] = 0;               # initialize most significant element
1297            my $z = '0' x $BASE_LEN;
1298            my $vd;
1299            while ($i >= 0) {
1300                $vd = $x->[$i];
1301                $vd = $z . $vd;
1302                $vd = substr($vd, $r - $BASE_LEN, $BASE_LEN - $r);
1303                $vd .= $i > 0 ? substr($z . $x->[$i - 1], -$BASE_LEN, $r)
1304                              : '0' x $r;
1305                $vd = substr($vd, -$BASE_LEN, $BASE_LEN) if length($vd) > $BASE_LEN;
1306                $x->[$i] = int($vd);    # e.g., "0...048" -> 48 etc.
1307                $i--;
1308            }
1309
1310            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        if ($q) {
1316            unshift @$x, (0) x $q;
1317        }
1318
1319    } else {
1320        $x = $c->_mul($x, $c->_pow($b, $n));
1321    }
1322
1323    return $x;
1324}
1325
1326sub _pow {
1327    # power of $x to $y
1328    # ref to array, ref to array, return ref to array
1329    my ($c, $cx, $cy) = @_;
1330
1331    if (@$cy == 1 && $cy->[0] == 0) {
1332        splice(@$cx, 1);
1333        $cx->[0] = 1;           # y == 0 => x => 1
1334        return $cx;
1335    }
1336
1337    if ((@$cx == 1 && $cx->[0] == 1) || #    x == 1
1338        (@$cy == 1 && $cy->[0] == 1))   # or y == 1
1339    {
1340        return $cx;
1341    }
1342
1343    if (@$cx == 1 && $cx->[0] == 0) {
1344        splice (@$cx, 1);
1345        $cx->[0] = 0;           # 0 ** y => 0 (if not y <= 0)
1346        return $cx;
1347    }
1348
1349    my $pow2 = $c->_one();
1350
1351    my $y_bin = $c->_as_bin($cy);
1352    $y_bin =~ s/^0b//;
1353    my $len = length($y_bin);
1354    while (--$len > 0) {
1355        $c->_mul($pow2, $cx) if substr($y_bin, $len, 1) eq '1'; # is odd?
1356        $c->_mul($cx, $cx);
1357    }
1358
1359    $c->_mul($cx, $pow2);
1360    $cx;
1361}
1362
1363sub _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    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        my $twok = $c->_mul($c->_two(), $c->_copy($k)); # 2 * k
1375        if ($c->_acmp($twok, $n) > 0) {               # if 2*k > n
1376            $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    if ($c->_is_zero($k)) {
1387        @$n = 1;
1388    } else {
1389
1390        # Make a copy of the original n, since we'll be modifying n in-place.
1391
1392        my $n_orig = $c->_copy($n);
1393
1394        # n = 5, f = 6, d = 2 (cf. example above)
1395
1396        $c->_sub($n, $k);
1397        $c->_inc($n);
1398
1399        my $f = $c->_copy($n);
1400        $c->_inc($f);
1401
1402        my $d = $c->_two();
1403
1404        # while f <= n (the original n, that is) ...
1405
1406        while ($c->_acmp($f, $n_orig) <= 0) {
1407
1408            # n = (n * f / d) == 5 * 6 / 2 (cf. example above)
1409
1410            $c->_mul($n, $f);
1411            $c->_div($n, $d);
1412
1413            # f = 7, d = 3 (cf. example above)
1414
1415            $c->_inc($f);
1416            $c->_inc($d);
1417        }
1418
1419    }
1420
1421    return $n;
1422}
1423
1424sub _fac {
1425    # factorial of $x
1426    # ref to array, return ref to array
1427    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    if (@$cx == 1) {
1433        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        if ($cx->[0] <= $#factorials) {
1447            my $tmp = $c -> _new($factorials[ $cx->[0] ]);
1448            @$cx = @$tmp;
1449            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    if ($BASE_LEN <= 2) {
1461        my $tmp = $c -> SUPER::_fac($cx);
1462        @$cx = @$tmp;
1463        return $cx;
1464    }
1465
1466    # This code does not work for small values of $BASE_LEN.
1467
1468    if ((@$cx == 1) &&          # we do this only if $x >= 12 and $x <= 7000
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        my $zero_elements = 0;
1484
1485        # If n is even, set n = n -1
1486        my $k = $c->_num($cx);
1487        my $even = 1;
1488        if (($k & 1) == 0) {
1489            $even = $k;
1490            $k --;
1491        }
1492        # set k to the center point
1493        $k = ($k + 1) / 2;
1494        #  print "k $k even: $even\n";
1495        # now calculate k * k
1496        my $k2 = $k * $k;
1497        my $odd = 1;
1498        my $sum = 1;
1499        my $i = $k - 1;
1500        # keep reference to x
1501        my $new_x = $c->_new($k * $even);
1502        @$cx = @$new_x;
1503        if ($cx->[0] == 0) {
1504            $zero_elements ++;
1505            shift @$cx;
1506        }
1507        #  print STDERR "x = ", $c->_str($cx), "\n";
1508        my $BASE2 = int(sqrt($BASE))-1;
1509        my $j = 1;
1510        while ($j <= $i) {
1511            my $m = ($k2 - $sum);
1512            $odd += 2;
1513            $sum += $odd;
1514            $j++;
1515            while ($j <= $i && ($m < $BASE2) && (($k2 - $sum) < $BASE2)) {
1516                $m *= ($k2 - $sum);
1517                $odd += 2;
1518                $sum += $odd;
1519                $j++;
1520                #      print STDERR "\n k2 $k2 m $m sum $sum odd $odd\n"; sleep(1);
1521            }
1522            if ($m < $BASE) {
1523                $c->_mul($cx, [$m]);
1524            } else {
1525                $c->_mul($cx, $c->_new($m));
1526            }
1527            if ($cx->[0] == 0) {
1528                $zero_elements ++;
1529                shift @$cx;
1530            }
1531            #    print STDERR "Calculate $k2 - $sum = $m (x = ", $c->_str($cx), ")\n";
1532        }
1533        # multiply in the zeros again
1534        unshift @$cx, (0) x $zero_elements;
1535        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    my $steps = 100;
1541    $steps = $cx->[0] if @$cx == 1;
1542    my $r = 2;
1543    my $cf = 3;
1544    my $step = 2;
1545    my $last = $r;
1546    while ($r * $cf < $BASE && $step < $steps) {
1547        $last = $r;
1548        $r *= $cf++;
1549        $step++;
1550    }
1551    if ((@$cx == 1) && $step == $cx->[0]) {
1552        # completely done, so keep reference to $x and return
1553        $cx->[0] = $r;
1554        return $cx;
1555    }
1556
1557    # now we must do the left over steps
1558    my $n;                      # steps still to do
1559    if (@$cx == 1) {
1560        $n = $cx->[0];
1561    } else {
1562        $n = $c->_copy($cx);
1563    }
1564
1565    # Set $cx to the last result below $BASE (but keep ref to $x)
1566    $cx->[0] = $last;
1567    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    my $zero_elements = 0;
1572
1573    # do left-over steps fit into a scalar?
1574    if (ref $n eq 'ARRAY') {
1575        # No, so use slower inc() & cmp()
1576        # ($n is at least $BASE here)
1577        my $base_2 = int(sqrt($BASE)) - 1;
1578        #print STDERR "base_2: $base_2\n";
1579        while ($step < $base_2) {
1580            if ($cx->[0] == 0) {
1581                $zero_elements ++;
1582                shift @$cx;
1583            }
1584            my $b = $step * ($step + 1);
1585            $step += 2;
1586            $c->_mul($cx, [$b]);
1587        }
1588        $step = [$step];
1589        while ($c->_acmp($step, $n) <= 0) {
1590            if ($cx->[0] == 0) {
1591                $zero_elements ++;
1592                shift @$cx;
1593            }
1594            $c->_mul($cx, $step);
1595            $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        my $base_4 = int(sqrt(sqrt($BASE))) - 2;
1603        #print STDERR "base_4: $base_4\n";
1604        my $n4 = $n - 4;
1605        while ($step < $n4 && $step < $base_4) {
1606            if ($cx->[0] == 0) {
1607                $zero_elements ++;
1608                shift @$cx;
1609            }
1610            my $b = $step * ($step + 1);
1611            $step += 2;
1612            $b *= $step * ($step + 1);
1613            $step += 2;
1614            $c->_mul($cx, [$b]);
1615        }
1616        my $base_2 = int(sqrt($BASE)) - 1;
1617        my $n2 = $n - 2;
1618        #print STDERR "base_2: $base_2\n";
1619        while ($step < $n2 && $step < $base_2) {
1620            if ($cx->[0] == 0) {
1621                $zero_elements ++;
1622                shift @$cx;
1623            }
1624            my $b = $step * ($step + 1);
1625            $step += 2;
1626            $c->_mul($cx, [$b]);
1627        }
1628        # do what's left over
1629        while ($step <= $n) {
1630            $c->_mul($cx, [$step]);
1631            $step++;
1632            if ($cx->[0] == 0) {
1633                $zero_elements ++;
1634                shift @$cx;
1635            }
1636        }
1637    }
1638    # multiply in the zeros again
1639    unshift @$cx, (0) x $zero_elements;
1640    $cx;                        # return result
1641}
1642
1643sub _log_int {
1644    # calculate integer log of $x to base $base
1645    # ref to array, ref to array - return ref to array
1646    my ($c, $x, $base) = @_;
1647
1648    # X == 0 => NaN
1649    return if @$x == 1 && $x->[0] == 0;
1650
1651    # BASE 0 or 1 => NaN
1652    return if @$base == 1 && $base->[0] < 2;
1653
1654    # X == 1 => 0 (is exact)
1655    if (@$x == 1 && $x->[0] == 1) {
1656        @$x = 0;
1657        return $x, 1;
1658    }
1659
1660    my $cmp = $c->_acmp($x, $base);
1661
1662    # X == BASE => 1 (is exact)
1663    if ($cmp == 0) {
1664        @$x = 1;
1665        return $x, 1;
1666    }
1667
1668    # 1 < X < BASE => 0 (is truncated)
1669    if ($cmp < 0) {
1670        @$x = 0;
1671        return $x, 0;
1672    }
1673
1674    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    my $len = $c->_len($x_org);
1679    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    $log += (@$base - 1) * $BASE_LEN;
1685
1686    # calculate now a guess based on the values obtained above:
1687    my $res = $c->_new(int($len / $log));
1688
1689    @$x = @$res;
1690    my $trial = $c->_pow($c->_copy($base), $x);
1691    my $acmp = $c->_acmp($trial, $x_org);
1692
1693    # Did we get the exact result?
1694
1695    return $x, 1 if $acmp == 0;
1696
1697    # Too small?
1698
1699    while ($acmp < 0) {
1700        $c->_mul($trial, $base);
1701        $c->_inc($x);
1702        $acmp = $c->_acmp($trial, $x_org);
1703    }
1704
1705    # Too big?
1706
1707    while ($acmp > 0) {
1708        $c->_div($trial, $base);
1709        $c->_dec($x);
1710        $acmp = $c->_acmp($trial, $x_org);
1711    }
1712
1713    return $x, 1 if $acmp == 0;         # result is exact
1714    return $x, 0;                       # result is too small
1715}
1716
1717sub _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    my ($c, $x) = @_;
1726    ($x, my $is_exact) = $c -> _log_int($x, $c -> _two());
1727    return wantarray ? ($x, $is_exact) : $x;
1728}
1729
1730sub _ilog10 {
1731    # calculate int(log10($x))
1732
1733    my ($c, $x) = @_;
1734
1735    # X == 0 => NaN
1736    return if @$x == 1 && $x->[0] == 0;
1737
1738    # X == 1 => 0 (is exact)
1739    if (@$x == 1 && $x->[0] == 1) {
1740        @$x = 0;
1741        return wantarray ? ($x, 1) : $x;
1742    }
1743
1744    my $x_orig = $c -> _copy($x);
1745    my $nm1 = $c -> _len($x) - 1;
1746
1747    my $xtmp = $c -> _new($nm1);
1748    @$x = @$xtmp;
1749
1750    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    my $is_pow10 = 1;
1757    for my $i (0 .. $#$x_orig - 1) {
1758        last unless $is_pow10 = $x_orig->[$i] == 0;
1759    }
1760    $is_pow10 &&= $x_orig->[-1] == 10**int(0.5 + log($x_orig->[-1]) / log(10));
1761
1762    return wantarray ? ($x, 1) : $x if $is_pow10;
1763    return wantarray ? ($x, 0) : $x;
1764}
1765
1766sub _clog2 {
1767    # calculate ceil(log2($x))
1768
1769    my ($c, $x) = @_;
1770
1771    # X == 0 => NaN
1772
1773    return if @$x == 1 && $x->[0] == 0;
1774
1775    # X == 1 => 0 (is exact)
1776
1777    if (@$x == 1 && $x->[0] == 1) {
1778        @$x = 0;
1779        return wantarray ? ($x, 1) : $x;
1780    }
1781
1782    my $base = $c -> _two();
1783    my $acmp = $c -> _acmp($x, $base);
1784
1785    # X == BASE => 1 (is exact)
1786
1787    if ($acmp == 0) {
1788        @$x = 1;
1789        return wantarray ? ($x, 1) : $x;
1790    }
1791
1792    # 1 < X < BASE => 0 (is truncated)
1793
1794    if ($acmp < 0) {
1795        @$x = 0;
1796        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    my $len    = $c -> _len($x);
1803    my $log    = log(2) / log(10);
1804    my $guess  = $c -> _new(int($len / $log));
1805    my $x_orig = $c -> _copy($x);
1806    @$x = @$guess;
1807
1808    my $trial = $c -> _pow($c -> _copy($base), $x);
1809    $acmp = $c -> _acmp($trial, $x_orig);
1810
1811    # Too big?
1812
1813    while ($acmp > 0) {
1814        $c -> _div($trial, $base);
1815        $c -> _dec($x);
1816        $acmp = $c -> _acmp($trial, $x_orig);
1817    }
1818
1819    # Too small?
1820
1821    while ($acmp < 0) {
1822        $c -> _mul($trial, $base);
1823        $c -> _inc($x);
1824        $acmp = $c -> _acmp($trial, $x_orig);
1825    }
1826
1827    return wantarray ? ($x, 1) : $x if $acmp == 0;      # result is exact
1828    return wantarray ? ($x, 0) : $x;                    # result is too small
1829}
1830
1831sub _clog10 {
1832    # calculate ceil(log2($x))
1833    my ($c, $x) = @_;
1834
1835    # X == 0 => NaN
1836    return if @$x == 1 && $x->[0] == 0;
1837
1838    # X == 1 => 0 (is exact)
1839    if (@$x == 1 && $x->[0] == 1) {
1840        @$x = 0;
1841        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    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    my $is_pow10 = 1;
1853    for my $i (0 .. $#$x - 1) {
1854        last unless $is_pow10 = $x->[$i] == 0;
1855    }
1856    $is_pow10 &&= $x->[-1] == 10**int(0.5 + log($x->[-1]) / log(10));
1857
1858    $n-- if $is_pow10;
1859
1860    my $xtmp = $c ->_new($n);
1861    @$x = @$xtmp;
1862
1863    return wantarray ? ($x, 1) : $x if $is_pow10;       # result is exact
1864    return wantarray ? ($x, 0) : $x;                    # result is too small
1865}
1866
1867# for debugging:
1868use constant DEBUG => 0;
1869my $steps = 0;
1870sub steps { $steps };
1871
1872sub _sqrt {
1873    # square-root of $x in-place
1874
1875    my ($c, $x) = @_;
1876
1877    if (@$x == 1) {
1878        # fits into one Perl scalar, so result can be computed directly
1879        $x->[0] = int(sqrt($x->[0]));
1880        return $x;
1881    }
1882
1883    # Create an initial guess for the square root.
1884
1885    my $s;
1886    if (@$x % 2) {
1887        $s = [ (0) x ((@$x - 1) / 2), int(sqrt($x->[-1])) ];
1888    } else {
1889        $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    my $cmp;
1899    while (1) {
1900        my $sq = $c -> _mul($c -> _copy($s), $s);
1901        $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        if ($cmp > 0) {
1910            my $num = $c -> _sub($c -> _copy($sq), $x);
1911            my $den = $c -> _mul($c -> _two(), $s);
1912            my $delta = $c -> _div($num, $den);
1913            last if $c -> _is_zero($delta);
1914            $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            my $num = $c -> _sub($c -> _copy($x), $sq);
1925            my $den = $c -> _mul($c -> _two(), $s);
1926            my $delta = $c -> _div($num, $den);
1927            last if $c -> _is_zero($delta);
1928            $s = $c -> _add($s, $delta);
1929        }
1930
1931        # If x(n)*x(n) = y, we have the exact result.
1932
1933        else {
1934            last;
1935        }
1936    }
1937
1938    $s = $c -> _dec($s) if $cmp > 0;    # never overshoot
1939    @$x = @$s;
1940    return $x;
1941}
1942
1943sub _root {
1944    # Take n'th root of $x in place.
1945
1946    my ($c, $x, $n) = @_;
1947
1948    # Small numbers.
1949
1950    if (@$x == 1) {
1951        return $x if $x -> [0] == 0 || $x -> [0] == 1;
1952
1953        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            my $y = int($x->[0] ** (1 / $n->[0]));
1957            my $yp1 = $y + 1;
1958            $y = $yp1 if $yp1 ** $n->[0] == $x->[0];
1959            $x->[0] = $y;
1960            return $x;
1961        }
1962    }
1963
1964    # If x <= n, the result is always (truncated to) 1.
1965
1966    if ((@$x > 1 || $x -> [0] > 0) &&           # if x is non-zero ...
1967        $c -> _acmp($x, $n) <= 0)               # ... and x <= n
1968    {
1969        my $one = $c -> _one();
1970        @$x = @$one;
1971        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    my $b = $c -> _as_bin($n);
1978    if ($b =~ /0b1(0+)$/) {
1979        my $count = length($1);       # 0b100 => len('00') => 2
1980        my $cnt = $count;             # counter for loop
1981        unshift @$x, 0;               # add one element, together with one
1982                                      #   more below in the loop this makes 2
1983        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            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            $c -> _sqrt($x);
1991        }
1992
1993        # $x is now one element too big, so truncate result by removing it.
1994        shift @$x;
1995
1996        return $x;
1997    }
1998
1999    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    my $x_str = $c -> _str($x);
2013    my $xm    = "." . $x_str;
2014    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    my $log10x = log($xm) / log(10) + $xe;
2026    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    my $ye = int $log10y;
2032    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    if ($DEBUG) {
2038        print "\n";
2039        print "xm     = $xm\n";
2040        print "xe     = $xe\n";
2041        print "log10x = $log10x\n";
2042        print "log10y = $log10y\n";
2043        print "ym     = $ym\n";
2044        print "ye     = $ye\n";
2045        print "\n";
2046    }
2047
2048    my $d = $ye < 15 ? $ye : 15;
2049    $ym *= 10 ** $d;
2050    $ye -= $d;
2051
2052    my $y_str = sprintf('%.0f', $ym) . "0" x $ye;
2053    my $y = $c -> _new($y_str);
2054
2055    if ($DEBUG) {
2056        print "ym     = $ym\n";
2057        print "ye     = $ye\n";
2058        print "\n";
2059        print "y_str  = $y_str (initial guess)\n";
2060        print "\n";
2061    }
2062
2063    # See if our guess y is correct.
2064
2065    my $trial = $c -> _pow($c -> _copy($y), $n);
2066    my $acmp  = $c -> _acmp($trial, $x);
2067
2068    if ($acmp == 0) {
2069        @$x = @$y;
2070        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    my $lower;
2077    my $upper;
2078
2079    my $delta = $c -> _new("1" . ("0" x $ye));
2080    my $two   = $c -> _two();
2081
2082    if ($acmp < 0) {
2083        $lower = $y;
2084        while ($acmp < 0) {
2085            $upper = $c -> _add($c -> _copy($lower), $delta);
2086
2087            if ($DEBUG) {
2088                print "lower  = $lower\n";
2089                print "upper  = $upper\n";
2090                print "delta  = $delta\n";
2091                print "\n";
2092            }
2093            $acmp  = $c -> _acmp($c -> _pow($c -> _copy($upper), $n), $x);
2094            if ($acmp == 0) {
2095                @$x = @$upper;
2096                return $x;
2097            }
2098            $delta = $c -> _mul($delta, $two);
2099        }
2100    }
2101
2102    elsif ($acmp > 0) {
2103        $upper = $y;
2104        while ($acmp > 0) {
2105            if ($c -> _acmp($upper, $delta) <= 0) {
2106                $lower = $c -> _zero();
2107                last;
2108            }
2109            $lower = $c -> _sub($c -> _copy($upper), $delta);
2110
2111            if ($DEBUG) {
2112                print "lower  = $lower\n";
2113                print "upper  = $upper\n";
2114                print "delta  = $delta\n";
2115                print "\n";
2116            }
2117            $acmp  = $c -> _acmp($c -> _pow($c -> _copy($lower), $n), $x);
2118            if ($acmp == 0) {
2119                @$x = @$lower;
2120                return $x;
2121            }
2122            $delta = $c -> _mul($delta, $two);
2123        }
2124    }
2125
2126    # Use bisection to narrow down the interval.
2127
2128    my $one = $c -> _one();
2129    {
2130
2131        $delta = $c -> _sub($c -> _copy($upper), $lower);
2132        if ($c -> _acmp($delta, $one) <= 0) {
2133            @$x = @$lower;
2134            return $x;
2135        }
2136
2137        if ($DEBUG) {
2138            print "lower  = $lower\n";
2139            print "upper  = $upper\n";
2140            print "delta   = $delta\n";
2141            print "\n";
2142        }
2143
2144        $delta = $c -> _div($delta, $two);
2145        my $middle = $c -> _add($c -> _copy($lower), $delta);
2146
2147        $acmp  = $c -> _acmp($c -> _pow($c -> _copy($middle), $n), $x);
2148        if ($acmp < 0) {
2149            $lower = $middle;
2150        } elsif ($acmp > 0) {
2151            $upper = $middle;
2152        } else {
2153            @$x = @$middle;
2154            return $x;
2155        }
2156
2157        redo;
2158    }
2159
2160    $x;
2161}
2162
2163##############################################################################
2164# binary stuff
2165
2166sub _and {
2167    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    return $x if $c->_acmp($x, $y) == 0; # shortcut
2173
2174    my $m = $c->_one();
2175    my ($xr, $yr);
2176    my $mask = $AND_MASK;
2177
2178    my $x1 = $c->_copy($x);
2179    my $y1 = $c->_copy($y);
2180    my $z  = $c->_zero();
2181
2182    use integer;
2183    until ($c->_is_zero($x1) || $c->_is_zero($y1)) {
2184        ($x1, $xr) = $c->_div($x1, $mask);
2185        ($y1, $yr) = $c->_div($y1, $mask);
2186
2187        $c->_add($z, $c->_mul([ 0 + $xr->[0] & 0 + $yr->[0] ], $m));
2188        $c->_mul($m, $mask);
2189    }
2190
2191    @$x = @$z;
2192    return $x;
2193}
2194
2195sub _xor {
2196    my ($c, $x, $y) = @_;
2197
2198    return $c->_zero() if $c->_acmp($x, $y) == 0; # shortcut (see -and)
2199
2200    my $m = $c->_one();
2201    my ($xr, $yr);
2202    my $mask = $XOR_MASK;
2203
2204    my $x1 = $c->_copy($x);
2205    my $y1 = $c->_copy($y);      # make copy
2206    my $z  = $c->_zero();
2207
2208    use integer;
2209    until ($c->_is_zero($x1) || $c->_is_zero($y1)) {
2210        ($x1, $xr) = $c->_div($x1, $mask);
2211        ($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        $c->_add($z, $c->_mul([ 0 + $xr->[0] ^ 0 + $yr->[0] ], $m));
2218        $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    $c->_add($z, $c->_mul($x1, $m) ) if !$c->_is_zero($x1);
2224    $c->_add($z, $c->_mul($y1, $m) ) if !$c->_is_zero($y1);
2225
2226    @$x = @$z;
2227    return $x;
2228}
2229
2230sub _or {
2231    my ($c, $x, $y) = @_;
2232
2233    return $x if $c->_acmp($x, $y) == 0; # shortcut (see _and)
2234
2235    my $m = $c->_one();
2236    my ($xr, $yr);
2237    my $mask = $OR_MASK;
2238
2239    my $x1 = $c->_copy($x);
2240    my $y1 = $c->_copy($y);      # make copy
2241    my $z  = $c->_zero();
2242
2243    use integer;
2244    until ($c->_is_zero($x1) || $c->_is_zero($y1)) {
2245        ($x1, $xr) = $c->_div($x1, $mask);
2246        ($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        $c->_add($z, $c->_mul([ 0 + $xr->[0] | 0 + $yr->[0] ], $m));
2252        $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    $c->_add($z, $c->_mul($x1, $m) ) if !$c->_is_zero($x1);
2258    $c->_add($z, $c->_mul($y1, $m) ) if !$c->_is_zero($y1);
2259
2260    @$x = @$z;
2261    return $x;
2262}
2263
2264sub _as_hex {
2265    # convert a decimal number to hex (ref to array, return ref to string)
2266    my ($c, $x) = @_;
2267
2268    return "0x0" if @$x == 1 && $x->[0] == 0;
2269
2270    my $x1 = $c->_copy($x);
2271
2272    my $x10000 = [ 0x10000 ];
2273
2274    my $es = '';
2275    my $xr;
2276    until (@$x1 == 1 && $x1->[0] == 0) {        # _is_zero()
2277        ($x1, $xr) = $c->_div($x1, $x10000);
2278        $es = sprintf('%04x', $xr->[0]) . $es;
2279    }
2280    #$es = reverse $es;
2281    $es =~ s/^0*/0x/;
2282    return $es;
2283}
2284
2285sub _as_bin {
2286    # convert a decimal number to bin (ref to array, return ref to string)
2287    my ($c, $x) = @_;
2288
2289    return "0b0" if @$x == 1 && $x->[0] == 0;
2290
2291    my $x1 = $c->_copy($x);
2292
2293    my $x10000 = [ 0x10000 ];
2294
2295    my $es = '';
2296    my $xr;
2297
2298    until (@$x1 == 1 && $x1->[0] == 0) {        # _is_zero()
2299        ($x1, $xr) = $c->_div($x1, $x10000);
2300        $es = sprintf('%016b', $xr->[0]) . $es;
2301    }
2302    $es =~ s/^0*/0b/;
2303    return $es;
2304}
2305
2306sub _as_oct {
2307    # convert a decimal number to octal (ref to array, return ref to string)
2308    my ($c, $x) = @_;
2309
2310    return "00" if @$x == 1 && $x->[0] == 0;
2311
2312    my $x1 = $c->_copy($x);
2313
2314    my $x1000 = [ 1 << 15 ];    # 15 bits = 32768 = 0100000
2315
2316    my $es = '';
2317    my $xr;
2318    until (@$x1 == 1 && $x1->[0] == 0) {        # _is_zero()
2319        ($x1, $xr) = $c->_div($x1, $x1000);
2320        $es = sprintf("%05o", $xr->[0]) . $es;
2321    }
2322    $es =~ s/^0*/0/;            # excactly one leading zero
2323    return $es;
2324}
2325
2326sub _from_oct {
2327    # convert a octal number to decimal (string, return ref to array)
2328    my ($c, $os) = @_;
2329
2330    my $m = $c->_new(1 << 30);          # 30 bits at a time (<32 bits!)
2331    my $d = 10;                         # 10 octal digits at a time
2332
2333    my $mul = $c->_one();
2334    my $x = $c->_zero();
2335
2336    my $len = int((length($os) - 1) / $d);      # $d digit parts, w/o the '0'
2337    my $val;
2338    my $i = -$d;
2339    while ($len >= 0) {
2340        $val = substr($os, $i, $d);             # get oct digits
2341        $val = CORE::oct($val);
2342        $i -= $d;
2343        $len --;
2344        my $adder = $c -> _new($val);
2345        $c->_add($x, $c->_mul($adder, $mul)) if $val != 0;
2346        $c->_mul($mul, $m) if $len >= 0;        # skip last mul
2347    }
2348    $x;
2349}
2350
2351sub _from_hex {
2352    # convert a hex number to decimal (string, return ref to array)
2353    my ($c, $hs) = @_;
2354
2355    my $m = $c->_new(0x10000000);       # 28 bit at a time (<32 bit!)
2356    my $d = 7;                          # 7 hexadecimal digits at a time
2357    my $mul = $c->_one();
2358    my $x = $c->_zero();
2359
2360    my $len = int((length($hs) - 2) / $d); # $d digit parts, w/o the '0x'
2361    my $val;
2362    my $i = -$d;
2363    while ($len >= 0) {
2364        $val = substr($hs, $i, $d);     # get hex digits
2365        $val =~ s/^0x// if $len == 0; # for last part only because
2366        $val = CORE::hex($val);       # hex does not like wrong chars
2367        $i -= $d;
2368        $len --;
2369        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        if (CORE::length($val) > $BASE_LEN) {
2373            $adder = $c->_new($val);
2374        }
2375        $c->_add($x, $c->_mul($adder, $mul)) if $val != 0;
2376        $c->_mul($mul, $m) if $len >= 0; # skip last mul
2377    }
2378    $x;
2379}
2380
2381sub _from_bin {
2382    # convert a hex number to decimal (string, return ref to array)
2383    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    my $hs = $bs;
2389    $hs =~ s/^[+-]?0b//;                                # remove sign and 0b
2390    my $l = length($hs);                                # bits
2391    $hs = '0' x (8 - ($l % 8)) . $hs if ($l % 8) != 0;  # padd left side w/ 0
2392    my $h = '0x' . unpack('H*', pack ('B*', $hs));      # repack as hex
2393
2394    $c->_from_hex($h);
2395}
2396
2397##############################################################################
2398# special modulus functions
2399
2400sub _modinv {
2401
2402    # modular multiplicative inverse
2403    my ($c, $x, $y) = @_;
2404
2405    # modulo zero
2406    if ($c->_is_zero($y)) {
2407        return;
2408    }
2409
2410    # modulo one
2411    if ($c->_is_one($y)) {
2412        return $c->_zero(), '+';
2413    }
2414
2415    my $u = $c->_zero();
2416    my $v = $c->_one();
2417    my $a = $c->_copy($y);
2418    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    my $q;
2423    my $sign = 1;
2424    {
2425        ($a, $q, $b) = ($b, $c->_div($a, $b));          # step 1
2426        last if $c->_is_zero($b);
2427
2428        my $t = $c->_add(                               # step 2:
2429                         $c->_mul($c->_copy($v), $q),   #  t =   v * q
2430                         $u);                           #      + u
2431        $u = $v;                                        #  u = v
2432        $v = $t;                                        #  v = t
2433        $sign = -$sign;
2434        redo;
2435    }
2436
2437    # if the gcd is not 1, then return NaN
2438    return unless $c->_is_one($a);
2439
2440    ($v, $sign == 1 ? '+' : '-');
2441}
2442
2443sub _modpow {
2444    # modulus of power ($x ** $y) % $z
2445    my ($c, $num, $exp, $mod) = @_;
2446
2447    # a^b (mod 1) = 0 for all a and b
2448    if ($c->_is_one($mod)) {
2449        @$num = 0;
2450        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    if ($c->_is_zero($num)) {
2456        if ($c->_is_zero($exp)) {
2457            @$num = 1;
2458        } else {
2459            @$num = 0;
2460        }
2461        return $num;
2462    }
2463
2464    #  $num = $c->_mod($num, $mod);   # this does not make it faster
2465
2466    my $acc = $c->_copy($num);
2467    my $t = $c->_one();
2468
2469    my $expbin = $c->_as_bin($exp);
2470    $expbin =~ s/^0b//;
2471    my $len = length($expbin);
2472    while (--$len >= 0) {
2473        if (substr($expbin, $len, 1) eq '1') { # is_odd
2474            $t = $c->_mul($t, $acc);
2475            $t = $c->_mod($t, $mod);
2476        }
2477        $acc = $c->_mul($acc, $acc);
2478        $acc = $c->_mod($acc, $mod);
2479    }
2480    @$num = @$t;
2481    $num;
2482}
2483
2484sub _gcd {
2485    # Greatest common divisor.
2486
2487    my ($c, $x, $y) = @_;
2488
2489    # gcd(0, 0) = 0
2490    # gcd(0, a) = a, if a != 0
2491
2492    if (@$x == 1 && $x->[0] == 0) {
2493        if (@$y == 1 && $y->[0] == 0) {
2494            @$x = 0;
2495        } else {
2496            @$x = @$y;
2497        }
2498        return $x;
2499    }
2500
2501    # Until $y is zero ...
2502
2503    until (@$y == 1 && $y->[0] == 0) {
2504
2505        # Compute remainder.
2506
2507        $c->_mod($x, $y);
2508
2509        # Swap $x and $y.
2510
2511        my $tmp = $c->_copy($x);
2512        @$x = @$y;
2513        $y = $tmp;              # no deref here; that would modify input $y
2514    }
2515
2516    return $x;
2517}
2518
25191;
2520
2521=pod
2522
2523=head1 NAME
2524
2525Math::BigInt::Calc - pure Perl module to support Math::BigInt
2526
2527=head1 SYNOPSIS
2528
2529    # to use it with Math::BigInt
2530    use Math::BigInt lib => 'Calc';
2531
2532    # to use it with Math::BigFloat
2533    use Math::BigFloat lib => 'Calc';
2534
2535    # to use it with Math::BigRat
2536    use Math::BigRat lib => 'Calc';
2537
2538    # explicitly set base length and whether to "use integer"
2539    use Math::BigInt::Calc base_len => 4, use_int => 1;
2540    use Math::BigInt lib => 'Calc';
2541
2542=head1 DESCRIPTION
2543
2544Math::BigInt::Calc inherits from Math::BigInt::Lib.
2545
2546In this library, the numbers are represented interenally in base B = 10**N,
2547where N is the largest possible integer that does not cause overflow in the
2548intermediate computations. The base B elements are stored in an array, with the
2549least significant element stored in array element zero. There are no leading
2550zero elements, except a single zero element when the number is zero. For
2551instance, if B = 10000, the number 1234567890 is represented internally as
2552[7890, 3456, 12].
2553
2554=head1 OPTIONS
2555
2556When the module is loaded, it computes the maximum exponent, i.e., power of 10,
2557that can be used with and without "use integer" in the computations. The default
2558is to use this maximum exponent. If the combination of the 'base_len' value and
2559the 'use_int' value exceeds the maximum value, an error is thrown.
2560
2561=over 4
2562
2563=item base_len
2564
2565The base length can be specified explicitly with the 'base_len' option. The
2566value must be a positive integer.
2567
2568    use Math::BigInt::Calc base_len => 4;  # use 10000 as internal base
2569
2570=item use_int
2571
2572This option is used to specify whether "use integer" should be used in the
2573internal computations. The value is interpreted as a boolean value, so use 0 or
2574"" for false and anything else for true. If the 'base_len' is not specified
2575together with 'use_int', the current value for the base length is used.
2576
2577    use Math::BigInt::Calc use_int => 1;   # use "use integer" internally
2578
2579=back
2580
2581=head1 METHODS
2582
2583This overview constains only the methods that are specific to
2584C<Math::BigInt::Calc>. For the other methods, see L<Math::BigInt::Lib>.
2585
2586=over 4
2587
2588=item _base_len()
2589
2590Specify the desired base length and whether to enable "use integer" in the
2591computations.
2592
2593    Math::BigInt::Calc -> _base_len($base_len, $use_int);
2594
2595Note that it is better to specify the base length and whether to use integers as
2596options when the module is loaded, for example like this
2597
2598    use Math::BigInt::Calc base_len => 6, use_int => 1;
2599
2600=back
2601
2602=head1 SEE ALSO
2603
2604L<Math::BigInt::Lib> for a description of the API.
2605
2606Alternative libraries L<Math::BigInt::FastCalc>, L<Math::BigInt::GMP>,
2607L<Math::BigInt::Pari>, L<Math::BigInt::GMPz>, and L<Math::BigInt::BitVect>.
2608
2609Some of the modules that use these libraries L<Math::BigInt>,
2610L<Math::BigFloat>, and L<Math::BigRat>.
2611
2612=cut
2613