xref: /openbsd-src/gnu/usr.bin/perl/cpan/Math-BigInt/lib/Math/BigInt/Calc.pm (revision c90a81c56dcebd6a1b73fe4aff9b03385b8e63b3)
1package Math::BigInt::Calc;
2
3use 5.006001;
4use strict;
5use warnings;
6
7our $VERSION = '1.999715';
8$VERSION = eval $VERSION;
9
10# Package to store unsigned big integers in decimal and do math with them
11
12# Internally the numbers are stored in an array with at least 1 element, no
13# leading zero parts (except the first) and in base 1eX where X is determined
14# automatically at loading time to be the maximum possible value
15
16# todo:
17# - fully remove funky $# stuff in div() (maybe - that code scares me...)
18
19# USE_MUL: due to problems on certain os (os390, posix-bc) "* 1e-5" is used
20# instead of "/ 1e5" at some places, (marked with USE_MUL). Other platforms
21# BS2000, some Crays need USE_DIV instead.
22# The BEGIN block is used to determine which of the two variants gives the
23# correct result.
24
25# Beware of things like:
26# $i = $i * $y + $car; $car = int($i / $BASE); $i = $i % $BASE;
27# This works on x86, but fails on ARM (SA1100, iPAQ) due to who knows what
28# reasons. So, use this instead (slower, but correct):
29# $i = $i * $y + $car; $car = int($i / $BASE); $i -= $BASE * $car;
30
31##############################################################################
32# global constants, flags and accessory
33
34# announce that we are compatible with MBI v1.83 and up
35sub api_version () { 2; }
36
37# constants for easier life
38my ($BASE,$BASE_LEN,$RBASE,$MAX_VAL);
39my ($AND_BITS,$XOR_BITS,$OR_BITS);
40my ($AND_MASK,$XOR_MASK,$OR_MASK);
41
42sub _base_len
43  {
44  # Set/get the BASE_LEN and assorted other, connected values.
45  # Used only by the testsuite, the set variant is used only by the BEGIN
46  # block below:
47  shift;
48
49  my ($b, $int) = @_;
50  if (defined $b)
51    {
52    # avoid redefinitions
53    undef &_mul;
54    undef &_div;
55
56    if ($] >= 5.008 && $int && $b > 7)
57      {
58      $BASE_LEN = $b;
59      *_mul = \&_mul_use_div_64;
60      *_div = \&_div_use_div_64;
61      $BASE = int("1e".$BASE_LEN);
62      $MAX_VAL = $BASE-1;
63      return $BASE_LEN unless wantarray;
64      return ($BASE_LEN, $BASE, $AND_BITS, $XOR_BITS, $OR_BITS, $BASE_LEN, $MAX_VAL,);
65      }
66
67    # find whether we can use mul or div in mul()/div()
68    $BASE_LEN = $b+1;
69    my $caught = 0;
70    while (--$BASE_LEN > 5)
71      {
72      $BASE = int("1e".$BASE_LEN);
73      $RBASE = abs('1e-'.$BASE_LEN);			# see USE_MUL
74      $caught = 0;
75      $caught += 1 if (int($BASE * $RBASE) != 1);	# should be 1
76      $caught += 2 if (int($BASE / $BASE) != 1);	# should be 1
77      last if $caught != 3;
78      }
79    $BASE = int("1e".$BASE_LEN);
80    $RBASE = abs('1e-'.$BASE_LEN);			# see USE_MUL
81    $MAX_VAL = $BASE-1;
82
83    # ($caught & 1) != 0 => cannot use MUL
84    # ($caught & 2) != 0 => cannot use DIV
85    if ($caught == 2)				# 2
86      {
87      # must USE_MUL since we cannot use DIV
88      *_mul = \&_mul_use_mul;
89      *_div = \&_div_use_mul;
90      }
91    else					# 0 or 1
92      {
93      # can USE_DIV instead
94      *_mul = \&_mul_use_div;
95      *_div = \&_div_use_div;
96      }
97    }
98  return $BASE_LEN unless wantarray;
99  return ($BASE_LEN, $BASE, $AND_BITS, $XOR_BITS, $OR_BITS, $BASE_LEN, $MAX_VAL);
100  }
101
102sub _new {
103    # Given a string representing an integer, returns a reference to an array
104    # of integers, where each integer represents a chunk of the original input
105    # integer. Assumes normalized value as input.
106
107    my ($proto, $str) = @_;
108
109    my $input_len = length($str) - 1;
110
111    # Shortcut for small numbers.
112    return [ int($str) ] if $input_len < $BASE_LEN;
113
114    my $format = "a" . (($input_len % $BASE_LEN) + 1);
115    $format .= $] < 5.008 ? "a$BASE_LEN" x int($input_len / $BASE_LEN)
116                          : "(a$BASE_LEN)*";
117
118    [ reverse(map { 0 + $_ } unpack($format, $str)) ];
119}
120
121BEGIN
122  {
123  # from Daniel Pfeiffer: determine largest group of digits that is precisely
124  # multipliable with itself plus carry
125  # Test now changed to expect the proper pattern, not a result off by 1 or 2
126  my ($e, $num) = 3;	# lowest value we will use is 3+1-1 = 3
127  do {
128      $num = '9' x ++$e;
129      $num *= $num + 1;
130  } while $num =~ /9{$e}0{$e}/;		# must be a certain pattern
131  $e--; 				# last test failed, so retract one step
132  # the limits below brush the problems with the test above under the rug:
133  # the test should be able to find the proper $e automatically
134  $e = 5 if $^O =~ /^uts/;	# UTS get's some special treatment
135  $e = 5 if $^O =~ /^unicos/;	# unicos is also problematic (6 seems to work
136				# there, but we play safe)
137
138  my $int = 0;
139  if ($e > 7)
140    {
141    use integer;
142    my $e1 = 7;
143    $num = 7;
144    do
145      {
146      $num = ('9' x ++$e1) + 0;
147      $num *= $num + 1;
148      } while ("$num" =~ /9{$e1}0{$e1}/);	# must be a certain pattern
149    $e1--; 					# last test failed, so retract one step
150    if ($e1 > 7)
151      {
152      $int = 1; $e = $e1;
153      }
154    }
155
156  __PACKAGE__->_base_len($e,$int);	# set and store
157
158  use integer;
159  # find out how many bits _and, _or and _xor can take (old default = 16)
160  # I don't think anybody has yet 128 bit scalars, so let's play safe.
161  local $^W = 0;	# don't warn about 'nonportable number'
162  $AND_BITS = 15; $XOR_BITS = 15; $OR_BITS = 15;
163
164  # find max bits, we will not go higher than numberofbits that fit into $BASE
165  # to make _and etc simpler (and faster for smaller, slower for large numbers)
166  my $max = 16;
167  while (2 ** $max < $BASE) { $max++; }
168  {
169    no integer;
170    $max = 16 if $] < 5.006;	# older Perls might not take >16 too well
171  }
172  my ($x,$y,$z);
173  do {
174    $AND_BITS++;
175    $x = CORE::oct('0b' . '1' x $AND_BITS); $y = $x & $x;
176    $z = (2 ** $AND_BITS) - 1;
177    } while ($AND_BITS < $max && $x == $z && $y == $x);
178  $AND_BITS --;						# retreat one step
179  do {
180    $XOR_BITS++;
181    $x = CORE::oct('0b' . '1' x $XOR_BITS); $y = $x ^ 0;
182    $z = (2 ** $XOR_BITS) - 1;
183    } while ($XOR_BITS < $max && $x == $z && $y == $x);
184  $XOR_BITS --;						# retreat one step
185  do {
186    $OR_BITS++;
187    $x = CORE::oct('0b' . '1' x $OR_BITS); $y = $x | $x;
188    $z = (2 ** $OR_BITS) - 1;
189    } while ($OR_BITS < $max && $x == $z && $y == $x);
190  $OR_BITS --;						# retreat one step
191
192  $AND_MASK = __PACKAGE__->_new( ( 2 ** $AND_BITS ));
193  $XOR_MASK = __PACKAGE__->_new( ( 2 ** $XOR_BITS ));
194  $OR_MASK = __PACKAGE__->_new( ( 2 ** $OR_BITS ));
195
196  # We can compute the approximate length no faster than the real length:
197  *_alen = \&_len;
198  }
199
200###############################################################################
201
202sub _zero
203  {
204  # create a zero
205  [ 0 ];
206  }
207
208sub _one
209  {
210  # create a one
211  [ 1 ];
212  }
213
214sub _two
215  {
216  # create a two (used internally for shifting)
217  [ 2 ];
218  }
219
220sub _ten
221  {
222  # create a 10 (used internally for shifting)
223  [ 10 ];
224  }
225
226sub _1ex
227  {
228  # create a 1Ex
229  my $rem = $_[1] % $BASE_LEN;		# remainder
230  my $parts = $_[1] / $BASE_LEN;	# parts
231
232  # 000000, 000000, 100
233  [ (0) x $parts, '1' . ('0' x $rem) ];
234  }
235
236sub _copy
237  {
238  # make a true copy
239  [ @{$_[1]} ];
240  }
241
242# catch and throw away
243sub import { }
244
245##############################################################################
246# convert back to string and number
247
248sub _str {
249    # Convert number from internal base 1eN format to string format. Internal
250    # format is always normalized, i.e., no leading zeros.
251
252    my $ary = $_[1];
253    my $idx = $#$ary;             # index of last element
254
255    if ($idx < 0) {               # should not happen
256        require Carp;
257        Carp::croak("$_[1] has no elements");
258    }
259
260    # Handle first one differently, since it should not have any leading zeros.
261    my $ret = int($ary->[$idx]);
262    if ($idx > 0) {
263        $idx--;
264        # Interestingly, the pre-padd method uses more time
265        # the old grep variant takes longer (14 vs. 10 sec)
266        my $z = '0' x ($BASE_LEN - 1);
267        while ($idx >= 0) {
268            $ret .= substr($z . $ary->[$idx], -$BASE_LEN);
269            $idx--;
270        }
271    }
272    $ret;
273}
274
275sub _num
276  {
277    # Make a Perl scalar number (int/float) from a BigInt object.
278    my $x = $_[1];
279
280    return 0 + $x->[0] if scalar @$x == 1;      # below $BASE
281
282    # Start with the most significant element and work towards the least
283    # significant element. Avoid multiplying "inf" (which happens if the number
284    # overflows) with "0" (if there are zero elements in $x) since this gives
285    # "nan" which propagates to the output.
286
287    my $num = 0;
288    for (my $i = $#$x ; $i >= 0 ; --$i) {
289        $num *= $BASE;
290        $num += $x -> [$i];
291    }
292    return $num;
293  }
294
295##############################################################################
296# actual math code
297
298sub _add {
299    # (ref to int_num_array, ref to int_num_array)
300    #
301    # Routine to add two base 1eX numbers stolen from Knuth Vol 2 Algorithm A
302    # pg 231. There are separate routines to add and sub as per Knuth pg 233.
303    # This routine modifies array x, but not y.
304
305    my ($c, $x, $y) = @_;
306
307    return $x if @$y == 1 && $y->[0] == 0;      # $x + 0 => $x
308    if (@$x == 1 && $x->[0] == 0) {             # 0 + $y => $y->copy
309        # Twice as slow as $x = [ @$y ], but necessary to modify $x in-place.
310        @$x = @$y;
311        return $x;
312    }
313
314    # For each in Y, add Y to X and carry. If after that, something is left in
315    # X, foreach in X add carry to X and then return X, carry. Trades one
316    # "$j++" for having to shift arrays.
317    my $i;
318    my $car = 0;
319    my $j = 0;
320    for $i (@$y) {
321        $x->[$j] -= $BASE if $car = (($x->[$j] += $i + $car) >= $BASE) ? 1 : 0;
322        $j++;
323    }
324    while ($car != 0) {
325        $x->[$j] -= $BASE if $car = (($x->[$j] += $car) >= $BASE) ? 1 : 0;
326        $j++;
327    }
328    $x;
329}
330
331sub _inc {
332    # (ref to int_num_array, ref to int_num_array)
333    # Add 1 to $x, modify $x in place
334    my ($c, $x) = @_;
335
336    for my $i (@$x) {
337        return $x if ($i += 1) < $BASE;		# early out
338        $i = 0;					# overflow, next
339    }
340    push @$x, 1 if $x->[-1] == 0;		# last overflowed, so extend
341    $x;
342}
343
344sub _dec {
345    # (ref to int_num_array, ref to int_num_array)
346    # Sub 1 from $x, modify $x in place
347    my ($c, $x) = @_;
348
349    my $MAX = $BASE - 1;			# since MAX_VAL based on BASE
350    for my $i (@$x) {
351        last if ($i -= 1) >= 0;			# early out
352        $i = $MAX;				# underflow, next
353    }
354    pop @$x if $x->[-1] == 0 && @$x > 1;	# last underflowed (but leave 0)
355    $x;
356}
357
358sub _sub {
359    # (ref to int_num_array, ref to int_num_array, swap)
360    #
361    # Subtract base 1eX numbers -- stolen from Knuth Vol 2 pg 232, $x > $y
362    # subtract Y from X by modifying x in place
363    my ($c, $sx, $sy, $s) = @_;
364
365    my $car = 0;
366    my $i;
367    my $j = 0;
368    if (!$s) {
369        for $i (@$sx) {
370            last unless defined $sy->[$j] || $car;
371            $i += $BASE if $car = (($i -= ($sy->[$j] || 0) + $car) < 0);
372            $j++;
373        }
374        # might leave leading zeros, so fix that
375        return __strip_zeros($sx);
376    }
377    for $i (@$sx) {
378        # We can't do an early out if $x < $y, since we need to copy the high
379        # chunks from $y. Found by Bob Mathews.
380        #last unless defined $sy->[$j] || $car;
381        $sy->[$j] += $BASE
382          if $car = ($sy->[$j] = $i - ($sy->[$j] || 0) - $car) < 0;
383        $j++;
384    }
385    # might leave leading zeros, so fix that
386    __strip_zeros($sy);
387}
388
389sub _mul_use_mul
390  {
391  # (ref to int_num_array, ref to int_num_array)
392  # multiply two numbers in internal representation
393  # modifies first arg, second need not be different from first
394  my ($c,$xv,$yv) = @_;
395
396  if (@$yv == 1)
397    {
398    # shortcut for two very short numbers (improved by Nathan Zook)
399    # works also if xv and yv are the same reference, and handles also $x == 0
400    if (@$xv == 1)
401      {
402      if (($xv->[0] *= $yv->[0]) >= $BASE)
403         {
404         $xv->[0] = $xv->[0] - ($xv->[1] = int($xv->[0] * $RBASE)) * $BASE;
405         };
406      return $xv;
407      }
408    # $x * 0 => 0
409    if ($yv->[0] == 0)
410      {
411      @$xv = (0);
412      return $xv;
413      }
414    # multiply a large number a by a single element one, so speed up
415    my $y = $yv->[0]; my $car = 0;
416    foreach my $i (@$xv)
417      {
418      $i = $i * $y + $car; $car = int($i * $RBASE); $i -= $car * $BASE;
419      }
420    push @$xv, $car if $car != 0;
421    return $xv;
422    }
423  # shortcut for result $x == 0 => result = 0
424  return $xv if ( ((@$xv == 1) && ($xv->[0] == 0)) );
425
426  # since multiplying $x with $x fails, make copy in this case
427  $yv = [@$xv] if $xv == $yv;	# same references?
428
429  my @prod = (); my ($prod,$car,$cty,$xi,$yi);
430
431  for $xi (@$xv)
432    {
433    $car = 0; $cty = 0;
434
435    # slow variant
436#    for $yi (@$yv)
437#      {
438#      $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
439#      $prod[$cty++] =
440#       $prod - ($car = int($prod * RBASE)) * $BASE;  # see USE_MUL
441#      }
442#    $prod[$cty] += $car if $car; # need really to check for 0?
443#    $xi = shift @prod;
444
445    # faster variant
446    # looping through this if $xi == 0 is silly - so optimize it away!
447    $xi = (shift @prod || 0), next if $xi == 0;
448    for $yi (@$yv)
449      {
450      $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
451##     this is actually a tad slower
452##        $prod = $prod[$cty]; $prod += ($car + $xi * $yi);	# no ||0 here
453      $prod[$cty++] =
454       $prod - ($car = int($prod * $RBASE)) * $BASE;  # see USE_MUL
455      }
456    $prod[$cty] += $car if $car; # need really to check for 0?
457    $xi = shift @prod || 0;	# || 0 makes v5.005_3 happy
458    }
459  push @$xv, @prod;
460  # can't have leading zeros
461#  __strip_zeros($xv);
462  $xv;
463  }
464
465sub _mul_use_div_64
466  {
467  # (ref to int_num_array, ref to int_num_array)
468  # multiply two numbers in internal representation
469  # modifies first arg, second need not be different from first
470  # works for 64 bit integer with "use integer"
471  my ($c,$xv,$yv) = @_;
472
473  use integer;
474  if (@$yv == 1)
475    {
476    # shortcut for two small numbers, also handles $x == 0
477    if (@$xv == 1)
478      {
479      # shortcut for two very short numbers (improved by Nathan Zook)
480      # works also if xv and yv are the same reference, and handles also $x == 0
481      if (($xv->[0] *= $yv->[0]) >= $BASE)
482          {
483          $xv->[0] =
484              $xv->[0] - ($xv->[1] = $xv->[0] / $BASE) * $BASE;
485          };
486      return $xv;
487      }
488    # $x * 0 => 0
489    if ($yv->[0] == 0)
490      {
491      @$xv = (0);
492      return $xv;
493      }
494    # multiply a large number a by a single element one, so speed up
495    my $y = $yv->[0]; my $car = 0;
496    foreach my $i (@$xv)
497      {
498      #$i = $i * $y + $car; $car = $i / $BASE; $i -= $car * $BASE;
499      $i = $i * $y + $car; $i -= ($car = $i / $BASE) * $BASE;
500      }
501    push @$xv, $car if $car != 0;
502    return $xv;
503    }
504  # shortcut for result $x == 0 => result = 0
505  return $xv if ( ((@$xv == 1) && ($xv->[0] == 0)) );
506
507  # since multiplying $x with $x fails, make copy in this case
508  $yv = [@$xv] if $xv == $yv;	# same references?
509
510  my @prod = (); my ($prod,$car,$cty,$xi,$yi);
511  for $xi (@$xv)
512    {
513    $car = 0; $cty = 0;
514    # looping through this if $xi == 0 is silly - so optimize it away!
515    $xi = (shift @prod || 0), next if $xi == 0;
516    for $yi (@$yv)
517      {
518      $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
519      $prod[$cty++] = $prod - ($car = $prod / $BASE) * $BASE;
520      }
521    $prod[$cty] += $car if $car; # need really to check for 0?
522    $xi = shift @prod || 0;	# || 0 makes v5.005_3 happy
523    }
524  push @$xv, @prod;
525  $xv;
526  }
527
528sub _mul_use_div
529  {
530  # (ref to int_num_array, ref to int_num_array)
531  # multiply two numbers in internal representation
532  # modifies first arg, second need not be different from first
533  my ($c,$xv,$yv) = @_;
534
535  if (@$yv == 1)
536    {
537    # shortcut for two small numbers, also handles $x == 0
538    if (@$xv == 1)
539      {
540      # shortcut for two very short numbers (improved by Nathan Zook)
541      # works also if xv and yv are the same reference, and handles also $x == 0
542      if (($xv->[0] *= $yv->[0]) >= $BASE)
543          {
544          $xv->[0] =
545              $xv->[0] - ($xv->[1] = int($xv->[0] / $BASE)) * $BASE;
546          };
547      return $xv;
548      }
549    # $x * 0 => 0
550    if ($yv->[0] == 0)
551      {
552      @$xv = (0);
553      return $xv;
554      }
555    # multiply a large number a by a single element one, so speed up
556    my $y = $yv->[0]; my $car = 0;
557    foreach my $i (@$xv)
558      {
559      $i = $i * $y + $car; $car = int($i / $BASE); $i -= $car * $BASE;
560      # This (together with use integer;) does not work on 32-bit Perls
561      #$i = $i * $y + $car; $i -= ($car = $i / $BASE) * $BASE;
562      }
563    push @$xv, $car if $car != 0;
564    return $xv;
565    }
566  # shortcut for result $x == 0 => result = 0
567  return $xv if ( ((@$xv == 1) && ($xv->[0] == 0)) );
568
569  # since multiplying $x with $x fails, make copy in this case
570  $yv = [@$xv] if $xv == $yv;	# same references?
571
572  my @prod = (); my ($prod,$car,$cty,$xi,$yi);
573  for $xi (@$xv)
574    {
575    $car = 0; $cty = 0;
576    # looping through this if $xi == 0 is silly - so optimize it away!
577    $xi = (shift @prod || 0), next if $xi == 0;
578    for $yi (@$yv)
579      {
580      $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
581      $prod[$cty++] = $prod - ($car = int($prod / $BASE)) * $BASE;
582      }
583    $prod[$cty] += $car if $car; # need really to check for 0?
584    $xi = shift @prod || 0;	# || 0 makes v5.005_3 happy
585    }
586  push @$xv, @prod;
587  # can't have leading zeros
588#  __strip_zeros($xv);
589  $xv;
590  }
591
592sub _div_use_mul
593  {
594  # ref to array, ref to array, modify first array and return remainder if
595  # in list context
596
597  # see comments in _div_use_div() for more explanations
598
599  my ($c,$x,$yorg) = @_;
600
601  # the general div algorithm here is about O(N*N) and thus quite slow, so
602  # we first check for some special cases and use shortcuts to handle them.
603
604  # This works, because we store the numbers in a chunked format where each
605  # element contains 5..7 digits (depending on system).
606
607  # if both numbers have only one element:
608  if (@$x == 1 && @$yorg == 1)
609    {
610    # shortcut, $yorg and $x are two small numbers
611    if (wantarray)
612      {
613      my $r = [ $x->[0] % $yorg->[0] ];
614      $x->[0] = int($x->[0] / $yorg->[0]);
615      return ($x,$r);
616      }
617    else
618      {
619      $x->[0] = int($x->[0] / $yorg->[0]);
620      return $x;
621      }
622    }
623
624  # if x has more than one, but y has only one element:
625  if (@$yorg == 1)
626    {
627    my $rem;
628    $rem = _mod($c,[ @$x ],$yorg) if wantarray;
629
630    # shortcut, $y is < $BASE
631    my $j = scalar @$x; my $r = 0;
632    my $y = $yorg->[0]; my $b;
633    while ($j-- > 0)
634      {
635      $b = $r * $BASE + $x->[$j];
636      $x->[$j] = int($b/$y);
637      $r = $b % $y;
638      }
639    pop @$x if @$x > 1 && $x->[-1] == 0;	# splice up a leading zero
640    return ($x,$rem) if wantarray;
641    return $x;
642    }
643
644  # now x and y have more than one element
645
646  # check whether y has more elements than x, if yet, the result will be 0
647  if (@$yorg > @$x)
648    {
649    my $rem;
650    $rem = [@$x] if wantarray;                  # make copy
651    splice (@$x,1);                             # keep ref to original array
652    $x->[0] = 0;                                # set to 0
653    return ($x,$rem) if wantarray;              # including remainder?
654    return $x;					# only x, which is [0] now
655    }
656  # check whether the numbers have the same number of elements, in that case
657  # the result will fit into one element and can be computed efficiently
658  if (@$yorg == @$x)
659    {
660    my $rem;
661    # if $yorg has more digits than $x (it's leading element is longer than
662    # the one from $x), the result will also be 0:
663    if (length(int($yorg->[-1])) > length(int($x->[-1])))
664      {
665      $rem = [@$x] if wantarray;		# make copy
666      splice (@$x,1);				# keep ref to org array
667      $x->[0] = 0;				# set to 0
668      return ($x,$rem) if wantarray;		# including remainder?
669      return $x;
670      }
671    # now calculate $x / $yorg
672    if (length(int($yorg->[-1])) == length(int($x->[-1])))
673      {
674      # same length, so make full compare
675
676      my $a = 0; my $j = scalar @$x - 1;
677      # manual way (abort if unequal, good for early ne)
678      while ($j >= 0)
679        {
680        last if ($a = $x->[$j] - $yorg->[$j]); $j--;
681        }
682      # $a contains the result of the compare between X and Y
683      # a < 0: x < y, a == 0: x == y, a > 0: x > y
684      if ($a <= 0)
685        {
686        $rem = [ 0 ];                   # a = 0 => x == y => rem 0
687        $rem = [@$x] if $a != 0;        # a < 0 => x < y => rem = x
688        splice(@$x,1);                  # keep single element
689        $x->[0] = 0;                    # if $a < 0
690        $x->[0] = 1 if $a == 0;         # $x == $y
691        return ($x,$rem) if wantarray;
692        return $x;
693        }
694      # $x >= $y, so proceed normally
695      }
696    }
697
698  # all other cases:
699
700  my $y = [ @$yorg ];				# always make copy to preserve
701
702  my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1,@d,$tmp,$q,$u2,$u1,$u0);
703
704  $car = $bar = $prd = 0;
705  if (($dd = int($BASE/($y->[-1]+1))) != 1)
706    {
707    for $xi (@$x)
708      {
709      $xi = $xi * $dd + $car;
710      $xi -= ($car = int($xi * $RBASE)) * $BASE;	# see USE_MUL
711      }
712    push(@$x, $car); $car = 0;
713    for $yi (@$y)
714      {
715      $yi = $yi * $dd + $car;
716      $yi -= ($car = int($yi * $RBASE)) * $BASE;	# see USE_MUL
717      }
718    }
719  else
720    {
721    push(@$x, 0);
722    }
723  @q = (); ($v2,$v1) = @$y[-2,-1];
724  $v2 = 0 unless $v2;
725  while ($#$x > $#$y)
726    {
727    ($u2,$u1,$u0) = @$x[-3..-1];
728    $u2 = 0 unless $u2;
729    #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"
730    # if $v1 == 0;
731    $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$BASE+$u1)/$v1));
732    --$q while ($v2*$q > ($u0*$BASE+$u1-$q*$v1)*$BASE+$u2);
733    if ($q)
734      {
735      ($car, $bar) = (0,0);
736      for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
737        {
738        $prd = $q * $y->[$yi] + $car;
739        $prd -= ($car = int($prd * $RBASE)) * $BASE;	# see USE_MUL
740	$x->[$xi] += $BASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0));
741	}
742      if ($x->[-1] < $car + $bar)
743        {
744        $car = 0; --$q;
745	for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
746          {
747	  $x->[$xi] -= $BASE
748	   if ($car = (($x->[$xi] += $y->[$yi] + $car) >= $BASE));
749	  }
750	}
751      }
752    pop(@$x);
753    unshift(@q, $q);
754    }
755  if (wantarray)
756    {
757    @d = ();
758    if ($dd != 1)
759      {
760      $car = 0;
761      for $xi (reverse @$x)
762        {
763        $prd = $car * $BASE + $xi;
764        $car = $prd - ($tmp = int($prd / $dd)) * $dd; # see USE_MUL
765        unshift(@d, $tmp);
766        }
767      }
768    else
769      {
770      @d = @$x;
771      }
772    @$x = @q;
773    my $d = \@d;
774    __strip_zeros($x);
775    __strip_zeros($d);
776    return ($x,$d);
777    }
778  @$x = @q;
779  __strip_zeros($x);
780  $x;
781  }
782
783sub _div_use_div_64
784  {
785  # ref to array, ref to array, modify first array and return remainder if
786  # in list context
787  # This version works on 64 bit integers
788  my ($c,$x,$yorg) = @_;
789
790  use integer;
791  # the general div algorithm here is about O(N*N) and thus quite slow, so
792  # we first check for some special cases and use shortcuts to handle them.
793
794  # This works, because we store the numbers in a chunked format where each
795  # element contains 5..7 digits (depending on system).
796
797  # if both numbers have only one element:
798  if (@$x == 1 && @$yorg == 1)
799    {
800    # shortcut, $yorg and $x are two small numbers
801    if (wantarray)
802      {
803      my $r = [ $x->[0] % $yorg->[0] ];
804      $x->[0] = int($x->[0] / $yorg->[0]);
805      return ($x,$r);
806      }
807    else
808      {
809      $x->[0] = int($x->[0] / $yorg->[0]);
810      return $x;
811      }
812    }
813  # if x has more than one, but y has only one element:
814  if (@$yorg == 1)
815    {
816    my $rem;
817    $rem = _mod($c,[ @$x ],$yorg) if wantarray;
818
819    # shortcut, $y is < $BASE
820    my $j = scalar @$x; my $r = 0;
821    my $y = $yorg->[0]; my $b;
822    while ($j-- > 0)
823      {
824      $b = $r * $BASE + $x->[$j];
825      $x->[$j] = int($b/$y);
826      $r = $b % $y;
827      }
828    pop @$x if @$x > 1 && $x->[-1] == 0;	# splice up a leading zero
829    return ($x,$rem) if wantarray;
830    return $x;
831    }
832  # now x and y have more than one element
833
834  # check whether y has more elements than x, if yet, the result will be 0
835  if (@$yorg > @$x)
836    {
837    my $rem;
838    $rem = [@$x] if wantarray;			# make copy
839    splice (@$x,1);				# keep ref to original array
840    $x->[0] = 0;				# set to 0
841    return ($x,$rem) if wantarray;		# including remainder?
842    return $x;					# only x, which is [0] now
843    }
844  # check whether the numbers have the same number of elements, in that case
845  # the result will fit into one element and can be computed efficiently
846  if (@$yorg == @$x)
847    {
848    my $rem;
849    # if $yorg has more digits than $x (it's leading element is longer than
850    # the one from $x), the result will also be 0:
851    if (length(int($yorg->[-1])) > length(int($x->[-1])))
852      {
853      $rem = [@$x] if wantarray;		# make copy
854      splice (@$x,1);				# keep ref to org array
855      $x->[0] = 0;				# set to 0
856      return ($x,$rem) if wantarray;		# including remainder?
857      return $x;
858      }
859    # now calculate $x / $yorg
860
861    if (length(int($yorg->[-1])) == length(int($x->[-1])))
862      {
863      # same length, so make full compare
864
865      my $a = 0; my $j = scalar @$x - 1;
866      # manual way (abort if unequal, good for early ne)
867      while ($j >= 0)
868        {
869        last if ($a = $x->[$j] - $yorg->[$j]); $j--;
870        }
871      # $a contains the result of the compare between X and Y
872      # a < 0: x < y, a == 0: x == y, a > 0: x > y
873      if ($a <= 0)
874        {
875        $rem = [ 0 ];			# a = 0 => x == y => rem 0
876        $rem = [@$x] if $a != 0;	# a < 0 => x < y => rem = x
877        splice(@$x,1);			# keep single element
878        $x->[0] = 0;			# if $a < 0
879        $x->[0] = 1 if $a == 0; 	# $x == $y
880        return ($x,$rem) if wantarray;	# including remainder?
881        return $x;
882        }
883      # $x >= $y, so proceed normally
884
885      }
886    }
887
888  # all other cases:
889
890  my $y = [ @$yorg ];				# always make copy to preserve
891
892  my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1,@d,$tmp,$q,$u2,$u1,$u0);
893
894  $car = $bar = $prd = 0;
895  if (($dd = int($BASE/($y->[-1]+1))) != 1)
896    {
897    for $xi (@$x)
898      {
899      $xi = $xi * $dd + $car;
900      $xi -= ($car = int($xi / $BASE)) * $BASE;
901      }
902    push(@$x, $car); $car = 0;
903    for $yi (@$y)
904      {
905      $yi = $yi * $dd + $car;
906      $yi -= ($car = int($yi / $BASE)) * $BASE;
907      }
908    }
909  else
910    {
911    push(@$x, 0);
912    }
913
914  # @q will accumulate the final result, $q contains the current computed
915  # part of the final result
916
917  @q = (); ($v2,$v1) = @$y[-2,-1];
918  $v2 = 0 unless $v2;
919  while ($#$x > $#$y)
920    {
921    ($u2,$u1,$u0) = @$x[-3..-1];
922    $u2 = 0 unless $u2;
923    #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"
924    # if $v1 == 0;
925    $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$BASE+$u1)/$v1));
926    --$q while ($v2*$q > ($u0*$BASE+$u1-$q*$v1)*$BASE+$u2);
927    if ($q)
928      {
929      ($car, $bar) = (0,0);
930      for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
931        {
932        $prd = $q * $y->[$yi] + $car;
933        $prd -= ($car = int($prd / $BASE)) * $BASE;
934	$x->[$xi] += $BASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0));
935	}
936      if ($x->[-1] < $car + $bar)
937        {
938        $car = 0; --$q;
939	for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
940          {
941	  $x->[$xi] -= $BASE
942	   if ($car = (($x->[$xi] += $y->[$yi] + $car) >= $BASE));
943	  }
944	}
945      }
946    pop(@$x); unshift(@q, $q);
947    }
948  if (wantarray)
949    {
950    @d = ();
951    if ($dd != 1)
952      {
953      $car = 0;
954      for $xi (reverse @$x)
955        {
956        $prd = $car * $BASE + $xi;
957        $car = $prd - ($tmp = int($prd / $dd)) * $dd;
958        unshift(@d, $tmp);
959        }
960      }
961    else
962      {
963      @d = @$x;
964      }
965    @$x = @q;
966    my $d = \@d;
967    __strip_zeros($x);
968    __strip_zeros($d);
969    return ($x,$d);
970    }
971  @$x = @q;
972  __strip_zeros($x);
973  $x;
974  }
975
976sub _div_use_div
977  {
978  # ref to array, ref to array, modify first array and return remainder if
979  # in list context
980  my ($c,$x,$yorg) = @_;
981
982  # the general div algorithm here is about O(N*N) and thus quite slow, so
983  # we first check for some special cases and use shortcuts to handle them.
984
985  # This works, because we store the numbers in a chunked format where each
986  # element contains 5..7 digits (depending on system).
987
988  # if both numbers have only one element:
989  if (@$x == 1 && @$yorg == 1)
990    {
991    # shortcut, $yorg and $x are two small numbers
992    if (wantarray)
993      {
994      my $r = [ $x->[0] % $yorg->[0] ];
995      $x->[0] = int($x->[0] / $yorg->[0]);
996      return ($x,$r);
997      }
998    else
999      {
1000      $x->[0] = int($x->[0] / $yorg->[0]);
1001      return $x;
1002      }
1003    }
1004  # if x has more than one, but y has only one element:
1005  if (@$yorg == 1)
1006    {
1007    my $rem;
1008    $rem = _mod($c,[ @$x ],$yorg) if wantarray;
1009
1010    # shortcut, $y is < $BASE
1011    my $j = scalar @$x; my $r = 0;
1012    my $y = $yorg->[0]; my $b;
1013    while ($j-- > 0)
1014      {
1015      $b = $r * $BASE + $x->[$j];
1016      $x->[$j] = int($b/$y);
1017      $r = $b % $y;
1018      }
1019    pop @$x if @$x > 1 && $x->[-1] == 0;	# splice up a leading zero
1020    return ($x,$rem) if wantarray;
1021    return $x;
1022    }
1023  # now x and y have more than one element
1024
1025  # check whether y has more elements than x, if yet, the result will be 0
1026  if (@$yorg > @$x)
1027    {
1028    my $rem;
1029    $rem = [@$x] if wantarray;			# make copy
1030    splice (@$x,1);				# keep ref to original array
1031    $x->[0] = 0;				# set to 0
1032    return ($x,$rem) if wantarray;		# including remainder?
1033    return $x;					# only x, which is [0] now
1034    }
1035  # check whether the numbers have the same number of elements, in that case
1036  # the result will fit into one element and can be computed efficiently
1037  if (@$yorg == @$x)
1038    {
1039    my $rem;
1040    # if $yorg has more digits than $x (it's leading element is longer than
1041    # the one from $x), the result will also be 0:
1042    if (length(int($yorg->[-1])) > length(int($x->[-1])))
1043      {
1044      $rem = [@$x] if wantarray;		# make copy
1045      splice (@$x,1);				# keep ref to org array
1046      $x->[0] = 0;				# set to 0
1047      return ($x,$rem) if wantarray;		# including remainder?
1048      return $x;
1049      }
1050    # now calculate $x / $yorg
1051
1052    if (length(int($yorg->[-1])) == length(int($x->[-1])))
1053      {
1054      # same length, so make full compare
1055
1056      my $a = 0; my $j = scalar @$x - 1;
1057      # manual way (abort if unequal, good for early ne)
1058      while ($j >= 0)
1059        {
1060        last if ($a = $x->[$j] - $yorg->[$j]); $j--;
1061        }
1062      # $a contains the result of the compare between X and Y
1063      # a < 0: x < y, a == 0: x == y, a > 0: x > y
1064      if ($a <= 0)
1065        {
1066        $rem = [ 0 ];			# a = 0 => x == y => rem 0
1067        $rem = [@$x] if $a != 0;	# a < 0 => x < y => rem = x
1068        splice(@$x,1);			# keep single element
1069        $x->[0] = 0;			# if $a < 0
1070        $x->[0] = 1 if $a == 0; 	# $x == $y
1071        return ($x,$rem) if wantarray;	# including remainder?
1072        return $x;
1073        }
1074      # $x >= $y, so proceed normally
1075
1076      }
1077    }
1078
1079  # all other cases:
1080
1081  my $y = [ @$yorg ];				# always make copy to preserve
1082
1083  my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1,@d,$tmp,$q,$u2,$u1,$u0);
1084
1085  $car = $bar = $prd = 0;
1086  if (($dd = int($BASE/($y->[-1]+1))) != 1)
1087    {
1088    for $xi (@$x)
1089      {
1090      $xi = $xi * $dd + $car;
1091      $xi -= ($car = int($xi / $BASE)) * $BASE;
1092      }
1093    push(@$x, $car); $car = 0;
1094    for $yi (@$y)
1095      {
1096      $yi = $yi * $dd + $car;
1097      $yi -= ($car = int($yi / $BASE)) * $BASE;
1098      }
1099    }
1100  else
1101    {
1102    push(@$x, 0);
1103    }
1104
1105  # @q will accumulate the final result, $q contains the current computed
1106  # part of the final result
1107
1108  @q = (); ($v2,$v1) = @$y[-2,-1];
1109  $v2 = 0 unless $v2;
1110  while ($#$x > $#$y)
1111    {
1112    ($u2,$u1,$u0) = @$x[-3..-1];
1113    $u2 = 0 unless $u2;
1114    #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"
1115    # if $v1 == 0;
1116    $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$BASE+$u1)/$v1));
1117    --$q while ($v2*$q > ($u0*$BASE+$u1-$q*$v1)*$BASE+$u2);
1118    if ($q)
1119      {
1120      ($car, $bar) = (0,0);
1121      for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
1122        {
1123        $prd = $q * $y->[$yi] + $car;
1124        $prd -= ($car = int($prd / $BASE)) * $BASE;
1125	$x->[$xi] += $BASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0));
1126	}
1127      if ($x->[-1] < $car + $bar)
1128        {
1129        $car = 0; --$q;
1130	for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
1131          {
1132	  $x->[$xi] -= $BASE
1133	   if ($car = (($x->[$xi] += $y->[$yi] + $car) >= $BASE));
1134	  }
1135	}
1136      }
1137    pop(@$x); unshift(@q, $q);
1138    }
1139  if (wantarray)
1140    {
1141    @d = ();
1142    if ($dd != 1)
1143      {
1144      $car = 0;
1145      for $xi (reverse @$x)
1146        {
1147        $prd = $car * $BASE + $xi;
1148        $car = $prd - ($tmp = int($prd / $dd)) * $dd;
1149        unshift(@d, $tmp);
1150        }
1151      }
1152    else
1153      {
1154      @d = @$x;
1155      }
1156    @$x = @q;
1157    my $d = \@d;
1158    __strip_zeros($x);
1159    __strip_zeros($d);
1160    return ($x,$d);
1161    }
1162  @$x = @q;
1163  __strip_zeros($x);
1164  $x;
1165  }
1166
1167##############################################################################
1168# testing
1169
1170sub _acmp {
1171    # Internal absolute post-normalized compare (ignore signs)
1172    # ref to array, ref to array, return <0, 0, >0
1173    # Arrays must have at least one entry; this is not checked for.
1174    my ($c, $cx, $cy) = @_;
1175
1176    # shortcut for short numbers
1177    return (($cx->[0] <=> $cy->[0]) <=> 0)
1178      if @$cx == @$cy && @$cx == 1;
1179
1180    # fast comp based on number of array elements (aka pseudo-length)
1181    my $lxy = (@$cx - @$cy)
1182      # or length of first element if same number of elements (aka difference 0)
1183      ||
1184        # need int() here because sometimes the last element is '00018' vs '18'
1185        (length(int($cx->[-1])) - length(int($cy->[-1])));
1186
1187    return -1 if $lxy < 0;      # already differs, ret
1188    return  1 if $lxy > 0;      # ditto
1189
1190    # manual way (abort if unequal, good for early ne)
1191    my $a;
1192    my $j = @$cx;
1193    while (--$j >= 0) {
1194        last if $a = $cx->[$j] - $cy->[$j];
1195    }
1196    $a <=> 0;
1197}
1198
1199sub _len {
1200    # compute number of digits in base 10
1201
1202    # int() because add/sub sometimes leaves strings (like '00005') instead of
1203    # '5' in this place, thus causing length() to report wrong length
1204    my $cx = $_[1];
1205
1206    (@$cx - 1) * $BASE_LEN + length(int($cx->[-1]));
1207}
1208
1209sub _digit {
1210    # Return the nth digit. Zero is rightmost, so _digit(123,0) gives 3.
1211    # Negative values count from the left, so _digit(123, -1) gives 1.
1212    my ($c, $x, $n) = @_;
1213
1214    my $len = _len('', $x);
1215
1216    $n += $len if $n < 0;               # -1 last, -2 second-to-last
1217    return "0" if $n < 0 || $n >= $len; # return 0 for digits out of range
1218
1219    my $elem = int($n / $BASE_LEN);     # which array element
1220    my $digit = $n % $BASE_LEN;         # which digit in this element
1221    substr("$x->[$elem]", -$digit - 1, 1);
1222}
1223
1224sub _zeros {
1225    # Return number of trailing zeros in decimal.
1226    # Check each array element for having 0 at end as long as elem == 0
1227    # Upon finding a elem != 0, stop.
1228
1229    my $x = $_[1];
1230
1231    return 0 if @$x == 1 && $x->[0] == 0;
1232
1233    my $zeros = 0;
1234    my $elem;
1235    foreach my $e (@$x) {
1236        if ($e != 0) {
1237            $elem = "$e";               # preserve x
1238            $elem =~ s/.*?(0*$)/$1/;    # strip anything not zero
1239            $zeros *= $BASE_LEN;        # elems * 5
1240            $zeros += length($elem);    # count trailing zeros
1241            last;                       # early out
1242        }
1243        $zeros ++;                      # real else branch: 50% slower!
1244    }
1245    $zeros;
1246}
1247
1248##############################################################################
1249# _is_* routines
1250
1251sub _is_zero {
1252    # return true if arg is zero
1253    @{$_[1]} == 1 && $_[1]->[0] == 0 ? 1 : 0;
1254}
1255
1256sub _is_even {
1257    # return true if arg is even
1258    $_[1]->[0] & 1 ? 0 : 1;
1259}
1260
1261sub _is_odd {
1262    # return true if arg is odd
1263    $_[1]->[0] & 1 ? 1 : 0;
1264}
1265
1266sub _is_one {
1267    # return true if arg is one
1268    @{$_[1]} == 1 && $_[1]->[0] == 1 ? 1 : 0;
1269}
1270
1271sub _is_two {
1272    # return true if arg is two
1273    @{$_[1]} == 1 && $_[1]->[0] == 2 ? 1 : 0;
1274}
1275
1276sub _is_ten {
1277    # return true if arg is ten
1278    @{$_[1]} == 1 && $_[1]->[0] == 10 ? 1 : 0;
1279}
1280
1281sub __strip_zeros {
1282    # Internal normalization function that strips leading zeros from the array.
1283    # Args: ref to array
1284    my $s = shift;
1285
1286    my $cnt = @$s;              # get count of parts
1287    my $i = $cnt - 1;
1288    push @$s, 0 if $i < 0;	# div might return empty results, so fix it
1289
1290    return $s if @$s == 1;	# early out
1291
1292    #print "strip: cnt $cnt i $i\n";
1293    # '0', '3', '4', '0', '0',
1294    #  0    1    2    3    4
1295    # cnt = 5, i = 4
1296    # i = 4
1297    # i = 3
1298    # => fcnt = cnt - i (5-2 => 3, cnt => 5-1 = 4, throw away from 4th pos)
1299    # >= 1: skip first part (this can be zero)
1300    while ($i > 0) {
1301        last if $s->[$i] != 0;
1302        $i--;
1303    }
1304    $i++;
1305    splice @$s, $i if $i < $cnt;        # $i cant be 0
1306    $s;
1307}
1308
1309###############################################################################
1310# check routine to test internal state for corruptions
1311
1312sub _check {
1313    # used by the test suite
1314    my $x = $_[1];
1315
1316    return "$x is not a reference" if !ref($x);
1317
1318    # are all parts are valid?
1319    my $i = 0;
1320    my $j = @$x;
1321    my ($e, $try);
1322    while ($i < $j) {
1323        $e = $x->[$i]; $e = 'undef' unless defined $e;
1324        $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e)";
1325        last if $e !~ /^[+]?[0-9]+$/;
1326        $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e) (stringify)";
1327        last if "$e" !~ /^[+]?[0-9]+$/;
1328        $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e) (cat-stringify)";
1329        last if '' . "$e" !~ /^[+]?[0-9]+$/;
1330        $try = ' < 0 || >= $BASE; '."($x, $e)";
1331        last if $e <0 || $e >= $BASE;
1332        # This test is disabled, since new/bnorm and certain ops (like early out
1333        # in add/sub) are allowed/expected to leave '00000' in some elements.
1334        #$try = '=~ /^00+/; '."($x, $e)";
1335        #last if $e =~ /^00+/;
1336        $i++;
1337    }
1338    return "Illegal part '$e' at pos $i (tested: $try)" if $i < $j;
1339    0;
1340}
1341
1342###############################################################################
1343
1344sub _mod {
1345    # if possible, use mod shortcut
1346    my ($c, $x, $yo) = @_;
1347
1348    # slow way since $y too big
1349    if (@$yo > 1) {
1350        my ($xo, $rem) = _div($c, $x, $yo);
1351        @$x = @$rem;
1352        return $x;
1353    }
1354
1355    my $y = $yo->[0];
1356
1357    # if both are single element arrays
1358    if (scalar @$x == 1) {
1359        $x->[0] %= $y;
1360        return $x;
1361    }
1362
1363    # if @$x has more than one element, but @$y is a single element
1364    my $b = $BASE % $y;
1365    if ($b == 0) {
1366        # when BASE % Y == 0 then (B * BASE) % Y == 0
1367        # (B * BASE) % $y + A % Y => A % Y
1368        # so need to consider only last element: O(1)
1369        $x->[0] %= $y;
1370    } elsif ($b == 1) {
1371        # else need to go through all elements in @$x: O(N), but loop is a bit
1372        # simplified
1373        my $r = 0;
1374        foreach (@$x) {
1375            $r = ($r + $_) % $y;        # not much faster, but heh...
1376            #$r += $_ % $y; $r %= $y;
1377        }
1378        $r = 0 if $r == $y;
1379        $x->[0] = $r;
1380    } else {
1381        # else need to go through all elements in @$x: O(N)
1382        my $r = 0;
1383        my $bm = 1;
1384        foreach (@$x) {
1385            $r = ($_ * $bm + $r) % $y;
1386            $bm = ($bm * $b) % $y;
1387
1388            #$r += ($_ % $y) * $bm;
1389            #$bm *= $b;
1390            #$bm %= $y;
1391            #$r %= $y;
1392        }
1393        $r = 0 if $r == $y;
1394        $x->[0] = $r;
1395    }
1396    @$x = $x->[0];		# keep one element of @$x
1397    return $x;
1398}
1399
1400##############################################################################
1401# shifts
1402
1403sub _rsft {
1404    my ($c, $x, $y, $n) = @_;
1405
1406    if ($n != 10) {
1407        $n = _new($c, $n);
1408        return _div($c, $x, _pow($c, $n, $y));
1409    }
1410
1411    # shortcut (faster) for shifting by 10)
1412    # multiples of $BASE_LEN
1413    my $dst = 0;                                            # destination
1414    my $src = _num($c, $y);                                 # as normal int
1415    my $xlen = (@$x - 1) * $BASE_LEN + length(int($x->[-1]));
1416    if ($src >= $xlen or ($src == $xlen and !defined $x->[1])) {
1417        # 12345 67890 shifted right by more than 10 digits => 0
1418        splice(@$x, 1);                 # leave only one element
1419        $x->[0] = 0;                    # set to zero
1420        return $x;
1421    }
1422    my $rem = $src % $BASE_LEN;         # remainder to shift
1423    $src = int($src / $BASE_LEN);       # source
1424    if ($rem == 0) {
1425        splice(@$x, 0, $src);           # even faster, 38.4 => 39.3
1426    } else {
1427        my $len = @$x - $src;           # elems to go
1428        my $vd;
1429        my $z = '0' x $BASE_LEN;
1430        $x->[@$x] = 0;                  # avoid || 0 test inside loop
1431        while ($dst < $len) {
1432            $vd = $z . $x->[$src];
1433            $vd = substr($vd, -$BASE_LEN, $BASE_LEN - $rem);
1434            $src++;
1435            $vd = substr($z . $x->[$src], -$rem, $rem) . $vd;
1436            $vd = substr($vd, -$BASE_LEN, $BASE_LEN) if length($vd) > $BASE_LEN;
1437            $x->[$dst] = int($vd);
1438            $dst++;
1439        }
1440        splice(@$x, $dst) if $dst > 0;          # kill left-over array elems
1441        pop @$x if $x->[-1] == 0 && @$x > 1;    # kill last element if 0
1442    }                                           # else rem == 0
1443    $x;
1444}
1445
1446sub _lsft {
1447    my ($c, $x, $y, $n) = @_;
1448
1449    if ($n != 10) {
1450        $n = _new($c, $n);
1451        return _mul($c, $x, _pow($c, $n, $y));
1452    }
1453
1454    # shortcut (faster) for shifting by 10) since we are in base 10eX
1455    # multiples of $BASE_LEN:
1456    my $src = @$x;                              # source
1457    my $len = _num($c, $y);		        # shift-len as normal int
1458    my $rem = $len % $BASE_LEN;	        	# remainder to shift
1459    my $dst = $src + int($len / $BASE_LEN);     # destination
1460    my $vd;                                     # further speedup
1461    $x->[$src] = 0;                             # avoid first ||0 for speed
1462    my $z = '0' x $BASE_LEN;
1463    while ($src >= 0) {
1464        $vd = $x->[$src];
1465        $vd = $z . $vd;
1466        $vd = substr($vd, -$BASE_LEN + $rem, $BASE_LEN - $rem);
1467        $vd .= $src > 0 ? substr($z . $x->[$src - 1], -$BASE_LEN, $rem)
1468                        : '0' x $rem;
1469        $vd = substr($vd, -$BASE_LEN, $BASE_LEN) if length($vd) > $BASE_LEN;
1470        $x->[$dst] = int($vd);
1471        $dst--;
1472        $src--;
1473    }
1474    # set lowest parts to 0
1475    while ($dst >= 0) {
1476        $x->[$dst--] = 0;
1477    }
1478    # fix spurious last zero element
1479    splice @$x, -1 if $x->[-1] == 0;
1480    $x;
1481}
1482
1483sub _pow {
1484    # power of $x to $y
1485    # ref to array, ref to array, return ref to array
1486    my ($c, $cx, $cy) = @_;
1487
1488    if (@$cy == 1 && $cy->[0] == 0) {
1489        splice(@$cx, 1);
1490        $cx->[0] = 1;                   # y == 0 => x => 1
1491        return $cx;
1492    }
1493
1494    if ((@$cx == 1 && $cx->[0] == 1) ||     #    x == 1
1495        (@$cy == 1 && $cy->[0] == 1))       # or y == 1
1496    {
1497        return $cx;
1498    }
1499
1500    if (@$cx == 1 && $cx->[0] == 0) {
1501        splice (@$cx, 1);
1502        $cx->[0] = 0;                   # 0 ** y => 0 (if not y <= 0)
1503        return $cx;
1504    }
1505
1506    my $pow2 = _one();
1507
1508    my $y_bin = _as_bin($c, $cy);
1509    $y_bin =~ s/^0b//;
1510    my $len = length($y_bin);
1511    while (--$len > 0) {
1512        _mul($c, $pow2, $cx) if substr($y_bin, $len, 1) eq '1'; # is odd?
1513        _mul($c, $cx, $cx);
1514    }
1515
1516    _mul($c, $cx, $pow2);
1517    $cx;
1518}
1519
1520sub _nok {
1521    # Return binomial coefficient (n over k).
1522    # Given refs to arrays, return ref to array.
1523    # First input argument is modified.
1524
1525    my ($c, $n, $k) = @_;
1526
1527    # If k > n/2, or, equivalently, 2*k > n, compute nok(n, k) as
1528    # nok(n, n-k), to minimize the number if iterations in the loop.
1529
1530    {
1531        my $twok = _mul($c, _two($c), _copy($c, $k));   # 2 * k
1532        if (_acmp($c, $twok, $n) > 0) {                 # if 2*k > n
1533            $k = _sub($c, _copy($c, $n), $k);           # k = n - k
1534        }
1535    }
1536
1537    # Example:
1538    #
1539    # / 7 \       7!       1*2*3*4 * 5*6*7   5 * 6 * 7       6   7
1540    # |   | = --------- =  --------------- = --------- = 5 * - * -
1541    # \ 3 /   (7-3)! 3!    1*2*3*4 * 1*2*3   1 * 2 * 3       2   3
1542
1543    if (_is_zero($c, $k)) {
1544        @$n = 1;
1545    }
1546
1547    else {
1548
1549        # Make a copy of the original n, since we'll be modifying n in-place.
1550
1551        my $n_orig = _copy($c, $n);
1552
1553        # n = 5, f = 6, d = 2 (cf. example above)
1554
1555        _sub($c, $n, $k);
1556        _inc($c, $n);
1557
1558        my $f = _copy($c, $n);
1559        _inc($c, $f);
1560
1561        my $d = _two($c);
1562
1563        # while f <= n (the original n, that is) ...
1564
1565        while (_acmp($c, $f, $n_orig) <= 0) {
1566
1567            # n = (n * f / d) == 5 * 6 / 2 (cf. example above)
1568
1569            _mul($c, $n, $f);
1570            _div($c, $n, $d);
1571
1572            # f = 7, d = 3 (cf. example above)
1573
1574            _inc($c, $f);
1575            _inc($c, $d);
1576        }
1577
1578    }
1579
1580    return $n;
1581}
1582
1583my @factorials = (
1584  1,
1585  1,
1586  2,
1587  2*3,
1588  2*3*4,
1589  2*3*4*5,
1590  2*3*4*5*6,
1591  2*3*4*5*6*7,
1592);
1593
1594sub _fac
1595  {
1596  # factorial of $x
1597  # ref to array, return ref to array
1598  my ($c,$cx) = @_;
1599
1600  if ((@$cx == 1) && ($cx->[0] <= 7))
1601    {
1602    $cx->[0] = $factorials[$cx->[0]];		# 0 => 1, 1 => 1, 2 => 2 etc.
1603    return $cx;
1604    }
1605
1606  if ((@$cx == 1) && 		# we do this only if $x >= 12 and $x <= 7000
1607      ($cx->[0] >= 12 && $cx->[0] < 7000))
1608    {
1609
1610  # Calculate (k-j) * (k-j+1) ... k .. (k+j-1) * (k + j)
1611  # See http://blogten.blogspot.com/2007/01/calculating-n.html
1612  # The above series can be expressed as factors:
1613  #   k * k - (j - i) * 2
1614  # We cache k*k, and calculate (j * j) as the sum of the first j odd integers
1615
1616  # This will not work when N exceeds the storage of a Perl scalar, however,
1617  # in this case the algorithm would be way to slow to terminate, anyway.
1618
1619  # As soon as the last element of $cx is 0, we split it up and remember
1620  # how many zeors we got so far. The reason is that n! will accumulate
1621  # zeros at the end rather fast.
1622  my $zero_elements = 0;
1623
1624  # If n is even, set n = n -1
1625  my $k = _num($c,$cx); my $even = 1;
1626  if (($k & 1) == 0)
1627    {
1628    $even = $k; $k --;
1629    }
1630  # set k to the center point
1631  $k = ($k + 1) / 2;
1632#  print "k $k even: $even\n";
1633  # now calculate k * k
1634  my $k2 = $k * $k;
1635  my $odd = 1; my $sum = 1;
1636  my $i = $k - 1;
1637  # keep reference to x
1638  my $new_x = _new($c, $k * $even);
1639  @$cx = @$new_x;
1640  if ($cx->[0] == 0)
1641    {
1642    $zero_elements ++; shift @$cx;
1643    }
1644#  print STDERR "x = ", _str($c,$cx),"\n";
1645  my $BASE2 = int(sqrt($BASE))-1;
1646  my $j = 1;
1647  while ($j <= $i)
1648    {
1649    my $m = ($k2 - $sum); $odd += 2; $sum += $odd; $j++;
1650    while ($j <= $i && ($m < $BASE2) && (($k2 - $sum) < $BASE2))
1651      {
1652      $m *= ($k2 - $sum);
1653      $odd += 2; $sum += $odd; $j++;
1654#      print STDERR "\n k2 $k2 m $m sum $sum odd $odd\n"; sleep(1);
1655      }
1656    if ($m < $BASE)
1657      {
1658      _mul($c,$cx,[$m]);
1659      }
1660    else
1661      {
1662      _mul($c,$cx,$c->_new($m));
1663      }
1664    if ($cx->[0] == 0)
1665      {
1666      $zero_elements ++; shift @$cx;
1667      }
1668#    print STDERR "Calculate $k2 - $sum = $m (x = ", _str($c,$cx),")\n";
1669    }
1670  # multiply in the zeros again
1671  unshift @$cx, (0) x $zero_elements;
1672  return $cx;
1673  }
1674
1675  # go forward until $base is exceeded
1676  # limit is either $x steps (steps == 100 means a result always too high) or
1677  # $base.
1678  my $steps = 100; $steps = $cx->[0] if @$cx == 1;
1679  my $r = 2; my $cf = 3; my $step = 2; my $last = $r;
1680  while ($r*$cf < $BASE && $step < $steps)
1681    {
1682    $last = $r; $r *= $cf++; $step++;
1683    }
1684  if ((@$cx == 1) && $step == $cx->[0])
1685    {
1686    # completely done, so keep reference to $x and return
1687    $cx->[0] = $r;
1688    return $cx;
1689    }
1690
1691  # now we must do the left over steps
1692  my $n;					# steps still to do
1693  if (scalar @$cx == 1)
1694    {
1695    $n = $cx->[0];
1696    }
1697  else
1698    {
1699    $n = _copy($c,$cx);
1700    }
1701
1702  # Set $cx to the last result below $BASE (but keep ref to $x)
1703  $cx->[0] = $last; splice (@$cx,1);
1704  # As soon as the last element of $cx is 0, we split it up and remember
1705  # how many zeors we got so far. The reason is that n! will accumulate
1706  # zeros at the end rather fast.
1707  my $zero_elements = 0;
1708
1709  # do left-over steps fit into a scalar?
1710  if (ref $n eq 'ARRAY')
1711    {
1712    # No, so use slower inc() & cmp()
1713    # ($n is at least $BASE here)
1714    my $base_2 = int(sqrt($BASE)) - 1;
1715    #print STDERR "base_2: $base_2\n";
1716    while ($step < $base_2)
1717      {
1718      if ($cx->[0] == 0)
1719        {
1720        $zero_elements ++; shift @$cx;
1721        }
1722      my $b = $step * ($step + 1); $step += 2;
1723      _mul($c,$cx,[$b]);
1724      }
1725    $step = [$step];
1726    while (_acmp($c,$step,$n) <= 0)
1727      {
1728      if ($cx->[0] == 0)
1729        {
1730        $zero_elements ++; shift @$cx;
1731        }
1732      _mul($c,$cx,$step); _inc($c,$step);
1733      }
1734    }
1735  else
1736    {
1737    # Yes, so we can speed it up slightly
1738
1739#    print "# left over steps $n\n";
1740
1741    my $base_4 = int(sqrt(sqrt($BASE))) - 2;
1742    #print STDERR "base_4: $base_4\n";
1743    my $n4 = $n - 4;
1744    while ($step < $n4 && $step < $base_4)
1745      {
1746      if ($cx->[0] == 0)
1747        {
1748        $zero_elements ++; shift @$cx;
1749        }
1750      my $b = $step * ($step + 1); $step += 2; $b *= $step * ($step + 1); $step += 2;
1751      _mul($c,$cx,[$b]);
1752      }
1753    my $base_2 = int(sqrt($BASE)) - 1;
1754    my $n2 = $n - 2;
1755    #print STDERR "base_2: $base_2\n";
1756    while ($step < $n2 && $step < $base_2)
1757      {
1758      if ($cx->[0] == 0)
1759        {
1760        $zero_elements ++; shift @$cx;
1761        }
1762      my $b = $step * ($step + 1); $step += 2;
1763      _mul($c,$cx,[$b]);
1764      }
1765    # do what's left over
1766    while ($step <= $n)
1767      {
1768      _mul($c,$cx,[$step]); $step++;
1769      if ($cx->[0] == 0)
1770        {
1771        $zero_elements ++; shift @$cx;
1772        }
1773      }
1774    }
1775  # multiply in the zeros again
1776  unshift @$cx, (0) x $zero_elements;
1777  $cx;			# return result
1778  }
1779
1780#############################################################################
1781
1782sub _log_int
1783  {
1784  # calculate integer log of $x to base $base
1785  # ref to array, ref to array - return ref to array
1786  my ($c,$x,$base) = @_;
1787
1788  # X == 0 => NaN
1789  return if (scalar @$x == 1 && $x->[0] == 0);
1790  # BASE 0 or 1 => NaN
1791  return if (scalar @$base == 1 && $base->[0] < 2);
1792  my $cmp = _acmp($c,$x,$base); # X == BASE => 1
1793  if ($cmp == 0)
1794    {
1795    splice (@$x,1); $x->[0] = 1;
1796    return ($x,1)
1797    }
1798  # X < BASE
1799  if ($cmp < 0)
1800    {
1801    splice (@$x,1); $x->[0] = 0;
1802    return ($x,undef);
1803    }
1804
1805  my $x_org = _copy($c,$x);		# preserve x
1806  splice(@$x,1); $x->[0] = 1;		# keep ref to $x
1807
1808  # Compute a guess for the result based on:
1809  # $guess = int ( length_in_base_10(X) / ( log(base) / log(10) ) )
1810  my $len = _len($c,$x_org);
1811  my $log = log($base->[-1]) / log(10);
1812
1813  # for each additional element in $base, we add $BASE_LEN to the result,
1814  # based on the observation that log($BASE,10) is BASE_LEN and
1815  # log(x*y) == log(x) + log(y):
1816  $log += ((scalar @$base)-1) * $BASE_LEN;
1817
1818  # calculate now a guess based on the values obtained above:
1819  my $res = int($len / $log);
1820
1821  $x->[0] = $res;
1822  my $trial = _pow ($c, _copy($c, $base), $x);
1823  my $a = _acmp($c,$trial,$x_org);
1824
1825#  print STDERR "# trial ", _str($c,$x)," was: $a (0 = exact, -1 too small, +1 too big)\n";
1826
1827  # found an exact result?
1828  return ($x,1) if $a == 0;
1829
1830  if ($a > 0)
1831    {
1832    # or too big
1833    _div($c,$trial,$base); _dec($c, $x);
1834    while (($a = _acmp($c,$trial,$x_org)) > 0)
1835      {
1836#      print STDERR "# big _log_int at ", _str($c,$x), "\n";
1837      _div($c,$trial,$base); _dec($c, $x);
1838      }
1839    # result is now exact (a == 0), or too small (a < 0)
1840    return ($x, $a == 0 ? 1 : 0);
1841    }
1842
1843  # else: result was to small
1844  _mul($c,$trial,$base);
1845
1846  # did we now get the right result?
1847  $a = _acmp($c,$trial,$x_org);
1848
1849  if ($a == 0)				# yes, exactly
1850    {
1851    _inc($c, $x);
1852    return ($x,1);
1853    }
1854  return ($x,0) if $a > 0;
1855
1856  # Result still too small (we should come here only if the estimate above
1857  # was very off base):
1858
1859  # Now let the normal trial run obtain the real result
1860  # Simple loop that increments $x by 2 in each step, possible overstepping
1861  # the real result
1862
1863  my $base_mul = _mul($c, _copy($c,$base), $base);	# $base * $base
1864
1865  while (($a = _acmp($c,$trial,$x_org)) < 0)
1866    {
1867#    print STDERR "# small _log_int at ", _str($c,$x), "\n";
1868    _mul($c,$trial,$base_mul); _add($c, $x, [2]);
1869    }
1870
1871  my $exact = 1;
1872  if ($a > 0)
1873    {
1874    # overstepped the result
1875    _dec($c, $x);
1876    _div($c,$trial,$base);
1877    $a = _acmp($c,$trial,$x_org);
1878    if ($a > 0)
1879      {
1880      _dec($c, $x);
1881      }
1882    $exact = 0 if $a != 0;		# a = -1 => not exact result, a = 0 => exact
1883    }
1884
1885  ($x,$exact);				# return result
1886  }
1887
1888# for debugging:
1889  use constant DEBUG => 0;
1890  my $steps = 0;
1891  sub steps { $steps };
1892
1893sub _sqrt
1894  {
1895  # square-root of $x in place
1896  # Compute a guess of the result (by rule of thumb), then improve it via
1897  # Newton's method.
1898  my ($c,$x) = @_;
1899
1900  if (scalar @$x == 1)
1901    {
1902    # fits into one Perl scalar, so result can be computed directly
1903    $x->[0] = int(sqrt($x->[0]));
1904    return $x;
1905    }
1906  my $y = _copy($c,$x);
1907  # hopefully _len/2 is < $BASE, the -1 is to always undershot the guess
1908  # since our guess will "grow"
1909  my $l = int((_len($c,$x)-1) / 2);
1910
1911  my $lastelem = $x->[-1];					# for guess
1912  my $elems = scalar @$x - 1;
1913  # not enough digits, but could have more?
1914  if ((length($lastelem) <= 3) && ($elems > 1))
1915    {
1916    # right-align with zero pad
1917    my $len = length($lastelem) & 1;
1918    print "$lastelem => " if DEBUG;
1919    $lastelem .= substr($x->[-2] . '0' x $BASE_LEN,0,$BASE_LEN);
1920    # former odd => make odd again, or former even to even again
1921    $lastelem = $lastelem / 10 if (length($lastelem) & 1) != $len;
1922    print "$lastelem\n" if DEBUG;
1923    }
1924
1925  # construct $x (instead of _lsft($c,$x,$l,10)
1926  my $r = $l % $BASE_LEN;	# 10000 00000 00000 00000 ($BASE_LEN=5)
1927  $l = int($l / $BASE_LEN);
1928  print "l =  $l " if DEBUG;
1929
1930  splice @$x,$l;		# keep ref($x), but modify it
1931
1932  # we make the first part of the guess not '1000...0' but int(sqrt($lastelem))
1933  # that gives us:
1934  # 14400 00000 => sqrt(14400) => guess first digits to be 120
1935  # 144000 000000 => sqrt(144000) => guess 379
1936
1937  print "$lastelem (elems $elems) => " if DEBUG;
1938  $lastelem = $lastelem / 10 if ($elems & 1 == 1);		# odd or even?
1939  my $g = sqrt($lastelem); $g =~ s/\.//;			# 2.345 => 2345
1940  $r -= 1 if $elems & 1 == 0;					# 70 => 7
1941
1942  # padd with zeros if result is too short
1943  $x->[$l--] = int(substr($g . '0' x $r,0,$r+1));
1944  print "now ",$x->[-1] if DEBUG;
1945  print " would have been ", int('1' . '0' x $r),"\n" if DEBUG;
1946
1947  # If @$x > 1, we could compute the second elem of the guess, too, to create
1948  # an even better guess. Not implemented yet. Does it improve performance?
1949  $x->[$l--] = 0 while ($l >= 0);	# all other digits of guess are zero
1950
1951  print "start x= ",_str($c,$x),"\n" if DEBUG;
1952  my $two = _two();
1953  my $last = _zero();
1954  my $lastlast = _zero();
1955  $steps = 0 if DEBUG;
1956  while (_acmp($c,$last,$x) != 0 && _acmp($c,$lastlast,$x) != 0)
1957    {
1958    $steps++ if DEBUG;
1959    $lastlast = _copy($c,$last);
1960    $last = _copy($c,$x);
1961    _add($c,$x, _div($c,_copy($c,$y),$x));
1962    _div($c,$x, $two );
1963    print " x= ",_str($c,$x),"\n" if DEBUG;
1964    }
1965  print "\nsteps in sqrt: $steps, " if DEBUG;
1966  _dec($c,$x) if _acmp($c,$y,_mul($c,_copy($c,$x),$x)) < 0;	# overshot?
1967  print " final ",$x->[-1],"\n" if DEBUG;
1968  $x;
1969  }
1970
1971sub _root
1972  {
1973  # take n'th root of $x in place (n >= 3)
1974  my ($c,$x,$n) = @_;
1975
1976  if (scalar @$x == 1)
1977    {
1978    if (scalar @$n > 1)
1979      {
1980      # result will always be smaller than 2 so trunc to 1 at once
1981      $x->[0] = 1;
1982      }
1983    else
1984      {
1985      # fits into one Perl scalar, so result can be computed directly
1986      # cannot use int() here, because it rounds wrongly (try
1987      # (81 ** 3) ** (1/3) to see what I mean)
1988      #$x->[0] = int( $x->[0] ** (1 / $n->[0]) );
1989      # round to 8 digits, then truncate result to integer
1990      $x->[0] = int ( sprintf ("%.8f", $x->[0] ** (1 / $n->[0]) ) );
1991      }
1992    return $x;
1993    }
1994
1995  # we know now that X is more than one element long
1996
1997  # if $n is a power of two, we can repeatedly take sqrt($X) and find the
1998  # proper result, because sqrt(sqrt($x)) == root($x,4)
1999  my $b = _as_bin($c,$n);
2000  if ($b =~ /0b1(0+)$/)
2001    {
2002    my $count = CORE::length($1);	# 0b100 => len('00') => 2
2003    my $cnt = $count;			# counter for loop
2004    unshift (@$x, 0);			# add one element, together with one
2005					# more below in the loop this makes 2
2006    while ($cnt-- > 0)
2007      {
2008      # 'inflate' $X by adding one element, basically computing
2009      # $x * $BASE * $BASE. This gives us more $BASE_LEN digits for result
2010      # since len(sqrt($X)) approx == len($x) / 2.
2011      unshift (@$x, 0);
2012      # calculate sqrt($x), $x is now one element to big, again. In the next
2013      # round we make that two, again.
2014      _sqrt($c,$x);
2015      }
2016    # $x is now one element to big, so truncate result by removing it
2017    splice (@$x,0,1);
2018    }
2019  else
2020    {
2021    # trial computation by starting with 2,4,8,16 etc until we overstep
2022    my $step;
2023    my $trial = _two();
2024
2025    # while still to do more than X steps
2026    do
2027      {
2028      $step = _two();
2029      while (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) < 0)
2030        {
2031        _mul ($c, $step, [2]);
2032        _add ($c, $trial, $step);
2033        }
2034
2035      # hit exactly?
2036      if (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) == 0)
2037        {
2038        @$x = @$trial;			# make copy while preserving ref to $x
2039        return $x;
2040        }
2041      # overstepped, so go back on step
2042      _sub($c, $trial, $step);
2043      } while (scalar @$step > 1 || $step->[0] > 128);
2044
2045    # reset step to 2
2046    $step = _two();
2047    # add two, because $trial cannot be exactly the result (otherwise we would
2048    # already have found it)
2049    _add($c, $trial, $step);
2050
2051    # and now add more and more (2,4,6,8,10 etc)
2052    while (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) < 0)
2053      {
2054      _add ($c, $trial, $step);
2055      }
2056
2057    # hit not exactly? (overstepped)
2058    if (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) > 0)
2059      {
2060      _dec($c,$trial);
2061      }
2062
2063    # hit not exactly? (overstepped)
2064    # 80 too small, 81 slightly too big, 82 too big
2065    if (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) > 0)
2066      {
2067      _dec ($c, $trial);
2068      }
2069
2070    @$x = @$trial;			# make copy while preserving ref to $x
2071    return $x;
2072    }
2073  $x;
2074  }
2075
2076##############################################################################
2077# binary stuff
2078
2079sub _and
2080  {
2081  my ($c,$x,$y) = @_;
2082
2083  # the shortcut makes equal, large numbers _really_ fast, and makes only a
2084  # very small performance drop for small numbers (e.g. something with less
2085  # than 32 bit) Since we optimize for large numbers, this is enabled.
2086  return $x if _acmp($c,$x,$y) == 0;		# shortcut
2087
2088  my $m = _one(); my ($xr,$yr);
2089  my $mask = $AND_MASK;
2090
2091  my $x1 = $x;
2092  my $y1 = _copy($c,$y);			# make copy
2093  $x = _zero();
2094  my ($b,$xrr,$yrr);
2095  use integer;
2096  while (!_is_zero($c,$x1) && !_is_zero($c,$y1))
2097    {
2098    ($x1, $xr) = _div($c,$x1,$mask);
2099    ($y1, $yr) = _div($c,$y1,$mask);
2100
2101    # make ints() from $xr, $yr
2102    # this is when the AND_BITS are greater than $BASE and is slower for
2103    # small (<256 bits) numbers, but faster for large numbers. Disabled
2104    # due to KISS principle
2105
2106#    $b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }
2107#    $b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }
2108#    _add($c,$x, _mul($c, _new( $c, ($xrr & $yrr) ), $m) );
2109
2110    # 0+ due to '&' doesn't work in strings
2111    _add($c,$x, _mul($c, [ 0+$xr->[0] & 0+$yr->[0] ], $m) );
2112    _mul($c,$m,$mask);
2113    }
2114  $x;
2115  }
2116
2117sub _xor
2118  {
2119  my ($c,$x,$y) = @_;
2120
2121  return _zero() if _acmp($c,$x,$y) == 0;	# shortcut (see -and)
2122
2123  my $m = _one(); my ($xr,$yr);
2124  my $mask = $XOR_MASK;
2125
2126  my $x1 = $x;
2127  my $y1 = _copy($c,$y);			# make copy
2128  $x = _zero();
2129  my ($b,$xrr,$yrr);
2130  use integer;
2131  while (!_is_zero($c,$x1) && !_is_zero($c,$y1))
2132    {
2133    ($x1, $xr) = _div($c,$x1,$mask);
2134    ($y1, $yr) = _div($c,$y1,$mask);
2135    # make ints() from $xr, $yr (see _and())
2136    #$b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }
2137    #$b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }
2138    #_add($c,$x, _mul($c, _new( $c, ($xrr ^ $yrr) ), $m) );
2139
2140    # 0+ due to '^' doesn't work in strings
2141    _add($c,$x, _mul($c, [ 0+$xr->[0] ^ 0+$yr->[0] ], $m) );
2142    _mul($c,$m,$mask);
2143    }
2144  # the loop stops when the shorter of the two numbers is exhausted
2145  # the remainder of the longer one will survive bit-by-bit, so we simple
2146  # multiply-add it in
2147  _add($c,$x, _mul($c, $x1, $m) ) if !_is_zero($c,$x1);
2148  _add($c,$x, _mul($c, $y1, $m) ) if !_is_zero($c,$y1);
2149
2150  $x;
2151  }
2152
2153sub _or
2154  {
2155  my ($c,$x,$y) = @_;
2156
2157  return $x if _acmp($c,$x,$y) == 0;		# shortcut (see _and)
2158
2159  my $m = _one(); my ($xr,$yr);
2160  my $mask = $OR_MASK;
2161
2162  my $x1 = $x;
2163  my $y1 = _copy($c,$y);			# make copy
2164  $x = _zero();
2165  my ($b,$xrr,$yrr);
2166  use integer;
2167  while (!_is_zero($c,$x1) && !_is_zero($c,$y1))
2168    {
2169    ($x1, $xr) = _div($c,$x1,$mask);
2170    ($y1, $yr) = _div($c,$y1,$mask);
2171    # make ints() from $xr, $yr (see _and())
2172#    $b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }
2173#    $b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }
2174#    _add($c,$x, _mul($c, _new( $c, ($xrr | $yrr) ), $m) );
2175
2176    # 0+ due to '|' doesn't work in strings
2177    _add($c,$x, _mul($c, [ 0+$xr->[0] | 0+$yr->[0] ], $m) );
2178    _mul($c,$m,$mask);
2179    }
2180  # the loop stops when the shorter of the two numbers is exhausted
2181  # the remainder of the longer one will survive bit-by-bit, so we simple
2182  # multiply-add it in
2183  _add($c,$x, _mul($c, $x1, $m) ) if !_is_zero($c,$x1);
2184  _add($c,$x, _mul($c, $y1, $m) ) if !_is_zero($c,$y1);
2185
2186  $x;
2187  }
2188
2189sub _as_hex
2190  {
2191  # convert a decimal number to hex (ref to array, return ref to string)
2192  my ($c,$x) = @_;
2193
2194  # fits into one element (handle also 0x0 case)
2195  return sprintf("0x%x",$x->[0]) if @$x == 1;
2196
2197  my $x1 = _copy($c,$x);
2198
2199  my $es = '';
2200  my ($xr, $h, $x10000);
2201  if ($] >= 5.006)
2202    {
2203    $x10000 = [ 0x10000 ]; $h = 'h4';
2204    }
2205  else
2206    {
2207    $x10000 = [ 0x1000 ]; $h = 'h3';
2208    }
2209  while (@$x1 != 1 || $x1->[0] != 0)		# _is_zero()
2210    {
2211    ($x1, $xr) = _div($c,$x1,$x10000);
2212    $es .= unpack($h,pack('V',$xr->[0]));
2213    }
2214  $es = reverse $es;
2215  $es =~ s/^[0]+//;   # strip leading zeros
2216  '0x' . $es;					# return result prepended with 0x
2217  }
2218
2219sub _as_bin
2220  {
2221  # convert a decimal number to bin (ref to array, return ref to string)
2222  my ($c,$x) = @_;
2223
2224  # fits into one element (and Perl recent enough), handle also 0b0 case
2225  # handle zero case for older Perls
2226  if ($] <= 5.005 && @$x == 1 && $x->[0] == 0)
2227    {
2228    my $t = '0b0'; return $t;
2229    }
2230  if (@$x == 1 && $] >= 5.006)
2231    {
2232    my $t = sprintf("0b%b",$x->[0]);
2233    return $t;
2234    }
2235  my $x1 = _copy($c,$x);
2236
2237  my $es = '';
2238  my ($xr, $b, $x10000);
2239  if ($] >= 5.006)
2240    {
2241    $x10000 = [ 0x10000 ]; $b = 'b16';
2242    }
2243  else
2244    {
2245    $x10000 = [ 0x1000 ]; $b = 'b12';
2246    }
2247  while (!(@$x1 == 1 && $x1->[0] == 0))		# _is_zero()
2248    {
2249    ($x1, $xr) = _div($c,$x1,$x10000);
2250    $es .= unpack($b,pack('v',$xr->[0]));
2251    }
2252  $es = reverse $es;
2253  $es =~ s/^[0]+//;   # strip leading zeros
2254  '0b' . $es;					# return result prepended with 0b
2255  }
2256
2257sub _as_oct
2258  {
2259  # convert a decimal number to octal (ref to array, return ref to string)
2260  my ($c,$x) = @_;
2261
2262  # fits into one element (handle also 0 case)
2263  return sprintf("0%o",$x->[0]) if @$x == 1;
2264
2265  my $x1 = _copy($c,$x);
2266
2267  my $es = '';
2268  my $xr;
2269  my $x1000 = [ 0100000 ];
2270  while (@$x1 != 1 || $x1->[0] != 0)		# _is_zero()
2271    {
2272    ($x1, $xr) = _div($c,$x1,$x1000);
2273    $es .= reverse sprintf("%05o", $xr->[0]);
2274    }
2275  $es = reverse $es;
2276  $es =~ s/^0+//;   # strip leading zeros
2277  '0' . $es;					# return result prepended with 0
2278  }
2279
2280sub _from_oct
2281  {
2282  # convert a octal number to decimal (string, return ref to array)
2283  my ($c,$os) = @_;
2284
2285  # for older Perls, play safe
2286  my $m = [ 0100000 ];
2287  my $d = 5;					# 5 digits at a time
2288
2289  my $mul = _one();
2290  my $x = _zero();
2291
2292  my $len = int( (length($os)-1)/$d );		# $d digit parts, w/o the '0'
2293  my $val; my $i = -$d;
2294  while ($len >= 0)
2295    {
2296    $val = substr($os,$i,$d);			# get oct digits
2297    $val = CORE::oct($val);
2298    $i -= $d; $len --;
2299    my $adder = [ $val ];
2300    _add ($c, $x, _mul ($c, $adder, $mul ) ) if $val != 0;
2301    _mul ($c, $mul, $m ) if $len >= 0; 		# skip last mul
2302    }
2303  $x;
2304  }
2305
2306sub _from_hex
2307  {
2308  # convert a hex number to decimal (string, return ref to array)
2309  my ($c,$hs) = @_;
2310
2311  my $m = _new($c, 0x10000000);			# 28 bit at a time (<32 bit!)
2312  my $d = 7;					# 7 digits at a time
2313  if ($] <= 5.006)
2314    {
2315    # for older Perls, play safe
2316    $m = [ 0x10000 ];				# 16 bit at a time (<32 bit!)
2317    $d = 4;					# 4 digits at a time
2318    }
2319
2320  my $mul = _one();
2321  my $x = _zero();
2322
2323  my $len = int( (length($hs)-2)/$d );		# $d digit parts, w/o the '0x'
2324  my $val; my $i = -$d;
2325  while ($len >= 0)
2326    {
2327    $val = substr($hs,$i,$d);			# get hex digits
2328    $val =~ s/^0x// if $len == 0;		# for last part only because
2329    $val = CORE::hex($val);			# hex does not like wrong chars
2330    $i -= $d; $len --;
2331    my $adder = [ $val ];
2332    # if the resulting number was to big to fit into one element, create a
2333    # two-element version (bug found by Mark Lakata - Thanx!)
2334    if (CORE::length($val) > $BASE_LEN)
2335      {
2336      $adder = _new($c,$val);
2337      }
2338    _add ($c, $x, _mul ($c, $adder, $mul ) ) if $val != 0;
2339    _mul ($c, $mul, $m ) if $len >= 0; 		# skip last mul
2340    }
2341  $x;
2342  }
2343
2344sub _from_bin
2345  {
2346  # convert a hex number to decimal (string, return ref to array)
2347  my ($c,$bs) = @_;
2348
2349  # instead of converting X (8) bit at a time, it is faster to "convert" the
2350  # number to hex, and then call _from_hex.
2351
2352  my $hs = $bs;
2353  $hs =~ s/^[+-]?0b//;					# remove sign and 0b
2354  my $l = length($hs);					# bits
2355  $hs = '0' x (8-($l % 8)) . $hs if ($l % 8) != 0;	# padd left side w/ 0
2356  my $h = '0x' . unpack('H*', pack ('B*', $hs));	# repack as hex
2357
2358  $c->_from_hex($h);
2359  }
2360
2361##############################################################################
2362# special modulus functions
2363
2364sub _modinv
2365  {
2366  # modular multiplicative inverse
2367  my ($c,$x,$y) = @_;
2368
2369  # modulo zero
2370  if (_is_zero($c, $y)) {
2371      return (undef, undef);
2372  }
2373
2374  # modulo one
2375  if (_is_one($c, $y)) {
2376      return (_zero($c), '+');
2377  }
2378
2379  my $u = _zero($c);
2380  my $v = _one($c);
2381  my $a = _copy($c,$y);
2382  my $b = _copy($c,$x);
2383
2384  # Euclid's Algorithm for bgcd(), only that we calc bgcd() ($a) and the result
2385  # ($u) at the same time. See comments in BigInt for why this works.
2386  my $q;
2387  my $sign = 1;
2388  {
2389      ($a, $q, $b) = ($b, _div($c, $a, $b));        # step 1
2390      last if _is_zero($c, $b);
2391
2392      my $t = _add($c,                              # step 2:
2393                   _mul($c, _copy($c, $v), $q) ,    #  t =   v * q
2394                   $u );                            #      + u
2395      $u = $v;                                      #  u = v
2396      $v = $t;                                      #  v = t
2397      $sign = -$sign;
2398      redo;
2399  }
2400
2401  # if the gcd is not 1, then return NaN
2402  return (undef, undef) unless _is_one($c, $a);
2403
2404  ($v, $sign == 1 ? '+' : '-');
2405  }
2406
2407sub _modpow
2408  {
2409  # modulus of power ($x ** $y) % $z
2410  my ($c,$num,$exp,$mod) = @_;
2411
2412  # a^b (mod 1) = 0 for all a and b
2413  if (_is_one($c,$mod))
2414    {
2415        @$num = 0;
2416        return $num;
2417    }
2418
2419  # 0^a (mod m) = 0 if m != 0, a != 0
2420  # 0^0 (mod m) = 1 if m != 0
2421  if (_is_zero($c, $num)) {
2422      if (_is_zero($c, $exp)) {
2423          @$num = 1;
2424      } else {
2425          @$num = 0;
2426      }
2427      return $num;
2428  }
2429
2430#  $num = _mod($c,$num,$mod);	# this does not make it faster
2431
2432  my $acc = _copy($c,$num); my $t = _one();
2433
2434  my $expbin = _as_bin($c,$exp); $expbin =~ s/^0b//;
2435  my $len = length($expbin);
2436  while (--$len >= 0)
2437    {
2438    if ( substr($expbin,$len,1) eq '1')			# is_odd
2439      {
2440      _mul($c,$t,$acc);
2441      $t = _mod($c,$t,$mod);
2442      }
2443    _mul($c,$acc,$acc);
2444    $acc = _mod($c,$acc,$mod);
2445    }
2446  @$num = @$t;
2447  $num;
2448  }
2449
2450sub _gcd {
2451    # Greatest common divisor.
2452
2453    my ($c, $x, $y) = @_;
2454
2455    # gcd(0,0) = 0
2456    # gcd(0,a) = a, if a != 0
2457
2458    if (@$x == 1 && $x->[0] == 0) {
2459        if (@$y == 1 && $y->[0] == 0) {
2460            @$x = 0;
2461        } else {
2462            @$x = @$y;
2463        }
2464        return $x;
2465    }
2466
2467    # Until $y is zero ...
2468
2469    until (@$y == 1 && $y->[0] == 0) {
2470
2471        # Compute remainder.
2472
2473        _mod($c, $x, $y);
2474
2475        # Swap $x and $y.
2476
2477        my $tmp = [ @$x ];
2478        @$x = @$y;
2479        $y = $tmp;      # no deref here; that would modify input $y
2480    }
2481
2482    return $x;
2483}
2484
2485##############################################################################
2486##############################################################################
2487
24881;
2489__END__
2490
2491=pod
2492
2493=head1 NAME
2494
2495Math::BigInt::Calc - Pure Perl module to support Math::BigInt
2496
2497=head1 SYNOPSIS
2498
2499This library provides support for big integer calculations. It is not
2500intended to be used by other modules. Other modules which support the same
2501API (see below) can also be used to support Math::BigInt, like
2502Math::BigInt::GMP and Math::BigInt::Pari.
2503
2504=head1 DESCRIPTION
2505
2506In this library, the numbers are represented in base B = 10**N, where N is
2507the largest possible value that does not cause overflow in the intermediate
2508computations. The base B elements are stored in an array, with the least
2509significant element stored in array element zero. There are no leading zero
2510elements, except a single zero element when the number is zero.
2511
2512For instance, if B = 10000, the number 1234567890 is represented internally
2513as [3456, 7890, 12].
2514
2515=head1 THE Math::BigInt API
2516
2517In order to allow for multiple big integer libraries, Math::BigInt was
2518rewritten to use a plug-in library for core math routines. Any module which
2519conforms to the API can be used by Math::BigInt by using this in your program:
2520
2521	use Math::BigInt lib => 'libname';
2522
2523'libname' is either the long name, like 'Math::BigInt::Pari', or only the short
2524version, like 'Pari'.
2525
2526=head2 General Notes
2527
2528A library only needs to deal with unsigned big integers. Testing of input
2529parameter validity is done by the caller, so there is no need to worry about
2530underflow (e.g., in C<_sub()> and C<_dec()>) nor about division by zero (e.g.,
2531in C<_div()>) or similar cases.
2532
2533For some methods, the first parameter can be modified. That includes the
2534possibility that you return a reference to a completely different object
2535instead. Although keeping the reference and just changing its contents is
2536preferred over creating and returning a different reference.
2537
2538Return values are always objects, strings, Perl scalars, or true/false for
2539comparison routines.
2540
2541=head2 API version 1
2542
2543The following methods must be defined in order to support the use by
2544Math::BigInt v1.70 or later.
2545
2546=head3 API version
2547
2548=over 4
2549
2550=item I<api_version()>
2551
2552Return API version as a Perl scalar, 1 for Math::BigInt v1.70, 2 for
2553Math::BigInt v1.83.
2554
2555=back
2556
2557=head3 Constructors
2558
2559=over 4
2560
2561=item I<_new(STR)>
2562
2563Convert a string representing an unsigned decimal number to an object
2564representing the same number. The input is normalize, i.e., it matches
2565C<^(0|[1-9]\d*)$>.
2566
2567=item I<_zero()>
2568
2569Return an object representing the number zero.
2570
2571=item I<_one()>
2572
2573Return an object representing the number one.
2574
2575=item I<_two()>
2576
2577Return an object representing the number two.
2578
2579=item I<_ten()>
2580
2581Return an object representing the number ten.
2582
2583=item I<_from_bin(STR)>
2584
2585Return an object given a string representing a binary number. The input has a
2586'0b' prefix and matches the regular expression C<^0[bB](0|1[01]*)$>.
2587
2588=item I<_from_oct(STR)>
2589
2590Return an object given a string representing an octal number. The input has a
2591'0' prefix and matches the regular expression C<^0[1-7]*$>.
2592
2593=item I<_from_hex(STR)>
2594
2595Return an object given a string representing a hexadecimal number. The input
2596has a '0x' prefix and matches the regular expression
2597C<^0x(0|[1-9a-fA-F][\da-fA-F]*)$>.
2598
2599=back
2600
2601=head3 Mathematical functions
2602
2603Each of these methods may modify the first input argument, except I<_bgcd()>,
2604which shall not modify any input argument, and I<_sub()> which may modify the
2605second input argument.
2606
2607=over 4
2608
2609=item I<_add(OBJ1, OBJ2)>
2610
2611Returns the result of adding OBJ2 to OBJ1.
2612
2613=item I<_mul(OBJ1, OBJ2)>
2614
2615Returns the result of multiplying OBJ2 and OBJ1.
2616
2617=item I<_div(OBJ1, OBJ2)>
2618
2619Returns the result of dividing OBJ1 by OBJ2 and truncating the result to an
2620integer.
2621
2622=item I<_sub(OBJ1, OBJ2, FLAG)>
2623
2624=item I<_sub(OBJ1, OBJ2)>
2625
2626Returns the result of subtracting OBJ2 by OBJ1. If C<flag> is false or omitted,
2627OBJ1 might be modified. If C<flag> is true, OBJ2 might be modified.
2628
2629=item I<_dec(OBJ)>
2630
2631Decrement OBJ by one.
2632
2633=item I<_inc(OBJ)>
2634
2635Increment OBJ by one.
2636
2637=item I<_mod(OBJ1, OBJ2)>
2638
2639Return OBJ1 modulo OBJ2, i.e., the remainder after dividing OBJ1 by OBJ2.
2640
2641=item I<_sqrt(OBJ)>
2642
2643Return the square root of the object, truncated to integer.
2644
2645=item I<_root(OBJ, N)>
2646
2647Return Nth root of the object, truncated to int. N is E<gt>= 3.
2648
2649=item I<_fac(OBJ)>
2650
2651Return factorial of object (1*2*3*4*...).
2652
2653=item I<_pow(OBJ1, OBJ2)>
2654
2655Return OBJ1 to the power of OBJ2. By convention, 0**0 = 1.
2656
2657=item I<_modinv(OBJ1, OBJ2)>
2658
2659Return modular multiplicative inverse, i.e., return OBJ3 so that
2660
2661    (OBJ3 * OBJ1) % OBJ2 = 1 % OBJ2
2662
2663The result is returned as two arguments. If the modular multiplicative
2664inverse does not exist, both arguments are undefined. Otherwise, the
2665arguments are a number (object) and its sign ("+" or "-").
2666
2667The output value, with its sign, must either be a positive value in the
2668range 1,2,...,OBJ2-1 or the same value subtracted OBJ2. For instance, if the
2669input arguments are objects representing the numbers 7 and 5, the method
2670must either return an object representing the number 3 and a "+" sign, since
2671(3*7) % 5 = 1 % 5, or an object representing the number 2 and "-" sign,
2672since (-2*7) % 5 = 1 % 5.
2673
2674=item I<_modpow(OBJ1, OBJ2, OBJ3)>
2675
2676Return modular exponentiation, (OBJ1 ** OBJ2) % OBJ3.
2677
2678=item I<_rsft(OBJ, N, B)>
2679
2680Shift object N digits right in base B and return the resulting object. This is
2681equivalent to performing integer division by B**N and discarding the remainder,
2682except that it might be much faster, depending on how the number is represented
2683internally.
2684
2685For instance, if the object $obj represents the hexadecimal number 0xabcde,
2686then C<_rsft($obj, 2, 16)> returns an object representing the number 0xabc. The
2687"remainer", 0xde, is discarded and not returned.
2688
2689=item I<_lsft(OBJ, N, B)>
2690
2691Shift the object N digits left in base B. This is equivalent to multiplying by
2692B**N, except that it might be much faster, depending on how the number is
2693represented internally.
2694
2695=item I<_log_int(OBJ, B)>
2696
2697Return integer log of OBJ to base BASE. This method has two output arguments,
2698the OBJECT and a STATUS. The STATUS is Perl scalar; it is 1 if OBJ is the exact
2699result, 0 if the result was truncted to give OBJ, and undef if it is unknown
2700whether OBJ is the exact result.
2701
2702=item I<_gcd(OBJ1, OBJ2)>
2703
2704Return the greatest common divisor of OBJ1 and OBJ2.
2705
2706=back
2707
2708=head3 Bitwise operators
2709
2710Each of these methods may modify the first input argument.
2711
2712=over 4
2713
2714=item I<_and(OBJ1, OBJ2)>
2715
2716Return bitwise and. If necessary, the smallest number is padded with leading
2717zeros.
2718
2719=item I<_or(OBJ1, OBJ2)>
2720
2721Return bitwise or. If necessary, the smallest number is padded with leading
2722zeros.
2723
2724=item I<_xor(OBJ1, OBJ2)>
2725
2726Return bitwise exclusive or. If necessary, the smallest number is padded
2727with leading zeros.
2728
2729=back
2730
2731=head3 Boolean operators
2732
2733=over 4
2734
2735=item I<_is_zero(OBJ)>
2736
2737Returns a true value if OBJ is zero, and false value otherwise.
2738
2739=item I<_is_one(OBJ)>
2740
2741Returns a true value if OBJ is one, and false value otherwise.
2742
2743=item I<_is_two(OBJ)>
2744
2745Returns a true value if OBJ is two, and false value otherwise.
2746
2747=item I<_is_ten(OBJ)>
2748
2749Returns a true value if OBJ is ten, and false value otherwise.
2750
2751=item I<_is_even(OBJ)>
2752
2753Return a true value if OBJ is an even integer, and a false value otherwise.
2754
2755=item I<_is_odd(OBJ)>
2756
2757Return a true value if OBJ is an even integer, and a false value otherwise.
2758
2759=item I<_acmp(OBJ1, OBJ2)>
2760
2761Compare OBJ1 and OBJ2 and return -1, 0, or 1, if OBJ1 is less than, equal
2762to, or larger than OBJ2, respectively.
2763
2764=back
2765
2766=head3 String conversion
2767
2768=over 4
2769
2770=item I<_str(OBJ)>
2771
2772Return a string representing the object. The returned string should have no
2773leading zeros, i.e., it should match C<^(0|[1-9]\d*)$>.
2774
2775=item I<_as_bin(OBJ)>
2776
2777Return the binary string representation of the number. The string must have a
2778'0b' prefix.
2779
2780=item I<_as_oct(OBJ)>
2781
2782Return the octal string representation of the number. The string must have
2783a '0x' prefix.
2784
2785Note: This method was required from Math::BigInt version 1.78, but the required
2786API version number was not incremented, so there are older libraries that
2787support API version 1, but do not support C<_as_oct()>.
2788
2789=item I<_as_hex(OBJ)>
2790
2791Return the hexadecimal string representation of the number. The string must
2792have a '0x' prefix.
2793
2794=back
2795
2796=head3 Numeric conversion
2797
2798=over 4
2799
2800=item I<_num(OBJ)>
2801
2802Given an object, return a Perl scalar number (int/float) representing this
2803number.
2804
2805=back
2806
2807=head3 Miscellaneous
2808
2809=over 4
2810
2811=item I<_copy(OBJ)>
2812
2813Return a true copy of the object.
2814
2815=item I<_len(OBJ)>
2816
2817Returns the number of the decimal digits in the number. The output is a
2818Perl scalar.
2819
2820=item I<_zeros(OBJ)>
2821
2822Return the number of trailing decimal zeros. The output is a Perl scalar.
2823
2824=item I<_digit(OBJ, N)>
2825
2826Return the Nth digit as a Perl scalar. N is a Perl scalar, where zero refers to
2827the rightmost (least significant) digit, and negative values count from the
2828left (most significant digit). If $obj represents the number 123, then
2829I<_digit($obj, 0)> is 3 and I<_digit(123, -1)> is 1.
2830
2831=item I<_check(OBJ)>
2832
2833Return a true value if the object is OK, and a false value otherwise. This is a
2834check routine to test the internal state of the object for corruption.
2835
2836=back
2837
2838=head2 API version 2
2839
2840The following methods are required for an API version of 2 or greater.
2841
2842=head3 Constructors
2843
2844=over 4
2845
2846=item I<_1ex(N)>
2847
2848Return an object representing the number 10**N where N E<gt>= 0 is a Perl
2849scalar.
2850
2851=back
2852
2853=head3 Mathematical functions
2854
2855=over 4
2856
2857=item I<_nok(OBJ1, OBJ2)>
2858
2859Return the binomial coefficient OBJ1 over OBJ1.
2860
2861=back
2862
2863=head3 Miscellaneous
2864
2865=over 4
2866
2867=item I<_alen(OBJ)>
2868
2869Return the approximate number of decimal digits of the object. The
2870output is one Perl scalar. This estimate must be greater than or equal
2871to what C<_len()> returns.
2872
2873=back
2874
2875=head2 API optional methods
2876
2877The following methods are optional, and can be defined if the underlying lib
2878has a fast way to do them. If undefined, Math::BigInt will use pure Perl (hence
2879slow) fallback routines to emulate these:
2880
2881=head3 Signed bitwise operators.
2882
2883Each of these methods may modify the first input argument.
2884
2885=over 4
2886
2887=item I<_signed_or(OBJ1, OBJ2, SIGN1, SIGN2)>
2888
2889Return the signed bitwise or.
2890
2891=item I<_signed_and(OBJ1, OBJ2, SIGN1, SIGN2)>
2892
2893Return the signed bitwise and.
2894
2895=item I<_signed_xor(OBJ1, OBJ2, SIGN1, SIGN2)>
2896
2897Return the signed bitwise exclusive or.
2898
2899=back
2900
2901=head1 WRAP YOUR OWN
2902
2903If you want to port your own favourite c-lib for big numbers to the
2904Math::BigInt interface, you can take any of the already existing modules as
2905a rough guideline. You should really wrap up the latest BigInt and BigFloat
2906testsuites with your module, and replace in them any of the following:
2907
2908	use Math::BigInt;
2909
2910by this:
2911
2912	use Math::BigInt lib => 'yourlib';
2913
2914This way you ensure that your library really works 100% within Math::BigInt.
2915
2916=head1 BUGS
2917
2918Please report any bugs or feature requests to
2919C<bug-math-bigint at rt.cpan.org>, or through the web interface at
2920L<https://rt.cpan.org/Ticket/Create.html?Queue=Math-BigInt>
2921(requires login).
2922We will be notified, and then you'll automatically be notified of progress on
2923your bug as I make changes.
2924
2925=head1 SUPPORT
2926
2927You can find documentation for this module with the perldoc command.
2928
2929    perldoc Math::BigInt::Calc
2930
2931You can also look for information at:
2932
2933=over 4
2934
2935=item * RT: CPAN's request tracker
2936
2937L<https://rt.cpan.org/Public/Dist/Display.html?Name=Math-BigInt>
2938
2939=item * AnnoCPAN: Annotated CPAN documentation
2940
2941L<http://annocpan.org/dist/Math-BigInt>
2942
2943=item * CPAN Ratings
2944
2945L<http://cpanratings.perl.org/dist/Math-BigInt>
2946
2947=item * Search CPAN
2948
2949L<http://search.cpan.org/dist/Math-BigInt/>
2950
2951=item * CPAN Testers Matrix
2952
2953L<http://matrix.cpantesters.org/?dist=Math-BigInt>
2954
2955=item * The Bignum mailing list
2956
2957=over 4
2958
2959=item * Post to mailing list
2960
2961C<bignum at lists.scsys.co.uk>
2962
2963=item * View mailing list
2964
2965L<http://lists.scsys.co.uk/pipermail/bignum/>
2966
2967=item * Subscribe/Unsubscribe
2968
2969L<http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/bignum>
2970
2971=back
2972
2973=back
2974
2975=head1 LICENSE
2976
2977This program is free software; you may redistribute it and/or modify it under
2978the same terms as Perl itself.
2979
2980=head1 AUTHORS
2981
2982=over 4
2983
2984=item *
2985
2986Original math code by Mark Biggar, rewritten by Tels L<http://bloodgate.com/>
2987in late 2000.
2988
2989=item *
2990
2991Separated from BigInt and shaped API with the help of John Peacock.
2992
2993=item *
2994
2995Fixed, speed-up, streamlined and enhanced by Tels 2001 - 2007.
2996
2997=item *
2998
2999API documentation corrected and extended by Peter John Acklam,
3000E<lt>pjacklam@online.noE<gt>
3001
3002=back
3003
3004=head1 SEE ALSO
3005
3006L<Math::BigInt>, L<Math::BigFloat>,
3007L<Math::BigInt::GMP>, L<Math::BigInt::FastCalc> and L<Math::BigInt::Pari>.
3008
3009=cut
3010