1 // Copyright (c) 1997, 1998, 1999, 2000, 2006  Per M.A. Bothner.
2 // This is free software;  for terms and warranty disclaimer see ./COPYING.
3 
4 package gnu.math;
5 import java.io.*;
6 import java.math.BigDecimal;
7 import java.math.BigInteger;
8 
9 /** A class for infinite-precision integers.
10  * @author Per Bothner
11  */
12 
13 public class IntNum extends RatNum implements Externalizable
14 {
15   /** All integers are stored in 2's-complement form.
16    * If words == null, the ival is the value of this IntNum.
17    * Otherwise, the first ival elements of words make the value
18    * of this IntNum, stored in little-endian order, 2's-complement form. */
19   public int ival;
20   public int[] words;
21 
22 
23   /** We pre-allocate integers in the range minFixNum..maxFixNum. */
24   static final int minFixNum = -100;
25   static final int maxFixNum = 1024;
26   static final int numFixNum = maxFixNum-minFixNum+1;
27   static final IntNum[] smallFixNums = new IntNum[numFixNum];
28 
29   static {
30     for (int i = numFixNum;  --i >= 0; )
31       smallFixNums[i] = new IntNum(i + minFixNum);
32   }
33 
IntNum()34   public IntNum ()
35   {
36   }
37 
38   /** Create a new (non-shared) IntNum, and initialize to an int.
39    * @param value the initial value */
IntNum(int value)40   public IntNum (int value)
41   {
42     ival = value;
43   }
44 
zero()45   public static final IntNum zero ()
46   {
47     return smallFixNums[- minFixNum];
48   }
49 
one()50   public static final IntNum one ()
51   {
52     return smallFixNums[1 - minFixNum];
53   }
54 
ten()55   public static final IntNum ten ()
56   {
57     return smallFixNums[10 - minFixNum];
58   }
59 
60   /** Return the IntNum for -1. */
minusOne()61   public static IntNum minusOne ()
62   {
63     return smallFixNums[-1 - minFixNum];
64   }
65 
asIntNumOrNull(Object value)66   public static IntNum asIntNumOrNull (Object value)
67   {
68     if (value instanceof IntNum)
69       return (IntNum) value;
70     if (value instanceof UnsignedPrim)
71       return ((UnsignedPrim) value).toIntNum();
72     if (value instanceof BigInteger)
73       return IntNum.valueOf(value.toString(), 10);
74     if (value instanceof Number
75         && (value instanceof Integer || value instanceof Long
76             || value instanceof Short || value instanceof Byte))
77       return IntNum.make(((Number) value).longValue());
78     return null;
79   }
80 
81   /** Allocate a new non-shared IntNum.
82    * @param nwords number of words to allocate
83    */
alloc(int nwords)84   public static IntNum alloc (int nwords)
85   {
86     if (nwords <= 1)
87       return new IntNum ();
88     IntNum result = new IntNum ();
89     result.words = new int[nwords];
90     return result;
91   }
92 
93   /** Change words.length to nwords.
94   * We allow words.length to be upto nwords+2 without reallocating. */
realloc(int nwords)95   public void realloc (int nwords)
96   {
97     if (nwords == 0)
98       {
99 	if (words != null)
100 	  {
101 	    if (ival > 0)
102 	      ival = words[0];
103 	    words = null;
104 	  }
105       }
106     else if (words == null
107 	     || words.length < nwords
108 	     || words.length > nwords + 2)
109       {
110 	int[] new_words = new int [nwords];
111 	if (words == null)
112 	  {
113 	    new_words[0] = ival;
114 	    ival = 1;
115 	  }
116 	else
117 	  {
118 	    if (nwords < ival)
119 	      ival = nwords;
120 	    System.arraycopy (words, 0, new_words, 0, ival);
121 	  }
122 	words = new_words;
123       }
124   }
125 
numerator()126   public final IntNum numerator ()
127   {
128     return this;
129   }
130 
denominator()131   public final IntNum denominator ()
132   {
133     return one ();
134   }
135 
isNegative()136   public final boolean isNegative ()
137   {
138     return (words == null ? ival : words[ival-1]) < 0;
139   }
140 
sign()141   public int sign ()
142   {
143     int n = ival;
144     int[] w = words;
145     if (w == null)
146       return n > 0 ? 1 : n < 0 ? -1 : 0;
147     int i = w[--n];
148     if (i > 0)
149       return 1;
150     if (i < 0)
151       return -1;
152     for (;;)
153       {
154 	if (n == 0)
155 	  return 0;
156 	if (w[--n] != 0)
157 	  return 1;
158       }
159   }
160 
161   /** Return -1, 0, or 1, depending on which value is greater. */
compare(IntNum x, IntNum y)162   public static int compare (IntNum x, IntNum y)
163   {
164     if (x.words == null && y.words == null)
165       return x.ival < y.ival ? -1 : x.ival > y.ival ? 1 : 0;
166     boolean x_negative = x.isNegative ();
167     boolean y_negative = y.isNegative ();
168     if (x_negative != y_negative)
169       return x_negative ? -1 : 1;
170     int x_len = x.words == null ? 1 : x.ival;
171     int y_len = y.words == null ? 1 : y.ival;
172     if (x_len != y_len) // We assume x and y are canonicalized.
173       return (x_len > y_len)!=x_negative ? 1 : -1;
174     return MPN.cmp (x.words, y.words, x_len);
175   }
176 
177   /** Return -1, 0, or 1, depending on which value is greater. */
compare(IntNum x, long y)178  public static int compare (IntNum x, long y)
179   {
180     long x_word;
181     if (x.words == null)
182       x_word = x.ival;
183     else
184       {
185 	boolean x_negative = x.isNegative ();
186 	boolean y_negative = y < 0;
187 	if (x_negative != y_negative)
188 	  return x_negative ? -1 : 1;
189 	int x_len = x.words == null ? 1 : x.ival;
190 	if (x_len == 1)
191 	  x_word = x.words[0];
192 	else if (x_len == 2)
193 	  x_word = x.longValue();
194 	else // We assume x is canonicalized.
195 	  return x_negative ? -1 : 1;
196       }
197     return x_word < y ? -1 : x_word > y ? 1 : 0;
198   }
199 
200   public int compare (Object obj)
201   {
202     if (obj instanceof IntNum)
203       return compare (this, (IntNum) obj);
204     return ((Numeric)obj).compareReversed (this);
205   }
206 
207   public final boolean isOdd ()
208   {
209     int low = words == null ? ival : words[0];
210     return (low & 1) != 0;
211   }
212 
213   public final boolean isZero ()
214   {
215     return words == null && ival == 0;
216   }
217 
218   public final boolean isOne ()
219   {
220     return words == null && ival == 1;
221   }
222 
223   public final boolean isMinusOne ()
224   {
225     return words == null && ival == -1;
226   }
227 
228   /** Calculate how many words are significant in words[0:len-1].
229    * Returns the least value {@code x} such that
230    * {@code x>0 && words[0:x-1]==words[0:len-1]},
231    * when {@code words} is viewed as a 2's complement integer.
232    */
233   public static int wordsNeeded (int[] words, int len)
234   {
235     int i = len;
236     if (i > 0)
237       {
238 	int word = words[--i];
239 	if (word == -1)
240 	  {
241 	    while (i > 0 && (word = words[i-1]) < 0)
242 	      {
243 		i--;
244 		if (word != -1) break;
245 	      }
246 	  }
247 	else
248 	  {
249 	    while (word == 0 && i > 0 && (word = words[i-1]) >= 0)  i--;
250 	  }
251       }
252     return i+1;
253   }
254 
canonicalize()255   public IntNum canonicalize ()
256   {
257     if (words != null
258 	&& (ival = IntNum.wordsNeeded (words, ival)) <= 1)
259       {
260 	if (ival == 1)
261 	  ival = words[0];
262 	words = null;
263       }
264     if (words == null && ival >= minFixNum && ival <= maxFixNum)
265       return smallFixNums[(int) ival - minFixNum];
266     return this;
267   }
268 
269   /** Add two ints, yielding an IntNum. */
add(int x, int y)270   public static final IntNum add (int x, int y)
271   {
272     return IntNum.make ((long) x + (long) y);
273   }
274 
275   /** Add an IntNum and an int, yielding a new IntNum. */
add(IntNum x, int y)276   public static IntNum add (IntNum x, int y)
277   {
278     if (x.words == null)
279       return IntNum.add (x.ival, y);
280     IntNum result = new IntNum (0);
281     result.setAdd (x, y);
282     return result.canonicalize ();
283   }
284 
285   /** Set this to the sum of x and y.
286    * OK if x==this. */
setAdd(IntNum x, int y)287   public void setAdd (IntNum x, int y)
288   {
289     if (x.words == null)
290       {
291 	set ((long) x.ival + (long) y);
292 	return;
293       }
294     int len = x.ival;
295     realloc (len + 1);
296     long carry = y;
297     for (int i = 0;  i < len;  i++)
298       {
299 	carry += ((long) x.words[i] & 0xffffffffL);
300 	words[i] = (int) carry;
301 	carry >>= 32;
302       }
303     if (x.words[len - 1] < 0)
304       carry--;
305     words[len] = (int) carry;
306     ival = wordsNeeded (words, len+1);
307   }
308 
309   /** Destructively add an int to this. */
setAdd(int y)310   public final void setAdd (int y)
311   {
312     setAdd (this, y);
313   }
314 
315   /** Destructively set the value of this to an int. */
set(int y)316   public final void set (int y)
317   {
318     words = null;
319     ival = y;
320   }
321 
322   /** Destructively set the value of this to a long. */
set(long y)323   public final void set (long y)
324   {
325     int i = (int) y;
326     if ((long) i == y)
327       {
328 	ival = i;
329 	words = null;
330       }
331     else
332       {
333 	realloc (2);
334 	words[0] = i;
335 	words[1] = (int) (y >> 32);
336 	ival = 2;
337       }
338   }
339 
340   /** Destructively set the value of this to the given words.
341   * The words array is reused, not copied. */
set(int[] words, int length)342   public final void set (int[] words, int length)
343   {
344     this.ival = length;
345     this.words = words;
346   }
347 
348   /** Destructively set the value of this to that of y. */
set(IntNum y)349   public final void set (IntNum y)
350   {
351     if (y.words == null)
352       set (y.ival);
353     else if (this != y)
354       {
355 	realloc(y.ival);
356 	System.arraycopy(y.words, 0, words, 0, y.ival);
357 	ival = y.ival;
358       }
359   }
360 
361   /** Add two IntNums, yielding their sum as another IntNum. */
add(IntNum x, IntNum y)362   public static IntNum add (IntNum x, IntNum y)
363   {
364     return add(x, y, 1);
365   }
366 
367   /** Subtract two IntNums, yielding their sum as another IntNum. */
sub(IntNum x, IntNum y)368   public static IntNum sub (IntNum x, IntNum y)
369   {
370     return add(x, y, -1);
371   }
372 
373   /** Add two IntNums, yielding their sum as another IntNum. */
add(IntNum x, IntNum y, int k)374   public static IntNum add (IntNum x, IntNum y, int k)
375   {
376     if (y.words == null) {
377         int yval = y.ival;
378         if (yval == 0)
379             return x;
380         if (x.words == null)
381             return IntNum.make((long) k * (long) yval + (long) x.ival);
382     }
383     if (k != 1)
384       {
385 	if (k == -1)
386 	  y = IntNum.neg (y);
387 	else
388 	  y = IntNum.times (y, IntNum.make (k));
389       }
390     if (x.words == null)
391       return IntNum.add (y, x.ival);
392     if (y.words == null)
393       return IntNum.add (x, y.ival);
394     // Both are big
395     int len;
396     if (y.ival > x.ival)
397       { // Swap so x is longer then y.
398 	IntNum tmp = x;  x = y;  y = tmp;
399       }
400     IntNum result = alloc (x.ival + 1);
401     int i = y.ival;
402     long carry = MPN.add_n (result.words, x.words, y.words, i);
403     long y_ext = y.words[i-1] < 0 ? 0xffffffffL : 0;
404     for (; i < x.ival;  i++)
405       {
406 	carry += ((long) x.words[i] & 0xffffffffL) + y_ext;;
407 	result.words[i] = (int) carry;
408 	carry >>>= 32;
409       }
410     if (x.words[i - 1] < 0)
411       y_ext--;
412     result.words[i] = (int) (carry + y_ext);
413     result.ival = i+1;
414     return result.canonicalize ();
415   }
416 
417   /** Multiply two ints, yielding an IntNum. */
times(int x, int y)418   public static final IntNum times (int x, int y)
419   {
420     return IntNum.make ((long) x * (long) y);
421   }
422 
times(IntNum x, int y)423   public static final IntNum times (IntNum x, int y)
424   {
425     if (y == 0)
426       return zero();
427     if (y == 1)
428       return x;
429     int[] xwords = x.words;
430     int xlen = x.ival;
431     if (xwords == null)
432       return IntNum.make ((long) xlen * (long) y);
433     boolean negative;
434     IntNum result = IntNum.alloc (xlen+1);
435     if (xwords[xlen-1] < 0)
436       {
437 	negative = true;
438 	negate(result.words, xwords, xlen);
439 	xwords = result.words;
440       }
441     else
442       negative = false;
443     if (y < 0)
444       {
445 	negative = !negative;
446 	y = -y;
447       }
448     result.words[xlen] = MPN.mul_1 (result.words, xwords, xlen, y);
449     result.ival = xlen+1;
450     if (negative)
451       result.setNegative ();
452     return result.canonicalize ();
453   }
454 
times(IntNum x, IntNum y)455   public static final IntNum times (IntNum x, IntNum y)
456   {
457     if (y.words == null)
458       return times(x, y.ival);
459     if (x.words == null)
460       return times(y, x.ival);
461     boolean negative = false;
462     int[] xwords;
463     int[] ywords;
464     int xlen = x.ival;
465     int ylen = y.ival;
466     if (x.isNegative ())
467       {
468 	negative = true;
469 	xwords = new int[xlen];
470 	negate(xwords, x.words, xlen);
471       }
472     else
473       {
474 	negative = false;
475 	xwords = x.words;
476       }
477     if (y.isNegative ())
478       {
479 	negative = !negative;
480 	ywords = new int[ylen];
481 	negate(ywords, y.words, ylen);
482       }
483     else
484       ywords = y.words;
485     // Swap if x is shorter then y.
486     if (xlen < ylen)
487       {
488 	int[] twords = xwords;  xwords = ywords;  ywords = twords;
489 	int tlen = xlen;  xlen = ylen;  ylen = tlen;
490       }
491     IntNum result = IntNum.alloc (xlen+ylen);
492     MPN.mul (result.words, xwords, xlen, ywords, ylen);
493     result.ival = xlen+ylen;
494     if (negative)
495       result.setNegative ();
496     return result.canonicalize ();
497   }
498 
divide(long x, long y, IntNum quotient, IntNum remainder, int rounding_mode)499   public static void divide (long x, long y,
500 			     IntNum quotient, IntNum remainder,
501 			     int rounding_mode)
502   {
503     boolean xNegative, yNegative;
504     if (rounding_mode == NONNEG_MOD)
505       rounding_mode = y < 0 ? CEILING : FLOOR;
506     if (x < 0)
507       {
508 	xNegative = true;
509 	if (x == Long.MIN_VALUE)
510 	  {
511 	    divide (IntNum.make (x), IntNum.make (y),
512 		    quotient, remainder, rounding_mode);
513 	    return;
514 	  }
515 	x = -x;
516       }
517     else
518       xNegative = false;
519 
520     if (y < 0)
521       {
522 	yNegative = true;
523 	if (y == Long.MIN_VALUE)
524 	  {
525 	    if (rounding_mode == TRUNCATE)
526 	      { // x != Long.Min_VALUE implies abs(x) < abs(y)
527 		if (quotient != null)
528 		  quotient.set (0);
529 		if (remainder != null)
530 		  remainder.set (x);
531 	      }
532 	    else
533 	      divide (IntNum.make (x), IntNum.make (y),
534 		      quotient, remainder, rounding_mode);
535 	    return;
536 	  }
537 	y = -y;
538       }
539     else
540       yNegative = false;
541 
542     long q = x / y;
543     long r = x % y;
544     boolean qNegative = xNegative ^ yNegative;
545 
546     boolean add_one = false;
547     if (r != 0)
548       {
549 	switch (rounding_mode)
550 	  {
551 	  case TRUNCATE:
552 	    break;
553 	  case CEILING:
554 	  case FLOOR:
555 	    if (qNegative == (rounding_mode == FLOOR))
556 	      add_one = true;
557 	    break;
558 	  case ROUND:
559 	    add_one = r > ((y - (q & 1)) >> 1);
560 	    break;
561 	  }
562       }
563     if (quotient != null)
564       {
565 	if (add_one)
566 	  q++;
567 	if (qNegative)
568 	  q = -q;
569 	quotient.set (q);
570       }
571     if (remainder != null)
572       {
573 	// The remainder is by definition: X-Q*Y
574 	if (add_one)
575 	  {
576 	    // Subtract the remainder from Y.
577 	    r = y - r;
578 	    // In this case, abs(Q*Y) > abs(X).
579 	    // So sign(remainder) = -sign(X).
580 	    xNegative = ! xNegative;
581 	  }
582 	else
583 	  {
584 	    // If !add_one, then: abs(Q*Y) <= abs(X).
585 	    // So sign(remainder) = sign(X).
586 	  }
587 	if (xNegative)
588 	  r = -r;
589 	remainder.set (r);
590       }
591   }
592 
593   /** Divide two integers, yielding quotient and remainder.
594    * @param x the numerator in the division
595    * @param y the denominator in the division
596    * @param quotient is set to the quotient of the result (iff quotient!=null)
597    * @param remainder is set to the remainder of the result
598    *  (iff remainder!=null)
599    * @param rounding_mode one of FLOOR, CEILING, TRUNCATE, or ROUND.
600    */
601   public static void divide (IntNum x, IntNum y,
602 			     IntNum quotient, IntNum remainder,
603 			     int rounding_mode)
604   {
605     if ((x.words == null || x.ival <= 2)
606 	&& (y.words == null || y.ival <= 2))
607       {
608 	long x_l = x.longValue ();
609 	long y_l = y.longValue ();
610 	if (x_l != Long.MIN_VALUE && y_l != Long.MIN_VALUE)
611 	  {
612 	    divide (x_l, y_l, quotient, remainder, rounding_mode);
613 	    return;
614 	  }
615       }
616 
617     boolean xNegative = x.isNegative ();
618     boolean yNegative = y.isNegative ();
619     boolean qNegative = xNegative ^ yNegative;
620 
621     int ylen = y.words == null ? 1 : y.ival;
622     int[] ywords = new int[ylen];
623     y.getAbsolute (ywords);
624     while (ylen > 1 && ywords[ylen-1] == 0)  ylen--;
625 
626     int xlen = x.words == null ? 1 : x.ival;
627     int[] xwords = new int[xlen+2];
628     x.getAbsolute (xwords);
629     while (xlen > 1 && xwords[xlen-1] == 0)  xlen--;
630 
631     int qlen, rlen;
632 
633     int cmpval = MPN.cmp (xwords, xlen, ywords, ylen);
634     if (cmpval < 0)  // abs(x) < abs(y)
635       { // quotient = 0;  remainder = num.
636 	int[] rwords = xwords;  xwords = ywords;  ywords = rwords;
637 	rlen = xlen;  qlen = 1;  xwords[0] = 0;
638       }
639     else if (cmpval == 0)  // abs(x) == abs(y)
640       {
641 	xwords[0] = 1;  qlen = 1;  // quotient = 1
642 	ywords[0] = 0;  rlen = 1;  // remainder = 0;
643       }
644     else if (ylen == 1)
645       {
646 	qlen = xlen;
647 	rlen = 1;
648 	ywords[0] = MPN.divmod_1 (xwords, xwords, xlen, ywords[0]);
649       }
650     else  // abs(x) > abs(y)
651       {
652 	// Normalize the denominator, i.e. make its most significant bit set by
653 	// shifting it normalization_steps bits to the left.  Also shift the
654 	// numerator the same number of steps (to keep the quotient the same!).
655 
656 	int nshift = MPN.count_leading_zeros (ywords[ylen-1]);
657 	if (nshift != 0)
658 	  {
659 	    // Shift up the denominator setting the most significant bit of
660 	    // the most significant word.
661 	    MPN.lshift (ywords, 0, ywords, ylen, nshift);
662 
663 	    // Shift up the numerator, possibly introducing a new most
664 	    // significant word.
665 	    int x_high = MPN.lshift (xwords, 0, xwords, xlen, nshift);
666 	    xwords[xlen++] = x_high;
667 	}
668 
669 	if (xlen == ylen)
670 	  xwords[xlen++] = 0;
671 	MPN.divide (xwords, xlen, ywords, ylen);
672 	rlen = ylen;
673         MPN.rshift0 (ywords, xwords, 0, rlen, nshift);
674 
675 	qlen = xlen + 1 - ylen;
676 	if (quotient != null)
677 	  {
678 	    for (int i = 0;  i < qlen;  i++)
679 	      xwords[i] = xwords[i+ylen];
680 	  }
681       }
682 
683     while (rlen > 1 && ywords[rlen-1] == 0)
684       rlen--;
685     if (ywords[rlen-1] < 0)
686       {
687         ywords[rlen] = 0;
688         rlen++;
689       }
690 
691     // Now the quotient is in xwords, and the remainder is in ywords.
692 
693     boolean add_one = false;
694     if (rlen > 1 || ywords[0] != 0)
695       { // Non-zero remainder i.e. in-exact quotient.
696         if (rounding_mode == NONNEG_MOD)
697           {
698             rounding_mode = yNegative ? CEILING : FLOOR;
699           }
700 	switch (rounding_mode)
701 	  {
702 	  case TRUNCATE:
703 	    break;
704 	  case CEILING:
705 	  case FLOOR:
706 	    if (qNegative == (rounding_mode == FLOOR))
707 	      add_one = true;
708 	    break;
709 	  case ROUND:
710 	    // int cmp = compare (remainder<<1, abs(y));
711 	    IntNum tmp = remainder == null ? new IntNum() : remainder;
712 	    tmp.set (ywords, rlen);
713 	    tmp = shift (tmp, 1);
714 	    if (yNegative)
715 	      tmp.setNegative();
716 	    int cmp = compare (tmp, y);
717 	    // Now cmp == compare(sign(y)*(remainder<<1), y)
718 	    if (yNegative)
719 	      cmp = -cmp;
720 	    add_one = (cmp == 1) || (cmp == 0 && (xwords[0]&1) != 0);
721 	  }
722       }
723     if (quotient != null)
724       {
725         if (xwords[qlen-1] < 0)
726           {
727             xwords[qlen] = 0;
728             qlen++;
729           }
730 	quotient.set (xwords, qlen);
731 	if (qNegative)
732 	  {
733 	    if (add_one)  // -(quotient + 1) == ~(quotient)
734 	      quotient.setInvert ();
735 	    else
736 	      quotient.setNegative ();
737 	  }
738 	else if (add_one)
739 	  quotient.setAdd (1);
740       }
741     if (remainder != null)
742       {
743 	// The remainder is by definition: X-Q*Y
744 	remainder.set (ywords, rlen);
745 	if (add_one)
746 	  {
747 	    // Subtract the remainder from Y:
748 	    // abs(R) = abs(Y) - abs(orig_rem) = -(abs(orig_rem) - abs(Y)).
749 	    IntNum tmp;
750 	    if (y.words == null)
751 	      {
752 		tmp = remainder;
753 		tmp.set(yNegative ? ywords[0] + y.ival : ywords[0] - y.ival);
754 	      }
755 	    else
756 	      tmp = IntNum.add(remainder, y, yNegative ? 1 : -1);
757 	    // Now tmp <= 0.
758 	    // In this case, abs(Q) = 1 + floor(abs(X)/abs(Y)).
759 	    // Hence, abs(Q*Y) > abs(X).
760 	    // So sign(remainder) = -sign(X).
761 	    if (xNegative)
762 	      remainder.setNegative(tmp);
763 	    else
764 	      remainder.set(tmp);
765 	  }
766 	else
767 	  {
768 	    // If !add_one, then: abs(Q*Y) <= abs(X).
769 	    // So sign(remainder) = sign(X).
770 	    if (xNegative)
771 	      remainder.setNegative ();
772 	  }
773       }
774   }
775 
776   public static IntNum quotient (IntNum x, IntNum y, int rounding_mode)
777   {
778     IntNum quotient = new IntNum ();
779     divide (x, y, quotient, null, rounding_mode);
780     return quotient.canonicalize ();
781   }
782 
783   public static IntNum quotient (IntNum x, IntNum y)
784   {
785     return quotient (x, y, TRUNCATE);
786   }
787 
788   public IntNum toExactInt (int rounding_mode)
789   {
790     return this;
791   }
792 
793   public RealNum toInt (int rounding_mode)
794   {
795     return this;
796   }
797 
798   public static IntNum remainder (IntNum x, IntNum y, int rounding_mode)
799   {
800     if (y.isZero())
801       return x;
802     IntNum rem = new IntNum ();
803     divide (x, y, null, rem, rounding_mode);
804     return rem.canonicalize ();
805   }
806 
807   public static IntNum remainder (IntNum x, IntNum y)
808   {
809     return remainder(x, y, TRUNCATE);
810   }
811 
812   public static IntNum modulo (IntNum x, IntNum y)
813   {
814     return remainder(x, y, FLOOR);
815   }
816 
817   public Numeric power (IntNum y)
818   {
819     if (isOne())
820       return this;
821     if (isMinusOne())
822       return y.isOdd () ? this : IntNum.one ();
823     if (y.words == null && y.ival >= 0)
824       return power (this, y.ival);
825     if (isZero())
826       return y.isNegative () ? RatNum.infinity(-1) : (RatNum) this;
827     return super.power (y);
828   }
829 
830   /** Calculate the integral power of an IntNum.
831    * @param x the value (base) to exponentiate
832    * @param y the exponent (must be non-negative)
833    */
834   public static IntNum power (IntNum x, int y)
835   {
836     if (y <= 0)
837       {
838 	if (y == 0)
839 	  return one ();
840 	else
841 	  throw new IllegalArgumentException("negative exponent");
842       }
843     if (x.isZero ())
844       return x;
845     int plen = x.words == null ? 1 : x.ival;  // Length of pow2.
846     int blen = ((x.intLength () * y) >> 5) + 2 * plen;
847     boolean negative = x.isNegative () && (y & 1) != 0;
848     int[] pow2 = new int [blen];
849     int[] rwords = new int [blen];
850     int[] work = new int [blen];
851     x.getAbsolute (pow2);	// pow2 = abs(x);
852     int rlen = 1;
853     rwords[0] = 1; // rwords = 1;
854     for (;;)  // for (i = 0;  ; i++)
855       {
856 	// pow2 == x**(2**i)
857 	// prod = x**(sum(j=0..i-1, (y>>j)&1))
858 	if ((y & 1) != 0)
859 	  { // r *= pow2
860 	    MPN.mul (work, pow2, plen, rwords, rlen);
861 	    int[] temp = work;  work = rwords;  rwords = temp;
862 	    rlen += plen;
863 	    while (rwords[rlen-1] == 0)  rlen--;
864 	  }
865 	y >>= 1;
866 	if (y == 0)
867 	  break;
868 	// pow2 *= pow2;
869 	MPN.mul (work, pow2, plen, pow2, plen);
870 	int[] temp = work;  work = pow2;  pow2 = temp;  // swap to avoid a copy
871 	plen *= 2;
872 	while (pow2[plen-1] == 0)  plen--;
873       }
874     if (rwords[rlen-1] < 0)
875       rlen++;
876     if (negative)
877       negate (rwords, rwords, rlen);
878     return IntNum.make (rwords, rlen);
879   }
880 
881   /** Calculate Greatest Common Divisor for non-negative ints. */
882   public static final int gcd (int a, int b)
883   {
884     // Euclid's algorithm, copied from libg++.
885     if (b > a)
886       {
887 	int tmp = a; a = b; b = tmp;
888       }
889     for(;;)
890       {
891 	if (b == 0)
892 	  return a;
893 	else if (b == 1)
894 	  return b;
895 	else
896 	  {
897 	    int tmp = b;
898 	    b = a % b;
899 	    a = tmp;
900 	  }
901       }
902   }
903 
904   public static IntNum gcd (IntNum x, IntNum y)
905   {
906     int xval = x.ival;
907     int yval = y.ival;
908     if (x.words == null)
909       {
910 	if (xval == 0)
911 	  return IntNum.abs(y);
912 	if (y.words == null
913 	    && xval != Integer.MIN_VALUE && yval != Integer.MIN_VALUE)
914 	  {
915 	    if (xval < 0)
916 	      xval = -xval;
917 	    if (yval < 0)
918 	      yval = -yval;
919 	    return IntNum.make (IntNum.gcd (xval, yval));
920 	  }
921 	xval = 1;
922       }
923     if (y.words == null)
924       {
925 	if (yval == 0)
926 	  return IntNum.abs(x);
927 	yval = 1;
928       }
929     int len = xval > yval ? xval : yval;
930     int[] xwords = new int[len];
931     int[] ywords = new int[len];
932     x.getAbsolute (xwords);
933     y.getAbsolute (ywords);
934     len = MPN.gcd (xwords, ywords, len);
935     IntNum result = new IntNum (0);
936     // If the high-order bit in the result is set, the number needs one more
937     // word to make the 2^er complement positive.
938     if (xwords[len-1] < 0)
939       xwords[len++] = 0;
940     result.ival = len;
941     result.words = xwords;
942     return result.canonicalize ();
943   }
944 
945   public static IntNum lcm (IntNum x, IntNum y)
946   {
947     if (x.isZero () || y.isZero ())
948       return IntNum.zero ();
949     x = IntNum.abs (x);
950     y = IntNum.abs (y);
951     IntNum quotient = new IntNum ();
952     divide (times (x, y), gcd (x, y), quotient, null, TRUNCATE);
953     return quotient.canonicalize ();
954   }
955 
956   void setInvert ()
957   {
958     if (words == null)
959       ival = ~ival;
960     else
961       {
962 	for (int i = ival;  --i >= 0; )
963 	  words[i] = ~words[i];
964       }
965   }
966 
967   void setShiftLeft (IntNum x, int count)
968   {
969     int[] xwords;
970     int xlen;
971     if (x.words == null)
972       {
973 	if (count < 32)
974 	  {
975 	    set ((long) x.ival << count);
976 	    return;
977 	  }
978 	xwords = new int[1];
979 	xwords[0] = x.ival;
980 	xlen = 1;
981       }
982     else
983       {
984 	xwords = x.words;
985 	xlen = x.ival;
986       }
987     int word_count = count >> 5;
988     count &= 31;
989     int new_len = xlen + word_count;
990     if (count == 0)
991       {
992 	realloc (new_len);
993 	for (int i = xlen;  --i >= 0; )
994 	  words[i+word_count] = xwords[i];
995       }
996     else
997       {
998 	new_len++;
999 	realloc (new_len);
1000 	int shift_out = MPN.lshift (words, word_count, xwords, xlen, count);
1001 	count = 32 - count;
1002 	words[new_len-1] = (shift_out << count) >> count;  // sign-extend.
1003       }
1004     ival = new_len;
1005     for (int i = word_count;  --i >= 0; )
1006       words[i] = 0;
1007   }
1008 
1009   void setShiftRight (IntNum x, int count)
1010   {
1011     if (x.words == null)
1012       set (count < 32 ? x.ival >> count : x.ival < 0 ? -1 : 0);
1013     else if (count == 0)
1014       set (x);
1015     else
1016       {
1017 	boolean neg = x.isNegative ();
1018 	int word_count = count >> 5;
1019 	count &= 31;
1020 	int d_len = x.ival - word_count;
1021 	if (d_len <= 0)
1022 	  set (neg ? -1 : 0);
1023 	else
1024 	  {
1025 	    if (words == null || words.length < d_len)
1026 	      realloc (d_len);
1027 	    MPN.rshift0 (words, x.words, word_count, d_len, count);
1028 	    ival = d_len;
1029 	    if (neg)
1030 	      words[d_len-1] |= -2 << (31 - count);
1031 	  }
1032       }
1033   }
1034 
1035   void setShift (IntNum x, int count)
1036   {
1037     if (count > 0)
1038       setShiftLeft (x, count);
1039     else
1040       setShiftRight (x, -count);
1041   }
1042 
1043   public static IntNum shift (IntNum x, int count)
1044   {
1045     if (x.words == null)
1046       {
1047 	if (count <= 0)
1048 	  return make (count > -32 ? x.ival >> (-count) : x.ival < 0 ? -1 : 0);
1049 	if (count < 32)
1050 	  return make ((long) x.ival << count);
1051       }
1052     if (count == 0)
1053       return x;
1054     IntNum result = new IntNum (0);
1055     result.setShift (x, count);
1056     return result.canonicalize ();
1057   }
1058 
1059   /* #ifdef JAVA5 */
1060   public void format (int radix, StringBuffer buffer)
1061   {
1062     if (radix == 10)
1063       {
1064         if (words == null)
1065           {
1066             buffer.append(ival);
1067             return;
1068           }
1069         else if (ival <= 2)
1070           {
1071             buffer.append(longValue());
1072             return;
1073           }
1074       }
1075     buffer.append(toString(radix));
1076   }
1077   /* #endif */
1078 
1079   public void format (int radix,
1080                       /* #ifdef JAVA5 */
1081                       StringBuilder buffer
1082                       /* #else */
1083                       // StringBuffer buffer
1084                       /* #endif */
1085                       )
1086   {
1087     if (words == null)
1088       {
1089         if (radix == 10)
1090           buffer.append(ival);
1091         else
1092           buffer.append(Integer.toString (ival, radix));
1093       }
1094     else if (ival <= 2)
1095       {
1096         long lval = longValue();
1097         if (radix == 10)
1098           buffer.append(lval);
1099         else
1100           buffer.append(Long.toString (lval, radix));
1101       }
1102     else
1103       {
1104 	boolean neg = isNegative ();
1105 	int[] work;
1106 	if (neg || radix != 16)
1107 	  {
1108 	    work = new int[ival];
1109 	    getAbsolute (work);
1110 	  }
1111 	else
1112 	  work = words;
1113 	int len = ival;
1114 
1115 	if (radix == 16)
1116 	  {
1117 	    if (neg)
1118 	      buffer.append ('-');
1119 	    int buf_start = buffer.length ();
1120 	    for (int i = len;  --i >= 0; )
1121 	      {
1122 		int word = work[i];
1123 		for (int j = 8;  --j >= 0; )
1124 		  {
1125 		    int hex_digit = (word >> (4 * j)) & 0xF;
1126 		    // Suppress leading zeros:
1127 		    if (hex_digit > 0 || buffer.length () > buf_start)
1128 		      buffer.append (Character.forDigit (hex_digit, 16));
1129 		  }
1130 	      }
1131 	  }
1132 	else
1133 	  {
1134             int chars_per_word = MPN.chars_per_word(radix);
1135             int wradix = radix;
1136             for (int j = chars_per_word; --j > 0; )
1137               wradix = wradix * radix;
1138 	    int i = buffer.length();
1139 	    for (;;)
1140 	      {
1141 		int wdigit = MPN.divmod_1(work, work, len, wradix);
1142 		while (len > 0 && work[len-1] == 0) len--;
1143                 for (int j = chars_per_word; --j >= 0; ) {
1144                   int digit;
1145                   if (len == 0 && wdigit == 0)
1146                     break;
1147                   if (wdigit < 0) // Overflow
1148                     {
1149                       long ldigit = (long) wdigit & 0xFFFFFFFF;
1150                       digit = (int)(ldigit % radix);
1151                       wdigit = (int) (wdigit / radix);
1152                     }
1153                   else
1154                     {
1155                       digit = wdigit % radix;
1156                       wdigit = wdigit / radix;
1157                     }
1158                   buffer.append (Character.forDigit(digit, radix));
1159                 }
1160 		if (len == 0)
1161 		  break;
1162 	      }
1163 	    if (neg)
1164 	      buffer.append ('-');
1165 	    /* Reverse buffer. */
1166 	    int j = buffer.length () - 1;
1167 	    while (i < j)
1168 	      {
1169 		char tmp = buffer.charAt (i);
1170 		buffer.setCharAt (i, buffer.charAt (j));
1171 		buffer.setCharAt (j, tmp);
1172 		i++;  j--;
1173 	      }
1174 	  }
1175       }
1176   }
1177 
1178   public String toString (int radix)
1179   {
1180     if (words == null)
1181       return Integer.toString (ival, radix);
1182     else if (ival <= 2)
1183       return Long.toString (longValue (), radix);
1184     int buf_size = ival * (MPN.chars_per_word (radix) + 1);
1185     /* #ifdef JAVA5 */
1186     StringBuilder buffer = new StringBuilder (buf_size);
1187     /* #else */
1188     // StringBuffer buffer = new StringBuffer (buf_size);
1189     /* #endif */
1190     format(radix, buffer);
1191     return buffer.toString ();
1192   }
1193 
1194   public int intValue ()
1195   {
1196     if (words == null)
1197       return ival;
1198     return words[0];
1199   }
1200 
1201   /** Cast an Object to an int.  The Object must (currently) be an IntNum. */
1202   public static int intValue (Object obj)
1203   {
1204     IntNum inum = (IntNum) obj;
1205     if (inum.words != null)
1206       // This is not quite appropriate, but will do.
1207       throw new ClassCastException ("integer too large");
1208     return inum.ival;
1209   }
1210 
1211   public long longValue ()
1212   {
1213     if (words == null)
1214       return ival;
1215     if (ival == 1)
1216       return words[0];
1217     return ((long)words[1] << 32) + ((long)words[0] & 0xffffffffL);
1218   }
1219 
1220   public int hashCode ()
1221   {
1222     return words == null ? ival : (words[0] + words[ival-1]);
1223   }
1224 
1225   /* Assumes x and y are both canonicalized. */
1226   public static boolean equals (IntNum x, IntNum y)
1227   {
1228     if (x.words == null && y.words == null)
1229       return x.ival == y.ival;
1230     if (x.words == null || y.words == null || x.ival != y.ival)
1231       return false;
1232     for (int i = x.ival; --i >= 0; )
1233       {
1234 	if (x.words[i] != y.words[i])
1235 	  return false;
1236       }
1237     return true;
1238   }
1239 
1240   /* Assumes this and obj are both canonicalized. */
1241   public boolean equals (Object obj)
1242   {
1243     if (obj == null || ! (obj instanceof IntNum))
1244       return false;
1245     return IntNum.equals (this, (IntNum) obj);
1246   }
1247 
1248     /** Return a (possibly-shared) IntNum with a given int value. */
1249     public static IntNum make (int value) { return valueOf(value); }
1250 
1251     /** Make an IntNum from an unsigned 64-bit value. */
1252     public static IntNum valueOfUnsigned(long value) {
1253         if (value >= 0)
1254             return valueOf(value);
1255         IntNum result = alloc(3);
1256         result.ival = 3;
1257         result.words[0] = (int) value;
1258         result.words[1] = (int) (value >> 32);
1259         result.words[2] = 0;
1260         return result;
1261     }
1262 
1263     /** Make an IntNum from an unsigned 32-bit value. */
1264     public static IntNum valueOfUnsigned(int value) {
1265         if (value >= 0)
1266             return valueOf(value);
1267         IntNum result = alloc(2);
1268         result.ival = 2;
1269         result.words[0] = value;
1270         result.words[1] = 0;
1271         return result;
1272     }
1273 
1274   /** Make a canonicalized IntNum from an array of words.
1275    * The array may be reused (without copying). */
1276   public static IntNum make (int[] words, int len)
1277   {
1278     if (words == null)
1279       return make (len);
1280     len = IntNum.wordsNeeded (words, len);
1281     if (len <= 1)
1282       return len == 0 ? zero () : make (words[0]);
1283     IntNum num = new IntNum ();
1284     num.words = words;
1285     num.ival = len;
1286     return num;
1287   }
1288 
1289     public static IntNum make(int[] words) {
1290         return make(words, words.length);
1291     }
1292 
1293     public static IntNum make(long value) {
1294         return valueOf(value);
1295     }
1296 
1297     /** Return a (possibly-shared) IntNum with a given int value. */
1298     public static IntNum valueOf(int value) {
1299         if (value >= minFixNum && value <= maxFixNum)
1300             return smallFixNums[(int) value - minFixNum];
1301         else
1302             return new IntNum(value);
1303     }
1304 
1305     /** Return a (possibly-shared) IntNum with a given long value. */
1306     public static IntNum valueOf(long value) {
1307         if (value >= minFixNum && value <= maxFixNum)
1308             return smallFixNums[(int)value - minFixNum];
1309         int i = (int) value;
1310         if ((long)i == value)
1311             return new IntNum (i);
1312         IntNum result = alloc (2);
1313         result.ival = 2;
1314         result.words[0] = i;
1315         result.words[1] = (int) (value >> 32);
1316         return result;
1317     }
1318 
1319   public static IntNum valueOf (char[] buf, int offset, int length,
1320 				int radix, boolean negative)
1321   {
1322     int byte_len = 0;
1323     byte[] bytes = new byte[length];
1324     for (int i = 0;  i < length;  i++)
1325       {
1326 	char ch = buf[offset + i];
1327 	if (ch == '-')
1328 	  negative = true;
1329 	else if (ch == '_' || (byte_len == 0 && (ch == ' ' || ch == '\t')))
1330 	  continue;
1331 	else
1332 	  {
1333 	    int digit = Character.digit(ch, radix);
1334 	    if (digit < 0)
1335 	      break;
1336 	    bytes[byte_len++] = (byte) digit;
1337 	  }
1338       }
1339     return valueOf (bytes, byte_len, negative, radix);
1340   }
1341 
1342   public static IntNum valueOf (String s, int radix)
1343        throws NumberFormatException
1344   {
1345     int len = s.length ();
1346     // Testing (len < 2 * MPN.chars_per_word(radix)) would be more accurate,
1347     // but slightly more expensive, for little practical gain.
1348     if (len + radix <= 28)
1349       {
1350         /* #ifndef JAVA7 */
1351         // if (len > 1 && s.charAt(0) == '+'
1352         //     && Character.digit(s.charAt(1), radix) >= 0)
1353         //   s = s.substring(1);
1354         /* #endif */
1355         return IntNum.make (Long.parseLong (s, radix));
1356       }
1357 
1358     int byte_len = 0;
1359     byte[] bytes = new byte[len];
1360     boolean negative = false;
1361     for (int i = 0;  i < len;  i++)
1362       {
1363 	char ch = s.charAt (i);
1364 	if (ch == '-' && i == 0)
1365 	  negative = true;
1366 	else if (ch == '+' && i == 0)
1367           ; // ignore
1368 	else if (ch == '_' || (byte_len == 0 && (ch == ' ' || ch == '\t')))
1369 	  continue;
1370 	else
1371 	  {
1372 	    int digit = Character.digit (ch, radix);
1373 	    if (digit < 0)
1374 	      throw new NumberFormatException("For input string: \""+s+'"');
1375 	    bytes[byte_len++] = (byte) digit;
1376 	  }
1377       }
1378     return valueOf (bytes, byte_len, negative, radix);
1379   }
1380 
1381   public static IntNum valueOf (byte[] digits, int byte_len,
1382 				boolean negative, int radix)
1383   {
1384     int chars_per_word = MPN.chars_per_word(radix);
1385     int[] words = new int[byte_len / chars_per_word + 1];
1386     int size = MPN.set_str(words, digits, byte_len, radix);
1387     if (size == 0)
1388       return zero();
1389     if (words[size-1] < 0)
1390       words[size++] = 0;
1391     if (negative)
1392       negate (words, words, size);
1393     return make (words, size);
1394   }
1395 
1396   public static IntNum valueOf (String s)
1397        throws NumberFormatException
1398   {
1399     return IntNum.valueOf (s, 10);
1400   }
1401 
1402   public double doubleValue ()
1403   {
1404     if (words == null)
1405       return (double) ival;
1406     if (ival <= 2)
1407       return (double) longValue ();
1408     if (isNegative ())
1409       return IntNum.neg (this).roundToDouble (0, true, false);
1410     else
1411       return roundToDouble (0, false, false);
1412   }
1413 
1414   /** Return true if any of the lowest n bits are one.
1415    * (false if n is negative).  */
1416   boolean checkBits (int n)
1417   {
1418     if (n <= 0)
1419       return false;
1420     if (words == null)
1421       return n > 31 || ((ival & ((1 << n) - 1)) != 0);
1422     int i;
1423     for (i = 0; i < (n >> 5) ; i++)
1424       if (words[i] != 0)
1425 	return true;
1426     return (n & 31) != 0 && (words[i] & ((1 << (n & 31)) - 1)) != 0;
1427   }
1428 
1429   /** Convert a semi-processed IntNum to double.
1430    * Number must be non-negative.  Multiplies by a power of two, applies sign,
1431    * and converts to double, with the usual java rounding.
1432    * @param exp power of two, positive or negative, by which to multiply
1433    * @param neg true if negative
1434    * @param remainder true if the IntNum is the result of a truncating
1435    * division that had non-zero remainder.  To ensure proper rounding in
1436    * this case, the IntNum must have at least 54 bits.  */
1437   public double roundToDouble (int exp, boolean neg, boolean remainder)
1438   {
1439     // Compute length.
1440     int il = intLength();
1441 
1442     // Exponent when normalized to have decimal point directly after
1443     // leading one.  This is stored excess 1023 in the exponent bit field.
1444     exp += il - 1;
1445 
1446     // Gross underflow.  If exp == -1075, we let the rounding
1447     // computation determine whether it is minval or 0 (which are just
1448     // 0x0000 0000 0000 0001 and 0x0000 0000 0000 0000 as bit
1449     // patterns).
1450     if (exp < -1075)
1451       return neg ? -0.0 : 0.0;
1452 
1453     // gross overflow
1454     if (exp > 1023)
1455       return neg ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
1456 
1457     // number of bits in mantissa, including the leading one.
1458     // 53 unless it's denormalized
1459     int ml = (exp >= -1022 ? 53 : 53 + exp + 1022);
1460 
1461     // Get top ml + 1 bits.  The extra one is for rounding.
1462     long m;
1463     int excess_bits = il - (ml + 1);
1464     if (excess_bits > 0)
1465       m = ((words == null) ? ival >> excess_bits
1466 	   : MPN.rshift_long (words, ival, excess_bits));
1467     else
1468       m = longValue () << (- excess_bits);
1469 
1470     // Special rounding for maxval.  If the number exceeds maxval by
1471     // any amount, even if it's less than half a step, it overflows.
1472     if (exp == 1023 && ((m >> 1) == (1L << 53) - 1))
1473       {
1474 	if (remainder || checkBits (il - ml))
1475 	  return neg ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
1476 	else
1477 	  return neg ? - Double.MAX_VALUE : Double.MAX_VALUE;
1478       }
1479 
1480     // Normal round-to-even rule: round up if the bit dropped is a one, and
1481     // the bit above it or any of the bits below it is a one.
1482     if ((m & 1) == 1
1483 	&& ((m & 2) == 2 || remainder || checkBits (excess_bits)))
1484       {
1485 	m += 2;
1486 	// Check if we overflowed the mantissa
1487 	if ((m & (1L << 54)) != 0)
1488 	  {
1489 	    exp++;
1490 	    // renormalize
1491 	    m >>= 1;
1492 	  }
1493 	// Check if a denormalized mantissa was just rounded up to a
1494 	// normalized one.
1495 	else if (ml == 52 && (m & (1L << 53)) != 0)
1496 	  exp++;
1497       }
1498 
1499     // Discard the rounding bit
1500     m >>= 1;
1501 
1502     long bits_sign = neg ? (1L << 63) : 0;
1503     exp += 1023;
1504     long bits_exp = (exp <= 0) ? 0 : ((long)exp) << 52;
1505     long bits_mant = m & ~(1L << 52);
1506     return Double.longBitsToDouble (bits_sign | bits_exp | bits_mant);
1507   }
1508 
1509 
1510   public Numeric add (Object y, int k)
1511   {
1512     if (y instanceof IntNum)
1513       return IntNum.add (this, (IntNum) y, k);
1514     if (!(y instanceof Numeric))
1515       throw new IllegalArgumentException ();
1516     return ((Numeric)y).addReversed (this, k);
1517   }
1518 
1519   public Numeric mul (Object y)
1520   {
1521     if (y instanceof IntNum)
1522       return IntNum.times (this, (IntNum) y);
1523     if (!(y instanceof Numeric))
1524       throw new IllegalArgumentException ();
1525     return ((Numeric)y).mulReversed (this);
1526   }
1527 
1528   public Numeric div (Object y)
1529   {
1530     if (y instanceof RatNum)
1531       {
1532 	RatNum r = (RatNum) y;
1533 	return RatNum.make (IntNum.times (this, r.denominator()),
1534 			    r.numerator());
1535       }
1536     if (! (y instanceof Numeric))
1537       throw new IllegalArgumentException ();
1538     return ((Numeric)y).divReversed (this);
1539   }
1540 
1541   /** Copy the abolute value of this into an array of words.
1542    * Assumes {@code words.length >= (this.words == null ? 1 : this.ival)}.
1543    * Result is zero-extended, but need not be a valid 2's complement number.
1544    */
1545 
1546   public void getAbsolute (int[] words)
1547   {
1548     int len;
1549     if (this.words == null)
1550       {
1551 	len = 1;
1552 	words[0] = this.ival;
1553       }
1554     else
1555       {
1556 	len = this.ival;
1557 	for (int i = len;  --i >= 0; )
1558 	  words[i] = this.words[i];
1559       }
1560     if (words[len-1] < 0)
1561       negate (words, words, len);
1562     for (int i = words.length;  --i > len; )
1563       words[i] = 0;
1564   }
1565 
1566   /** Set dest[0:len-1] to the negation of src[0:len-1].
1567    * Return true if overflow (i.e. if src is -2**(32*len-1)).
1568    * Ok for src==dest. */
1569   public static boolean negate (int[] dest, int[] src, int len)
1570   {
1571     long carry = 1;
1572     boolean negative = src[len-1] < 0;
1573     for (int i = 0;  i < len;  i++)
1574       {
1575         carry += ((long) (~src[i]) & 0xffffffffL);
1576         dest[i] = (int) carry;
1577         carry >>= 32;
1578       }
1579     return (negative && dest[len-1] < 0);
1580   }
1581 
1582   /** Destructively set this to the negative of x.
1583    * It is OK if x==this.*/
1584   public void setNegative (IntNum x)
1585   {
1586     int len = x.ival;
1587     if (x.words == null)
1588       {
1589 	if (len == Integer.MIN_VALUE)
1590 	  set (- (long) len);
1591 	else
1592 	  set (-len);
1593 	return;
1594       }
1595     realloc (len + 1);
1596     if (IntNum.negate (words, x.words, len))
1597       words[len++] = 0;
1598     ival = len;
1599   }
1600 
1601   /** Destructively negate this. */
1602   public final void setNegative ()
1603   {
1604     setNegative (this);
1605   }
1606 
1607   public static IntNum abs (IntNum x)
1608   {
1609     return x.isNegative () ? neg (x) : x;
1610   }
1611 
1612   public static IntNum neg (IntNum x)
1613   {
1614     if (x.words == null && x.ival != Integer.MIN_VALUE)
1615       return make (- x.ival);
1616     IntNum result = new IntNum (0);
1617     result.setNegative (x);
1618     return result.canonicalize ();
1619   }
1620 
1621   public Numeric neg ()
1622   {
1623     return IntNum.neg (this);
1624   }
1625 
1626   /** Calculates {@code ceiling(log2(this < 0 ? -this : this+1))}.
1627    * See Common Lisp: the Language, 2nd ed, p. 361.
1628    */
1629   public int intLength ()
1630   {
1631     if (words == null)
1632       return MPN.intLength (ival);
1633     else
1634       return MPN.intLength (words, ival);
1635   }
1636 
1637   /**
1638    * @serialData If the value is in the range (int)0xC0000000 .. 0x7fffffff
1639    * (inclusive) write out the value (using writeInt).
1640    * Otherwise, write (using writeInt) (0x80000000|nwords), where nwords is
1641    * the number of words following.  The words are the minimal
1642    * 2's complement big-endian representation of the value, written using
1643    * writeint.
1644    * (Even if the current value is not canonicalized, the output is).
1645    */
1646   public void writeExternal(ObjectOutput out) throws IOException
1647   {
1648     int nwords = words == null ? 1 : wordsNeeded(words, ival);
1649     if (nwords <= 1)
1650       {
1651 	int i = words == null ? ival : words.length == 0 ? 0 : words[0];
1652 	if (i >= (int)0xC0000000)
1653 	  out.writeInt(i);
1654 	else
1655 	  {
1656 	    out.writeInt(0x80000001);
1657 	    out.writeInt(i);
1658 	  }
1659       }
1660     else
1661       {
1662 	out.writeInt(0x80000000|nwords);
1663 	while (--nwords >= 0)
1664 	  out.writeInt(words[nwords]);
1665       }
1666 
1667   }
1668 
1669   public void readExternal(ObjectInput in)
1670     throws IOException, ClassNotFoundException
1671   {
1672     int i = in.readInt();
1673     if (i <= (int) 0xC0000000)
1674       {
1675 	i &= 0x7fffffff;
1676 	if (i == 1)
1677 	  i = in.readInt();
1678 	else
1679 	  {
1680 	    int[] w = new int[i];
1681 	    for (int j = i;  --j >= 0; )
1682 	      w[j] = in.readInt();
1683 	    words = w;
1684 	  }
1685       }
1686     ival = i;
1687   }
1688 
1689   public Object readResolve() throws ObjectStreamException
1690   {
1691     return canonicalize();
1692   }
1693 
1694   public BigInteger asBigInteger ()
1695   {
1696     if (words == null || ival <= 2)
1697       return BigInteger.valueOf(longValue());
1698     return new BigInteger(toString());
1699   }
1700 
1701   public BigDecimal asBigDecimal ()
1702   {
1703     if (words == null)
1704       return new BigDecimal(ival);
1705     if (ival <= 2)
1706       return BigDecimal.valueOf(longValue());
1707     return new BigDecimal(toString());
1708   }
1709 
1710   /** Is this integer both {@code >= lo} and {@code <= hi}?. */
1711   public boolean inRange (long lo, long hi)
1712   {
1713     return compare(this, lo) >= 0 && compare(this, hi) <= 0;
1714   }
1715 
1716   /** Does this value fit in a signed 32-bit {@code int}? */
1717   public boolean inIntRange ()
1718   {
1719     return inRange(Integer.MIN_VALUE, Integer.MAX_VALUE);
1720   }
1721 
1722   /** Does this value fit in a signed 64-bit {@code long}? */
1723   public boolean inLongRange ()
1724   {
1725     return inRange(Long.MIN_VALUE, Long.MAX_VALUE);
1726   }
1727 
1728 }
1729