1:
37:
38:
39:
40:
41: package ;
42:
43:
49:
50: public class MPN
51: {
52:
57: public static int add_1 (int[] dest, int[] x, int size, int y)
58: {
59: long carry = (long) y & 0xffffffffL;
60: for (int i = 0; i < size; i++)
61: {
62: carry += ((long) x[i] & 0xffffffffL);
63: dest[i] = (int) carry;
64: carry >>= 32;
65: }
66: return (int) carry;
67: }
68:
69:
75: public static int add_n (int dest[], int[] x, int[] y, int len)
76: {
77: long carry = 0;
78: for (int i = 0; i < len; i++)
79: {
80: carry += ((long) x[i] & 0xffffffffL)
81: + ((long) y[i] & 0xffffffffL);
82: dest[i] = (int) carry;
83: carry >>>= 32;
84: }
85: return (int) carry;
86: }
87:
88:
93:
94: public static int sub_n (int[] dest, int[] X, int[] Y, int size)
95: {
96: int cy = 0;
97: for (int i = 0; i < size; i++)
98: {
99: int y = Y[i];
100: int x = X[i];
101: y += cy;
102:
103:
104: cy = (y^0x80000000) < (cy^0x80000000) ? 1 : 0;
105: y = x - y;
106: cy += (y^0x80000000) > (x ^ 0x80000000) ? 1 : 0;
107: dest[i] = y;
108: }
109: return cy;
110: }
111:
112:
120:
121: public static int mul_1 (int[] dest, int[] x, int len, int y)
122: {
123: long yword = (long) y & 0xffffffffL;
124: long carry = 0;
125: for (int j = 0; j < len; j++)
126: {
127: carry += ((long) x[j] & 0xffffffffL) * yword;
128: dest[j] = (int) carry;
129: carry >>>= 32;
130: }
131: return (int) carry;
132: }
133:
134:
143:
144: public static void mul (int[] dest,
145: int[] x, int xlen,
146: int[] y, int ylen)
147: {
148: dest[xlen] = MPN.mul_1 (dest, x, xlen, y[0]);
149:
150: for (int i = 1; i < ylen; i++)
151: {
152: long yword = (long) y[i] & 0xffffffffL;
153: long carry = 0;
154: for (int j = 0; j < xlen; j++)
155: {
156: carry += ((long) x[j] & 0xffffffffL) * yword
157: + ((long) dest[i+j] & 0xffffffffL);
158: dest[i+j] = (int) carry;
159: carry >>>= 32;
160: }
161: dest[i+xlen] = (int) carry;
162: }
163: }
164:
165:
170: public static long udiv_qrnnd (long N, int D)
171: {
172: long q, r;
173: long a1 = N >>> 32;
174: long a0 = N & 0xffffffffL;
175: if (D >= 0)
176: {
177: if (a1 < ((D - a1 - (a0 >>> 31)) & 0xffffffffL))
178: {
179:
180: q = N / D;
181: r = N % D;
182: }
183: else
184: {
185:
186: long c = N - ((long) D << 31);
187:
188: q = c / D;
189: r = c % D;
190:
191: q += 1 << 31;
192: }
193: }
194: else
195: {
196: long b1 = D >>> 1;
197:
198:
199: long c = N >>> 1;
200: if (a1 < b1 || (a1 >> 1) < b1)
201: {
202: if (a1 < b1)
203: {
204: q = c / b1;
205: r = c % b1;
206: }
207: else
208: {
209: c = ~(c - (b1 << 32));
210: q = c / b1;
211: r = c % b1;
212: q = (~q) & 0xffffffffL;
213: r = (b1 - 1) - r;
214: }
215: r = 2 * r + (a0 & 1);
216: if ((D & 1) != 0)
217: {
218: if (r >= q) {
219: r = r - q;
220: } else if (q - r <= ((long) D & 0xffffffffL)) {
221: r = r - q + D;
222: q -= 1;
223: } else {
224: r = r - q + D + D;
225: q -= 2;
226: }
227: }
228: }
229: else
230: {
231: if (a0 >= ((long)(-D) & 0xffffffffL))
232: {
233: q = -1;
234: r = a0 + D;
235: }
236: else
237: {
238: q = -2;
239: r = a0 + D + D;
240: }
241: }
242: }
243:
244: return (r << 32) | (q & 0xFFFFFFFFl);
245: }
246:
247:
252:
253: public static int divmod_1 (int[] quotient, int[] dividend,
254: int len, int divisor)
255: {
256: int i = len - 1;
257: long r = dividend[i];
258: if ((r & 0xffffffffL) >= ((long)divisor & 0xffffffffL))
259: r = 0;
260: else
261: {
262: quotient[i--] = 0;
263: r <<= 32;
264: }
265:
266: for (; i >= 0; i--)
267: {
268: int n0 = dividend[i];
269: r = (r & ~0xffffffffL) | (n0 & 0xffffffffL);
270: r = udiv_qrnnd (r, divisor);
271: quotient[i] = (int) r;
272: }
273: return (int)(r >> 32);
274: }
275:
276:
281: public static int submul_1 (int[] dest, int offset, int[] x, int len, int y)
282: {
283: long yl = (long) y & 0xffffffffL;
284: int carry = 0;
285: int j = 0;
286: do
287: {
288: long prod = ((long) x[j] & 0xffffffffL) * yl;
289: int prod_low = (int) prod;
290: int prod_high = (int) (prod >> 32);
291: prod_low += carry;
292:
293:
294: carry = ((prod_low ^ 0x80000000) < (carry ^ 0x80000000) ? 1 : 0)
295: + prod_high;
296: int x_j = dest[offset+j];
297: prod_low = x_j - prod_low;
298: if ((prod_low ^ 0x80000000) > (x_j ^ 0x80000000))
299: carry++;
300: dest[offset+j] = prod_low;
301: }
302: while (++j < len);
303: return carry;
304: }
305:
306:
312:
313: public static void divide (int[] zds, int nx, int[] y, int ny)
314: {
315:
316:
317:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328: int j = nx;
329: do
330: {
331:
332:
333: int qhat;
334: if (zds[j]==y[ny-1])
335: qhat = -1;
336: else
337: {
338: long w = (((long)(zds[j])) << 32) + ((long)zds[j-1] & 0xffffffffL);
339: qhat = (int) udiv_qrnnd (w, y[ny-1]);
340: }
341: if (qhat != 0)
342: {
343: int borrow = submul_1 (zds, j - ny, y, ny, qhat);
344: int save = zds[j];
345: long num = ((long)save&0xffffffffL) - ((long)borrow&0xffffffffL);
346: while (num != 0)
347: {
348: qhat--;
349: long carry = 0;
350: for (int i = 0; i < ny; i++)
351: {
352: carry += ((long) zds[j-ny+i] & 0xffffffffL)
353: + ((long) y[i] & 0xffffffffL);
354: zds[j-ny+i] = (int) carry;
355: carry >>>= 32;
356: }
357: zds[j] += carry;
358: num = carry - 1;
359: }
360: }
361: zds[j] = qhat;
362: } while (--j >= ny);
363: }
364:
365:
371: public static int chars_per_word (int radix)
372: {
373: if (radix < 10)
374: {
375: if (radix < 8)
376: {
377: if (radix <= 2)
378: return 32;
379: else if (radix == 3)
380: return 20;
381: else if (radix == 4)
382: return 16;
383: else
384: return 18 - radix;
385: }
386: else
387: return 10;
388: }
389: else if (radix < 12)
390: return 9;
391: else if (radix <= 16)
392: return 8;
393: else if (radix <= 23)
394: return 7;
395: else if (radix <= 40)
396: return 6;
397:
398: else if (radix <= 256)
399: return 4;
400: else
401: return 1;
402: }
403:
404:
405: public static int count_leading_zeros (int i)
406: {
407: if (i == 0)
408: return 32;
409: int count = 0;
410: for (int k = 16; k > 0; k = k >> 1) {
411: int j = i >>> k;
412: if (j == 0)
413: count += k;
414: else
415: i = j;
416: }
417: return count;
418: }
419:
420: public static int set_str (int dest[], byte[] str, int str_len, int base)
421: {
422: int size = 0;
423: if ((base & (base - 1)) == 0)
424: {
425:
426:
427:
428: int next_bitpos = 0;
429: int bits_per_indigit = 0;
430: for (int i = base; (i >>= 1) != 0; ) bits_per_indigit++;
431: int res_digit = 0;
432:
433: for (int i = str_len; --i >= 0; )
434: {
435: int inp_digit = str[i];
436: res_digit |= inp_digit << next_bitpos;
437: next_bitpos += bits_per_indigit;
438: if (next_bitpos >= 32)
439: {
440: dest[size++] = res_digit;
441: next_bitpos -= 32;
442: res_digit = inp_digit >> (bits_per_indigit - next_bitpos);
443: }
444: }
445:
446: if (res_digit != 0)
447: dest[size++] = res_digit;
448: }
449: else
450: {
451:
452: int indigits_per_limb = MPN.chars_per_word (base);
453: int str_pos = 0;
454:
455: while (str_pos < str_len)
456: {
457: int chunk = str_len - str_pos;
458: if (chunk > indigits_per_limb)
459: chunk = indigits_per_limb;
460: int res_digit = str[str_pos++];
461: int big_base = base;
462:
463: while (--chunk > 0)
464: {
465: res_digit = res_digit * base + str[str_pos++];
466: big_base *= base;
467: }
468:
469: int cy_limb;
470: if (size == 0)
471: cy_limb = res_digit;
472: else
473: {
474: cy_limb = MPN.mul_1 (dest, dest, size, big_base);
475: cy_limb += MPN.add_1 (dest, dest, size, res_digit);
476: }
477: if (cy_limb != 0)
478: dest[size++] = cy_limb;
479: }
480: }
481: return size;
482: }
483:
484:
488: public static int cmp (int[] x, int[] y, int size)
489: {
490: while (--size >= 0)
491: {
492: int x_word = x[size];
493: int y_word = y[size];
494: if (x_word != y_word)
495: {
496:
497:
498:
499: return (x_word ^ 0x80000000) > (y_word ^0x80000000) ? 1 : -1;
500: }
501: }
502: return 0;
503: }
504:
505:
510: public static int cmp (int[] x, int xlen, int[] y, int ylen)
511: {
512: return xlen > ylen ? 1 : xlen < ylen ? -1 : cmp (x, y, xlen);
513: }
514:
515:
523: public static int rshift (int[] dest, int[] x, int x_start,
524: int len, int count)
525: {
526: int count_2 = 32 - count;
527: int low_word = x[x_start];
528: int retval = low_word << count_2;
529: int i = 1;
530: for (; i < len; i++)
531: {
532: int high_word = x[x_start+i];
533: dest[i-1] = (low_word >>> count) | (high_word << count_2);
534: low_word = high_word;
535: }
536: dest[i-1] = low_word >>> count;
537: return retval;
538: }
539:
540:
548: public static void rshift0 (int[] dest, int[] x, int x_start,
549: int len, int count)
550: {
551: if (count > 0)
552: rshift(dest, x, x_start, len, count);
553: else
554: for (int i = 0; i < len; i++)
555: dest[i] = x[i + x_start];
556: }
557:
558:
564: public static long rshift_long (int[] x, int len, int count)
565: {
566: int wordno = count >> 5;
567: count &= 31;
568: int sign = x[len-1] < 0 ? -1 : 0;
569: int w0 = wordno >= len ? sign : x[wordno];
570: wordno++;
571: int w1 = wordno >= len ? sign : x[wordno];
572: if (count != 0)
573: {
574: wordno++;
575: int w2 = wordno >= len ? sign : x[wordno];
576: w0 = (w0 >>> count) | (w1 << (32-count));
577: w1 = (w1 >>> count) | (w2 << (32-count));
578: }
579: return ((long)w1 << 32) | ((long)w0 & 0xffffffffL);
580: }
581:
582:
588:
589: public static int lshift (int[] dest, int d_offset,
590: int[] x, int len, int count)
591: {
592: int count_2 = 32 - count;
593: int i = len - 1;
594: int high_word = x[i];
595: int retval = high_word >>> count_2;
596: d_offset++;
597: while (--i >= 0)
598: {
599: int low_word = x[i];
600: dest[d_offset+i] = (high_word << count) | (low_word >>> count_2);
601: high_word = low_word;
602: }
603: dest[d_offset+i] = high_word << count;
604: return retval;
605: }
606:
607:
608:
609: public static int findLowestBit (int word)
610: {
611: int i = 0;
612: while ((word & 0xF) == 0)
613: {
614: word >>= 4;
615: i += 4;
616: }
617: if ((word & 3) == 0)
618: {
619: word >>= 2;
620: i += 2;
621: }
622: if ((word & 1) == 0)
623: i += 1;
624: return i;
625: }
626:
627:
628:
629: public static int findLowestBit (int[] words)
630: {
631: for (int i = 0; ; i++)
632: {
633: if (words[i] != 0)
634: return 32 * i + findLowestBit (words[i]);
635: }
636: }
637:
638:
642:
643: public static int gcd (int[] x, int[] y, int len)
644: {
645: int i, word;
646:
647: for (i = 0; ; i++)
648: {
649: word = x[i] | y[i];
650: if (word != 0)
651: {
652:
653: break;
654: }
655: }
656: int initShiftWords = i;
657: int initShiftBits = findLowestBit (word);
658:
659:
660:
661: len -= initShiftWords;
662: MPN.rshift0 (x, x, initShiftWords, len, initShiftBits);
663: MPN.rshift0 (y, y, initShiftWords, len, initShiftBits);
664:
665: int[] odd_arg;
666: int[] other_arg;
667: if ((x[0] & 1) != 0)
668: {
669: odd_arg = x;
670: other_arg = y;
671: }
672: else
673: {
674: odd_arg = y;
675: other_arg = x;
676: }
677:
678: for (;;)
679: {
680:
681:
682:
683: for (i = 0; other_arg[i] == 0; ) i++;
684: if (i > 0)
685: {
686: int j;
687: for (j = 0; j < len-i; j++)
688: other_arg[j] = other_arg[j+i];
689: for ( ; j < len; j++)
690: other_arg[j] = 0;
691: }
692: i = findLowestBit(other_arg[0]);
693: if (i > 0)
694: MPN.rshift (other_arg, other_arg, 0, len, i);
695:
696:
697:
698:
699:
700: i = MPN.cmp(odd_arg, other_arg, len);
701: if (i == 0)
702: break;
703: if (i > 0)
704: {
705: MPN.sub_n (odd_arg, odd_arg, other_arg, len);
706:
707: int[] tmp = odd_arg; odd_arg = other_arg; other_arg = tmp;
708: }
709: else
710: {
711: MPN.sub_n (other_arg, other_arg, odd_arg, len);
712: }
713: while (odd_arg[len-1] == 0 && other_arg[len-1] == 0)
714: len--;
715: }
716: if (initShiftWords + initShiftBits > 0)
717: {
718: if (initShiftBits > 0)
719: {
720: int sh_out = MPN.lshift (x, initShiftWords, x, len, initShiftBits);
721: if (sh_out != 0)
722: x[(len++)+initShiftWords] = sh_out;
723: }
724: else
725: {
726: for (i = len; --i >= 0;)
727: x[i+initShiftWords] = x[i];
728: }
729: for (i = initShiftWords; --i >= 0; )
730: x[i] = 0;
731: len += initShiftWords;
732: }
733: return len;
734: }
735:
736: public static int intLength (int i)
737: {
738: return 32 - count_leading_zeros (i < 0 ? ~i : i);
739: }
740:
741:
743: public static int intLength (int[] words, int len)
744: {
745: len--;
746: return intLength (words[len]) + 32 * len;
747: }
748:
749:
771: }