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