Source file
src/math/big/nat.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14 package big
15
16 import (
17 "internal/byteorder"
18 "math/bits"
19 "math/rand"
20 "sync"
21 )
22
23
24
25
26
27
28
29
30
31
32
33
34 type nat []Word
35
36 var (
37 natOne = nat{1}
38 natTwo = nat{2}
39 natFive = nat{5}
40 natTen = nat{10}
41 )
42
43 func (z nat) String() string {
44 return "0x" + string(z.itoa(false, 16))
45 }
46
47 func (z nat) norm() nat {
48 i := len(z)
49 for i > 0 && z[i-1] == 0 {
50 i--
51 }
52 return z[0:i]
53 }
54
55 func (z nat) make(n int) nat {
56 if n <= cap(z) {
57 return z[:n]
58 }
59 if n == 1 {
60
61 return make(nat, 1)
62 }
63
64
65 const e = 4
66 return make(nat, n, n+e)
67 }
68
69 func (z nat) setWord(x Word) nat {
70 if x == 0 {
71 return z[:0]
72 }
73 z = z.make(1)
74 z[0] = x
75 return z
76 }
77
78 func (z nat) setUint64(x uint64) nat {
79
80 if w := Word(x); uint64(w) == x {
81 return z.setWord(w)
82 }
83
84 z = z.make(2)
85 z[1] = Word(x >> 32)
86 z[0] = Word(x)
87 return z
88 }
89
90 func (z nat) set(x nat) nat {
91 z = z.make(len(x))
92 copy(z, x)
93 return z
94 }
95
96 func (z nat) add(x, y nat) nat {
97 m := len(x)
98 n := len(y)
99
100 switch {
101 case m < n:
102 return z.add(y, x)
103 case m == 0:
104
105 return z[:0]
106 case n == 0:
107
108 return z.set(x)
109 }
110
111
112 z = z.make(m + 1)
113 c := addVV(z[0:n], x, y)
114 if m > n {
115 c = addVW(z[n:m], x[n:], c)
116 }
117 z[m] = c
118
119 return z.norm()
120 }
121
122 func (z nat) sub(x, y nat) nat {
123 m := len(x)
124 n := len(y)
125
126 switch {
127 case m < n:
128 panic("underflow")
129 case m == 0:
130
131 return z[:0]
132 case n == 0:
133
134 return z.set(x)
135 }
136
137
138 z = z.make(m)
139 c := subVV(z[0:n], x, y)
140 if m > n {
141 c = subVW(z[n:], x[n:], c)
142 }
143 if c != 0 {
144 panic("underflow")
145 }
146
147 return z.norm()
148 }
149
150 func (x nat) cmp(y nat) (r int) {
151 m := len(x)
152 n := len(y)
153 if m != n || m == 0 {
154 switch {
155 case m < n:
156 r = -1
157 case m > n:
158 r = 1
159 }
160 return
161 }
162
163 i := m - 1
164 for i > 0 && x[i] == y[i] {
165 i--
166 }
167
168 switch {
169 case x[i] < y[i]:
170 r = -1
171 case x[i] > y[i]:
172 r = 1
173 }
174 return
175 }
176
177 func (z nat) mulAddWW(x nat, y, r Word) nat {
178 m := len(x)
179 if m == 0 || y == 0 {
180 return z.setWord(r)
181 }
182
183
184 z = z.make(m + 1)
185 z[m] = mulAddVWW(z[0:m], x, y, r)
186
187 return z.norm()
188 }
189
190
191
192 func basicMul(z, x, y nat) {
193 clear(z[0 : len(x)+len(y)])
194 for i, d := range y {
195 if d != 0 {
196 z[len(x)+i] = addMulVVW(z[i:i+len(x)], x, d)
197 }
198 }
199 }
200
201
202
203
204
205
206
207
208
209
210 func (z nat) montgomery(x, y, m nat, k Word, n int) nat {
211
212
213
214
215 if len(x) != n || len(y) != n || len(m) != n {
216 panic("math/big: mismatched montgomery number lengths")
217 }
218 z = z.make(n * 2)
219 clear(z)
220 var c Word
221 for i := 0; i < n; i++ {
222 d := y[i]
223 c2 := addMulVVW(z[i:n+i], x, d)
224 t := z[i] * k
225 c3 := addMulVVW(z[i:n+i], m, t)
226 cx := c + c2
227 cy := cx + c3
228 z[n+i] = cy
229 if cx < c2 || cy < c3 {
230 c = 1
231 } else {
232 c = 0
233 }
234 }
235 if c != 0 {
236 subVV(z[:n], z[n:], m)
237 } else {
238 copy(z[:n], z[n:])
239 }
240 return z[:n]
241 }
242
243
244
245 func karatsubaAdd(z, x nat, n int) {
246 if c := addVV(z[0:n], z, x); c != 0 {
247 addVW(z[n:n+n>>1], z[n:], c)
248 }
249 }
250
251
252 func karatsubaSub(z, x nat, n int) {
253 if c := subVV(z[0:n], z, x); c != 0 {
254 subVW(z[n:n+n>>1], z[n:], c)
255 }
256 }
257
258
259
260
261 var karatsubaThreshold = 40
262
263
264
265
266
267 func karatsuba(z, x, y nat) {
268 n := len(y)
269
270
271
272
273 if n&1 != 0 || n < karatsubaThreshold || n < 2 {
274 basicMul(z, x, y)
275 return
276 }
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303 n2 := n >> 1
304 x1, x0 := x[n2:], x[0:n2]
305 y1, y0 := y[n2:], y[0:n2]
306
307
308
309
310
311
312
313
314
315
316
317 karatsuba(z, x0, y0)
318 karatsuba(z[n:], x1, y1)
319
320
321 s := 1
322 xd := z[2*n : 2*n+n2]
323 if subVV(xd, x1, x0) != 0 {
324 s = -s
325 subVV(xd, x0, x1)
326 }
327
328
329 yd := z[2*n+n2 : 3*n]
330 if subVV(yd, y0, y1) != 0 {
331 s = -s
332 subVV(yd, y1, y0)
333 }
334
335
336
337 p := z[n*3:]
338 karatsuba(p, xd, yd)
339
340
341
342 r := z[n*4:]
343 copy(r, z[:n*2])
344
345
346
347
348
349
350
351
352
353 karatsubaAdd(z[n2:], r, n)
354 karatsubaAdd(z[n2:], r[n:], n)
355 if s > 0 {
356 karatsubaAdd(z[n2:], p, n)
357 } else {
358 karatsubaSub(z[n2:], p, n)
359 }
360 }
361
362
363
364
365
366
367
368 func alias(x, y nat) bool {
369 return cap(x) > 0 && cap(y) > 0 && &x[0:cap(x)][cap(x)-1] == &y[0:cap(y)][cap(y)-1]
370 }
371
372
373
374
375 func addAt(z, x nat, i int) {
376 if n := len(x); n > 0 {
377 if c := addVV(z[i:i+n], z[i:], x); c != 0 {
378 j := i + n
379 if j < len(z) {
380 addVW(z[j:], z[j:], c)
381 }
382 }
383 }
384 }
385
386
387
388
389
390 func karatsubaLen(n, threshold int) int {
391 i := uint(0)
392 for n > threshold {
393 n >>= 1
394 i++
395 }
396 return n << i
397 }
398
399 func (z nat) mul(x, y nat) nat {
400 m := len(x)
401 n := len(y)
402
403 switch {
404 case m < n:
405 return z.mul(y, x)
406 case m == 0 || n == 0:
407 return z[:0]
408 case n == 1:
409 return z.mulAddWW(x, y[0], 0)
410 }
411
412
413
414 if alias(z, x) || alias(z, y) {
415 z = nil
416 }
417
418
419 if n < karatsubaThreshold {
420 z = z.make(m + n)
421 basicMul(z, x, y)
422 return z.norm()
423 }
424
425
426
427
428
429
430
431
432 k := karatsubaLen(n, karatsubaThreshold)
433
434
435
436 x0 := x[0:k]
437 y0 := y[0:k]
438 z = z.make(max(6*k, m+n))
439 karatsuba(z, x0, y0)
440 z = z[0 : m+n]
441 clear(z[2*k:])
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456 if k < n || m != n {
457 tp := getNat(3 * k)
458 t := *tp
459
460
461 x0 := x0.norm()
462 y1 := y[k:]
463 t = t.mul(x0, y1)
464 addAt(z, t, k)
465
466
467 y0 := y0.norm()
468 for i := k; i < len(x); i += k {
469 xi := x[i:]
470 if len(xi) > k {
471 xi = xi[:k]
472 }
473 xi = xi.norm()
474 t = t.mul(xi, y0)
475 addAt(z, t, i)
476 t = t.mul(xi, y1)
477 addAt(z, t, i+k)
478 }
479
480 putNat(tp)
481 }
482
483 return z.norm()
484 }
485
486
487
488
489
490 func basicSqr(z, x nat) {
491 n := len(x)
492 tp := getNat(2 * n)
493 t := *tp
494 clear(t)
495 z[1], z[0] = mulWW(x[0], x[0])
496 for i := 1; i < n; i++ {
497 d := x[i]
498
499 z[2*i+1], z[2*i] = mulWW(d, d)
500
501 t[2*i] = addMulVVW(t[i:2*i], x[0:i], d)
502 }
503 t[2*n-1] = shlVU(t[1:2*n-1], t[1:2*n-1], 1)
504 addVV(z, z, t)
505 putNat(tp)
506 }
507
508
509
510
511
512
513 func karatsubaSqr(z, x nat) {
514 n := len(x)
515
516 if n&1 != 0 || n < karatsubaSqrThreshold || n < 2 {
517 basicSqr(z[:2*n], x)
518 return
519 }
520
521 n2 := n >> 1
522 x1, x0 := x[n2:], x[0:n2]
523
524 karatsubaSqr(z, x0)
525 karatsubaSqr(z[n:], x1)
526
527
528 xd := z[2*n : 2*n+n2]
529 if subVV(xd, x1, x0) != 0 {
530 subVV(xd, x0, x1)
531 }
532
533 p := z[n*3:]
534 karatsubaSqr(p, xd)
535
536 r := z[n*4:]
537 copy(r, z[:n*2])
538
539 karatsubaAdd(z[n2:], r, n)
540 karatsubaAdd(z[n2:], r[n:], n)
541 karatsubaSub(z[n2:], p, n)
542 }
543
544
545
546
547 var basicSqrThreshold = 20
548 var karatsubaSqrThreshold = 260
549
550
551 func (z nat) sqr(x nat) nat {
552 n := len(x)
553 switch {
554 case n == 0:
555 return z[:0]
556 case n == 1:
557 d := x[0]
558 z = z.make(2)
559 z[1], z[0] = mulWW(d, d)
560 return z.norm()
561 }
562
563 if alias(z, x) {
564 z = nil
565 }
566
567 if n < basicSqrThreshold {
568 z = z.make(2 * n)
569 basicMul(z, x, x)
570 return z.norm()
571 }
572 if n < karatsubaSqrThreshold {
573 z = z.make(2 * n)
574 basicSqr(z, x)
575 return z.norm()
576 }
577
578
579
580
581
582
583 k := karatsubaLen(n, karatsubaSqrThreshold)
584
585 x0 := x[0:k]
586 z = z.make(max(6*k, 2*n))
587 karatsubaSqr(z, x0)
588 z = z[0 : 2*n]
589 clear(z[2*k:])
590
591 if k < n {
592 tp := getNat(2 * k)
593 t := *tp
594 x0 := x0.norm()
595 x1 := x[k:]
596 t = t.mul(x0, x1)
597 addAt(z, t, k)
598 addAt(z, t, k)
599 t = t.sqr(x1)
600 addAt(z, t, 2*k)
601 putNat(tp)
602 }
603
604 return z.norm()
605 }
606
607
608
609 func (z nat) mulRange(a, b uint64) nat {
610 switch {
611 case a == 0:
612
613 return z.setUint64(0)
614 case a > b:
615 return z.setUint64(1)
616 case a == b:
617 return z.setUint64(a)
618 case a+1 == b:
619 return z.mul(nat(nil).setUint64(a), nat(nil).setUint64(b))
620 }
621 m := a + (b-a)/2
622 return z.mul(nat(nil).mulRange(a, m), nat(nil).mulRange(m+1, b))
623 }
624
625
626
627 func getNat(n int) *nat {
628 var z *nat
629 if v := natPool.Get(); v != nil {
630 z = v.(*nat)
631 }
632 if z == nil {
633 z = new(nat)
634 }
635 *z = z.make(n)
636 if n > 0 {
637 (*z)[0] = 0xfedcb
638 }
639 return z
640 }
641
642 func putNat(x *nat) {
643 natPool.Put(x)
644 }
645
646 var natPool sync.Pool
647
648
649
650 func (x nat) bitLen() int {
651
652
653
654 if i := len(x) - 1; i >= 0 {
655
656
657
658 top := uint(x[i])
659 top |= top >> 1
660 top |= top >> 2
661 top |= top >> 4
662 top |= top >> 8
663 top |= top >> 16
664 top |= top >> 16 >> 16
665 return i*_W + bits.Len(top)
666 }
667 return 0
668 }
669
670
671
672 func (x nat) trailingZeroBits() uint {
673 if len(x) == 0 {
674 return 0
675 }
676 var i uint
677 for x[i] == 0 {
678 i++
679 }
680
681 return i*_W + uint(bits.TrailingZeros(uint(x[i])))
682 }
683
684
685 func (x nat) isPow2() (uint, bool) {
686 var i uint
687 for x[i] == 0 {
688 i++
689 }
690 if i == uint(len(x))-1 && x[i]&(x[i]-1) == 0 {
691 return i*_W + uint(bits.TrailingZeros(uint(x[i]))), true
692 }
693 return 0, false
694 }
695
696 func same(x, y nat) bool {
697 return len(x) == len(y) && len(x) > 0 && &x[0] == &y[0]
698 }
699
700
701 func (z nat) shl(x nat, s uint) nat {
702 if s == 0 {
703 if same(z, x) {
704 return z
705 }
706 if !alias(z, x) {
707 return z.set(x)
708 }
709 }
710
711 m := len(x)
712 if m == 0 {
713 return z[:0]
714 }
715
716
717 n := m + int(s/_W)
718 z = z.make(n + 1)
719 z[n] = shlVU(z[n-m:n], x, s%_W)
720 clear(z[0 : n-m])
721
722 return z.norm()
723 }
724
725
726 func (z nat) shr(x nat, s uint) nat {
727 if s == 0 {
728 if same(z, x) {
729 return z
730 }
731 if !alias(z, x) {
732 return z.set(x)
733 }
734 }
735
736 m := len(x)
737 n := m - int(s/_W)
738 if n <= 0 {
739 return z[:0]
740 }
741
742
743 z = z.make(n)
744 shrVU(z, x[m-n:], s%_W)
745
746 return z.norm()
747 }
748
749 func (z nat) setBit(x nat, i uint, b uint) nat {
750 j := int(i / _W)
751 m := Word(1) << (i % _W)
752 n := len(x)
753 switch b {
754 case 0:
755 z = z.make(n)
756 copy(z, x)
757 if j >= n {
758
759 return z
760 }
761 z[j] &^= m
762 return z.norm()
763 case 1:
764 if j >= n {
765 z = z.make(j + 1)
766 clear(z[n:])
767 } else {
768 z = z.make(n)
769 }
770 copy(z, x)
771 z[j] |= m
772
773 return z
774 }
775 panic("set bit is not 0 or 1")
776 }
777
778
779 func (x nat) bit(i uint) uint {
780 j := i / _W
781 if j >= uint(len(x)) {
782 return 0
783 }
784
785 return uint(x[j] >> (i % _W) & 1)
786 }
787
788
789
790 func (x nat) sticky(i uint) uint {
791 j := i / _W
792 if j >= uint(len(x)) {
793 if len(x) == 0 {
794 return 0
795 }
796 return 1
797 }
798
799 for _, x := range x[:j] {
800 if x != 0 {
801 return 1
802 }
803 }
804 if x[j]<<(_W-i%_W) != 0 {
805 return 1
806 }
807 return 0
808 }
809
810 func (z nat) and(x, y nat) nat {
811 m := len(x)
812 n := len(y)
813 if m > n {
814 m = n
815 }
816
817
818 z = z.make(m)
819 for i := 0; i < m; i++ {
820 z[i] = x[i] & y[i]
821 }
822
823 return z.norm()
824 }
825
826
827 func (z nat) trunc(x nat, n uint) nat {
828 w := (n + _W - 1) / _W
829 if uint(len(x)) < w {
830 return z.set(x)
831 }
832 z = z.make(int(w))
833 copy(z, x)
834 if n%_W != 0 {
835 z[len(z)-1] &= 1<<(n%_W) - 1
836 }
837 return z.norm()
838 }
839
840 func (z nat) andNot(x, y nat) nat {
841 m := len(x)
842 n := len(y)
843 if n > m {
844 n = m
845 }
846
847
848 z = z.make(m)
849 for i := 0; i < n; i++ {
850 z[i] = x[i] &^ y[i]
851 }
852 copy(z[n:m], x[n:m])
853
854 return z.norm()
855 }
856
857 func (z nat) or(x, y nat) nat {
858 m := len(x)
859 n := len(y)
860 s := x
861 if m < n {
862 n, m = m, n
863 s = y
864 }
865
866
867 z = z.make(m)
868 for i := 0; i < n; i++ {
869 z[i] = x[i] | y[i]
870 }
871 copy(z[n:m], s[n:m])
872
873 return z.norm()
874 }
875
876 func (z nat) xor(x, y nat) nat {
877 m := len(x)
878 n := len(y)
879 s := x
880 if m < n {
881 n, m = m, n
882 s = y
883 }
884
885
886 z = z.make(m)
887 for i := 0; i < n; i++ {
888 z[i] = x[i] ^ y[i]
889 }
890 copy(z[n:m], s[n:m])
891
892 return z.norm()
893 }
894
895
896
897 func (z nat) random(rand *rand.Rand, limit nat, n int) nat {
898 if alias(z, limit) {
899 z = nil
900 }
901 z = z.make(len(limit))
902
903 bitLengthOfMSW := uint(n % _W)
904 if bitLengthOfMSW == 0 {
905 bitLengthOfMSW = _W
906 }
907 mask := Word((1 << bitLengthOfMSW) - 1)
908
909 for {
910 switch _W {
911 case 32:
912 for i := range z {
913 z[i] = Word(rand.Uint32())
914 }
915 case 64:
916 for i := range z {
917 z[i] = Word(rand.Uint32()) | Word(rand.Uint32())<<32
918 }
919 default:
920 panic("unknown word size")
921 }
922 z[len(limit)-1] &= mask
923 if z.cmp(limit) < 0 {
924 break
925 }
926 }
927
928 return z.norm()
929 }
930
931
932
933 func (z nat) expNN(x, y, m nat, slow bool) nat {
934 if alias(z, x) || alias(z, y) {
935
936 z = nil
937 }
938
939
940 if len(m) == 1 && m[0] == 1 {
941 return z.setWord(0)
942 }
943
944
945
946 if len(y) == 0 {
947 return z.setWord(1)
948 }
949
950
951
952 if len(x) == 0 {
953 return z.setWord(0)
954 }
955
956
957
958 if len(x) == 1 && x[0] == 1 {
959 return z.setWord(1)
960 }
961
962
963
964 if len(y) == 1 && y[0] == 1 {
965 if len(m) != 0 {
966 return z.rem(x, m)
967 }
968 return z.set(x)
969 }
970
971
972 if len(m) != 0 {
973
974 z = z.make(len(m))
975
976
977
978
979
980
981 if len(y) > 1 && !slow {
982 if m[0]&1 == 1 {
983 return z.expNNMontgomery(x, y, m)
984 }
985 if logM, ok := m.isPow2(); ok {
986 return z.expNNWindowed(x, y, logM)
987 }
988 return z.expNNMontgomeryEven(x, y, m)
989 }
990 }
991
992 z = z.set(x)
993 v := y[len(y)-1]
994 shift := nlz(v) + 1
995 v <<= shift
996 var q nat
997
998 const mask = 1 << (_W - 1)
999
1000
1001
1002
1003
1004 w := _W - int(shift)
1005
1006
1007 var zz, r nat
1008 for j := 0; j < w; j++ {
1009 zz = zz.sqr(z)
1010 zz, z = z, zz
1011
1012 if v&mask != 0 {
1013 zz = zz.mul(z, x)
1014 zz, z = z, zz
1015 }
1016
1017 if len(m) != 0 {
1018 zz, r = zz.div(r, z, m)
1019 zz, r, q, z = q, z, zz, r
1020 }
1021
1022 v <<= 1
1023 }
1024
1025 for i := len(y) - 2; i >= 0; i-- {
1026 v = y[i]
1027
1028 for j := 0; j < _W; j++ {
1029 zz = zz.sqr(z)
1030 zz, z = z, zz
1031
1032 if v&mask != 0 {
1033 zz = zz.mul(z, x)
1034 zz, z = z, zz
1035 }
1036
1037 if len(m) != 0 {
1038 zz, r = zz.div(r, z, m)
1039 zz, r, q, z = q, z, zz, r
1040 }
1041
1042 v <<= 1
1043 }
1044 }
1045
1046 return z.norm()
1047 }
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057 func (z nat) expNNMontgomeryEven(x, y, m nat) nat {
1058
1059 n := m.trailingZeroBits()
1060 m1 := nat(nil).shl(natOne, n)
1061 m2 := nat(nil).shr(m, n)
1062
1063
1064
1065
1066
1067
1068
1069 z1 := nat(nil).expNN(x, y, m1, false)
1070 z2 := nat(nil).expNN(x, y, m2, false)
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082 z = z.set(z2)
1083
1084
1085 z1 = z1.subMod2N(z1, z2, n)
1086
1087
1088 m2inv := nat(nil).modInverse(m2, m1)
1089 z2 = z2.mul(z1, m2inv)
1090 z2 = z2.trunc(z2, n)
1091
1092
1093 z = z.add(z, z1.mul(z2, m2))
1094
1095 return z
1096 }
1097
1098
1099
1100 func (z nat) expNNWindowed(x, y nat, logM uint) nat {
1101 if len(y) <= 1 {
1102 panic("big: misuse of expNNWindowed")
1103 }
1104 if x[0]&1 == 0 {
1105
1106
1107 return z.setWord(0)
1108 }
1109 if logM == 1 {
1110 return z.setWord(1)
1111 }
1112
1113
1114
1115 w := int((logM + _W - 1) / _W)
1116 zzp := getNat(w)
1117 zz := *zzp
1118
1119 const n = 4
1120
1121 var powers [1 << n]*nat
1122 for i := range powers {
1123 powers[i] = getNat(w)
1124 }
1125 *powers[0] = powers[0].set(natOne)
1126 *powers[1] = powers[1].trunc(x, logM)
1127 for i := 2; i < 1<<n; i += 2 {
1128 p2, p, p1 := powers[i/2], powers[i], powers[i+1]
1129 *p = p.sqr(*p2)
1130 *p = p.trunc(*p, logM)
1131 *p1 = p1.mul(*p, x)
1132 *p1 = p1.trunc(*p1, logM)
1133 }
1134
1135
1136
1137
1138
1139
1140 i := len(y) - 1
1141 mtop := int((logM - 2) / _W)
1142 mmask := ^Word(0)
1143 if mbits := (logM - 1) & (_W - 1); mbits != 0 {
1144 mmask = (1 << mbits) - 1
1145 }
1146 if i > mtop {
1147 i = mtop
1148 }
1149 advance := false
1150 z = z.setWord(1)
1151 for ; i >= 0; i-- {
1152 yi := y[i]
1153 if i == mtop {
1154 yi &= mmask
1155 }
1156 for j := 0; j < _W; j += n {
1157 if advance {
1158
1159
1160
1161
1162 zz = zz.sqr(z)
1163 zz, z = z, zz
1164 z = z.trunc(z, logM)
1165
1166 zz = zz.sqr(z)
1167 zz, z = z, zz
1168 z = z.trunc(z, logM)
1169
1170 zz = zz.sqr(z)
1171 zz, z = z, zz
1172 z = z.trunc(z, logM)
1173
1174 zz = zz.sqr(z)
1175 zz, z = z, zz
1176 z = z.trunc(z, logM)
1177 }
1178
1179 zz = zz.mul(z, *powers[yi>>(_W-n)])
1180 zz, z = z, zz
1181 z = z.trunc(z, logM)
1182
1183 yi <<= n
1184 advance = true
1185 }
1186 }
1187
1188 *zzp = zz
1189 putNat(zzp)
1190 for i := range powers {
1191 putNat(powers[i])
1192 }
1193
1194 return z.norm()
1195 }
1196
1197
1198
1199 func (z nat) expNNMontgomery(x, y, m nat) nat {
1200 numWords := len(m)
1201
1202
1203
1204 if len(x) > numWords {
1205 _, x = nat(nil).div(nil, x, m)
1206
1207 }
1208 if len(x) < numWords {
1209 rr := make(nat, numWords)
1210 copy(rr, x)
1211 x = rr
1212 }
1213
1214
1215
1216
1217 k0 := 2 - m[0]
1218 t := m[0] - 1
1219 for i := 1; i < _W; i <<= 1 {
1220 t *= t
1221 k0 *= (t + 1)
1222 }
1223 k0 = -k0
1224
1225
1226 RR := nat(nil).setWord(1)
1227 zz := nat(nil).shl(RR, uint(2*numWords*_W))
1228 _, RR = nat(nil).div(RR, zz, m)
1229 if len(RR) < numWords {
1230 zz = zz.make(numWords)
1231 copy(zz, RR)
1232 RR = zz
1233 }
1234
1235 one := make(nat, numWords)
1236 one[0] = 1
1237
1238 const n = 4
1239
1240 var powers [1 << n]nat
1241 powers[0] = powers[0].montgomery(one, RR, m, k0, numWords)
1242 powers[1] = powers[1].montgomery(x, RR, m, k0, numWords)
1243 for i := 2; i < 1<<n; i++ {
1244 powers[i] = powers[i].montgomery(powers[i-1], powers[1], m, k0, numWords)
1245 }
1246
1247
1248 z = z.make(numWords)
1249 copy(z, powers[0])
1250
1251 zz = zz.make(numWords)
1252
1253
1254 for i := len(y) - 1; i >= 0; i-- {
1255 yi := y[i]
1256 for j := 0; j < _W; j += n {
1257 if i != len(y)-1 || j != 0 {
1258 zz = zz.montgomery(z, z, m, k0, numWords)
1259 z = z.montgomery(zz, zz, m, k0, numWords)
1260 zz = zz.montgomery(z, z, m, k0, numWords)
1261 z = z.montgomery(zz, zz, m, k0, numWords)
1262 }
1263 zz = zz.montgomery(z, powers[yi>>(_W-n)], m, k0, numWords)
1264 z, zz = zz, z
1265 yi <<= n
1266 }
1267 }
1268
1269 zz = zz.montgomery(z, one, m, k0, numWords)
1270
1271
1272
1273 if zz.cmp(m) >= 0 {
1274
1275
1276
1277
1278
1279
1280
1281 zz = zz.sub(zz, m)
1282 if zz.cmp(m) >= 0 {
1283 _, zz = nat(nil).div(nil, zz, m)
1284 }
1285 }
1286
1287 return zz.norm()
1288 }
1289
1290
1291
1292
1293
1294 func (z nat) bytes(buf []byte) (i int) {
1295
1296
1297
1298 i = len(buf)
1299 for _, d := range z {
1300 for j := 0; j < _S; j++ {
1301 i--
1302 if i >= 0 {
1303 buf[i] = byte(d)
1304 } else if byte(d) != 0 {
1305 panic("math/big: buffer too small to fit value")
1306 }
1307 d >>= 8
1308 }
1309 }
1310
1311 if i < 0 {
1312 i = 0
1313 }
1314 for i < len(buf) && buf[i] == 0 {
1315 i++
1316 }
1317
1318 return
1319 }
1320
1321
1322 func bigEndianWord(buf []byte) Word {
1323 if _W == 64 {
1324 return Word(byteorder.BeUint64(buf))
1325 }
1326 return Word(byteorder.BeUint32(buf))
1327 }
1328
1329
1330
1331 func (z nat) setBytes(buf []byte) nat {
1332 z = z.make((len(buf) + _S - 1) / _S)
1333
1334 i := len(buf)
1335 for k := 0; i >= _S; k++ {
1336 z[k] = bigEndianWord(buf[i-_S : i])
1337 i -= _S
1338 }
1339 if i > 0 {
1340 var d Word
1341 for s := uint(0); i > 0; s += 8 {
1342 d |= Word(buf[i-1]) << s
1343 i--
1344 }
1345 z[len(z)-1] = d
1346 }
1347
1348 return z.norm()
1349 }
1350
1351
1352 func (z nat) sqrt(x nat) nat {
1353 if x.cmp(natOne) <= 0 {
1354 return z.set(x)
1355 }
1356 if alias(z, x) {
1357 z = nil
1358 }
1359
1360
1361
1362
1363
1364
1365 var z1, z2 nat
1366 z1 = z
1367 z1 = z1.setUint64(1)
1368 z1 = z1.shl(z1, uint(x.bitLen()+1)/2)
1369 for n := 0; ; n++ {
1370 z2, _ = z2.div(nil, x, z1)
1371 z2 = z2.add(z2, z1)
1372 z2 = z2.shr(z2, 1)
1373 if z2.cmp(z1) >= 0 {
1374
1375
1376 if n&1 == 0 {
1377 return z1
1378 }
1379 return z.set(z1)
1380 }
1381 z1, z2 = z2, z1
1382 }
1383 }
1384
1385
1386 func (z nat) subMod2N(x, y nat, n uint) nat {
1387 if uint(x.bitLen()) > n {
1388 if alias(z, x) {
1389
1390 x = x.trunc(x, n)
1391 } else {
1392 x = nat(nil).trunc(x, n)
1393 }
1394 }
1395 if uint(y.bitLen()) > n {
1396 if alias(z, y) {
1397
1398 y = y.trunc(y, n)
1399 } else {
1400 y = nat(nil).trunc(y, n)
1401 }
1402 }
1403 if x.cmp(y) >= 0 {
1404 return z.sub(x, y)
1405 }
1406
1407 z = z.sub(y, x)
1408 for uint(len(z))*_W < n {
1409 z = append(z, 0)
1410 }
1411 for i := range z {
1412 z[i] = ^z[i]
1413 }
1414 z = z.trunc(z, n)
1415 return z.add(z, natOne)
1416 }
1417
View as plain text