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