1package Math::BigInt::Calc;
2
3use 5.005;
4use strict;
5# use warnings;	# dont use warnings for older Perls
6
7use vars qw/$VERSION/;
8
9$VERSION = '0.47';
10
11# Package to store unsigned big integers in decimal and do math with them
12
13# Internally the numbers are stored in an array with at least 1 element, no
14# leading zero parts (except the first) and in base 1eX where X is determined
15# automatically at loading time to be the maximum possible value
16
17# todo:
18# - fully remove funky $# stuff in div() (maybe - that code scares me...)
19
20# USE_MUL: due to problems on certain os (os390, posix-bc) "* 1e-5" is used
21# instead of "/ 1e5" at some places, (marked with USE_MUL). Other platforms
22# BS2000, some Crays need USE_DIV instead.
23# The BEGIN block is used to determine which of the two variants gives the
24# correct result.
25
26# Beware of things like:
27# $i = $i * $y + $car; $car = int($i / $MBASE); $i = $i % $MBASE;
28# This works on x86, but fails on ARM (SA1100, iPAQ) due to whoknows what
29# reasons. So, use this instead (slower, but correct):
30# $i = $i * $y + $car; $car = int($i / $MBASE); $i -= $MBASE * $car;
31
32##############################################################################
33# global constants, flags and accessory
34
35# announce that we are compatible with MBI v1.70 and up
36sub api_version () { 1; }
37
38# constants for easier life
39my ($BASE,$BASE_LEN,$MBASE,$RBASE,$MAX_VAL,$BASE_LEN_SMALL);
40my ($AND_BITS,$XOR_BITS,$OR_BITS);
41my ($AND_MASK,$XOR_MASK,$OR_MASK);
42
43sub _base_len
44  {
45  # set/get the BASE_LEN and assorted other, connected values
46  # used only be the testsuite, set is used only by the BEGIN block below
47  shift;
48
49  my $b = shift;
50  if (defined $b)
51    {
52    # find whether we can use mul or div or none in mul()/div()
53    # (in last case reduce BASE_LEN_SMALL)
54    $BASE_LEN_SMALL = $b+1;
55    my $caught = 0;
56    while (--$BASE_LEN_SMALL > 5)
57      {
58      $MBASE = int("1e".$BASE_LEN_SMALL);
59      $RBASE = abs('1e-'.$BASE_LEN_SMALL);		# see USE_MUL
60      $caught = 0;
61      $caught += 1 if (int($MBASE * $RBASE) != 1);	# should be 1
62      $caught += 2 if (int($MBASE / $MBASE) != 1);	# should be 1
63      last if $caught != 3;
64      }
65    # BASE_LEN is used for anything else than mul()/div()
66    $BASE_LEN = $BASE_LEN_SMALL;
67    $BASE_LEN = shift if (defined $_[0]);		# one more arg?
68    $BASE = int("1e".$BASE_LEN);
69
70    $MBASE = int("1e".$BASE_LEN_SMALL);
71    $RBASE = abs('1e-'.$BASE_LEN_SMALL);		# see USE_MUL
72    $MAX_VAL = $MBASE-1;
73
74    # avoid redefinitions
75
76    undef &_mul;
77    undef &_div;
78
79    # $caught & 1 != 0 => cannot use MUL
80    # $caught & 2 != 0 => cannot use DIV
81    # The parens around ($caught & 1) were important, indeed, if we would use
82    # & here.
83    if ($caught == 2)				# 2
84      {
85      # must USE_MUL since we cannot use DIV
86      *{_mul} = \&_mul_use_mul;
87      *{_div} = \&_div_use_mul;
88      }
89    else					# 0 or 1
90      {
91      # can USE_DIV instead
92      *{_mul} = \&_mul_use_div;
93      *{_div} = \&_div_use_div;
94      }
95    }
96  return $BASE_LEN unless wantarray;
97  return ($BASE_LEN, $AND_BITS, $XOR_BITS, $OR_BITS, $BASE_LEN_SMALL, $MAX_VAL, $BASE);
98  }
99
100sub _new
101  {
102  # (ref to string) return ref to num_array
103  # Convert a number from string format (without sign) to internal base
104  # 1ex format. Assumes normalized value as input.
105  my $il = length($_[1])-1;
106
107  # < BASE_LEN due len-1 above
108  return [ int($_[1]) ] if $il < $BASE_LEN;	# shortcut for short numbers
109
110  # this leaves '00000' instead of int 0 and will be corrected after any op
111  [ reverse(unpack("a" . ($il % $BASE_LEN+1)
112    . ("a$BASE_LEN" x ($il / $BASE_LEN)), $_[1])) ];
113  }
114
115BEGIN
116  {
117  # from Daniel Pfeiffer: determine largest group of digits that is precisely
118  # multipliable with itself plus carry
119  # Test now changed to expect the proper pattern, not a result off by 1 or 2
120  my ($e, $num) = 3;	# lowest value we will use is 3+1-1 = 3
121  do
122    {
123    $num = ('9' x ++$e) + 0;
124    $num *= $num + 1.0;
125    } while ("$num" =~ /9{$e}0{$e}/);	# must be a certain pattern
126  $e--; 				# last test failed, so retract one step
127  # the limits below brush the problems with the test above under the rug:
128  # the test should be able to find the proper $e automatically
129  $e = 5 if $^O =~ /^uts/;	# UTS get's some special treatment
130  $e = 5 if $^O =~ /^unicos/;	# unicos is also problematic (6 seems to work
131				# there, but we play safe)
132  $e = 5 if $] < 5.006;		# cap, for older Perls
133  $e = 7 if $e > 7;		# cap, for VMS, OS/390 and other 64 bit systems
134				# 8 fails inside random testsuite, so take 7
135
136  __PACKAGE__->_base_len($e);	# set and store
137
138  use integer;
139  # find out how many bits _and, _or and _xor can take (old default = 16)
140  # I don't think anybody has yet 128 bit scalars, so let's play safe.
141  local $^W = 0;	# don't warn about 'nonportable number'
142  $AND_BITS = 15; $XOR_BITS = 15; $OR_BITS = 15;
143
144  # find max bits, we will not go higher than numberofbits that fit into $BASE
145  # to make _and etc simpler (and faster for smaller, slower for large numbers)
146  my $max = 16;
147  while (2 ** $max < $BASE) { $max++; }
148  {
149    no integer;
150    $max = 16 if $] < 5.006;	# older Perls might not take >16 too well
151  }
152  my ($x,$y,$z);
153  do {
154    $AND_BITS++;
155    $x = oct('0b' . '1' x $AND_BITS); $y = $x & $x;
156    $z = (2 ** $AND_BITS) - 1;
157    } while ($AND_BITS < $max && $x == $z && $y == $x);
158  $AND_BITS --;						# retreat one step
159  do {
160    $XOR_BITS++;
161    $x = oct('0b' . '1' x $XOR_BITS); $y = $x ^ 0;
162    $z = (2 ** $XOR_BITS) - 1;
163    } while ($XOR_BITS < $max && $x == $z && $y == $x);
164  $XOR_BITS --;						# retreat one step
165  do {
166    $OR_BITS++;
167    $x = oct('0b' . '1' x $OR_BITS); $y = $x | $x;
168    $z = (2 ** $OR_BITS) - 1;
169    } while ($OR_BITS < $max && $x == $z && $y == $x);
170  $OR_BITS --;						# retreat one step
171
172  $AND_MASK = __PACKAGE__->_new( ( 2 ** $AND_BITS ));
173  $XOR_MASK = __PACKAGE__->_new( ( 2 ** $XOR_BITS ));
174  $OR_MASK = __PACKAGE__->_new( ( 2 ** $OR_BITS ));
175  }
176
177###############################################################################
178
179sub _zero
180  {
181  # create a zero
182  [ 0 ];
183  }
184
185sub _one
186  {
187  # create a one
188  [ 1 ];
189  }
190
191sub _two
192  {
193  # create a two (used internally for shifting)
194  [ 2 ];
195  }
196
197sub _ten
198  {
199  # create a 10 (used internally for shifting)
200  [ 10 ];
201  }
202
203sub _copy
204  {
205  # make a true copy
206  [ @{$_[1]} ];
207  }
208
209# catch and throw away
210sub import { }
211
212##############################################################################
213# convert back to string and number
214
215sub _str
216  {
217  # (ref to BINT) return num_str
218  # Convert number from internal base 100000 format to string format.
219  # internal format is always normalized (no leading zeros, "-0" => "+0")
220  my $ar = $_[1];
221
222  my $l = scalar @$ar;				# number of parts
223  if ($l < 1)					# should not happen
224    {
225    require Carp;
226    Carp::croak("$_[1] has no elements");
227    }
228
229  my $ret = "";
230  # handle first one different to strip leading zeros from it (there are no
231  # leading zero parts in internal representation)
232  $l --; $ret .= int($ar->[$l]); $l--;
233  # Interestingly, the pre-padd method uses more time
234  # the old grep variant takes longer (14 vs. 10 sec)
235  my $z = '0' x ($BASE_LEN-1);
236  while ($l >= 0)
237    {
238    $ret .= substr($z.$ar->[$l],-$BASE_LEN); # fastest way I could think of
239    $l--;
240    }
241  $ret;
242  }
243
244sub _num
245  {
246  # Make a number (scalar int/float) from a BigInt object
247  my $x = $_[1];
248
249  return 0+$x->[0] if scalar @$x == 1;  # below $BASE
250  my $fac = 1;
251  my $num = 0;
252  foreach (@$x)
253    {
254    $num += $fac*$_; $fac *= $BASE;
255    }
256  $num;
257  }
258
259##############################################################################
260# actual math code
261
262sub _add
263  {
264  # (ref to int_num_array, ref to int_num_array)
265  # routine to add two base 1eX numbers
266  # stolen from Knuth Vol 2 Algorithm A pg 231
267  # there are separate routines to add and sub as per Knuth pg 233
268  # This routine clobbers up array x, but not y.
269
270  my ($c,$x,$y) = @_;
271
272  return $x if (@$y == 1) && $y->[0] == 0;		# $x + 0 => $x
273  if ((@$x == 1) && $x->[0] == 0)			# 0 + $y => $y->copy
274    {
275    # twice as slow as $x = [ @$y ], but necc. to retain $x as ref :(
276    @$x = @$y; return $x;
277    }
278
279  # for each in Y, add Y to X and carry. If after that, something is left in
280  # X, foreach in X add carry to X and then return X, carry
281  # Trades one "$j++" for having to shift arrays
282  my $i; my $car = 0; my $j = 0;
283  for $i (@$y)
284    {
285    $x->[$j] -= $BASE if $car = (($x->[$j] += $i + $car) >= $BASE) ? 1 : 0;
286    $j++;
287    }
288  while ($car != 0)
289    {
290    $x->[$j] -= $BASE if $car = (($x->[$j] += $car) >= $BASE) ? 1 : 0; $j++;
291    }
292  $x;
293  }
294
295sub _inc
296  {
297  # (ref to int_num_array, ref to int_num_array)
298  # Add 1 to $x, modify $x in place
299  my ($c,$x) = @_;
300
301  for my $i (@$x)
302    {
303    return $x if (($i += 1) < $BASE);		# early out
304    $i = 0;					# overflow, next
305    }
306  push @$x,1 if (($x->[-1] || 0) == 0);		# last overflowed, so extend
307  $x;
308  }
309
310sub _dec
311  {
312  # (ref to int_num_array, ref to int_num_array)
313  # Sub 1 from $x, modify $x in place
314  my ($c,$x) = @_;
315
316  my $MAX = $BASE-1;				# since MAX_VAL based on MBASE
317  for my $i (@$x)
318    {
319    last if (($i -= 1) >= 0);			# early out
320    $i = $MAX;					# underflow, next
321    }
322  pop @$x if $x->[-1] == 0 && @$x > 1;		# last underflowed (but leave 0)
323  $x;
324  }
325
326sub _sub
327  {
328  # (ref to int_num_array, ref to int_num_array, swap)
329  # subtract base 1eX numbers -- stolen from Knuth Vol 2 pg 232, $x > $y
330  # subtract Y from X by modifying x in place
331  my ($c,$sx,$sy,$s) = @_;
332
333  my $car = 0; my $i; my $j = 0;
334  if (!$s)
335    {
336    for $i (@$sx)
337      {
338      last unless defined $sy->[$j] || $car;
339      $i += $BASE if $car = (($i -= ($sy->[$j] || 0) + $car) < 0); $j++;
340      }
341    # might leave leading zeros, so fix that
342    return __strip_zeros($sx);
343    }
344  for $i (@$sx)
345    {
346    # we can't do an early out if $x is < than $y, since we
347    # need to copy the high chunks from $y. Found by Bob Mathews.
348    #last unless defined $sy->[$j] || $car;
349    $sy->[$j] += $BASE
350     if $car = (($sy->[$j] = $i-($sy->[$j]||0) - $car) < 0);
351    $j++;
352    }
353  # might leave leading zeros, so fix that
354  __strip_zeros($sy);
355  }
356
357sub _mul_use_mul
358  {
359  # (ref to int_num_array, ref to int_num_array)
360  # multiply two numbers in internal representation
361  # modifies first arg, second need not be different from first
362  my ($c,$xv,$yv) = @_;
363
364  if (@$yv == 1)
365    {
366    # shortcut for two very short numbers (improved by Nathan Zook)
367    # works also if xv and yv are the same reference, and handles also $x == 0
368    if (@$xv == 1)
369      {
370      if (($xv->[0] *= $yv->[0]) >= $MBASE)
371         {
372         $xv->[0] = $xv->[0] - ($xv->[1] = int($xv->[0] * $RBASE)) * $MBASE;
373         };
374      return $xv;
375      }
376    # $x * 0 => 0
377    if ($yv->[0] == 0)
378      {
379      @$xv = (0);
380      return $xv;
381      }
382    # multiply a large number a by a single element one, so speed up
383    my $y = $yv->[0]; my $car = 0;
384    foreach my $i (@$xv)
385      {
386      $i = $i * $y + $car; $car = int($i * $RBASE); $i -= $car * $MBASE;
387      }
388    push @$xv, $car if $car != 0;
389    return $xv;
390    }
391  # shortcut for result $x == 0 => result = 0
392  return $xv if ( ((@$xv == 1) && ($xv->[0] == 0)) );
393
394  # since multiplying $x with $x fails, make copy in this case
395  $yv = [@$xv] if $xv == $yv;	# same references?
396
397  my @prod = (); my ($prod,$car,$cty,$xi,$yi);
398
399  for $xi (@$xv)
400    {
401    $car = 0; $cty = 0;
402
403    # slow variant
404#    for $yi (@$yv)
405#      {
406#      $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
407#      $prod[$cty++] =
408#       $prod - ($car = int($prod * RBASE)) * $MBASE;  # see USE_MUL
409#      }
410#    $prod[$cty] += $car if $car; # need really to check for 0?
411#    $xi = shift @prod;
412
413    # faster variant
414    # looping through this if $xi == 0 is silly - so optimize it away!
415    $xi = (shift @prod || 0), next if $xi == 0;
416    for $yi (@$yv)
417      {
418      $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
419##     this is actually a tad slower
420##        $prod = $prod[$cty]; $prod += ($car + $xi * $yi);	# no ||0 here
421      $prod[$cty++] =
422       $prod - ($car = int($prod * $RBASE)) * $MBASE;  # see USE_MUL
423      }
424    $prod[$cty] += $car if $car; # need really to check for 0?
425    $xi = shift @prod || 0;	# || 0 makes v5.005_3 happy
426    }
427  push @$xv, @prod;
428  __strip_zeros($xv);
429  $xv;
430  }
431
432sub _mul_use_div
433  {
434  # (ref to int_num_array, ref to int_num_array)
435  # multiply two numbers in internal representation
436  # modifies first arg, second need not be different from first
437  my ($c,$xv,$yv) = @_;
438
439  if (@$yv == 1)
440    {
441    # shortcut for two small numbers, also handles $x == 0
442    if (@$xv == 1)
443      {
444      # shortcut for two very short numbers (improved by Nathan Zook)
445      # works also if xv and yv are the same reference, and handles also $x == 0
446      if (($xv->[0] *= $yv->[0]) >= $MBASE)
447          {
448          $xv->[0] =
449              $xv->[0] - ($xv->[1] = int($xv->[0] / $MBASE)) * $MBASE;
450          };
451      return $xv;
452      }
453    # $x * 0 => 0
454    if ($yv->[0] == 0)
455      {
456      @$xv = (0);
457      return $xv;
458      }
459    # multiply a large number a by a single element one, so speed up
460    my $y = $yv->[0]; my $car = 0;
461    foreach my $i (@$xv)
462      {
463      $i = $i * $y + $car; $car = int($i / $MBASE); $i -= $car * $MBASE;
464      }
465    push @$xv, $car if $car != 0;
466    return $xv;
467    }
468  # shortcut for result $x == 0 => result = 0
469  return $xv if ( ((@$xv == 1) && ($xv->[0] == 0)) );
470
471  # since multiplying $x with $x fails, make copy in this case
472  $yv = [@$xv] if $xv == $yv;	# same references?
473
474  my @prod = (); my ($prod,$car,$cty,$xi,$yi);
475  for $xi (@$xv)
476    {
477    $car = 0; $cty = 0;
478    # looping through this if $xi == 0 is silly - so optimize it away!
479    $xi = (shift @prod || 0), next if $xi == 0;
480    for $yi (@$yv)
481      {
482      $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
483      $prod[$cty++] =
484       $prod - ($car = int($prod / $MBASE)) * $MBASE;
485      }
486    $prod[$cty] += $car if $car; # need really to check for 0?
487    $xi = shift @prod || 0;	# || 0 makes v5.005_3 happy
488    }
489  push @$xv, @prod;
490  __strip_zeros($xv);
491  $xv;
492  }
493
494sub _div_use_mul
495  {
496  # ref to array, ref to array, modify first array and return remainder if
497  # in list context
498
499  # see comments in _div_use_div() for more explanations
500
501  my ($c,$x,$yorg) = @_;
502
503  # the general div algorithmn here is about O(N*N) and thus quite slow, so
504  # we first check for some special cases and use shortcuts to handle them.
505
506  # This works, because we store the numbers in a chunked format where each
507  # element contains 5..7 digits (depending on system).
508
509  # if both numbers have only one element:
510  if (@$x == 1 && @$yorg == 1)
511    {
512    # shortcut, $yorg and $x are two small numbers
513    if (wantarray)
514      {
515      my $r = [ $x->[0] % $yorg->[0] ];
516      $x->[0] = int($x->[0] / $yorg->[0]);
517      return ($x,$r);
518      }
519    else
520      {
521      $x->[0] = int($x->[0] / $yorg->[0]);
522      return $x;
523      }
524    }
525
526  # if x has more than one, but y has only one element:
527  if (@$yorg == 1)
528    {
529    my $rem;
530    $rem = _mod($c,[ @$x ],$yorg) if wantarray;
531
532    # shortcut, $y is < $BASE
533    my $j = scalar @$x; my $r = 0;
534    my $y = $yorg->[0]; my $b;
535    while ($j-- > 0)
536      {
537      $b = $r * $MBASE + $x->[$j];
538      $x->[$j] = int($b/$y);
539      $r = $b % $y;
540      }
541    pop @$x if @$x > 1 && $x->[-1] == 0;	# splice up a leading zero
542    return ($x,$rem) if wantarray;
543    return $x;
544    }
545
546  # now x and y have more than one element
547
548  # check whether y has more elements than x, if yet, the result will be 0
549  if (@$yorg > @$x)
550    {
551    my $rem;
552    $rem = [@$x] if wantarray;                  # make copy
553    splice (@$x,1);                             # keep ref to original array
554    $x->[0] = 0;                                # set to 0
555    return ($x,$rem) if wantarray;              # including remainder?
556    return $x;					# only x, which is [0] now
557    }
558  # check whether the numbers have the same number of elements, in that case
559  # the result will fit into one element and can be computed efficiently
560  if (@$yorg == @$x)
561    {
562    my $rem;
563    # if $yorg has more digits than $x (it's leading element is longer than
564    # the one from $x), the result will also be 0:
565    if (length(int($yorg->[-1])) > length(int($x->[-1])))
566      {
567      $rem = [@$x] if wantarray;		# make copy
568      splice (@$x,1);				# keep ref to org array
569      $x->[0] = 0;				# set to 0
570      return ($x,$rem) if wantarray;		# including remainder?
571      return $x;
572      }
573    # now calculate $x / $yorg
574    if (length(int($yorg->[-1])) == length(int($x->[-1])))
575      {
576      # same length, so make full compare
577
578      my $a = 0; my $j = scalar @$x - 1;
579      # manual way (abort if unequal, good for early ne)
580      while ($j >= 0)
581        {
582        last if ($a = $x->[$j] - $yorg->[$j]); $j--;
583        }
584      # $a contains the result of the compare between X and Y
585      # a < 0: x < y, a == 0: x == y, a > 0: x > y
586      if ($a <= 0)
587        {
588        $rem = [ 0 ];                   # a = 0 => x == y => rem 0
589        $rem = [@$x] if $a != 0;        # a < 0 => x < y => rem = x
590        splice(@$x,1);                  # keep single element
591        $x->[0] = 0;                    # if $a < 0
592        $x->[0] = 1 if $a == 0;         # $x == $y
593        return ($x,$rem) if wantarray;
594        return $x;
595        }
596      # $x >= $y, so proceed normally
597      }
598    }
599
600  # all other cases:
601
602  my $y = [ @$yorg ];				# always make copy to preserve
603
604  my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1,@d,$tmp,$q,$u2,$u1,$u0);
605
606  $car = $bar = $prd = 0;
607  if (($dd = int($MBASE/($y->[-1]+1))) != 1)
608    {
609    for $xi (@$x)
610      {
611      $xi = $xi * $dd + $car;
612      $xi -= ($car = int($xi * $RBASE)) * $MBASE;	# see USE_MUL
613      }
614    push(@$x, $car); $car = 0;
615    for $yi (@$y)
616      {
617      $yi = $yi * $dd + $car;
618      $yi -= ($car = int($yi * $RBASE)) * $MBASE;	# see USE_MUL
619      }
620    }
621  else
622    {
623    push(@$x, 0);
624    }
625  @q = (); ($v2,$v1) = @$y[-2,-1];
626  $v2 = 0 unless $v2;
627  while ($#$x > $#$y)
628    {
629    ($u2,$u1,$u0) = @$x[-3..-1];
630    $u2 = 0 unless $u2;
631    #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"
632    # if $v1 == 0;
633    $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$MBASE+$u1)/$v1));
634    --$q while ($v2*$q > ($u0*$MBASE+$u1-$q*$v1)*$MBASE+$u2);
635    if ($q)
636      {
637      ($car, $bar) = (0,0);
638      for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
639        {
640        $prd = $q * $y->[$yi] + $car;
641        $prd -= ($car = int($prd * $RBASE)) * $MBASE;	# see USE_MUL
642	$x->[$xi] += $MBASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0));
643	}
644      if ($x->[-1] < $car + $bar)
645        {
646        $car = 0; --$q;
647	for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
648          {
649	  $x->[$xi] -= $MBASE
650	   if ($car = (($x->[$xi] += $y->[$yi] + $car) >= $MBASE));
651	  }
652	}
653      }
654    pop(@$x);
655    unshift(@q, $q);
656    }
657  if (wantarray)
658    {
659    @d = ();
660    if ($dd != 1)
661      {
662      $car = 0;
663      for $xi (reverse @$x)
664        {
665        $prd = $car * $MBASE + $xi;
666        $car = $prd - ($tmp = int($prd / $dd)) * $dd; # see USE_MUL
667        unshift(@d, $tmp);
668        }
669      }
670    else
671      {
672      @d = @$x;
673      }
674    @$x = @q;
675    my $d = \@d;
676    __strip_zeros($x);
677    __strip_zeros($d);
678    return ($x,$d);
679    }
680  @$x = @q;
681  __strip_zeros($x);
682  $x;
683  }
684
685sub _div_use_div
686  {
687  # ref to array, ref to array, modify first array and return remainder if
688  # in list context
689  my ($c,$x,$yorg) = @_;
690
691  # the general div algorithmn here is about O(N*N) and thus quite slow, so
692  # we first check for some special cases and use shortcuts to handle them.
693
694  # This works, because we store the numbers in a chunked format where each
695  # element contains 5..7 digits (depending on system).
696
697  # if both numbers have only one element:
698  if (@$x == 1 && @$yorg == 1)
699    {
700    # shortcut, $yorg and $x are two small numbers
701    if (wantarray)
702      {
703      my $r = [ $x->[0] % $yorg->[0] ];
704      $x->[0] = int($x->[0] / $yorg->[0]);
705      return ($x,$r);
706      }
707    else
708      {
709      $x->[0] = int($x->[0] / $yorg->[0]);
710      return $x;
711      }
712    }
713  # if x has more than one, but y has only one element:
714  if (@$yorg == 1)
715    {
716    my $rem;
717    $rem = _mod($c,[ @$x ],$yorg) if wantarray;
718
719    # shortcut, $y is < $BASE
720    my $j = scalar @$x; my $r = 0;
721    my $y = $yorg->[0]; my $b;
722    while ($j-- > 0)
723      {
724      $b = $r * $MBASE + $x->[$j];
725      $x->[$j] = int($b/$y);
726      $r = $b % $y;
727      }
728    pop @$x if @$x > 1 && $x->[-1] == 0;	# splice up a leading zero
729    return ($x,$rem) if wantarray;
730    return $x;
731    }
732  # now x and y have more than one element
733
734  # check whether y has more elements than x, if yet, the result will be 0
735  if (@$yorg > @$x)
736    {
737    my $rem;
738    $rem = [@$x] if wantarray;			# make copy
739    splice (@$x,1);				# keep ref to original array
740    $x->[0] = 0;				# set to 0
741    return ($x,$rem) if wantarray;		# including remainder?
742    return $x;					# only x, which is [0] now
743    }
744  # check whether the numbers have the same number of elements, in that case
745  # the result will fit into one element and can be computed efficiently
746  if (@$yorg == @$x)
747    {
748    my $rem;
749    # if $yorg has more digits than $x (it's leading element is longer than
750    # the one from $x), the result will also be 0:
751    if (length(int($yorg->[-1])) > length(int($x->[-1])))
752      {
753      $rem = [@$x] if wantarray;		# make copy
754      splice (@$x,1);				# keep ref to org array
755      $x->[0] = 0;				# set to 0
756      return ($x,$rem) if wantarray;		# including remainder?
757      return $x;
758      }
759    # now calculate $x / $yorg
760
761    if (length(int($yorg->[-1])) == length(int($x->[-1])))
762      {
763      # same length, so make full compare
764
765      my $a = 0; my $j = scalar @$x - 1;
766      # manual way (abort if unequal, good for early ne)
767      while ($j >= 0)
768        {
769        last if ($a = $x->[$j] - $yorg->[$j]); $j--;
770        }
771      # $a contains the result of the compare between X and Y
772      # a < 0: x < y, a == 0: x == y, a > 0: x > y
773      if ($a <= 0)
774        {
775        $rem = [ 0 ];			# a = 0 => x == y => rem 0
776        $rem = [@$x] if $a != 0;	# a < 0 => x < y => rem = x
777        splice(@$x,1);			# keep single element
778        $x->[0] = 0;			# if $a < 0
779        $x->[0] = 1 if $a == 0; 	# $x == $y
780        return ($x,$rem) if wantarray;	# including remainder?
781        return $x;
782        }
783      # $x >= $y, so proceed normally
784
785      }
786    }
787
788  # all other cases:
789
790  my $y = [ @$yorg ];				# always make copy to preserve
791
792  my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1,@d,$tmp,$q,$u2,$u1,$u0);
793
794  $car = $bar = $prd = 0;
795  if (($dd = int($MBASE/($y->[-1]+1))) != 1)
796    {
797    for $xi (@$x)
798      {
799      $xi = $xi * $dd + $car;
800      $xi -= ($car = int($xi / $MBASE)) * $MBASE;
801      }
802    push(@$x, $car); $car = 0;
803    for $yi (@$y)
804      {
805      $yi = $yi * $dd + $car;
806      $yi -= ($car = int($yi / $MBASE)) * $MBASE;
807      }
808    }
809  else
810    {
811    push(@$x, 0);
812    }
813
814  # @q will accumulate the final result, $q contains the current computed
815  # part of the final result
816
817  @q = (); ($v2,$v1) = @$y[-2,-1];
818  $v2 = 0 unless $v2;
819  while ($#$x > $#$y)
820    {
821    ($u2,$u1,$u0) = @$x[-3..-1];
822    $u2 = 0 unless $u2;
823    #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"
824    # if $v1 == 0;
825    $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$MBASE+$u1)/$v1));
826    --$q while ($v2*$q > ($u0*$MBASE+$u1-$q*$v1)*$MBASE+$u2);
827    if ($q)
828      {
829      ($car, $bar) = (0,0);
830      for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
831        {
832        $prd = $q * $y->[$yi] + $car;
833        $prd -= ($car = int($prd / $MBASE)) * $MBASE;
834	$x->[$xi] += $MBASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0));
835	}
836      if ($x->[-1] < $car + $bar)
837        {
838        $car = 0; --$q;
839	for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)
840          {
841	  $x->[$xi] -= $MBASE
842	   if ($car = (($x->[$xi] += $y->[$yi] + $car) >= $MBASE));
843	  }
844	}
845      }
846    pop(@$x); unshift(@q, $q);
847    }
848  if (wantarray)
849    {
850    @d = ();
851    if ($dd != 1)
852      {
853      $car = 0;
854      for $xi (reverse @$x)
855        {
856        $prd = $car * $MBASE + $xi;
857        $car = $prd - ($tmp = int($prd / $dd)) * $dd;
858        unshift(@d, $tmp);
859        }
860      }
861    else
862      {
863      @d = @$x;
864      }
865    @$x = @q;
866    my $d = \@d;
867    __strip_zeros($x);
868    __strip_zeros($d);
869    return ($x,$d);
870    }
871  @$x = @q;
872  __strip_zeros($x);
873  $x;
874  }
875
876##############################################################################
877# testing
878
879sub _acmp
880  {
881  # internal absolute post-normalized compare (ignore signs)
882  # ref to array, ref to array, return <0, 0, >0
883  # arrays must have at least one entry; this is not checked for
884  my ($c,$cx,$cy) = @_;
885
886  # shortcut for short numbers
887  return (($cx->[0] <=> $cy->[0]) <=> 0)
888   if scalar @$cx == scalar @$cy && scalar @$cx == 1;
889
890  # fast comp based on number of array elements (aka pseudo-length)
891  my $lxy = (scalar @$cx - scalar @$cy)
892  # or length of first element if same number of elements (aka difference 0)
893    ||
894  # need int() here because sometimes the last element is '00018' vs '18'
895   (length(int($cx->[-1])) - length(int($cy->[-1])));
896  return -1 if $lxy < 0;				# already differs, ret
897  return 1 if $lxy > 0;					# ditto
898
899  # manual way (abort if unequal, good for early ne)
900  my $a; my $j = scalar @$cx;
901  while (--$j >= 0)
902    {
903    last if ($a = $cx->[$j] - $cy->[$j]);
904    }
905  $a <=> 0;
906  }
907
908sub _len
909  {
910  # compute number of digits
911
912  # int() because add/sub sometimes leaves strings (like '00005') instead of
913  # '5' in this place, thus causing length() to report wrong length
914  my $cx = $_[1];
915
916  (@$cx-1)*$BASE_LEN+length(int($cx->[-1]));
917  }
918
919sub _digit
920  {
921  # return the nth digit, negative values count backward
922  # zero is rightmost, so _digit(123,0) will give 3
923  my ($c,$x,$n) = @_;
924
925  my $len = _len('',$x);
926
927  $n = $len+$n if $n < 0;		# -1 last, -2 second-to-last
928  $n = abs($n);				# if negative was too big
929  $len--; $n = $len if $n > $len;	# n to big?
930
931  my $elem = int($n / $BASE_LEN);	# which array element
932  my $digit = $n % $BASE_LEN;		# which digit in this element
933  $elem = '0' x $BASE_LEN . @$x[$elem];	# get element padded with 0's
934  substr($elem,-$digit-1,1);
935  }
936
937sub _zeros
938  {
939  # return amount of trailing zeros in decimal
940  # check each array elem in _m for having 0 at end as long as elem == 0
941  # Upon finding a elem != 0, stop
942  my $x = $_[1];
943
944  return 0 if scalar @$x == 1 && $x->[0] == 0;
945
946  my $zeros = 0; my $elem;
947  foreach my $e (@$x)
948    {
949    if ($e != 0)
950      {
951      $elem = "$e";				# preserve x
952      $elem =~ s/.*?(0*$)/$1/;			# strip anything not zero
953      $zeros *= $BASE_LEN;			# elems * 5
954      $zeros += length($elem);			# count trailing zeros
955      last;					# early out
956      }
957    $zeros ++;					# real else branch: 50% slower!
958    }
959  $zeros;
960  }
961
962##############################################################################
963# _is_* routines
964
965sub _is_zero
966  {
967  # return true if arg is zero
968  (((scalar @{$_[1]} == 1) && ($_[1]->[0] == 0))) <=> 0;
969  }
970
971sub _is_even
972  {
973  # return true if arg is even
974  (!($_[1]->[0] & 1)) <=> 0;
975  }
976
977sub _is_odd
978  {
979  # return true if arg is even
980  (($_[1]->[0] & 1)) <=> 0;
981  }
982
983sub _is_one
984  {
985  # return true if arg is one
986  (scalar @{$_[1]} == 1) && ($_[1]->[0] == 1) <=> 0;
987  }
988
989sub _is_two
990  {
991  # return true if arg is two
992  (scalar @{$_[1]} == 1) && ($_[1]->[0] == 2) <=> 0;
993  }
994
995sub _is_ten
996  {
997  # return true if arg is ten
998  (scalar @{$_[1]} == 1) && ($_[1]->[0] == 10) <=> 0;
999  }
1000
1001sub __strip_zeros
1002  {
1003  # internal normalization function that strips leading zeros from the array
1004  # args: ref to array
1005  my $s = shift;
1006
1007  my $cnt = scalar @$s; # get count of parts
1008  my $i = $cnt-1;
1009  push @$s,0 if $i < 0;		# div might return empty results, so fix it
1010
1011  return $s if @$s == 1;		# early out
1012
1013  #print "strip: cnt $cnt i $i\n";
1014  # '0', '3', '4', '0', '0',
1015  #  0    1    2    3    4
1016  # cnt = 5, i = 4
1017  # i = 4
1018  # i = 3
1019  # => fcnt = cnt - i (5-2 => 3, cnt => 5-1 = 4, throw away from 4th pos)
1020  # >= 1: skip first part (this can be zero)
1021  while ($i > 0) { last if $s->[$i] != 0; $i--; }
1022  $i++; splice @$s,$i if ($i < $cnt); # $i cant be 0
1023  $s;
1024  }
1025
1026###############################################################################
1027# check routine to test internal state for corruptions
1028
1029sub _check
1030  {
1031  # used by the test suite
1032  my $x = $_[1];
1033
1034  return "$x is not a reference" if !ref($x);
1035
1036  # are all parts are valid?
1037  my $i = 0; my $j = scalar @$x; my ($e,$try);
1038  while ($i < $j)
1039    {
1040    $e = $x->[$i]; $e = 'undef' unless defined $e;
1041    $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e)";
1042    last if $e !~ /^[+]?[0-9]+$/;
1043    $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e) (stringify)";
1044    last if "$e" !~ /^[+]?[0-9]+$/;
1045    $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e) (cat-stringify)";
1046    last if '' . "$e" !~ /^[+]?[0-9]+$/;
1047    $try = ' < 0 || >= $BASE; '."($x, $e)";
1048    last if $e <0 || $e >= $BASE;
1049    # this test is disabled, since new/bnorm and certain ops (like early out
1050    # in add/sub) are allowed/expected to leave '00000' in some elements
1051    #$try = '=~ /^00+/; '."($x, $e)";
1052    #last if $e =~ /^00+/;
1053    $i++;
1054    }
1055  return "Illegal part '$e' at pos $i (tested: $try)" if $i < $j;
1056  0;
1057  }
1058
1059
1060###############################################################################
1061
1062sub _mod
1063  {
1064  # if possible, use mod shortcut
1065  my ($c,$x,$yo) = @_;
1066
1067  # slow way since $y to big
1068  if (scalar @$yo > 1)
1069    {
1070    my ($xo,$rem) = _div($c,$x,$yo);
1071    return $rem;
1072    }
1073
1074  my $y = $yo->[0];
1075  # both are single element arrays
1076  if (scalar @$x == 1)
1077    {
1078    $x->[0] %= $y;
1079    return $x;
1080    }
1081
1082  # @y is a single element, but @x has more than one element
1083  my $b = $BASE % $y;
1084  if ($b == 0)
1085    {
1086    # when BASE % Y == 0 then (B * BASE) % Y == 0
1087    # (B * BASE) % $y + A % Y => A % Y
1088    # so need to consider only last element: O(1)
1089    $x->[0] %= $y;
1090    }
1091  elsif ($b == 1)
1092    {
1093    # else need to go through all elements: O(N), but loop is a bit simplified
1094    my $r = 0;
1095    foreach (@$x)
1096      {
1097      $r = ($r + $_) % $y;		# not much faster, but heh...
1098      #$r += $_ % $y; $r %= $y;
1099      }
1100    $r = 0 if $r == $y;
1101    $x->[0] = $r;
1102    }
1103  else
1104    {
1105    # else need to go through all elements: O(N)
1106    my $r = 0; my $bm = 1;
1107    foreach (@$x)
1108      {
1109      $r = ($_ * $bm + $r) % $y;
1110      $bm = ($bm * $b) % $y;
1111
1112      #$r += ($_ % $y) * $bm;
1113      #$bm *= $b;
1114      #$bm %= $y;
1115      #$r %= $y;
1116      }
1117    $r = 0 if $r == $y;
1118    $x->[0] = $r;
1119    }
1120  splice (@$x,1);		# keep one element of $x
1121  $x;
1122  }
1123
1124##############################################################################
1125# shifts
1126
1127sub _rsft
1128  {
1129  my ($c,$x,$y,$n) = @_;
1130
1131  if ($n != 10)
1132    {
1133    $n = _new($c,$n); return _div($c,$x, _pow($c,$n,$y));
1134    }
1135
1136  # shortcut (faster) for shifting by 10)
1137  # multiples of $BASE_LEN
1138  my $dst = 0;				# destination
1139  my $src = _num($c,$y);		# as normal int
1140  my $xlen = (@$x-1)*$BASE_LEN+length(int($x->[-1]));  # len of x in digits
1141  if ($src >= $xlen or ($src == $xlen and ! defined $x->[1]))
1142    {
1143    # 12345 67890 shifted right by more than 10 digits => 0
1144    splice (@$x,1);                    # leave only one element
1145    $x->[0] = 0;                       # set to zero
1146    return $x;
1147    }
1148  my $rem = $src % $BASE_LEN;		# remainder to shift
1149  $src = int($src / $BASE_LEN);		# source
1150  if ($rem == 0)
1151    {
1152    splice (@$x,0,$src);		# even faster, 38.4 => 39.3
1153    }
1154  else
1155    {
1156    my $len = scalar @$x - $src;	# elems to go
1157    my $vd; my $z = '0'x $BASE_LEN;
1158    $x->[scalar @$x] = 0;		# avoid || 0 test inside loop
1159    while ($dst < $len)
1160      {
1161      $vd = $z.$x->[$src];
1162      $vd = substr($vd,-$BASE_LEN,$BASE_LEN-$rem);
1163      $src++;
1164      $vd = substr($z.$x->[$src],-$rem,$rem) . $vd;
1165      $vd = substr($vd,-$BASE_LEN,$BASE_LEN) if length($vd) > $BASE_LEN;
1166      $x->[$dst] = int($vd);
1167      $dst++;
1168      }
1169    splice (@$x,$dst) if $dst > 0;		# kill left-over array elems
1170    pop @$x if $x->[-1] == 0 && @$x > 1;	# kill last element if 0
1171    } # else rem == 0
1172  $x;
1173  }
1174
1175sub _lsft
1176  {
1177  my ($c,$x,$y,$n) = @_;
1178
1179  if ($n != 10)
1180    {
1181    $n = _new($c,$n); return _mul($c,$x, _pow($c,$n,$y));
1182    }
1183
1184  # shortcut (faster) for shifting by 10) since we are in base 10eX
1185  # multiples of $BASE_LEN:
1186  my $src = scalar @$x;			# source
1187  my $len = _num($c,$y);		# shift-len as normal int
1188  my $rem = $len % $BASE_LEN;		# remainder to shift
1189  my $dst = $src + int($len/$BASE_LEN);	# destination
1190  my $vd;				# further speedup
1191  $x->[$src] = 0;			# avoid first ||0 for speed
1192  my $z = '0' x $BASE_LEN;
1193  while ($src >= 0)
1194    {
1195    $vd = $x->[$src]; $vd = $z.$vd;
1196    $vd = substr($vd,-$BASE_LEN+$rem,$BASE_LEN-$rem);
1197    $vd .= $src > 0 ? substr($z.$x->[$src-1],-$BASE_LEN,$rem) : '0' x $rem;
1198    $vd = substr($vd,-$BASE_LEN,$BASE_LEN) if length($vd) > $BASE_LEN;
1199    $x->[$dst] = int($vd);
1200    $dst--; $src--;
1201    }
1202  # set lowest parts to 0
1203  while ($dst >= 0) { $x->[$dst--] = 0; }
1204  # fix spurios last zero element
1205  splice @$x,-1 if $x->[-1] == 0;
1206  $x;
1207  }
1208
1209sub _pow
1210  {
1211  # power of $x to $y
1212  # ref to array, ref to array, return ref to array
1213  my ($c,$cx,$cy) = @_;
1214
1215  if (scalar @$cy == 1 && $cy->[0] == 0)
1216    {
1217    splice (@$cx,1); $cx->[0] = 1;		# y == 0 => x => 1
1218    return $cx;
1219    }
1220  if ((scalar @$cx == 1 && $cx->[0] == 1) ||	#    x == 1
1221      (scalar @$cy == 1 && $cy->[0] == 1))	# or y == 1
1222    {
1223    return $cx;
1224    }
1225  if (scalar @$cx == 1 && $cx->[0] == 0)
1226    {
1227    splice (@$cx,1); $cx->[0] = 0;		# 0 ** y => 0 (if not y <= 0)
1228    return $cx;
1229    }
1230
1231  my $pow2 = _one();
1232
1233  my $y_bin = _as_bin($c,$cy); $y_bin =~ s/^0b//;
1234  my $len = length($y_bin);
1235  while (--$len > 0)
1236    {
1237    _mul($c,$pow2,$cx) if substr($y_bin,$len,1) eq '1';		# is odd?
1238    _mul($c,$cx,$cx);
1239    }
1240
1241  _mul($c,$cx,$pow2);
1242  $cx;
1243  }
1244
1245sub _fac
1246  {
1247  # factorial of $x
1248  # ref to array, return ref to array
1249  my ($c,$cx) = @_;
1250
1251  if ((@$cx == 1) && ($cx->[0] <= 2))
1252    {
1253    $cx->[0] ||= 1;		# 0 => 1, 1 => 1, 2 => 2
1254    return $cx;
1255    }
1256
1257  # go forward until $base is exceeded
1258  # limit is either $x steps (steps == 100 means a result always too high) or
1259  # $base.
1260  my $steps = 100; $steps = $cx->[0] if @$cx == 1;
1261  my $r = 2; my $cf = 3; my $step = 2; my $last = $r;
1262  while ($r*$cf < $BASE && $step < $steps)
1263    {
1264    $last = $r; $r *= $cf++; $step++;
1265    }
1266  if ((@$cx == 1) && $step == $cx->[0])
1267    {
1268    # completely done, so keep reference to $x and return
1269    $cx->[0] = $r;
1270    return $cx;
1271    }
1272
1273  # now we must do the left over steps
1274  my $n;					# steps still to do
1275  if (scalar @$cx == 1)
1276    {
1277    $n = $cx->[0];
1278    }
1279  else
1280    {
1281    $n = _copy($c,$cx);
1282    }
1283
1284  $cx->[0] = $last; splice (@$cx,1);		# keep ref to $x
1285  my $zero_elements = 0;
1286
1287  # do left-over steps fit into a scalar?
1288  if (ref $n eq 'ARRAY')
1289    {
1290    # No, so use slower inc() & cmp()
1291    $step = [$step];
1292    while (_acmp($step,$n) <= 0)
1293      {
1294      # as soon as the last element of $cx is 0, we split it up and remember
1295      # how many zeors we got so far. The reason is that n! will accumulate
1296      # zeros at the end rather fast.
1297      if ($cx->[0] == 0)
1298        {
1299        $zero_elements ++; shift @$cx;
1300        }
1301      _mul($c,$cx,$step); _inc($c,$step);
1302      }
1303    }
1304  else
1305    {
1306    # Yes, so we can speed it up slightly
1307    while ($step <= $n)
1308      {
1309      # When the last element of $cx is 0, we split it up and remember
1310      # how many we got so far. The reason is that n! will accumulate
1311      # zeros at the end rather fast.
1312      if ($cx->[0] == 0)
1313        {
1314        $zero_elements ++; shift @$cx;
1315        }
1316      _mul($c,$cx,[$step]); $step++;
1317      }
1318    }
1319  # multiply in the zeros again
1320  while ($zero_elements-- > 0)
1321    {
1322    unshift @$cx, 0;
1323    }
1324  $cx;			# return result
1325  }
1326
1327#############################################################################
1328
1329sub _log_int
1330  {
1331  # calculate integer log of $x to base $base
1332  # ref to array, ref to array - return ref to array
1333  my ($c,$x,$base) = @_;
1334
1335  # X == 0 => NaN
1336  return if (scalar @$x == 1 && $x->[0] == 0);
1337  # BASE 0 or 1 => NaN
1338  return if (scalar @$base == 1 && $base->[0] < 2);
1339  my $cmp = _acmp($c,$x,$base); # X == BASE => 1
1340  if ($cmp == 0)
1341    {
1342    splice (@$x,1); $x->[0] = 1;
1343    return ($x,1)
1344    }
1345  # X < BASE
1346  if ($cmp < 0)
1347    {
1348    splice (@$x,1); $x->[0] = 0;
1349    return ($x,undef);
1350    }
1351
1352  # this trial multiplication is very fast, even for large counts (like for
1353  # 2 ** 1024, since this still requires only 1024 very fast steps
1354  # (multiplication of a large number by a very small number is very fast))
1355  my $x_org = _copy($c,$x);		# preserve x
1356  splice(@$x,1); $x->[0] = 1;		# keep ref to $x
1357
1358  my $trial = _copy($c,$base);
1359
1360  # XXX TODO this only works if $base has only one element
1361  if (scalar @$base == 1)
1362    {
1363    # compute int ( length_in_base_10(X) / ( log(base) / log(10) ) )
1364    my $len = _len($c,$x_org);
1365    my $res = int($len / (log($base->[0]) / log(10))) || 1; # avoid $res == 0
1366
1367    $x->[0] = $res;
1368    $trial = _pow ($c, _copy($c, $base), $x);
1369    my $a = _acmp($x,$trial,$x_org);
1370    return ($x,1) if $a == 0;
1371    # we now know that $res is too small
1372    if ($res < 0)
1373      {
1374      _mul($c,$trial,$base); _add($c, $x, [1]);
1375      }
1376    else
1377      {
1378      # or too big
1379      _div($c,$trial,$base); _sub($c, $x, [1]);
1380      }
1381    # did we now get the right result?
1382    $a = _acmp($x,$trial,$x_org);
1383    return ($x,1) if $a == 0;		# yes, exactly
1384    # still too big
1385    if ($a > 0)
1386      {
1387      _div($c,$trial,$base); _sub($c, $x, [1]);
1388      }
1389    }
1390
1391  # simple loop that increments $x by two in each step, possible overstepping
1392  # the real result by one
1393
1394  my $a;
1395  my $base_mul = _mul($c, _copy($c,$base), $base);
1396
1397  while (($a = _acmp($c,$trial,$x_org)) < 0)
1398    {
1399    _mul($c,$trial,$base_mul); _add($c, $x, [2]);
1400    }
1401
1402  my $exact = 1;
1403  if ($a > 0)
1404    {
1405    # overstepped the result
1406    _dec($c, $x);
1407    _div($c,$trial,$base);
1408    $a = _acmp($c,$trial,$x_org);
1409    if ($a > 0)
1410      {
1411      _dec($c, $x);
1412      }
1413    $exact = 0 if $a != 0;
1414    }
1415
1416  ($x,$exact);				# return result
1417  }
1418
1419# for debugging:
1420  use constant DEBUG => 0;
1421  my $steps = 0;
1422  sub steps { $steps };
1423
1424sub _sqrt
1425  {
1426  # square-root of $x in place
1427  # Compute a guess of the result (by rule of thumb), then improve it via
1428  # Newton's method.
1429  my ($c,$x) = @_;
1430
1431  if (scalar @$x == 1)
1432    {
1433    # fit's into one Perl scalar, so result can be computed directly
1434    $x->[0] = int(sqrt($x->[0]));
1435    return $x;
1436    }
1437  my $y = _copy($c,$x);
1438  # hopefully _len/2 is < $BASE, the -1 is to always undershot the guess
1439  # since our guess will "grow"
1440  my $l = int((_len($c,$x)-1) / 2);
1441
1442  my $lastelem = $x->[-1];					# for guess
1443  my $elems = scalar @$x - 1;
1444  # not enough digits, but could have more?
1445  if ((length($lastelem) <= 3) && ($elems > 1))
1446    {
1447    # right-align with zero pad
1448    my $len = length($lastelem) & 1;
1449    print "$lastelem => " if DEBUG;
1450    $lastelem .= substr($x->[-2] . '0' x $BASE_LEN,0,$BASE_LEN);
1451    # former odd => make odd again, or former even to even again
1452    $lastelem = $lastelem / 10 if (length($lastelem) & 1) != $len;
1453    print "$lastelem\n" if DEBUG;
1454    }
1455
1456  # construct $x (instead of _lsft($c,$x,$l,10)
1457  my $r = $l % $BASE_LEN;	# 10000 00000 00000 00000 ($BASE_LEN=5)
1458  $l = int($l / $BASE_LEN);
1459  print "l =  $l " if DEBUG;
1460
1461  splice @$x,$l;		# keep ref($x), but modify it
1462
1463  # we make the first part of the guess not '1000...0' but int(sqrt($lastelem))
1464  # that gives us:
1465  # 14400 00000 => sqrt(14400) => guess first digits to be 120
1466  # 144000 000000 => sqrt(144000) => guess 379
1467
1468  print "$lastelem (elems $elems) => " if DEBUG;
1469  $lastelem = $lastelem / 10 if ($elems & 1 == 1);		# odd or even?
1470  my $g = sqrt($lastelem); $g =~ s/\.//;			# 2.345 => 2345
1471  $r -= 1 if $elems & 1 == 0;					# 70 => 7
1472
1473  # padd with zeros if result is too short
1474  $x->[$l--] = int(substr($g . '0' x $r,0,$r+1));
1475  print "now ",$x->[-1] if DEBUG;
1476  print " would have been ", int('1' . '0' x $r),"\n" if DEBUG;
1477
1478  # If @$x > 1, we could compute the second elem of the guess, too, to create
1479  # an even better guess. Not implemented yet. Does it improve performance?
1480  $x->[$l--] = 0 while ($l >= 0);	# all other digits of guess are zero
1481
1482  print "start x= ",_str($c,$x),"\n" if DEBUG;
1483  my $two = _two();
1484  my $last = _zero();
1485  my $lastlast = _zero();
1486  $steps = 0 if DEBUG;
1487  while (_acmp($c,$last,$x) != 0 && _acmp($c,$lastlast,$x) != 0)
1488    {
1489    $steps++ if DEBUG;
1490    $lastlast = _copy($c,$last);
1491    $last = _copy($c,$x);
1492    _add($c,$x, _div($c,_copy($c,$y),$x));
1493    _div($c,$x, $two );
1494    print " x= ",_str($c,$x),"\n" if DEBUG;
1495    }
1496  print "\nsteps in sqrt: $steps, " if DEBUG;
1497  _dec($c,$x) if _acmp($c,$y,_mul($c,_copy($c,$x),$x)) < 0;	# overshot?
1498  print " final ",$x->[-1],"\n" if DEBUG;
1499  $x;
1500  }
1501
1502sub _root
1503  {
1504  # take n'th root of $x in place (n >= 3)
1505  my ($c,$x,$n) = @_;
1506
1507  if (scalar @$x == 1)
1508    {
1509    if (scalar @$n > 1)
1510      {
1511      # result will always be smaller than 2 so trunc to 1 at once
1512      $x->[0] = 1;
1513      }
1514    else
1515      {
1516      # fit's into one Perl scalar, so result can be computed directly
1517      # cannot use int() here, because it rounds wrongly (try
1518      # (81 ** 3) ** (1/3) to see what I mean)
1519      #$x->[0] = int( $x->[0] ** (1 / $n->[0]) );
1520      # round to 8 digits, then truncate result to integer
1521      $x->[0] = int ( sprintf ("%.8f", $x->[0] ** (1 / $n->[0]) ) );
1522      }
1523    return $x;
1524    }
1525
1526  # we know now that X is more than one element long
1527
1528  # if $n is a power of two, we can repeatedly take sqrt($X) and find the
1529  # proper result, because sqrt(sqrt($x)) == root($x,4)
1530  my $b = _as_bin($c,$n);
1531  if ($b =~ /0b1(0+)$/)
1532    {
1533    my $count = CORE::length($1);	# 0b100 => len('00') => 2
1534    my $cnt = $count;			# counter for loop
1535    unshift (@$x, 0);			# add one element, together with one
1536					# more below in the loop this makes 2
1537    while ($cnt-- > 0)
1538      {
1539      # 'inflate' $X by adding one element, basically computing
1540      # $x * $BASE * $BASE. This gives us more $BASE_LEN digits for result
1541      # since len(sqrt($X)) approx == len($x) / 2.
1542      unshift (@$x, 0);
1543      # calculate sqrt($x), $x is now one element to big, again. In the next
1544      # round we make that two, again.
1545      _sqrt($c,$x);
1546      }
1547    # $x is now one element to big, so truncate result by removing it
1548    splice (@$x,0,1);
1549    }
1550  else
1551    {
1552    # trial computation by starting with 2,4,8,16 etc until we overstep
1553    my $step;
1554    my $trial = _two();
1555
1556    # while still to do more than X steps
1557    do
1558      {
1559      $step = _two();
1560      while (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) < 0)
1561        {
1562        _mul ($c, $step, [2]);
1563        _add ($c, $trial, $step);
1564        }
1565
1566      # hit exactly?
1567      if (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) == 0)
1568        {
1569        @$x = @$trial;			# make copy while preserving ref to $x
1570        return $x;
1571        }
1572      # overstepped, so go back on step
1573      _sub($c, $trial, $step);
1574      } while (scalar @$step > 1 || $step->[0] > 128);
1575
1576    # reset step to 2
1577    $step = _two();
1578    # add two, because $trial cannot be exactly the result (otherwise we would
1579    # alrady have found it)
1580    _add($c, $trial, $step);
1581
1582    # and now add more and more (2,4,6,8,10 etc)
1583    while (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) < 0)
1584      {
1585      _add ($c, $trial, $step);
1586      }
1587
1588    # hit not exactly? (overstepped)
1589    if (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) > 0)
1590      {
1591      _dec($c,$trial);
1592      }
1593
1594    # hit not exactly? (overstepped)
1595    # 80 too small, 81 slightly too big, 82 too big
1596    if (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) > 0)
1597      {
1598      _dec ($c, $trial);
1599      }
1600
1601    @$x = @$trial;			# make copy while preserving ref to $x
1602    return $x;
1603    }
1604  $x;
1605  }
1606
1607##############################################################################
1608# binary stuff
1609
1610sub _and
1611  {
1612  my ($c,$x,$y) = @_;
1613
1614  # the shortcut makes equal, large numbers _really_ fast, and makes only a
1615  # very small performance drop for small numbers (e.g. something with less
1616  # than 32 bit) Since we optimize for large numbers, this is enabled.
1617  return $x if _acmp($c,$x,$y) == 0;		# shortcut
1618
1619  my $m = _one(); my ($xr,$yr);
1620  my $mask = $AND_MASK;
1621
1622  my $x1 = $x;
1623  my $y1 = _copy($c,$y);			# make copy
1624  $x = _zero();
1625  my ($b,$xrr,$yrr);
1626  use integer;
1627  while (!_is_zero($c,$x1) && !_is_zero($c,$y1))
1628    {
1629    ($x1, $xr) = _div($c,$x1,$mask);
1630    ($y1, $yr) = _div($c,$y1,$mask);
1631
1632    # make ints() from $xr, $yr
1633    # this is when the AND_BITS are greater than $BASE and is slower for
1634    # small (<256 bits) numbers, but faster for large numbers. Disabled
1635    # due to KISS principle
1636
1637#    $b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }
1638#    $b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }
1639#    _add($c,$x, _mul($c, _new( $c, ($xrr & $yrr) ), $m) );
1640
1641    # 0+ due to '&' doesn't work in strings
1642    _add($c,$x, _mul($c, [ 0+$xr->[0] & 0+$yr->[0] ], $m) );
1643    _mul($c,$m,$mask);
1644    }
1645  $x;
1646  }
1647
1648sub _xor
1649  {
1650  my ($c,$x,$y) = @_;
1651
1652  return _zero() if _acmp($c,$x,$y) == 0;	# shortcut (see -and)
1653
1654  my $m = _one(); my ($xr,$yr);
1655  my $mask = $XOR_MASK;
1656
1657  my $x1 = $x;
1658  my $y1 = _copy($c,$y);			# make copy
1659  $x = _zero();
1660  my ($b,$xrr,$yrr);
1661  use integer;
1662  while (!_is_zero($c,$x1) && !_is_zero($c,$y1))
1663    {
1664    ($x1, $xr) = _div($c,$x1,$mask);
1665    ($y1, $yr) = _div($c,$y1,$mask);
1666    # make ints() from $xr, $yr (see _and())
1667    #$b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }
1668    #$b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }
1669    #_add($c,$x, _mul($c, _new( $c, ($xrr ^ $yrr) ), $m) );
1670
1671    # 0+ due to '^' doesn't work in strings
1672    _add($c,$x, _mul($c, [ 0+$xr->[0] ^ 0+$yr->[0] ], $m) );
1673    _mul($c,$m,$mask);
1674    }
1675  # the loop stops when the shorter of the two numbers is exhausted
1676  # the remainder of the longer one will survive bit-by-bit, so we simple
1677  # multiply-add it in
1678  _add($c,$x, _mul($c, $x1, $m) ) if !_is_zero($c,$x1);
1679  _add($c,$x, _mul($c, $y1, $m) ) if !_is_zero($c,$y1);
1680
1681  $x;
1682  }
1683
1684sub _or
1685  {
1686  my ($c,$x,$y) = @_;
1687
1688  return $x if _acmp($c,$x,$y) == 0;		# shortcut (see _and)
1689
1690  my $m = _one(); my ($xr,$yr);
1691  my $mask = $OR_MASK;
1692
1693  my $x1 = $x;
1694  my $y1 = _copy($c,$y);			# make copy
1695  $x = _zero();
1696  my ($b,$xrr,$yrr);
1697  use integer;
1698  while (!_is_zero($c,$x1) && !_is_zero($c,$y1))
1699    {
1700    ($x1, $xr) = _div($c,$x1,$mask);
1701    ($y1, $yr) = _div($c,$y1,$mask);
1702    # make ints() from $xr, $yr (see _and())
1703#    $b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }
1704#    $b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }
1705#    _add($c,$x, _mul($c, _new( $c, ($xrr | $yrr) ), $m) );
1706
1707    # 0+ due to '|' doesn't work in strings
1708    _add($c,$x, _mul($c, [ 0+$xr->[0] | 0+$yr->[0] ], $m) );
1709    _mul($c,$m,$mask);
1710    }
1711  # the loop stops when the shorter of the two numbers is exhausted
1712  # the remainder of the longer one will survive bit-by-bit, so we simple
1713  # multiply-add it in
1714  _add($c,$x, _mul($c, $x1, $m) ) if !_is_zero($c,$x1);
1715  _add($c,$x, _mul($c, $y1, $m) ) if !_is_zero($c,$y1);
1716
1717  $x;
1718  }
1719
1720sub _as_hex
1721  {
1722  # convert a decimal number to hex (ref to array, return ref to string)
1723  my ($c,$x) = @_;
1724
1725  # fit's into one element (handle also 0x0 case)
1726  return sprintf("0x%x",$x->[0]) if @$x == 1;
1727
1728  my $x1 = _copy($c,$x);
1729
1730  my $es = '';
1731  my ($xr, $h, $x10000);
1732  if ($] >= 5.006)
1733    {
1734    $x10000 = [ 0x10000 ]; $h = 'h4';
1735    }
1736  else
1737    {
1738    $x10000 = [ 0x1000 ]; $h = 'h3';
1739    }
1740  while (@$x1 != 1 || $x1->[0] != 0)		# _is_zero()
1741    {
1742    ($x1, $xr) = _div($c,$x1,$x10000);
1743    $es .= unpack($h,pack('v',$xr->[0]));	# XXX TODO: why pack('v',...)?
1744    }
1745  $es = reverse $es;
1746  $es =~ s/^[0]+//;   # strip leading zeros
1747  '0x' . $es;					# return result prepended with 0x
1748  }
1749
1750sub _as_bin
1751  {
1752  # convert a decimal number to bin (ref to array, return ref to string)
1753  my ($c,$x) = @_;
1754
1755  # fit's into one element (and Perl recent enough), handle also 0b0 case
1756  # handle zero case for older Perls
1757  if ($] <= 5.005 && @$x == 1 && $x->[0] == 0)
1758    {
1759    my $t = '0b0'; return $t;
1760    }
1761  if (@$x == 1 && $] >= 5.006)
1762    {
1763    my $t = sprintf("0b%b",$x->[0]);
1764    return $t;
1765    }
1766  my $x1 = _copy($c,$x);
1767
1768  my $es = '';
1769  my ($xr, $b, $x10000);
1770  if ($] >= 5.006)
1771    {
1772    $x10000 = [ 0x10000 ]; $b = 'b16';
1773    }
1774  else
1775    {
1776    $x10000 = [ 0x1000 ]; $b = 'b12';
1777    }
1778  while (!(@$x1 == 1 && $x1->[0] == 0))		# _is_zero()
1779    {
1780    ($x1, $xr) = _div($c,$x1,$x10000);
1781    $es .= unpack($b,pack('v',$xr->[0]));	# XXX TODO: why pack('v',...)?
1782    # $es .= unpack($b,$xr->[0]);
1783    }
1784  $es = reverse $es;
1785  $es =~ s/^[0]+//;   # strip leading zeros
1786  '0b' . $es;					# return result prepended with 0b
1787  }
1788
1789sub _from_hex
1790  {
1791  # convert a hex number to decimal (ref to string, return ref to array)
1792  my ($c,$hs) = @_;
1793
1794  my $m = _new($c, 0x10000000);			# 28 bit at a time (<32 bit!)
1795  my $d = 7;					# 7 digits at a time
1796  if ($] <= 5.006)
1797    {
1798    # for older Perls, play safe
1799    $m = [ 0x10000 ];				# 16 bit at a time (<32 bit!)
1800    $d = 4;					# 4 digits at a time
1801    }
1802
1803  my $mul = _one();
1804  my $x = _zero();
1805
1806  my $len = int( (length($hs)-2)/$d );		# $d digit parts, w/o the '0x'
1807  my $val; my $i = -$d;
1808  while ($len >= 0)
1809    {
1810    $val = substr($hs,$i,$d);			# get hex digits
1811    $val =~ s/^[+-]?0x// if $len == 0;		# for last part only because
1812    $val = hex($val);				# hex does not like wrong chars
1813    $i -= $d; $len --;
1814    my $adder = [ $val ];
1815    # if the resulting number was to big to fit into one element, create a
1816    # two-element version (bug found by Mark Lakata - Thanx!)
1817    if (CORE::length($val) > $BASE_LEN)
1818      {
1819      $adder = _new($c,$val);
1820      }
1821    _add ($c, $x, _mul ($c, $adder, $mul ) ) if $val != 0;
1822    _mul ($c, $mul, $m ) if $len >= 0; 		# skip last mul
1823    }
1824  $x;
1825  }
1826
1827sub _from_bin
1828  {
1829  # convert a hex number to decimal (ref to string, return ref to array)
1830  my ($c,$bs) = @_;
1831
1832  # instead of converting X (8) bit at a time, it is faster to "convert" the
1833  # number to hex, and then call _from_hex.
1834
1835  my $hs = $bs;
1836  $hs =~ s/^[+-]?0b//;					# remove sign and 0b
1837  my $l = length($hs);					# bits
1838  $hs = '0' x (8-($l % 8)) . $hs if ($l % 8) != 0;	# padd left side w/ 0
1839  my $h = '0x' . unpack('H*', pack ('B*', $hs));	# repack as hex
1840
1841  $c->_from_hex($h);
1842  }
1843
1844##############################################################################
1845# special modulus functions
1846
1847sub _modinv
1848  {
1849  # modular inverse
1850  my ($c,$x,$y) = @_;
1851
1852  my $u = _zero($c); my $u1 = _one($c);
1853  my $a = _copy($c,$y); my $b = _copy($c,$x);
1854
1855  # Euclid's Algorithm for bgcd(), only that we calc bgcd() ($a) and the
1856  # result ($u) at the same time. See comments in BigInt for why this works.
1857  my $q;
1858  ($a, $q, $b) = ($b, _div($c,$a,$b));		# step 1
1859  my $sign = 1;
1860  while (!_is_zero($c,$b))
1861    {
1862    my $t = _add($c, 				# step 2:
1863       _mul($c,_copy($c,$u1), $q) ,		#  t =  u1 * q
1864       $u );					#     + u
1865    $u = $u1;					#  u = u1, u1 = t
1866    $u1 = $t;
1867    $sign = -$sign;
1868    ($a, $q, $b) = ($b, _div($c,$a,$b));	# step 1
1869    }
1870
1871  # if the gcd is not 1, then return NaN
1872  return (undef,undef) unless _is_one($c,$a);
1873
1874  ($u1, $sign == 1 ? '+' : '-');
1875  }
1876
1877sub _modpow
1878  {
1879  # modulus of power ($x ** $y) % $z
1880  my ($c,$num,$exp,$mod) = @_;
1881
1882  # in the trivial case,
1883  if (_is_one($c,$mod))
1884    {
1885    splice @$num,0,1; $num->[0] = 0;
1886    return $num;
1887    }
1888  if ((scalar @$num == 1) && (($num->[0] == 0) || ($num->[0] == 1)))
1889    {
1890    $num->[0] = 1;
1891    return $num;
1892    }
1893
1894#  $num = _mod($c,$num,$mod);	# this does not make it faster
1895
1896  my $acc = _copy($c,$num); my $t = _one();
1897
1898  my $expbin = _as_bin($c,$exp); $expbin =~ s/^0b//;
1899  my $len = length($expbin);
1900  while (--$len >= 0)
1901    {
1902    if ( substr($expbin,$len,1) eq '1')			# is_odd
1903      {
1904      _mul($c,$t,$acc);
1905      $t = _mod($c,$t,$mod);
1906      }
1907    _mul($c,$acc,$acc);
1908    $acc = _mod($c,$acc,$mod);
1909    }
1910  @$num = @$t;
1911  $num;
1912  }
1913
1914sub _gcd
1915  {
1916  # greatest common divisor
1917  my ($c,$x,$y) = @_;
1918
1919  while ( (scalar @$y != 1) || ($y->[0] != 0) )		# while ($y != 0)
1920    {
1921    my $t = _copy($c,$y);
1922    $y = _mod($c, $x, $y);
1923    $x = $t;
1924    }
1925  $x;
1926  }
1927
1928##############################################################################
1929##############################################################################
1930
19311;
1932__END__
1933
1934=head1 NAME
1935
1936Math::BigInt::Calc - Pure Perl module to support Math::BigInt
1937
1938=head1 SYNOPSIS
1939
1940Provides support for big integer calculations. Not intended to be used by other
1941modules. Other modules which sport the same functions can also be used to support
1942Math::BigInt, like Math::BigInt::GMP or Math::BigInt::Pari.
1943
1944=head1 DESCRIPTION
1945
1946In order to allow for multiple big integer libraries, Math::BigInt was
1947rewritten to use library modules for core math routines. Any module which
1948follows the same API as this can be used instead by using the following:
1949
1950	use Math::BigInt lib => 'libname';
1951
1952'libname' is either the long name ('Math::BigInt::Pari'), or only the short
1953version like 'Pari'.
1954
1955=head1 STORAGE
1956
1957=head1 METHODS
1958
1959The following functions MUST be defined in order to support the use by
1960Math::BigInt v1.70 or later:
1961
1962	api_version()	return API version, minimum 1 for v1.70
1963	_new(string)	return ref to new object from ref to decimal string
1964	_zero()		return a new object with value 0
1965	_one()		return a new object with value 1
1966	_two()		return a new object with value 2
1967	_ten()		return a new object with value 10
1968
1969	_str(obj)	return ref to a string representing the object
1970	_num(obj)	returns a Perl integer/floating point number
1971			NOTE: because of Perl numeric notation defaults,
1972			the _num'ified obj may lose accuracy due to
1973			machine-dependend floating point size limitations
1974
1975	_add(obj,obj)	Simple addition of two objects
1976	_mul(obj,obj)	Multiplication of two objects
1977	_div(obj,obj)	Division of the 1st object by the 2nd
1978			In list context, returns (result,remainder).
1979			NOTE: this is integer math, so no
1980			fractional part will be returned.
1981			The second operand will be not be 0, so no need to
1982			check for that.
1983	_sub(obj,obj)	Simple subtraction of 1 object from another
1984			a third, optional parameter indicates that the params
1985			are swapped. In this case, the first param needs to
1986			be preserved, while you can destroy the second.
1987			sub (x,y,1) => return x - y and keep x intact!
1988	_dec(obj)	decrement object by one (input is garant. to be > 0)
1989	_inc(obj)	increment object by one
1990
1991
1992	_acmp(obj,obj)	<=> operator for objects (return -1, 0 or 1)
1993
1994	_len(obj)	returns count of the decimal digits of the object
1995	_digit(obj,n)	returns the n'th decimal digit of object
1996
1997	_is_one(obj)	return true if argument is 1
1998	_is_two(obj)	return true if argument is 2
1999	_is_ten(obj)	return true if argument is 10
2000	_is_zero(obj)	return true if argument is 0
2001	_is_even(obj)	return true if argument is even (0,2,4,6..)
2002	_is_odd(obj)	return true if argument is odd (1,3,5,7..)
2003
2004	_copy		return a ref to a true copy of the object
2005
2006	_check(obj)	check whether internal representation is still intact
2007			return 0 for ok, otherwise error message as string
2008
2009	_from_hex(str)	return ref to new object from ref to hexadecimal string
2010	_from_bin(str)	return ref to new object from ref to binary string
2011
2012	_as_hex(str)	return string containing the value as
2013			unsigned hex string, with the '0x' prepended.
2014			Leading zeros must be stripped.
2015	_as_bin(str)	Like as_hex, only as binary string containing only
2016			zeros and ones. Leading zeros must be stripped and a
2017			'0b' must be prepended.
2018
2019	_rsft(obj,N,B)	shift object in base B by N 'digits' right
2020	_lsft(obj,N,B)	shift object in base B by N 'digits' left
2021
2022	_xor(obj1,obj2)	XOR (bit-wise) object 1 with object 2
2023			Note: XOR, AND and OR pad with zeros if size mismatches
2024	_and(obj1,obj2)	AND (bit-wise) object 1 with object 2
2025	_or(obj1,obj2)	OR (bit-wise) object 1 with object 2
2026
2027	_mod(obj,obj)	Return remainder of div of the 1st by the 2nd object
2028	_sqrt(obj)	return the square root of object (truncated to int)
2029	_root(obj)	return the n'th (n >= 3) root of obj (truncated to int)
2030	_fac(obj)	return factorial of object 1 (1*2*3*4..)
2031	_pow(obj,obj)	return object 1 to the power of object 2
2032			return undef for NaN
2033	_zeros(obj)	return number of trailing decimal zeros
2034	_modinv		return inverse modulus
2035	_modpow		return modulus of power ($x ** $y) % $z
2036	_log_int(X,N)	calculate integer log() of X in base N
2037			X >= 0, N >= 0 (return undef for NaN)
2038			returns (RESULT, EXACT) where EXACT is:
2039			 1     : result is exactly RESULT
2040			 0     : result was truncated to RESULT
2041			 undef : unknown whether result is exactly RESULT
2042        _gcd(obj,obj)	return Greatest Common Divisor of two objects
2043
2044The following functions are optional, and can be defined if the underlying lib
2045has a fast way to do them. If undefined, Math::BigInt will use pure Perl (hence
2046slow) fallback routines to emulate these:
2047
2048	_signed_or
2049	_signed_and
2050	_signed_xor
2051
2052
2053Input strings come in as unsigned but with prefix (i.e. as '123', '0xabc'
2054or '0b1101').
2055
2056So the library needs only to deal with unsigned big integers. Testing of input
2057parameter validity is done by the caller, so you need not worry about
2058underflow (f.i. in C<_sub()>, C<_dec()>) nor about division by zero or similar
2059cases.
2060
2061The first parameter can be modified, that includes the possibility that you
2062return a reference to a completely different object instead. Although keeping
2063the reference and just changing it's contents is prefered over creating and
2064returning a different reference.
2065
2066Return values are always references to objects, strings, or true/false for
2067comparisation routines.
2068
2069=head1 WRAP YOUR OWN
2070
2071If you want to port your own favourite c-lib for big numbers to the
2072Math::BigInt interface, you can take any of the already existing modules as
2073a rough guideline. You should really wrap up the latest BigInt and BigFloat
2074testsuites with your module, and replace in them any of the following:
2075
2076	use Math::BigInt;
2077
2078by this:
2079
2080	use Math::BigInt lib => 'yourlib';
2081
2082This way you ensure that your library really works 100% within Math::BigInt.
2083
2084=head1 LICENSE
2085
2086This program is free software; you may redistribute it and/or modify it under
2087the same terms as Perl itself.
2088
2089=head1 AUTHORS
2090
2091Original math code by Mark Biggar, rewritten by Tels L<http://bloodgate.com/>
2092in late 2000.
2093Seperated from BigInt and shaped API with the help of John Peacock.
2094
2095Fixed, speed-up, streamlined and enhanced by Tels 2001 - 2005.
2096
2097=head1 SEE ALSO
2098
2099L<Math::BigInt>, L<Math::BigFloat>, L<Math::BigInt::BitVect>,
2100L<Math::BigInt::GMP>, L<Math::BigInt::FastCalc> and L<Math::BigInt::Pari>.
2101
2102=cut
2103