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