a114d09ee83c8e9975d0ca6e5a8a9c8d2bc409b8
[p5sagit/p5-mst-13.2.git] / lib / Math / BigInt / Calc.pm
1 package Math::BigInt::Calc;
2
3 use 5.005;
4 use strict;
5 # use warnings; # dont use warnings for older Perls
6
7 require Exporter;
8 use vars qw/@ISA $VERSION/;
9 @ISA = qw(Exporter);
10
11 $VERSION = '0.28';
12
13 # Package to store unsigned big integers in decimal and do math with them
14
15 # Internally the numbers are stored in an array with at least 1 element, no
16 # leading zero parts (except the first) and in base 1eX where X is determined
17 # automatically at loading time to be the maximum possible value
18
19 # todo:
20 # - fully remove funky $# stuff (maybe)
21
22 # USE_MUL: due to problems on certain os (os390, posix-bc) "* 1e-5" is used
23 # instead of "/ 1e5" at some places, (marked with USE_MUL). Other platforms
24 # BS2000, some Crays need USE_DIV instead.
25 # The BEGIN block is used to determine which of the two variants gives the
26 # correct result.
27
28 ##############################################################################
29 # global constants, flags and accessory
30  
31 # constants for easier life
32 my $nan = 'NaN';
33 my ($MBASE,$BASE,$RBASE,$BASE_LEN,$MAX_VAL,$BASE_LEN2,$BASE_LEN_SMALL);
34 my ($AND_BITS,$XOR_BITS,$OR_BITS);
35 my ($AND_MASK,$XOR_MASK,$OR_MASK);
36 my ($LEN_CONVERT);
37
38 sub _base_len 
39   {
40   # set/get the BASE_LEN and assorted other, connected values
41   # used only be the testsuite, set is used only by the BEGIN block below
42   shift;
43
44   my $b = shift;
45   if (defined $b)
46     {
47     # find whether we can use mul or div or none in mul()/div()
48     # (in last case reduce BASE_LEN_SMALL)
49     $BASE_LEN_SMALL = $b+1;
50     my $caught = 0;
51     while (--$BASE_LEN_SMALL > 5)
52       {
53       $MBASE = int("1e".$BASE_LEN_SMALL);
54       $RBASE = abs('1e-'.$BASE_LEN_SMALL);              # see USE_MUL
55       $caught = 0;
56       $caught += 1 if (int($MBASE * $RBASE) != 1);      # should be 1
57       $caught += 2 if (int($MBASE / $MBASE) != 1);      # should be 1
58       last if $caught != 3;
59       }
60     # BASE_LEN is used for anything else than mul()/div()
61     $BASE_LEN = $BASE_LEN_SMALL;
62     $BASE_LEN = shift if (defined $_[0]);               # one more arg?
63     $BASE = int("1e".$BASE_LEN);
64
65     $BASE_LEN2 = int($BASE_LEN_SMALL / 2);              # for mul shortcut
66     $MBASE = int("1e".$BASE_LEN_SMALL);
67     $RBASE = abs('1e-'.$BASE_LEN_SMALL);                # see USE_MUL
68     $MAX_VAL = $MBASE-1;
69     $LEN_CONVERT = 0;
70     $LEN_CONVERT = 1 if $BASE_LEN_SMALL != $BASE_LEN;
71
72     #print "BASE_LEN: $BASE_LEN MAX_VAL: $MAX_VAL BASE: $BASE RBASE: $RBASE ";
73     #print "BASE_LEN_SMALL: $BASE_LEN_SMALL MBASE: $MBASE\n";
74
75     undef &_mul;
76     undef &_div;
77     if ($caught & 1 != 0)
78       {
79       # must USE_MUL
80       *{_mul} = \&_mul_use_mul;
81       *{_div} = \&_div_use_mul;
82       }
83     else                # $caught must be 2, since it can't be 1 nor 3
84       {
85       # can USE_DIV instead
86       *{_mul} = \&_mul_use_div;
87       *{_div} = \&_div_use_div;
88       }
89     }
90   return $BASE_LEN unless wantarray;
91   return ($BASE_LEN, $AND_BITS, $XOR_BITS, $OR_BITS, $BASE_LEN_SMALL, $MAX_VAL);
92   }
93
94 BEGIN
95   {
96   # from Daniel Pfeiffer: determine largest group of digits that is precisely
97   # multipliable with itself plus carry
98   # Test now changed to expect the proper pattern, not a result off by 1 or 2
99   my ($e, $num) = 3;    # lowest value we will use is 3+1-1 = 3
100   do 
101     {
102     $num = ('9' x ++$e) + 0;
103     $num *= $num + 1.0;
104     } while ("$num" =~ /9{$e}0{$e}/);   # must be a certain pattern
105   $e--;                                 # last test failed, so retract one step
106   # the limits below brush the problems with the test above under the rug:
107   # the test should be able to find the proper $e automatically
108   $e = 5 if $^O =~ /^uts/;      # UTS get's some special treatment
109   $e = 5 if $^O =~ /^unicos/;   # unicos is also problematic (6 seems to work
110                                 # there, but we play safe)
111   $e = 7 if $e > 7;             # cap, for VMS, OS/390 and other 64 bit systems
112                                 # 8 fails inside random testsuite, so take 7
113
114   # determine how many digits fit into an integer and can be safely added 
115   # together plus carry w/o causing an overflow
116
117   # this below detects 15 on a 64 bit system, because after that it becomes
118   # 1e16  and not 1000000 :/ I can make it detect 18, but then I get a lot of
119   # test failures. Ugh! (Tomake detect 18: uncomment lines marked with *)
120   use integer;
121   my $bi = 5;                   # approx. 16 bit
122   $num = int('9' x $bi);
123   # $num = 99999; # *
124   # while ( ($num+$num+1) eq '1' . '9' x $bi)   # *
125   while ( int($num+$num+1) eq '1' . '9' x $bi)
126     {
127     $bi++; $num = int('9' x $bi);
128     # $bi++; $num *= 10; $num += 9;     # *
129     }
130   $bi--;                                # back off one step
131   # by setting them equal, we ignore the findings and use the default
132   # one-size-fits-all approach from former versions
133   $bi = $e;                             # XXX, this should work always
134
135   __PACKAGE__->_base_len($e,$bi);       # set and store
136
137   # find out how many bits _and, _or and _xor can take (old default = 16)
138   # I don't think anybody has yet 128 bit scalars, so let's play safe.
139   local $^W = 0;        # don't warn about 'nonportable number'
140   $AND_BITS = 15; $XOR_BITS = 15; $OR_BITS  = 15;
141
142   # find max bits, we will not go higher than numberofbits that fit into $BASE
143   # to make _and etc simpler (and faster for smaller, slower for large numbers)
144   my $max = 16;
145   while (2 ** $max < $BASE) { $max++; }
146   my ($x,$y,$z);
147   do {
148     $AND_BITS++;
149     $x = oct('0b' . '1' x $AND_BITS); $y = $x & $x;
150     $z = (2 ** $AND_BITS) - 1;
151     } while ($AND_BITS < $max && $x == $z && $y == $x);
152   $AND_BITS --;                                         # retreat one step
153   do {
154     $XOR_BITS++;
155     $x = oct('0b' . '1' x $XOR_BITS); $y = $x ^ 0;
156     $z = (2 ** $XOR_BITS) - 1;
157     } while ($XOR_BITS < $max && $x == $z && $y == $x);
158   $XOR_BITS --;                                         # retreat one step
159   do {
160     $OR_BITS++;
161     $x = oct('0b' . '1' x $OR_BITS); $y = $x | $x;
162     $z = (2 ** $OR_BITS) - 1;
163     } while ($OR_BITS < $max && $x == $z && $y == $x);
164   $OR_BITS --;                                          # retreat one step
165   
166   }
167
168 ##############################################################################
169 # convert between the "small" and the "large" representation
170
171 sub _to_large
172   {
173   # take an array in base $BASE_LEN_SMALL and convert it in-place to $BASE_LEN
174   my ($c,$x) = @_;
175
176 #  print "_to_large $BASE_LEN_SMALL => $BASE_LEN\n";
177
178   return $x if $LEN_CONVERT == 0 ||             # nothing to converconvertor
179          @$x == 1;                              # only one element => early out
180   
181   #     12345    67890    12345    67890   contents
182   # to      3        2        1        0   index 
183   #             123456  7890123  4567890   contents 
184
185 #  # faster variant
186 #  my @d; my $str = '';
187 #  my $z = '0' x $BASE_LEN_SMALL;
188 #  foreach (@$x)
189 #    {
190 #    # ... . 04321 . 000321
191 #    $str = substr($z.$_,-$BASE_LEN_SMALL,$BASE_LEN_SMALL) . $str;
192 #    if (length($str) > $BASE_LEN)
193 #      {
194 #      push @d, substr($str,-$BASE_LEN,$BASE_LEN);      # extract one piece
195 #      substr($str,-$BASE_LEN,$BASE_LEN) = '';          # remove it
196 #      }
197 #    }
198 #  push @d, $str if $str !~ /^0*$/;                     # extract last piece
199 #  @$x = @d;
200 #  $x->[-1] = int($x->[-1]);                    # strip leading zero
201 #  $x;
202
203   my $ret = "";
204   my $l = scalar @$x;           # number of parts
205   $l --; $ret .= int($x->[$l]); $l--;
206   my $z = '0' x ($BASE_LEN_SMALL-1);                            
207   while ($l >= 0)
208     {
209     $ret .= substr($z.$x->[$l],-$BASE_LEN_SMALL); 
210     $l--;
211     }
212   my $str = _new($c,\$ret);                     # make array
213   @$x = @$str;                                  # clobber contents of $x
214   $x->[-1] = int($x->[-1]);                     # strip leading zero
215   }
216
217 sub _to_small
218   {
219   # take an array in base $BASE_LEN and convert it in-place to $BASE_LEN_SMALL
220   my ($c,$x) = @_;
221
222   return $x if $LEN_CONVERT == 0;               # nothing to do
223   return $x if @$x == 1 && length(int($x->[0])) <= $BASE_LEN_SMALL;
224
225   my $d = _str($c,$x);
226   my $il = length($$d)-1;
227   ## this leaves '00000' instead of int 0 and will be corrected after any op
228   # clobber contents of $x
229   @$x = reverse(unpack("a" . ($il % $BASE_LEN_SMALL+1) 
230       . ("a$BASE_LEN_SMALL" x ($il / $BASE_LEN_SMALL)), $$d));  
231
232   $x->[-1] = int($x->[-1]);                     # strip leading zero
233   }
234
235 ###############################################################################
236
237 sub _new
238   {
239   # (ref to string) return ref to num_array
240   # Convert a number from string format (without sign) to internal base
241   # 1ex format. Assumes normalized value as input.
242   my $d = $_[1];
243   my $il = length($$d)-1;
244   # this leaves '00000' instead of int 0 and will be corrected after any op
245   [ reverse(unpack("a" . ($il % $BASE_LEN+1) 
246     . ("a$BASE_LEN" x ($il / $BASE_LEN)), $$d)) ];
247   }                                                                             
248   
249 BEGIN
250   {
251   $AND_MASK = __PACKAGE__->_new( \( 2 ** $AND_BITS ));
252   $XOR_MASK = __PACKAGE__->_new( \( 2 ** $XOR_BITS ));
253   $OR_MASK = __PACKAGE__->_new( \( 2 ** $OR_BITS ));
254   }
255
256 sub _zero
257   {
258   # create a zero
259   [ 0 ];
260   }
261
262 sub _one
263   {
264   # create a one
265   [ 1 ];
266   }
267
268 sub _two
269   {
270   # create a two (for _pow)
271   [ 2 ];
272   }
273
274 sub _copy
275   {
276   [ @{$_[1]} ];
277   }
278
279 # catch and throw away
280 sub import { }
281
282 ##############################################################################
283 # convert back to string and number
284
285 sub _str
286   {
287   # (ref to BINT) return num_str
288   # Convert number from internal base 100000 format to string format.
289   # internal format is always normalized (no leading zeros, "-0" => "+0")
290   my $ar = $_[1];
291   my $ret = "";
292
293   my $l = scalar @$ar;          # number of parts
294   return $nan if $l < 1;        # should not happen
295
296   # handle first one different to strip leading zeros from it (there are no
297   # leading zero parts in internal representation)
298   $l --; $ret .= int($ar->[$l]); $l--;
299   # Interestingly, the pre-padd method uses more time
300   # the old grep variant takes longer (14 to 10 sec)
301   my $z = '0' x ($BASE_LEN-1);                            
302   while ($l >= 0)
303     {
304     $ret .= substr($z.$ar->[$l],-$BASE_LEN); # fastest way I could think of
305     $l--;
306     }
307   \$ret;
308   }                                                                             
309
310 sub _num
311   {
312   # Make a number (scalar int/float) from a BigInt object
313   my $x = $_[1];
314   return $x->[0] if scalar @$x == 1;  # below $BASE
315   my $fac = 1;
316   my $num = 0;
317   foreach (@$x)
318     {
319     $num += $fac*$_; $fac *= $BASE;
320     }
321   $num; 
322   }
323
324 ##############################################################################
325 # actual math code
326
327 sub _add
328   {
329   # (ref to int_num_array, ref to int_num_array)
330   # routine to add two base 1eX numbers
331   # stolen from Knuth Vol 2 Algorithm A pg 231
332   # there are separate routines to add and sub as per Knuth pg 233
333   # This routine clobbers up array x, but not y.
334  
335   my ($c,$x,$y) = @_;
336
337   return $x if (@$y == 1) && $y->[0] == 0;              # $x + 0 => $x
338   if ((@$x == 1) && $x->[0] == 0)                       # 0 + $y => $y->copy
339     {
340     # twice as slow as $x = [ @$y ], but necc. to retain $x as ref :(
341     @$x = @$y; return $x;               
342     }
343  
344   # for each in Y, add Y to X and carry. If after that, something is left in
345   # X, foreach in X add carry to X and then return X, carry
346   # Trades one "$j++" for having to shift arrays, $j could be made integer
347   # but this would impose a limit to number-length of 2**32.
348   my $i; my $car = 0; my $j = 0;
349   for $i (@$y)
350     {
351     $x->[$j] -= $BASE if $car = (($x->[$j] += $i + $car) >= $BASE) ? 1 : 0;
352     $j++;
353     }
354   while ($car != 0)
355     {
356     $x->[$j] -= $BASE if $car = (($x->[$j] += $car) >= $BASE) ? 1 : 0; $j++;
357     }
358   $x;
359   }                                                                             
360
361 sub _inc
362   {
363   # (ref to int_num_array, ref to int_num_array)
364   # routine to add 1 to a base 1eX numbers
365   # This routine clobbers up array x, but not y.
366   my ($c,$x) = @_;
367
368   for my $i (@$x)
369     {
370     return $x if (($i += 1) < $BASE);           # early out
371     $i = 0;                                     # overflow, next
372     }
373   push @$x,1 if ($x->[-1] == 0);                # last overflowed, so extend
374   $x;
375   }                                                                             
376
377 sub _dec
378   {
379   # (ref to int_num_array, ref to int_num_array)
380   # routine to add 1 to a base 1eX numbers
381   # This routine clobbers up array x, but not y.
382   my ($c,$x) = @_;
383
384   my $MAX = $BASE-1;                            # since MAX_VAL based on MBASE
385   for my $i (@$x)
386     {
387     last if (($i -= 1) >= 0);                   # early out
388     $i = $MAX;                                  # overflow, next
389     }
390   pop @$x if $x->[-1] == 0 && @$x > 1;          # last overflowed (but leave 0)
391   $x;
392   }                                                                             
393
394 sub _sub
395   {
396   # (ref to int_num_array, ref to int_num_array, swap)
397   # subtract base 1eX numbers -- stolen from Knuth Vol 2 pg 232, $x > $y
398   # subtract Y from X by modifying x in place
399   my ($c,$sx,$sy,$s) = @_;
400  
401   my $car = 0; my $i; my $j = 0;
402   if (!$s)
403     {
404     #print "case 2\n";
405     for $i (@$sx)
406       {
407       last unless defined $sy->[$j] || $car;
408       $i += $BASE if $car = (($i -= ($sy->[$j] || 0) + $car) < 0); $j++;
409       }
410     # might leave leading zeros, so fix that
411     return __strip_zeros($sx);
412     }
413   #print "case 1 (swap)\n";
414   for $i (@$sx)
415     {
416     # we can't do an early out if $x is than $y, since we
417     # need to copy the high chunks from $y. Found by Bob Mathews.
418     #last unless defined $sy->[$j] || $car;
419     $sy->[$j] += $BASE
420      if $car = (($sy->[$j] = $i-($sy->[$j]||0) - $car) < 0);
421     $j++;
422     }
423   # might leave leading zeros, so fix that
424   __strip_zeros($sy);
425   }                                                                             
426
427 sub _square_use_mul
428   {
429   # compute $x ** 2 or $x * $x in-place and return $x
430   my ($c,$x) = @_;
431
432   # From: Handbook of Applied Cryptography by A. Menezes, P. van Oorschot and
433   #       S. Vanstone., Chapter 14
434
435   #14.16 Algorithm Multiple-precision squaring
436   #INPUT: positive integer x = (xt 1 xt 2 ... x1 x0)b.
437   #OUTPUT: x * x = x ** 2 in radix b representation. 
438   #1. For i from 0 to (2t - 1) do: wi <- 0. 
439   #2.  For i from 0 to (t - 1) do the following: 
440   # 2.1 (uv)b w2i + xi * xi, w2i v, c u. 
441   # 2.2 For j from (i + 1)to (t - 1) do the following: 
442   #      (uv)b <- wi+j + 2*xj * xi + c, wi+j <- v, c <- u. 
443   # 2.3 wi+t <- u. 
444   #3. Return((w2t-1 w2t-2 ... w1 w0)b).
445
446 #  # Note: That description is crap. Half of the symbols are not explained or
447 #  # used with out beeing set.
448 #  my $t = scalar @$x;          # count
449 #  my ($c,$i,$j);
450 #  for ($i = 0; $i < $t; $i++)
451 #    {
452 #    $x->[$i] = $x->[$i*2] + $x[$i]*$x[$i];
453 #    $x->[$i*2] = $x[$i]; $c = $x[$i];
454 #    for ($j = $i+1; $j < $t; $j++)
455 #      {
456 #      $x->[$i] = $x->[$i+$j] + 2 * $x->[$i] * $x->[$j];
457 #      $x->[$i+$j] = $x[$j]; $c = $x[$i];
458 #      }
459 #    $x->[$i+$t] = $x[$i];
460 #    }
461   $x;
462   }
463
464 sub _mul_use_mul
465   {
466   # (ref to int_num_array, ref to int_num_array)
467   # multiply two numbers in internal representation
468   # modifies first arg, second need not be different from first
469   my ($c,$xv,$yv) = @_;
470
471   # shortcut for two very short numbers (improved by Nathan Zook)
472   # works also if xv and yv are the same reference
473   if ((@$xv == 1) && (@$yv == 1))
474     {
475     if (($xv->[0] *= $yv->[0]) >= $MBASE)
476        {
477        $xv->[0] = $xv->[0] - ($xv->[1] = int($xv->[0] * $RBASE)) * $MBASE;
478        };
479     return $xv;
480     }
481   # shortcut for result == 0
482   if ( ((@$xv == 1) && ($xv->[0] == 0)) ||
483        ((@$yv == 1) && ($yv->[0] == 0)) )
484     {
485     @$xv = (0);
486     return $xv;
487     }
488
489   # since multiplying $x with $x fails, make copy in this case
490   $yv = [@$xv] if $xv == $yv;   # same references?
491 #  $yv = [@$xv] if "$xv" eq "$yv";      # same references?
492
493   # since multiplying $x with $x would fail here, use the faster squaring
494 #  return _square($c,$xv) if $xv == $yv;        # same reference?
495
496   if ($LEN_CONVERT != 0)
497     {
498     $c->_to_small($xv); $c->_to_small($yv);
499     }
500
501   my @prod = (); my ($prod,$car,$cty,$xi,$yi);
502
503   for $xi (@$xv)
504     {
505     $car = 0; $cty = 0;
506
507     # slow variant
508 #    for $yi (@$yv)
509 #      {
510 #      $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
511 #      $prod[$cty++] =
512 #       $prod - ($car = int($prod * RBASE)) * $MBASE;  # see USE_MUL
513 #      }
514 #    $prod[$cty] += $car if $car; # need really to check for 0?
515 #    $xi = shift @prod;
516
517     # faster variant
518     # looping through this if $xi == 0 is silly - so optimize it away!
519     $xi = (shift @prod || 0), next if $xi == 0;
520     for $yi (@$yv)
521       {
522       $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
523 ##     this is actually a tad slower
524 ##        $prod = $prod[$cty]; $prod += ($car + $xi * $yi);     # no ||0 here
525       $prod[$cty++] =
526        $prod - ($car = int($prod * $RBASE)) * $MBASE;  # see USE_MUL
527       }
528     $prod[$cty] += $car if $car; # need really to check for 0?
529     $xi = shift @prod || 0;     # || 0 makes v5.005_3 happy
530     }
531   push @$xv, @prod;
532   if ($LEN_CONVERT != 0)
533     {
534     $c->_to_large($yv);
535     $c->_to_large($xv);
536     }
537   else
538     {
539     __strip_zeros($xv);
540     }
541   $xv;
542   }                                                                             
543
544 sub _mul_use_div
545   {
546   # (ref to int_num_array, ref to int_num_array)
547   # multiply two numbers in internal representation
548   # modifies first arg, second need not be different from first
549   my ($c,$xv,$yv) = @_;
550  
551   # shortcut for two very short numbers (improved by Nathan Zook)
552   # works also if xv and yv are the same reference
553   if ((@$xv == 1) && (@$yv == 1))
554     {
555     if (($xv->[0] *= $yv->[0]) >= $MBASE)
556         {
557         $xv->[0] =
558             $xv->[0] - ($xv->[1] = int($xv->[0] / $MBASE)) * $MBASE;
559         };
560     return $xv;
561     }
562   # shortcut for result == 0
563   if ( ((@$xv == 1) && ($xv->[0] == 0)) ||
564        ((@$yv == 1) && ($yv->[0] == 0)) )
565     {
566     @$xv = (0);
567     return $xv;
568     }
569
570  
571   # since multiplying $x with $x fails, make copy in this case
572   $yv = [@$xv] if $xv == $yv;   # same references?
573 #  $yv = [@$xv] if "$xv" eq "$yv";      # same references?
574   # since multiplying $x with $x would fail here, use the faster squaring
575 #  return _square($c,$xv) if $xv == $yv;        # same reference?
576
577   if ($LEN_CONVERT != 0)
578     {
579     $c->_to_small($xv); $c->_to_small($yv);
580     }
581   
582   my @prod = (); my ($prod,$car,$cty,$xi,$yi);
583   for $xi (@$xv)
584     {
585     $car = 0; $cty = 0;
586     # looping through this if $xi == 0 is silly - so optimize it away!
587     $xi = (shift @prod || 0), next if $xi == 0;
588     for $yi (@$yv)
589       {
590       $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
591       $prod[$cty++] =
592        $prod - ($car = int($prod / $MBASE)) * $MBASE;
593       }
594     $prod[$cty] += $car if $car; # need really to check for 0?
595     $xi = shift @prod || 0;     # || 0 makes v5.005_3 happy
596     }
597   push @$xv, @prod;
598   if ($LEN_CONVERT != 0)
599     {
600     $c->_to_large($yv);
601     $c->_to_large($xv);
602     }
603   else
604     {
605     __strip_zeros($xv);
606     }
607   $xv;
608   }                                                                             
609
610 sub _div_use_mul
611   {
612   # ref to array, ref to array, modify first array and return remainder if 
613   # in list context
614   my ($c,$x,$yorg) = @_;
615
616   if (@$x == 1 && @$yorg == 1)
617     {
618     # shortcut, $yorg and $x are two small numbers
619     if (wantarray)
620       {
621       my $r = [ $x->[0] % $yorg->[0] ];
622       $x->[0] = int($x->[0] / $yorg->[0]);
623       return ($x,$r); 
624       }
625     else
626       {
627       $x->[0] = int($x->[0] / $yorg->[0]);
628       return $x; 
629       }
630     }
631   if (@$yorg == 1)
632     {
633     my $rem;
634     $rem = _mod($c,[ @$x ],$yorg) if wantarray;
635
636     # shortcut, $y is < $BASE
637     my $j = scalar @$x; my $r = 0; 
638     my $y = $yorg->[0]; my $b;
639     while ($j-- > 0)
640       {
641       $b = $r * $MBASE + $x->[$j];
642       $x->[$j] = int($b/$y);
643       $r = $b % $y;
644       }
645     pop @$x if @$x > 1 && $x->[-1] == 0;        # splice up a leading zero 
646     return ($x,$rem) if wantarray;
647     return $x;
648     }
649
650   my $y = [ @$yorg ];                           # always make copy to preserve
651   if ($LEN_CONVERT != 0)
652     {
653     $c->_to_small($x); $c->_to_small($y);
654     }
655
656   my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1,@d,$tmp,$q,$u2,$u1,$u0);
657
658   $car = $bar = $prd = 0;
659   if (($dd = int($MBASE/($y->[-1]+1))) != 1) 
660     {
661     for $xi (@$x) 
662       {
663       $xi = $xi * $dd + $car;
664       $xi -= ($car = int($xi * $RBASE)) * $MBASE;       # see USE_MUL
665       }
666     push(@$x, $car); $car = 0;
667     for $yi (@$y) 
668       {
669       $yi = $yi * $dd + $car;
670       $yi -= ($car = int($yi * $RBASE)) * $MBASE;       # see USE_MUL
671       }
672     }
673   else 
674     {
675     push(@$x, 0);
676     }
677   @q = (); ($v2,$v1) = @$y[-2,-1];
678   $v2 = 0 unless $v2;
679   while ($#$x > $#$y) 
680     {
681     ($u2,$u1,$u0) = @$x[-3..-1];
682     $u2 = 0 unless $u2;
683     #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"
684     # if $v1 == 0;
685      $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$MBASE+$u1)/$v1));
686     --$q while ($v2*$q > ($u0*$MBASE+$u1-$q*$v1)*$MBASE+$u2);
687     if ($q)
688       {
689       ($car, $bar) = (0,0);
690       for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi) 
691         {
692         $prd = $q * $y->[$yi] + $car;
693         $prd -= ($car = int($prd * $RBASE)) * $MBASE;   # see USE_MUL
694         $x->[$xi] += $MBASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0));
695         }
696       if ($x->[-1] < $car + $bar) 
697         {
698         $car = 0; --$q;
699         for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi) 
700           {
701           $x->[$xi] -= $MBASE
702            if ($car = (($x->[$xi] += $y->[$yi] + $car) > $MBASE));
703           }
704         }   
705       }
706       pop(@$x); unshift(@q, $q);
707     }
708   if (wantarray) 
709     {
710     @d = ();
711     if ($dd != 1)  
712       {
713       $car = 0; 
714       for $xi (reverse @$x) 
715         {
716         $prd = $car * $MBASE + $xi;
717         $car = $prd - ($tmp = int($prd / $dd)) * $dd; # see USE_MUL
718         unshift(@d, $tmp);
719         }
720       }
721     else 
722       {
723       @d = @$x;
724       }
725     @$x = @q;
726     my $d = \@d; 
727     if ($LEN_CONVERT != 0)
728       {
729       $c->_to_large($x); $c->_to_large($d);
730       }
731     else
732       {
733       __strip_zeros($x);
734       __strip_zeros($d);
735       }
736     return ($x,$d);
737     }
738   @$x = @q;
739   if ($LEN_CONVERT != 0)
740     {
741     $c->_to_large($x);
742     }
743   else
744     {
745     __strip_zeros($x);
746     }
747   $x;
748   }
749
750 sub _div_use_div
751   {
752   # ref to array, ref to array, modify first array and return remainder if 
753   # in list context
754   my ($c,$x,$yorg) = @_;
755
756   if (@$x == 1 && @$yorg == 1)
757     {
758     # shortcut, $yorg and $x are two small numbers
759     if (wantarray)
760       {
761       my $r = [ $x->[0] % $yorg->[0] ];
762       $x->[0] = int($x->[0] / $yorg->[0]);
763       return ($x,$r); 
764       }
765     else
766       {
767       $x->[0] = int($x->[0] / $yorg->[0]);
768       return $x; 
769       }
770     }
771   if (@$yorg == 1)
772     {
773     my $rem;
774     $rem = _mod($c,[ @$x ],$yorg) if wantarray;
775
776     # shortcut, $y is < $BASE
777     my $j = scalar @$x; my $r = 0; 
778     my $y = $yorg->[0]; my $b;
779     while ($j-- > 0)
780       {
781       $b = $r * $MBASE + $x->[$j];
782       $x->[$j] = int($b/$y);
783       $r = $b % $y;
784       }
785     pop @$x if @$x > 1 && $x->[-1] == 0;        # splice up a leading zero 
786     return ($x,$rem) if wantarray;
787     return $x;
788     }
789
790   my $y = [ @$yorg ];                           # always make copy to preserve
791   if ($LEN_CONVERT != 0)
792     {
793     $c->_to_small($x); $c->_to_small($y);
794     }
795  
796   my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1,@d,$tmp,$q,$u2,$u1,$u0);
797
798   $car = $bar = $prd = 0;
799   if (($dd = int($MBASE/($y->[-1]+1))) != 1) 
800     {
801     for $xi (@$x) 
802       {
803       $xi = $xi * $dd + $car;
804       $xi -= ($car = int($xi / $MBASE)) * $MBASE;
805       }
806     push(@$x, $car); $car = 0;
807     for $yi (@$y) 
808       {
809       $yi = $yi * $dd + $car;
810       $yi -= ($car = int($yi / $MBASE)) * $MBASE;
811       }
812     }
813   else 
814     {
815     push(@$x, 0);
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     if ($LEN_CONVERT != 0)
868       {
869       $c->_to_large($x); $c->_to_large($d);
870       }
871     else
872       {
873       __strip_zeros($x);
874       __strip_zeros($d);
875       }
876     return ($x,$d);
877     }
878   @$x = @q;
879   if ($LEN_CONVERT != 0)
880     {
881     $c->_to_large($x);
882     }
883   else
884     {
885     __strip_zeros($x);
886     }
887   $x;
888   }
889
890 ##############################################################################
891 # testing
892
893 sub _acmp
894   {
895   # internal absolute post-normalized compare (ignore signs)
896   # ref to array, ref to array, return <0, 0, >0
897   # arrays must have at least one entry; this is not checked for
898
899   my ($c,$cx,$cy) = @_;
900
901   # fast comp based on array elements
902   my $lxy = scalar @$cx - scalar @$cy;
903   return -1 if $lxy < 0;                                # already differs, ret
904   return 1 if $lxy > 0;                                 # ditto
905   
906   # now calculate length based on digits, not parts
907   $lxy = _len($c,$cx) - _len($c,$cy);                   # difference
908   return -1 if $lxy < 0;
909   return 1 if $lxy > 0;
910
911   # hm, same lengths,  but same contents?
912   my $i = 0; my $a;
913   # first way takes 5.49 sec instead of 4.87, but has the early out advantage
914   # so grep is slightly faster, but more inflexible. hm. $_ instead of $k
915   # yields 5.6 instead of 5.5 sec huh?
916   # manual way (abort if unequal, good for early ne)
917   my $j = scalar @$cx - 1;
918   while ($j >= 0)
919     {
920     last if ($a = $cx->[$j] - $cy->[$j]); $j--;
921     }
922 #  my $j = scalar @$cx;
923 #  while (--$j >= 0)
924 #    {
925 #    last if ($a = $cx->[$j] - $cy->[$j]);
926 #    }
927   return 1 if $a > 0;
928   return -1 if $a < 0;
929   0;                                    # equal
930
931   # while it early aborts, it is even slower than the manual variant
932   #grep { return $a if ($a = $_ - $cy->[$i++]); } @$cx;
933   # grep way, go trough all (bad for early ne)
934   #grep { $a = $_ - $cy->[$i++]; } @$cx;
935   #return $a;
936   }
937
938 sub _len
939   {
940   # compute number of digits in bigint, minus the sign
941
942   # int() because add/sub sometimes leaves strings (like '00005') instead of
943   # '5' in this place, thus causing length() to report wrong length
944   my $cx = $_[1];
945
946   return (@$cx-1)*$BASE_LEN+length(int($cx->[-1]));
947   }
948
949 sub _digit
950   {
951   # return the nth digit, negative values count backward
952   # zero is rightmost, so _digit(123,0) will give 3
953   my ($c,$x,$n) = @_;
954
955   my $len = _len('',$x);
956
957   $n = $len+$n if $n < 0;               # -1 last, -2 second-to-last
958   $n = abs($n);                         # if negative was too big
959   $len--; $n = $len if $n > $len;       # n to big?
960   
961   my $elem = int($n / $BASE_LEN);       # which array element
962   my $digit = $n % $BASE_LEN;           # which digit in this element
963   $elem = '0000'.@$x[$elem];            # get element padded with 0's
964   return substr($elem,-$digit-1,1);
965   }
966
967 sub _zeros
968   {
969   # return amount of trailing zeros in decimal
970   # check each array elem in _m for having 0 at end as long as elem == 0
971   # Upon finding a elem != 0, stop
972   my $x = $_[1];
973   my $zeros = 0; my $elem;
974   foreach my $e (@$x)
975     {
976     if ($e != 0)
977       {
978       $elem = "$e";                             # preserve x
979       $elem =~ s/.*?(0*$)/$1/;                  # strip anything not zero
980       $zeros *= $BASE_LEN;                      # elems * 5
981       $zeros += length($elem);                  # count trailing zeros
982       last;                                     # early out
983       }
984     $zeros ++;                                  # real else branch: 50% slower!
985     }
986   $zeros;
987   }
988
989 ##############################################################################
990 # _is_* routines
991
992 sub _is_zero
993   {
994   # return true if arg (BINT or num_str) is zero (array '+', '0')
995   my $x = $_[1];
996
997   (((scalar @$x == 1) && ($x->[0] == 0))) <=> 0;
998   }
999
1000 sub _is_even
1001   {
1002   # return true if arg (BINT or num_str) is even
1003   my $x = $_[1];
1004   (!($x->[0] & 1)) <=> 0; 
1005   }
1006
1007 sub _is_odd
1008   {
1009   # return true if arg (BINT or num_str) is even
1010   my $x = $_[1];
1011
1012   (($x->[0] & 1)) <=> 0; 
1013   }
1014
1015 sub _is_one
1016   {
1017   # return true if arg (BINT or num_str) is one (array '+', '1')
1018   my $x = $_[1];
1019
1020   (scalar @$x == 1) && ($x->[0] == 1) <=> 0; 
1021   }
1022
1023 sub __strip_zeros
1024   {
1025   # internal normalization function that strips leading zeros from the array
1026   # args: ref to array
1027   my $s = shift;
1028  
1029   my $cnt = scalar @$s; # get count of parts
1030   my $i = $cnt-1;
1031   push @$s,0 if $i < 0;         # div might return empty results, so fix it
1032
1033   return $s if @$s == 1;                # early out
1034
1035   #print "strip: cnt $cnt i $i\n";
1036   # '0', '3', '4', '0', '0',
1037   #  0    1    2    3    4
1038   # cnt = 5, i = 4
1039   # i = 4
1040   # i = 3
1041   # => fcnt = cnt - i (5-2 => 3, cnt => 5-1 = 4, throw away from 4th pos)
1042   # >= 1: skip first part (this can be zero)
1043   while ($i > 0) { last if $s->[$i] != 0; $i--; }
1044   $i++; splice @$s,$i if ($i < $cnt); # $i cant be 0
1045   $s;                                                                    
1046   }                                                                             
1047
1048 ###############################################################################
1049 # check routine to test internal state of corruptions
1050
1051 sub _check
1052   {
1053   # used by the test suite
1054   my $x = $_[1];
1055
1056   return "$x is not a reference" if !ref($x);
1057
1058   # are all parts are valid?
1059   my $i = 0; my $j = scalar @$x; my ($e,$try);
1060   while ($i < $j)
1061     {
1062     $e = $x->[$i]; $e = 'undef' unless defined $e;
1063     $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e)";
1064     last if $e !~ /^[+]?[0-9]+$/;
1065     $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e) (stringify)";
1066     last if "$e" !~ /^[+]?[0-9]+$/;
1067     $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e) (cat-stringify)";
1068     last if '' . "$e" !~ /^[+]?[0-9]+$/;
1069     $try = ' < 0 || >= $BASE; '."($x, $e)";
1070     last if $e <0 || $e >= $BASE;
1071     # this test is disabled, since new/bnorm and certain ops (like early out
1072     # in add/sub) are allowed/expected to leave '00000' in some elements
1073     #$try = '=~ /^00+/; '."($x, $e)";
1074     #last if $e =~ /^00+/;
1075     $i++;
1076     }
1077   return "Illegal part '$e' at pos $i (tested: $try)" if $i < $j;
1078   return 0;
1079   }
1080
1081
1082 ###############################################################################
1083 ###############################################################################
1084 # some optional routines to make BigInt faster
1085
1086 sub _mod
1087   {
1088   # if possible, use mod shortcut
1089   my ($c,$x,$yo) = @_;
1090
1091   # slow way since $y to big
1092   if (scalar @$yo > 1)
1093     {
1094     my ($xo,$rem) = _div($c,$x,$yo);
1095     return $rem;
1096     }
1097   my $y = $yo->[0];
1098   # both are single element arrays
1099   if (scalar @$x == 1)
1100     {
1101     $x->[0] %= $y;
1102     return $x;
1103     }
1104
1105   # @y is single element, but @x has more than one
1106   my $b = $BASE % $y;
1107   if ($b == 0)
1108     {
1109     # when BASE % Y == 0 then (B * BASE) % Y == 0
1110     # (B * BASE) % $y + A % Y => A % Y
1111     # so need to consider only last element: O(1)
1112     $x->[0] %= $y;
1113     }
1114   elsif ($b == 1)
1115     {
1116     # else need to go trough all elements: O(N), but loop is a bit simplified
1117     my $r = 0;
1118     foreach (@$x)
1119       {
1120       $r = ($r + $_) % $y;              # not much faster, but heh...
1121       #$r += $_ % $y; $r %= $y;
1122       }
1123     $r = 0 if $r == $y;
1124     $x->[0] = $r;
1125     }
1126   else
1127     {
1128     # else need to go trough all elements: O(N)
1129     my $r = 0; my $bm = 1;
1130     foreach (@$x)
1131       {
1132       $r = ($_ * $bm + $r) % $y;
1133       $bm = ($bm * $b) % $y;
1134
1135       #$r += ($_ % $y) * $bm;
1136       #$bm *= $b;
1137       #$bm %= $y;
1138       #$r %= $y;
1139       }
1140     $r = 0 if $r == $y;
1141     $x->[0] = $r;
1142     }
1143   splice (@$x,1);
1144   $x;
1145   }
1146
1147 ##############################################################################
1148 # shifts
1149
1150 sub _rsft
1151   {
1152   my ($c,$x,$y,$n) = @_;
1153
1154   if ($n != 10)
1155     {
1156     $n = _new($c,\$n); return _div($c,$x, _pow($c,$n,$y));
1157     }
1158
1159   # shortcut (faster) for shifting by 10)
1160   # multiples of $BASE_LEN
1161   my $dst = 0;                          # destination
1162   my $src = _num($c,$y);                # as normal int
1163   my $rem = $src % $BASE_LEN;           # remainder to shift
1164   $src = int($src / $BASE_LEN);         # source
1165   if ($rem == 0)
1166     {
1167     splice (@$x,0,$src);                # even faster, 38.4 => 39.3
1168     }
1169   else
1170     {
1171     my $len = scalar @$x - $src;        # elems to go
1172     my $vd; my $z = '0'x $BASE_LEN;
1173     $x->[scalar @$x] = 0;               # avoid || 0 test inside loop
1174     while ($dst < $len)
1175       {
1176       $vd = $z.$x->[$src];
1177       $vd = substr($vd,-$BASE_LEN,$BASE_LEN-$rem);
1178       $src++;
1179       $vd = substr($z.$x->[$src],-$rem,$rem) . $vd;
1180       $vd = substr($vd,-$BASE_LEN,$BASE_LEN) if length($vd) > $BASE_LEN;
1181       $x->[$dst] = int($vd);
1182       $dst++;
1183       }
1184     splice (@$x,$dst) if $dst > 0;              # kill left-over array elems
1185     pop @$x if $x->[-1] == 0 && @$x > 1;        # kill last element if 0
1186     } # else rem == 0
1187   $x;
1188   }
1189
1190 sub _lsft
1191   {
1192   my ($c,$x,$y,$n) = @_;
1193
1194   if ($n != 10)
1195     {
1196     $n = _new($c,\$n); return _mul($c,$x, _pow($c,$n,$y));
1197     }
1198
1199   # shortcut (faster) for shifting by 10) since we are in base 10eX
1200   # multiples of $BASE_LEN:
1201   my $src = scalar @$x;                 # source
1202   my $len = _num($c,$y);                # shift-len as normal int
1203   my $rem = $len % $BASE_LEN;           # remainder to shift
1204   my $dst = $src + int($len/$BASE_LEN); # destination
1205   my $vd;                               # further speedup
1206   $x->[$src] = 0;                       # avoid first ||0 for speed
1207   my $z = '0' x $BASE_LEN;
1208   while ($src >= 0)
1209     {
1210     $vd = $x->[$src]; $vd = $z.$vd;
1211     $vd = substr($vd,-$BASE_LEN+$rem,$BASE_LEN-$rem);
1212     $vd .= $src > 0 ? substr($z.$x->[$src-1],-$BASE_LEN,$rem) : '0' x $rem;
1213     $vd = substr($vd,-$BASE_LEN,$BASE_LEN) if length($vd) > $BASE_LEN;
1214     $x->[$dst] = int($vd);
1215     $dst--; $src--;
1216     }
1217   # set lowest parts to 0
1218   while ($dst >= 0) { $x->[$dst--] = 0; }
1219   # fix spurios last zero element
1220   splice @$x,-1 if $x->[-1] == 0;
1221   $x;
1222   }
1223
1224 sub _pow
1225   {
1226   # power of $x to $y
1227   # ref to array, ref to array, return ref to array
1228   my ($c,$cx,$cy) = @_;
1229
1230   my $pow2 = _one();
1231   my $two = _two();
1232   my $y1 = _copy($c,$cy);
1233   while (!_is_one($c,$y1))
1234     {
1235     _mul($c,$pow2,$cx) if _is_odd($c,$y1);
1236     _div($c,$y1,$two);
1237     _mul($c,$cx,$cx);
1238     }
1239   _mul($c,$cx,$pow2) unless _is_one($c,$pow2);
1240   $cx;
1241   }
1242
1243 sub _fac
1244   {
1245   # factorial of $x
1246   # ref to array, return ref to array
1247   my ($c,$cx) = @_;
1248
1249   if ((@$cx == 1) && ($cx->[0] <= 2))
1250     {
1251     $cx->[0] = 1 * ($cx->[0]||1); # 0,1 => 1, 2 => 2
1252     return $cx;
1253     }
1254
1255   # go forward until $base is exceeded
1256   # limit is either $x or $base (x == 100 means as result too high)
1257   my $steps = 100; $steps = $cx->[0] if @$cx == 1;
1258   my $r = 2; my $cf = 3; my $step = 1; my $last = $r;
1259   while ($r < $BASE && $step < $steps)
1260     {
1261     $last = $r; $r *= $cf++; $step++;
1262     }
1263   if ((@$cx == 1) && ($step == $cx->[0]))
1264     {
1265     # completely done
1266     $cx = [$last];
1267     return $cx;
1268     }
1269   my $n = _copy($c,$cx);
1270   $cx = [$last];
1271
1272   #$cx = _one();
1273   while (!(@$n == 1 && $n->[0] == $step))
1274     {
1275     _mul($c,$cx,$n); _dec($c,$n);
1276     }
1277   $cx;
1278   }
1279
1280 use constant DEBUG => 0;
1281
1282 my $steps = 0;
1283
1284 sub steps { $steps };
1285
1286 sub _sqrt
1287   {
1288   # square-root of $x
1289   # ref to array, return ref to array
1290   my ($c,$x) = @_;
1291
1292   if (scalar @$x == 1)
1293     {
1294     # fit's into one Perl scalar
1295     $x->[0] = int(sqrt($x->[0]));
1296     return $x;
1297     } 
1298   my $y = _copy($c,$x);
1299   # hopefully _len/2 is < $BASE, the -1 is to always undershot the guess
1300   # since our guess will "grow"
1301   my $l = int((_len($c,$x)-1) / 2);     
1302
1303   my $lastelem = $x->[-1];      # for guess
1304   my $elems = scalar @$x - 1;
1305   # not enough digits, but could have more?
1306   if ((length($lastelem) <= 3) && ($elems > 1)) 
1307     {
1308     # right-align with zero pad
1309     my $len = length($lastelem) & 1;
1310     print "$lastelem => " if DEBUG;
1311     $lastelem .= substr($x->[-2] . '0' x $BASE_LEN,0,$BASE_LEN);
1312     # former odd => make odd again, or former even to even again
1313     $lastelem = $lastelem / 10 if (length($lastelem) & 1) != $len;      
1314     print "$lastelem\n" if DEBUG;
1315     }
1316
1317   # construct $x (instead of _lsft($c,$x,$l,10)
1318   my $r = $l % $BASE_LEN;       # 10000 00000 00000 00000 ($BASE_LEN=5)
1319   $l = int($l / $BASE_LEN);
1320   print "l =  $l " if DEBUG;
1321   
1322   splice @$x,$l;                # keep ref($x), but modify it
1323  
1324   # we make the first part of the guess not '1000...0' but int(sqrt($lastelem))
1325   # that gives us:
1326   # 14400 00000 => sqrt(14400) => 120
1327   # 144000 000000 => sqrt(144000) => 379
1328
1329   # $x->[$l--] = int('1' . '0' x $r);                   # old way of guessing
1330   print "$lastelem (elems $elems) => " if DEBUG;
1331   $lastelem = $lastelem / 10 if ($elems & 1 == 1);              # odd or even?
1332   my $g = sqrt($lastelem); $g =~ s/\.//;                        # 2.345 => 2345
1333   $r -= 1 if $elems & 1 == 0;                                   # 70 => 7
1334
1335   # padd with zeros if result is too short
1336   $x->[$l--] = int(substr($g . '0' x $r,0,$r+1));
1337   print "now ",$x->[-1] if DEBUG;
1338   print " would have been ", int('1' . '0' x $r),"\n" if DEBUG;
1339   
1340   # If @$x > 1, we could compute the second elem of the guess, too, to create
1341   # an even better guess. Not implemented yet.
1342   $x->[$l--] = 0 while ($l >= 0);       # all other digits of guess are zero
1343  
1344   print "start x= ",${_str($c,$x)},"\n" if DEBUG;
1345   my $two = _two();
1346   my $last = _zero();
1347   my $lastlast = _zero();
1348   $steps = 0 if DEBUG;
1349   while (_acmp($c,$last,$x) != 0 && _acmp($c,$lastlast,$x) != 0)
1350     {
1351     $steps++ if DEBUG;
1352     $lastlast = _copy($c,$last);
1353     $last = _copy($c,$x);
1354     _add($c,$x, _div($c,_copy($c,$y),$x));
1355     _div($c,$x, $two );
1356     print "      x= ",${_str($c,$x)},"\n" if DEBUG;
1357     }
1358   print "\nsteps in sqrt: $steps, " if DEBUG;
1359   _dec($c,$x) if _acmp($c,$y,_mul($c,_copy($c,$x),$x)) < 0;     # overshot? 
1360   print " final ",$x->[-1],"\n" if DEBUG;
1361   $x;
1362   }
1363
1364 ##############################################################################
1365 # binary stuff
1366
1367 sub _and
1368   {
1369   my ($c,$x,$y) = @_;
1370
1371   # the shortcut makes equal, large numbers _really_ fast, and makes only a
1372   # very small performance drop for small numbers (e.g. something with less
1373   # than 32 bit) Since we optimize for large numbers, this is enabled.
1374   return $x if _acmp($c,$x,$y) == 0;            # shortcut
1375   
1376   my $m = _one(); my ($xr,$yr);
1377   my $mask = $AND_MASK;
1378
1379   my $x1 = $x;
1380   my $y1 = _copy($c,$y);                        # make copy
1381   $x = _zero();
1382   my ($b,$xrr,$yrr);
1383   use integer;
1384   while (!_is_zero($c,$x1) && !_is_zero($c,$y1))
1385     {
1386     ($x1, $xr) = _div($c,$x1,$mask);
1387     ($y1, $yr) = _div($c,$y1,$mask);
1388
1389     # make ints() from $xr, $yr
1390     # this is when the AND_BITS are greater tahn $BASE and is slower for
1391     # small (<256 bits) numbers, but faster for large numbers. Disabled
1392     # due to KISS principle
1393
1394 #    $b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }
1395 #    $b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }
1396 #    _add($c,$x, _mul($c, _new( $c, \($xrr & $yrr) ), $m) );
1397     
1398     # 0+ due to '&' doesn't work in strings
1399     _add($c,$x, _mul($c, [ 0+$xr->[0] & 0+$yr->[0] ], $m) );
1400     _mul($c,$m,$mask);
1401     }
1402   $x;
1403   }
1404
1405 sub _xor
1406   {
1407   my ($c,$x,$y) = @_;
1408
1409   return _zero() if _acmp($c,$x,$y) == 0;       # shortcut (see -and)
1410
1411   my $m = _one(); my ($xr,$yr);
1412   my $mask = $XOR_MASK;
1413
1414   my $x1 = $x;
1415   my $y1 = _copy($c,$y);                        # make copy
1416   $x = _zero();
1417   my ($b,$xrr,$yrr);
1418   use integer;
1419   while (!_is_zero($c,$x1) && !_is_zero($c,$y1))
1420     {
1421     ($x1, $xr) = _div($c,$x1,$mask);
1422     ($y1, $yr) = _div($c,$y1,$mask);
1423     # make ints() from $xr, $yr (see _and())
1424     #$b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }
1425     #$b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }
1426     #_add($c,$x, _mul($c, _new( $c, \($xrr ^ $yrr) ), $m) );
1427
1428     # 0+ due to '^' doesn't work in strings
1429     _add($c,$x, _mul($c, [ 0+$xr->[0] ^ 0+$yr->[0] ], $m) );
1430     _mul($c,$m,$mask);
1431     }
1432   # the loop stops when the shorter of the two numbers is exhausted
1433   # the remainder of the longer one will survive bit-by-bit, so we simple
1434   # multiply-add it in
1435   _add($c,$x, _mul($c, $x1, $m) ) if !_is_zero($c,$x1);
1436   _add($c,$x, _mul($c, $y1, $m) ) if !_is_zero($c,$y1);
1437   
1438   $x;
1439   }
1440
1441 sub _or
1442   {
1443   my ($c,$x,$y) = @_;
1444
1445   return $x if _acmp($c,$x,$y) == 0;            # shortcut (see _and)
1446
1447   my $m = _one(); my ($xr,$yr);
1448   my $mask = $OR_MASK;
1449
1450   my $x1 = $x;
1451   my $y1 = _copy($c,$y);                        # make copy
1452   $x = _zero();
1453   my ($b,$xrr,$yrr);
1454   use integer;
1455   while (!_is_zero($c,$x1) && !_is_zero($c,$y1))
1456     {
1457     ($x1, $xr) = _div($c,$x1,$mask);
1458     ($y1, $yr) = _div($c,$y1,$mask);
1459     # make ints() from $xr, $yr (see _and())
1460 #    $b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }
1461 #    $b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }
1462 #    _add($c,$x, _mul($c, _new( $c, \($xrr | $yrr) ), $m) );
1463     
1464     # 0+ due to '|' doesn't work in strings
1465     _add($c,$x, _mul($c, [ 0+$xr->[0] | 0+$yr->[0] ], $m) );
1466     _mul($c,$m,$mask);
1467     }
1468   # the loop stops when the shorter of the two numbers is exhausted
1469   # the remainder of the longer one will survive bit-by-bit, so we simple
1470   # multiply-add it in
1471   _add($c,$x, _mul($c, $x1, $m) ) if !_is_zero($c,$x1);
1472   _add($c,$x, _mul($c, $y1, $m) ) if !_is_zero($c,$y1);
1473   
1474   $x;
1475   }
1476
1477 sub _as_hex
1478   {
1479   # convert a decimal number to hex (ref to array, return ref to string)
1480   my ($c,$x) = @_;
1481
1482   my $x1 = _copy($c,$x);
1483
1484   my $es = '';
1485   my $xr;
1486   my $x10000 = [ 0x10000 ];
1487   while (! _is_zero($c,$x1))
1488     {
1489     ($x1, $xr) = _div($c,$x1,$x10000);
1490     $es .= unpack('h4',pack('v',$xr->[0]));
1491     }
1492   $es = reverse $es;
1493   $es =~ s/^[0]+//;   # strip leading zeros
1494   $es = '0x' . $es;
1495   \$es;
1496   }
1497
1498 sub _as_bin
1499   {
1500   # convert a decimal number to bin (ref to array, return ref to string)
1501   my ($c,$x) = @_;
1502
1503   my $x1 = _copy($c,$x);
1504
1505   my $es = '';
1506   my $xr;
1507   my $x10000 = [ 0x10000 ];
1508   while (! _is_zero($c,$x1))
1509     {
1510     ($x1, $xr) = _div($c,$x1,$x10000);
1511     $es .= unpack('b16',pack('v',$xr->[0]));
1512     }
1513   $es = reverse $es;
1514   $es =~ s/^[0]+//;   # strip leading zeros
1515   $es = '0b' . $es;
1516   \$es;
1517   }
1518
1519 sub _from_hex
1520   {
1521   # convert a hex number to decimal (ref to string, return ref to array)
1522   my ($c,$hs) = @_;
1523
1524   my $mul = _one();
1525   my $m = [ 0x10000 ];                          # 16 bit at a time
1526   my $x = _zero();
1527
1528   my $len = length($$hs)-2;
1529   $len = int($len/4);                           # 4-digit parts, w/o '0x'
1530   my $val; my $i = -4;
1531   while ($len >= 0)
1532     {
1533     $val = substr($$hs,$i,4);
1534     $val =~ s/^[+-]?0x// if $len == 0;          # for last part only because
1535     $val = hex($val);                           # hex does not like wrong chars
1536     $i -= 4; $len --;
1537     _add ($c, $x, _mul ($c, [ $val ], $mul ) ) if $val != 0;
1538     _mul ($c, $mul, $m ) if $len >= 0;          # skip last mul
1539     }
1540   $x;
1541   }
1542
1543 sub _from_bin
1544   {
1545   # convert a hex number to decimal (ref to string, return ref to array)
1546   my ($c,$bs) = @_;
1547
1548   # instead of converting 8 bit at a time, it is faster to convert the
1549   # number to hex, and then call _from_hex.
1550
1551   my $hs = $$bs;
1552   $hs =~ s/^[+-]?0b//;                                  # remove sign and 0b
1553   my $l = length($hs);                                  # bits
1554   $hs = '0' x (8-($l % 8)) . $hs if ($l % 8) != 0;      # padd left side w/ 0
1555   my $h = unpack('H*', pack ('B*', $hs));               # repack as hex
1556   return $c->_from_hex(\('0x'.$h));
1557  
1558   my $mul = _one();
1559   my $m = [ 0x100 ];                            # 8 bit at a time
1560   my $x = _zero();
1561
1562   my $len = length($$bs)-2;
1563   $len = int($len/8);                           # 4-digit parts, w/o '0x'
1564   my $val; my $i = -8;
1565   while ($len >= 0)
1566     {
1567     $val = substr($$bs,$i,8);
1568     $val =~ s/^[+-]?0b// if $len == 0;          # for last part only
1569
1570     $val = ord(pack('B8',substr('00000000'.$val,-8,8))); 
1571
1572     $i -= 8; $len --;
1573     _add ($c, $x, _mul ($c, [ $val ], $mul ) ) if $val != 0;
1574     _mul ($c, $mul, $m ) if $len >= 0;          # skip last mul
1575     }
1576   $x;
1577   }
1578
1579 sub _modinv
1580   {
1581   # inverse modulus
1582   }
1583
1584 sub _modpow
1585   {
1586   # modulus of power ($x ** $y) % $z
1587   }
1588
1589 ##############################################################################
1590 ##############################################################################
1591
1592 1;
1593 __END__
1594
1595 =head1 NAME
1596
1597 Math::BigInt::Calc - Pure Perl module to support Math::BigInt
1598
1599 =head1 SYNOPSIS
1600
1601 Provides support for big integer calculations. Not intended to be used by other
1602 modules (except Math::BigInt::Cached). Other modules which sport the same
1603 functions can also be used to support Math::Bigint, like Math::BigInt::Pari.
1604
1605 =head1 DESCRIPTION
1606
1607 In order to allow for multiple big integer libraries, Math::BigInt was
1608 rewritten to use library modules for core math routines. Any module which
1609 follows the same API as this can be used instead by using the following:
1610
1611         use Math::BigInt lib => 'libname';
1612
1613 'libname' is either the long name ('Math::BigInt::Pari'), or only the short
1614 version like 'Pari'.
1615
1616 =head1 EXPORT
1617
1618 The following functions MUST be defined in order to support the use by
1619 Math::BigInt:
1620
1621         _new(string)    return ref to new object from ref to decimal string
1622         _zero()         return a new object with value 0
1623         _one()          return a new object with value 1
1624
1625         _str(obj)       return ref to a string representing the object
1626         _num(obj)       returns a Perl integer/floating point number
1627                         NOTE: because of Perl numeric notation defaults,
1628                         the _num'ified obj may lose accuracy due to 
1629                         machine-dependend floating point size limitations
1630                     
1631         _add(obj,obj)   Simple addition of two objects
1632         _mul(obj,obj)   Multiplication of two objects
1633         _div(obj,obj)   Division of the 1st object by the 2nd
1634                         In list context, returns (result,remainder).
1635                         NOTE: this is integer math, so no
1636                         fractional part will be returned.
1637         _sub(obj,obj)   Simple subtraction of 1 object from another
1638                         a third, optional parameter indicates that the params
1639                         are swapped. In this case, the first param needs to
1640                         be preserved, while you can destroy the second.
1641                         sub (x,y,1) => return x - y and keep x intact!
1642         _dec(obj)       decrement object by one (input is garant. to be > 0)
1643         _inc(obj)       increment object by one
1644
1645
1646         _acmp(obj,obj)  <=> operator for objects (return -1, 0 or 1)
1647
1648         _len(obj)       returns count of the decimal digits of the object
1649         _digit(obj,n)   returns the n'th decimal digit of object
1650
1651         _is_one(obj)    return true if argument is +1
1652         _is_zero(obj)   return true if argument is 0
1653         _is_even(obj)   return true if argument is even (0,2,4,6..)
1654         _is_odd(obj)    return true if argument is odd (1,3,5,7..)
1655
1656         _copy           return a ref to a true copy of the object
1657
1658         _check(obj)     check whether internal representation is still intact
1659                         return 0 for ok, otherwise error message as string
1660
1661 The following functions are optional, and can be defined if the underlying lib
1662 has a fast way to do them. If undefined, Math::BigInt will use pure Perl (hence
1663 slow) fallback routines to emulate these:
1664
1665         _from_hex(str)  return ref to new object from ref to hexadecimal string
1666         _from_bin(str)  return ref to new object from ref to binary string
1667         
1668         _as_hex(str)    return ref to scalar string containing the value as
1669                         unsigned hex string, with the '0x' prepended.
1670                         Leading zeros must be stripped.
1671         _as_bin(str)    Like as_hex, only as binary string containing only
1672                         zeros and ones. Leading zeros must be stripped and a
1673                         '0b' must be prepended.
1674         
1675         _rsft(obj,N,B)  shift object in base B by N 'digits' right
1676                         For unsupported bases B, return undef to signal failure
1677         _lsft(obj,N,B)  shift object in base B by N 'digits' left
1678                         For unsupported bases B, return undef to signal failure
1679         
1680         _xor(obj1,obj2) XOR (bit-wise) object 1 with object 2
1681                         Note: XOR, AND and OR pad with zeros if size mismatches
1682         _and(obj1,obj2) AND (bit-wise) object 1 with object 2
1683         _or(obj1,obj2)  OR (bit-wise) object 1 with object 2
1684
1685         _mod(obj,obj)   Return remainder of div of the 1st by the 2nd object
1686         _sqrt(obj)      return the square root of object (truncate to int)
1687         _fac(obj)       return factorial of object 1 (1*2*3*4..)
1688         _pow(obj,obj)   return object 1 to the power of object 2
1689         _gcd(obj,obj)   return Greatest Common Divisor of two objects
1690         
1691         _zeros(obj)     return number of trailing decimal zeros
1692         _modinv         return inverse modulus
1693         _modpow         return modulus of power ($x ** $y) % $z
1694
1695 Input strings come in as unsigned but with prefix (i.e. as '123', '0xabc'
1696 or '0b1101').
1697
1698 Testing of input parameter validity is done by the caller, so you need not
1699 worry about underflow (f.i. in C<_sub()>, C<_dec()>) nor about division by
1700 zero or similar cases.
1701
1702 The first parameter can be modified, that includes the possibility that you
1703 return a reference to a completely different object instead. Although keeping
1704 the reference and just changing it's contents is prefered over creating and
1705 returning a different reference.
1706
1707 Return values are always references to objects or strings. Exceptions are
1708 C<_lsft()> and C<_rsft()>, which return undef if they can not shift the
1709 argument. This is used to delegate shifting of bases different than the one
1710 you can support back to Math::BigInt, which will use some generic code to
1711 calculate the result.
1712
1713 =head1 WRAP YOUR OWN
1714
1715 If you want to port your own favourite c-lib for big numbers to the
1716 Math::BigInt interface, you can take any of the already existing modules as
1717 a rough guideline. You should really wrap up the latest BigInt and BigFloat
1718 testsuites with your module, and replace in them any of the following:
1719
1720         use Math::BigInt;
1721
1722 by this:
1723
1724         use Math::BigInt lib => 'yourlib';
1725
1726 This way you ensure that your library really works 100% within Math::BigInt.
1727
1728 =head1 LICENSE
1729  
1730 This program is free software; you may redistribute it and/or modify it under
1731 the same terms as Perl itself. 
1732
1733 =head1 AUTHORS
1734
1735 Original math code by Mark Biggar, rewritten by Tels L<http://bloodgate.com/>
1736 in late 2000, 2001.
1737 Seperated from BigInt and shaped API with the help of John Peacock.
1738
1739 =head1 SEE ALSO
1740
1741 L<Math::BigInt>, L<Math::BigFloat>, L<Math::BigInt::BitVect>,
1742 L<Math::BigInt::GMP>, L<Math::BigInt::Cached> and L<Math::BigInt::Pari>.
1743
1744 =cut