]>
git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cryptkit/lib/CurveParamDocs/schoofs.c
3 Elliptic curve order calculator, for
5 y^2 = x^3 + a x + b (mod p)
8 This version has order sieving, triggering on the
9 initial b parameter and incrementing same.
10 Parameter details are described in schoof.c)
14 % cc -O schoofs.c giants.c tools.c -lm -o schoofs
16 and run, entering the a,b parameters.
20 20 Mar 01 (REC) Added binarysegsquare() and base-4 ladder
21 20 Mar 01 (REC) Bumped MAX_DIGS as in schoof.c
22 4 Feb 99 (REC) Sieving invoked.
23 2 Feb 99 (REC) Added explicit CRT result
24 12 Jan 99 (REC) Removed (hopefully) last of memory crashes
25 20 Jan 98 (REC) Creation
27 * c. 1998 Perfectly Scientific, Inc.
28 * All Rights Reserved.
31 *************************************************************/
42 #define Q 256 /* See schoof.c for explanation. */
44 #define MAX_DIGS (2 + (Q+15)/8) /* Size of (squared) coefficients. */
45 #define MAX_COEFFS ((L_MAX+1)*(L_MAX+2))
52 typedef polystruct
*poly
;
55 static giant
*mcand
, coe
, tmp
, err
, aux
, aux2
, globx
, globy
, t1
, t2
,
57 static poly qscratch
, rscratch
, sscratch
, tscratch
, pbuff
, pbuff2
,
58 precip
, cubic
, powx
, powy
, kxn
, kyn
, kxd
, kyd
,
59 txn
, txd
, tyn
, tyd
, txn1
, txd1
, tyn1
, tyd1
,
60 nx
, dx
, ny
, dy
, mn
, md
, tmp1
, tmp2
, tmp3
, tmp4
;
61 static poly s
[L_MAX
+2], smonic
;
62 static giant p
, a
, b
, magcheck
;
65 void quickmodg(giant g
, giant x
)
70 if(gcompg(x
, g
) >= 0) subg(g
, x
);
90 for(j
= x
->deg
; j
>= 0; j
--) {
91 if(!is0(x
->coe
[j
])) break;
93 x
->deg
= (j
>0)? j
: 0;
99 for(j
=0; j
<= x
->deg
; j
++) {
108 giant
*p
= (giant
*)malloc(n
*sizeof(giant
));
111 p
[j
] = newgiant(MAX_DIGS
);
117 newpoly(int coeffs
) {
119 pol
= (poly
) malloc(sizeof(polystruct
));
120 pol
->coe
= (giant
*)newa(coeffs
);
128 j
= (2*Q
+ log_2(MAX_COEFFS
) + 32 + 15)/16;
129 globx
= newgiant(MAX_COEFFS
* j
);
130 globy
= newgiant(MAX_COEFFS
* j
);
132 init_tools(MAX_DIGS
);
133 powx
= newpoly(MAX_COEFFS
);
134 powy
= newpoly(MAX_COEFFS
);
135 kxn
= newpoly(MAX_COEFFS
);
136 kxd
= newpoly(MAX_COEFFS
);
137 kyn
= newpoly(MAX_COEFFS
);
138 kyd
= newpoly(MAX_COEFFS
);
139 txn
= newpoly(MAX_COEFFS
);
140 txd
= newpoly(MAX_COEFFS
);
141 tyn
= newpoly(MAX_COEFFS
);
142 tyd
= newpoly(MAX_COEFFS
);
143 txn1
= newpoly(MAX_COEFFS
);
144 txd1
= newpoly(MAX_COEFFS
);
145 tyn1
= newpoly(MAX_COEFFS
);
146 tyd1
= newpoly(MAX_COEFFS
);
147 nx
= newpoly(MAX_COEFFS
);
148 ny
= newpoly(MAX_COEFFS
);
149 dx
= newpoly(MAX_COEFFS
);
150 dy
= newpoly(MAX_COEFFS
);
151 mn
= newpoly(MAX_COEFFS
);
152 md
= newpoly(MAX_COEFFS
);
153 tmp1
= newpoly(MAX_COEFFS
);
154 tmp2
= newpoly(MAX_COEFFS
);
155 tmp3
= newpoly(MAX_COEFFS
);
156 tmp4
= newpoly(MAX_COEFFS
);
157 mcand
= (giant
*)newa(MAX_COEFFS
);
159 s
[0] = newpoly(MAX_COEFFS
);
161 for(j
=1; j
<=L_MAX
+1; j
++) {
162 s
[j
] = newpoly(j
*(j
+1));
164 smonic
= newpoly(MAX_COEFFS
);
165 /* The next three need extra space for remaindering routine. */
166 qscratch
= newpoly(2*MAX_COEFFS
);
167 rscratch
= newpoly(2*MAX_COEFFS
);
168 pbuff
= newpoly(2*MAX_COEFFS
);
169 pbuff2
= newpoly(MAX_COEFFS
);
170 sscratch
= newpoly(MAX_COEFFS
);
171 tscratch
= newpoly(MAX_COEFFS
);
172 tmp
= newgiant(MAX_DIGS
);
173 err
= newgiant(MAX_DIGS
);
174 coe
= newgiant(MAX_DIGS
);
175 aux
= newgiant(MAX_DIGS
);
176 aux2
= newgiant(MAX_DIGS
);
177 t1
= newgiant(MAX_DIGS
);
178 t2
= newgiant(MAX_DIGS
);
179 t3
= newgiant(MAX_DIGS
);
180 t4
= newgiant(MAX_DIGS
);
181 t5
= newgiant(MAX_DIGS
);
183 p
= newgiant(MAX_DIGS
);
184 a
= newgiant(MAX_DIGS
);
185 b
= newgiant(MAX_DIGS
);
186 magcheck
= newgiant(MAX_DIGS
);
187 precip
= newpoly(MAX_COEFFS
);
191 atoa(giant
*a
, giant
*b
, int n
) {
193 for(j
=0; j
<n
; j
++) gtog(a
[j
], b
[j
]);
201 atoa(x
->coe
, y
->coe
, y
->deg
+1);
208 for(j
=0; j
<= y
->deg
; j
++) {
210 quickmodg(p
, y
->coe
[j
]);
217 if(a
->sign
== 0) return(1);
224 if(x
->deg
== 0 && iszer(x
->coe
[0])) return 1;
245 if(y
->deg
> d
) d
= y
->deg
;
246 for(j
= 0; j
<= d
; j
++) {
247 if((j
<= x
->deg
) && (j
<= y
->deg
)) {
248 addg(x
->coe
[j
], y
->coe
[j
]);
249 quickmodg(p
, y
->coe
[j
]);
252 if((j
<= x
->deg
) && (j
> y
->deg
)) {
253 gtog(x
->coe
[j
], y
->coe
[j
]);
254 quickmodg(p
, y
->coe
[j
]);
268 if(y
->deg
> d
) d
= y
->deg
;
269 for(j
= 0; j
<= d
; j
++) {
270 if((j
<= x
->deg
) && (j
<= y
->deg
)) {
271 subg(x
->coe
[j
], y
->coe
[j
]);
272 quickmodg(p
, y
->coe
[j
]);
275 if((j
<= x
->deg
) && (j
> y
->deg
)) {
276 gtog(x
->coe
[j
], y
->coe
[j
]);
278 quickmodg(p
, y
->coe
[j
]);
288 grammarmulp(poly a
, poly b
)
291 int dega
= a
->deg
, degb
= b
->deg
, deg
= dega
+ degb
;
292 register int d
, kk
, first
, diffa
;
294 for(d
=deg
; d
>=0; d
--) {
297 for(kk
=0; kk
<=d
; kk
++) {
298 if((kk
>degb
)||(kk
<diffa
)) continue;
299 gtog(b
->coe
[kk
], tmp
);
300 mulg(a
->coe
[d
-kk
], tmp
);
307 atoa(mcand
, b
->coe
, deg
+1);
313 atop(giant
*a
, poly x
, int deg
)
314 /* Copy array to poly, with monic option. */
318 atoa(a
, x
->coe
, adeg
);
320 itog(1, x
->coe
[adeg
]);
322 gtog(a
[adeg
], x
->coe
[adeg
]);
328 while((g
->n
[g
->sign
-1] == 0) && (g
->sign
> 0)) --g
->sign
;
332 unstuff_partial(giant g
, poly y
, int words
){
334 for(j
=0; j
< y
->deg
; j
++) {
335 bcopy((g
->n
) + j
*words
, y
->coe
[j
]->n
, words
*sizeof(short));
336 y
->coe
[j
]->sign
= words
;
342 stuff(poly x
, giant g
, int words
) {
343 int deg
= x
->deg
, j
, coedigs
;
345 g
->sign
= words
*(1 + deg
);
346 for(j
=0; j
<= deg
; j
++) {
347 coedigs
= (x
->coe
[j
])->sign
;
348 bcopy(x
->coe
[j
]->n
, (g
->n
) + j
*words
, coedigs
*sizeof(short));
349 bzero((g
->n
) + (j
*words
+coedigs
),
350 sizeof(short)*(words
-coedigs
));
358 binarysegmul(poly x
, poly y
) {
359 int bits
= bitlen(p
), xwords
, ywords
, words
;
361 xwords
= (2*bits
+ log_2(x
->deg
+1) + 32 + 15)/16;
362 ywords
= (2*bits
+ log_2(y
->deg
+1) + 32 + 15)/16;
363 if(xwords
> ywords
) words
= xwords
; else words
= ywords
;
364 if(words
> maxwords
) {
366 // printf("m: %d\n", words);
369 stuff(x
, globx
, words
);
370 stuff(y
, globy
, words
);
372 gtog(y
->coe
[y
->deg
], globx
); /* Save high coeff. */
374 gtog(globx
, y
->coe
[y
->deg
]); /* Move high coeff. */
375 unstuff_partial(globy
, y
, words
);
376 mulg(x
->coe
[x
->deg
], y
->coe
[y
->deg
]); /* resolve high coeff. */
380 binarysegsquare(poly y
) {
381 int bits
= bitlen(p
), words
;
382 words
= (2*bits
+ log_2(y
->deg
+1) + 32 + 15)/16;
383 stuff(y
, globy
, words
);
385 gtog(y
->coe
[y
->deg
], globx
); /* Save high coeff. */
387 gtog(globx
, y
->coe
[y
->deg
]); /* Move high coeff. */
388 unstuff_partial(globy
, y
, words
);
389 mulg(y
->coe
[y
->deg
], y
->coe
[y
->deg
]); /* resolve high coeff. */
395 assess(poly x
, poly y
){
397 for(j
=0; j
<= x
->deg
; j
++) {
398 if(bitlen(x
->coe
[j
]) > max
) max
= bitlen(x
->coe
[j
]);
400 // printf("max: %d ", max);
402 for(j
=0; j
<= y
->deg
; j
++) {
403 if(bitlen(y
->coe
[j
]) > max
) max
= bitlen(y
->coe
[j
]);
405 // printf("%d\n", max);
411 pcompp(poly x
, poly y
) {
413 if(x
->deg
!= y
->deg
) return 1;
414 for(j
=0; j
<= x
->deg
; j
++) {
415 if(gcompg(x
->coe
[j
], y
->coe
[j
])) return 1;
426 int n
, degx
= x
->deg
, degy
= y
->deg
;
430 max_deg = degx; printf("xdeg: %d\n", degx);
434 max_deg = degy; printf("ydeg: %d\n", degy);
437 if((degx
< P_BREAK
) || (degy
< P_BREAK
)) {
442 if(x
==y
) binarysegsquare(y
);
443 else binarysegmul(x
, y
);
448 /* Reverse the coefficients of x. */
449 { int j
, deg
= x
->deg
;
451 for(j
=0; j
<= deg
/2; j
++) {
452 gtog(x
->coe
[deg
-j
], tmp
);
453 gtog(x
->coe
[j
], x
->coe
[deg
-j
]);
454 gtog(tmp
, x
->coe
[j
]);
460 recipp(poly f
, int deg
)
461 /* f := 1/f, via newton method. */
463 int lim
= deg
+ 1, prec
= 1;
465 sscratch
->deg
= 0; itog(1, sscratch
->coe
[0]);
469 if(prec
> lim
) prec
= lim
;
471 ptop(sscratch
, tscratch
);
473 tscratch
->deg
= prec
-1;
475 subg(aux
, tscratch
->coe
[0]);
476 quickmodg(p
, tscratch
->coe
[0]);
477 mulp(sscratch
, tscratch
);
478 tscratch
->deg
= prec
-1;
480 subp(tscratch
, sscratch
);
481 sscratch
->deg
= prec
-1;
489 left_justifyp(poly x
, int start
)
490 /* Left-justify the polynomial, checking from position "start." */
494 for(j
= start
; j
<= x
->deg
; j
++) {
495 if(!is0(x
->coe
[j
])) {
501 for(j
=0; j
<= x
->deg
; j
++) {
502 gtog(x
->coe
[j
+shift
], x
->coe
[j
]);
508 remp(poly x
, poly y
, int mode
)
510 mode = 0 is normal operation,
511 = 1 jams a fixed reciprocal,
512 = 2 uses the fixed reciprocal.
515 int degx
= x
->deg
, degy
= y
->deg
, d
, shift
;
530 case 0: recipp(rscratch
, d
);
532 case 1: recipp(rscratch
, degy
); /* degy -1. */
533 ptop(rscratch
, precip
);
534 rscratch
->deg
= d
; justifyp(rscratch
);
536 case 2: ptop(precip
, rscratch
);
537 rscratch
->deg
= d
; justifyp(rscratch
);
540 /* Next, a limited-precision multiply. */
541 if(d
< degx
) { x
->deg
= d
; justifyp(x
);}
546 x
->deg
= degx
; justifyp(x
);
550 shift
= left_justifyp(y
, d
+1);
551 for(d
= y
->deg
+1; d
<= degx
-shift
; d
++) itog(0, y
->coe
[d
]);
552 y
->deg
= degx
- shift
;
565 scalarmul(giant s
, poly x
) {
567 for(j
=0; j
<= x
->deg
; j
++) {
578 itog(0, s
[0]->coe
[0]);
581 itog(1, s
[1]->coe
[0]);
583 itog(2, s
[2]->coe
[0]);
586 gtog(a
, aux
); mulg(a
, aux
); negg(aux
);
587 gtog(aux
, s
[3]->coe
[0]);
588 gtog(b
, aux
); smulg(12, aux
);
589 gtog(aux
, s
[3]->coe
[1]);
590 gtog(a
, aux
); smulg(6, aux
);
591 gtog(aux
, s
[3]->coe
[2]);
592 itog(0, s
[3]->coe
[3]);
593 itog(3, s
[3]->coe
[4]);
596 gtog(a
, aux
); mulg(a
, aux
); mulg(a
, aux
);
597 gtog(b
, tmp
); mulg(b
, tmp
); smulg(8, tmp
); addg(tmp
, aux
);
599 gtog(aux
, s
[4]->coe
[0]);
600 gtog(b
, aux
); mulg(a
, aux
); smulg(4, aux
); negg(aux
);
601 gtog(aux
, s
[4]->coe
[1]);
602 gtog(a
, aux
); mulg(a
, aux
); smulg(5, aux
); negg(aux
);
603 gtog(aux
, s
[4]->coe
[2]);
604 gtog(b
, aux
); smulg(20, aux
);
605 gtog(aux
, s
[4]->coe
[3]);
606 gtog(a
, aux
); smulg(5, aux
);
607 gtog(aux
, s
[4]->coe
[4]);
608 itog(0, s
[4]->coe
[5]);
609 itog(1, s
[4]->coe
[6]);
611 scalarmul(aux
, s
[4]);
613 itog(1, cubic
->coe
[3]);
614 itog(0, cubic
->coe
[2]);
615 gtog(a
, cubic
->coe
[1]);
616 gtog(b
, cubic
->coe
[0]);
617 for(j
=5; j
<= el
; j
++) {
619 ptop(s
[j
/2 + 2], s
[j
]); mulp(s
[j
/2-1], s
[j
]);
620 polyrem(s
[j
]); mulp(s
[j
/2-1], s
[j
]); polyrem(s
[j
]);
621 ptop(s
[j
/2-2], s
[0]); mulp(s
[j
/2+1], s
[0]); polyrem(s
[0]);
622 mulp(s
[j
/2+1], s
[0]); polyrem(s
[0]);
623 subp(s
[0], s
[j
]); mulp(s
[j
/2], s
[j
]); polyrem(s
[j
]);
624 gtog(p
, aux
); iaddg(1, aux
); gshiftright(1, aux
);
625 scalarmul(aux
, s
[j
]);
627 ptop(s
[(j
-1)/2+2], s
[j
]);
628 mulp(s
[(j
-1)/2], s
[j
]); polyrem(s
[j
]);
629 mulp(s
[(j
-1)/2], s
[j
]); polyrem(s
[j
]);
630 mulp(s
[(j
-1)/2], s
[j
]); polyrem(s
[j
]);
631 ptop(s
[(j
-1)/2-1], s
[0]);
632 mulp(s
[(j
-1)/2 + 1], s
[0]); polyrem(s
[0]);
633 mulp(s
[(j
-1)/2 + 1], s
[0]); polyrem(s
[0]);
634 mulp(s
[(j
-1)/2 + 1], s
[0]); polyrem(s
[0]);
635 if(((j
-1)/2) % 2 == 1) {
636 mulp(cubic
, s
[0]); polyrem(s
[0]);
637 mulp(cubic
, s
[0]); polyrem(s
[0]);
639 mulp(cubic
, s
[j
]); polyrem(s
[j
]);
640 mulp(cubic
, s
[j
]); polyrem(s
[j
]);
642 // polyout(s[1]); polyout(s[3]); polyout(s[0]); polyout(s[j]);
653 mulp(cubic
, smonic
); polyrem(smonic
);
655 gtog(smonic
->coe
[smonic
->deg
], aux
); /* High coeff. */
657 scalarmul(aux
, smonic
); /* s is now monic. */
658 s
[0]->deg
= smonic
->deg
+ 1;
659 for(j
=0; j
<= s
[0]->deg
; j
++) itog(1, s
[0]->coe
[j
]);
661 remp(s
[0], pbuff
, 1); /* Initialize reciprocal of s as precip. */
664 void powerpoly(poly x
, giant n
)
667 ptop(x
, pbuff
); /* x. */
669 mulmod(pbuff2
, pbuff2
); mulmod(pbuff
, pbuff2
); /* x^3. */
674 if(bitval(n
, pos
) != 0) {
679 code
= (bitval(n
, pos
) != 0) * 2 + (bitval(n
, pos
-1) != 0);
681 case 0: mulmod(x
,x
); break;
685 case 2: mulmod(pbuff
, x
);
687 case 3: mulmod(x
,x
); mulmod(pbuff2
, x
); break;
693 mulmod(poly x
, poly y
) {
694 mulp(x
, y
); fullmod(y
);
697 elldoublep(poly n1
, poly d1
, poly m1
, poly c1
, poly n0
, poly d0
,
700 ptop(n1
, mn
); mulmod(n1
, mn
);
701 ptop(mn
, pbuff
); addp(mn
, mn
); addp(pbuff
, mn
);
703 ptop(d1
, pbuff
); mulmod(d1
, pbuff
);
704 scalarmul(a
, pbuff
); addp(pbuff
, mn
);
707 ptop(m1
, md
); addp(md
, md
);
708 mulmod(d1
, md
); mulmod(d1
, md
); mulmod(cubic
, md
);
710 ptop(d1
, n0
); mulmod(mn
, n0
); mulmod(mn
, n0
);
712 ptop(n1
, pbuff
); addp(pbuff
, pbuff
); fullmod(pbuff
);
713 mulmod(md
, pbuff
); mulmod(md
, pbuff
);
714 subp(pbuff
, n0
); fullmod(n0
);
715 ptop(md
, d0
); mulmod(md
, d0
); mulmod(d1
, d0
);
717 ptop(mn
, m0
); mulmod(c1
, m0
);
718 ptop(d0
, pbuff
); mulmod(n1
, pbuff
);
719 ptop(n0
, c0
); mulmod(d1
, c0
); subp(c0
, pbuff
);
722 ptop(m1
, pbuff
); mulmod(md
, pbuff
);
723 mulmod(d1
, pbuff
); mulmod(d0
, pbuff
);
724 subp(pbuff
, m0
); fullmod(m0
);
726 ptop(c1
, c0
); mulmod(md
, c0
); mulmod(d1
, c0
); mulmod(d0
, c0
);
729 elladdp(poly n1
, poly d1
, poly m1
, poly c1
, poly n2
, poly d2
, poly m2
, poly c2
, poly n0
, poly d0
, poly m0
, poly c0
) {
730 ptop(m2
, mn
); mulmod(c1
, mn
);
731 ptop(m1
, pbuff
); mulmod(c2
, pbuff
);
732 subp(pbuff
, mn
); fullmod(mn
);
733 mulmod(d1
, mn
); mulmod(d2
, mn
);
735 ptop(n2
, md
); mulmod(d1
, md
);
736 ptop(n1
, pbuff
); mulmod(d2
, pbuff
);
737 subp(pbuff
, md
); fullmod(md
);
738 mulmod(c1
, md
); mulmod(c2
, md
);
740 ptop(cubic
, n0
); mulmod(mn
, n0
); mulmod(mn
, n0
);
741 mulmod(d1
, n0
); mulmod(d2
, n0
);
742 ptop(n1
, pbuff
); mulmod(d2
, pbuff
);
743 ptop(n2
, d0
); mulmod(d1
, d0
);
744 addp(d0
, pbuff
); mulmod(md
, pbuff
); mulmod(md
, pbuff
);
745 subp(pbuff
, n0
); fullmod(n0
);
747 ptop(md
, d0
); mulmod(md
, d0
); mulmod(d1
, d0
); mulmod(d2
, d0
);
749 ptop(mn
, m0
); mulmod(c1
, m0
);
750 ptop(d0
, pbuff
); mulmod(n1
, pbuff
);
751 ptop(d1
, c0
); mulmod(n0
, c0
);
752 subp(c0
, pbuff
); fullmod(pbuff
);
754 ptop(m1
, pbuff
); mulmod(md
, pbuff
);
755 mulmod(d0
, pbuff
); mulmod(d1
, pbuff
);
756 subp(pbuff
, m0
); fullmod(m0
);
758 ptop(md
, c0
); mulmod(c1
, c0
); mulmod(d0
, c0
); mulmod(d1
, c0
);
764 for(j
=0; j
<= x
->deg
; j
++) {printf("%d: ",j
); gout(x
->coe
[j
]);}
769 main(int argc
, char **argv
) {
770 int j
, ct
, el
, xmatch
, ymatch
;
772 int T
[L_MAX
], P
[L_MAX
];
774 unsigned int ord
, ordminus
;
776 printf("Initializing...\n"); fflush(stdout
);
779 for(j
=0; j
< L_MAX
; j
++) { /* Array to be used for CRT reconstruction. */
783 printf("Give p, a, b on separate lines:\n"); fflush(stdout
);
784 gin(p
); /* Field prime. */
786 fprintf(stderr
, "p too large, larger than %d bits.\n", Q
);
790 gin(a
); gin(b
); /* Curve parameters. */
793 printf("Checking discriminant for:\nb = ");
795 gtog(a
, t1
); squareg(t1
); modg(p
, t1
); mulg(a
, t1
); modg(p
, t1
);
796 gshiftleft(2, t1
); /* 4 a^3. */
797 gtog(b
, t2
); squareg(t2
); modg(p
, t2
); smulg(27, t2
);
798 addg(t2
, t1
); modg(p
, t1
);
800 printf("Discriminant FAILED\n");
804 printf("Discriminant PASSED\n");
805 printf("Starting sieve process:\n");
808 schain(SIEVE_CUT
+ 1); /* Do first piece of chain, for small-sieving. */
812 for(el
= 2; el
<= L_MAX
; el
+= 1 + (el%2
)) {
813 if(!primeq(el
)) continue;
814 L
= el
; while(L
*el
<= 4) L
*= el
;
815 printf("Resolving Schoof L = %d...\n", L
);
816 P
[ct
] = L
; /* Stuff another prime power. */
818 gtog(magcheck
, tmp
); squareg(tmp
); gshiftright(2, tmp
);
819 if(gcompg(tmp
, p
) > 0) break; /* Done...go to CRT phase. */
820 if((L
> SIEVE_CUT
) && (linit
== 0)) {
825 // printf("s: "); polyout(s[L]);
827 k
= idivg(L
, aux2
); /* p (mod L). */
829 k2
= idivg(el
, aux2
);
830 // printf("power...\n");
831 txd
->deg
= 0; itog(1, txd
->coe
[0]);
832 tyd
->deg
= 0; itog(1, tyd
->coe
[0]);
833 txn
->deg
= 1; itog(0, txn
->coe
[0]); itog(1, txn
->coe
[1]);
837 powerpoly(txn
, aux2
); /* x^p. */
838 // printf("x^p done...\n");
840 powerpoly(powx
, aux2
);
841 // printf("x^p^2 done...\n");
843 gtog(p
, aux2
); itog(1, aux
); subg(aux
, aux2
);
844 gshiftright(1, aux2
); /* aux2 := (p-1)/2. */
845 powerpoly(tyn
, aux2
); /* y^p. */
846 // printf("y^p done...\n");
847 ptop(tyn
, powy
); mulp(tyn
, powy
); fullmod(powy
);
848 mulp(cubic
, powy
); fullmod(powy
);
849 powerpoly(powy
, aux2
);
850 mulp(tyn
, powy
); fullmod(powy
);
851 // printf("Powers done...\n");
853 // printf("pow" ); polyout(powx); polyout(powy);
854 ptop(txn
, txn1
); ptop(txd
, txd1
); /* Save t = 1 case. */
855 ptop(tyn
, tyn1
); ptop(tyd
, tyd1
);
857 (powx, y powy) + k(kxn/kxd, y kyn/kyd) = t(txn/txd, y tyn/tyd)
860 if(k
==1) { ptop(txd
, kxd
); ptop(txd
, kyd
);
863 ptop(s
[k
], kxd
); mulp(s
[k
], kxd
); fullmod(kxd
);
864 if(k%2
==0) { mulp(cubic
, kxd
); fullmod(kxd
); }
865 mulp(kxd
, kxn
); fullmod(kxn
);
866 ptop(s
[k
-1], pbuff
); mulp(s
[k
+1], pbuff
); fullmod(pbuff
);
867 if(k%2
==1) {mulp(cubic
, pbuff
); fullmod(pbuff
); }
868 subp(pbuff
, kxn
); fullmod(kxn
);
870 ptop(s
[k
+2], kyn
); mulp(s
[k
-1], kyn
); fullmod(kyn
);
871 mulp(s
[k
-1], kyn
); fullmod(kyn
);
873 ptop(s
[k
-2], pbuff
); mulp(s
[k
+1], pbuff
); fullmod(pbuff
);
874 mulp(s
[k
+1], pbuff
); fullmod(pbuff
);
875 subp(pbuff
, kyn
); fullmod(kyn
);
877 ptop(s
[k
], kyd
); mulp(s
[k
], kyd
); fullmod(kyd
);
878 mulp(s
[k
], kyd
); fullmod(kyd
);
879 if(k%2
==0) { mulp(cubic
, kyd
); fullmod(kyd
);
880 mulp(cubic
, kyd
); fullmod(kyd
);}
881 itog(4, aux2
); scalarmul(aux2
, kyd
);
883 //printf("kP: "); polyout(kxn); polyout(kxd); polyout(kyn); polyout(kyd);
884 /* Commence t = 0 check. */
885 // printf("Checking t = %d ...\n", 0);
888 ptop(powx
, pbuff
); mulp(kxd
, pbuff
);
895 /* Now check y coords. */
896 if(L
== 2) goto resolve
;
897 ptop(powy
, pbuff
); mulp(kyd
, pbuff
);
902 printf("%d %d\n", L
, 0);
904 if((k2
+ 1 - T
[ct
-1]) % el
== 0) {
905 printf("TILT: %d\n", el
);
913 /* Combine pt1 and pt2. */
914 if((xmatch
== 1) && (ymatch
== 1))
915 elldoublep(powx
, txd
, powy
, txd
, nx
, dx
, ny
, dy
);
917 elladdp(powx
, txd
, powy
, txd
, kxn
, kxd
, kyn
, kyd
, nx
, dx
, ny
, dy
);
919 /* Now {nx/dx, ny/dy} is (fixed) LHS. */
920 // printf("add12: "); polyout(nx); polyout(dx); polyout(ny); polyout(dy);
921 /* Commence t > 0 check. */
922 for(t
=1; t
<= L
/2; t
++) {
923 // printf("Checking t = %d ...\n", t);
924 if(t
> 1) { /* Add (tx1, ty1) to (txn, tyn). */
925 ptop(txn1
, pbuff
); mulmod(txd
, pbuff
);
926 ptop(txn
, powx
); mulmod(txd1
, powx
);
927 subp(powx
, pbuff
); fullmod(pbuff
);
929 elladdp(txn1
, txd1
, tyn1
, tyd1
, txn
, txd
, tyn
, tyd
,
930 tmp1
, tmp2
, tmp3
, tmp4
);
931 else elldoublep(txn
, txd
, tyn
, tyd
,
932 tmp1
, tmp2
, tmp3
, tmp4
);
933 ptop(tmp1
, txn
); ptop(tmp2
, txd
);
934 ptop(tmp3
, tyn
); ptop(tmp4
, tyd
);
936 // printf("tQ: "); polyout(txn); polyout(txd); polyout(tyn); polyout(tyd);
937 /* Next, check {nx/dx, ny/dy} =? {txn/txd, tyn/tyd}. */
938 ptop(nx
, pbuff
); mulmod(txd
, pbuff
);
939 ptop(dx
, powx
); mulmod(txn
, powx
);
940 subp(powx
, pbuff
); fullmod(pbuff
);
941 if(!iszerop(pbuff
)) continue;
943 // printf("y check!\n");
944 ptop(ny
, pbuff
); mulmod(tyd
, pbuff
);
945 ptop(dy
, powx
); mulmod(tyn
, powx
);
946 subp(powx
, pbuff
); fullmod(pbuff
);
948 printf("%d %d\n", L
, t
);
951 printf("%d %d\n", L
, L
-t
);
954 if((k2
+ 1 - T
[ct
-1]) % el
== 0) {
955 printf("TILT: %d\n", el
);
966 /* Now, prime powers P[] and CRT residues T[] are intact. */
967 printf("Prime powers L:\n");
969 for(j
=0; j
< ct
-1; j
++) {
970 printf("%d, ", P
[j
]);
972 printf("%d }\n", P
[ct
-1]);
974 printf("Residues t (mod L):\n");
976 for(j
=0; j
< ct
-1; j
++) {
977 printf("%d, ", T
[j
]);
979 printf("%d }\n", T
[ct
-1]);
981 /* Mathematica algorithm for order:
982 plis = {2^5, 3^3, 5^2, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47};
983 tlis = {1, 26, 4, 2, 4, 11, 6, 5, 19, 22, 10, 16, 7, 22, 11};
984 prod = Apply[Times, plis];
986 invlis = Table[PowerMod[prlis[[q]], -1, plis[[q]]],{q,1,Length[plis]}];
988 t = Mod[tlis . (prlis * invlis), prod];
989 ord = p + 1 - If[t^2 > 4p, t - prod, t]
993 for(j
=0; j
< ct
; j
++) {
997 for(j
=0; j
< 2*ct
; j
++) {
998 if(!ss
[j
]) ss
[j
] = newgiant(MAX_DIGS
);
1001 for(j
=0; j
< ct
; j
++) {
1007 for(j
=0; j
< ct
; j
++) {
1008 gtog(ss
[j
], ss
[j
+ct
]);
1014 for(j
=0; j
< ct
; j
++) {
1025 gtog(p
, t3
); gshiftleft(2, t3
);
1026 if(gcompg(t4
, t3
) > 0) subg(t1
, t2
);
1028 printf("Parameters:\n");
1029 printf("p = "); gout(p
);
1030 printf("a = "); gout(a
);
1031 printf("b = "); gout(b
);
1032 printf("Curve order:\n");
1033 printf("o = "); gout(t5
);
1034 printf("pprob: %d\n", prime_probable(t5
));
1035 printf("Twist order:\n");
1040 printf("pprob: %d\n", prime_probable(t5
));