]>
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 *************************************************************/
41 #define Q 256 /* See schoof.c for explanation. */
43 #define MAX_DIGS (2 + (Q+15)/8) /* Size of (squared) coefficients. */
44 #define MAX_COEFFS ((L_MAX+1)*(L_MAX+2))
51 typedef polystruct
*poly
;
54 static giant
*mcand
, coe
, tmp
, err
, aux
, aux2
, globx
, globy
, t1
, t2
,
56 static poly qscratch
, rscratch
, sscratch
, tscratch
, pbuff
, pbuff2
,
57 precip
, cubic
, powx
, powy
, kxn
, kyn
, kxd
, kyd
,
58 txn
, txd
, tyn
, tyd
, txn1
, txd1
, tyn1
, tyd1
,
59 nx
, dx
, ny
, dy
, mn
, md
, tmp1
, tmp2
, tmp3
, tmp4
;
60 static poly s
[L_MAX
+2], smonic
;
61 static giant p
, a
, b
, magcheck
;
64 void quickmodg(giant g
, giant x
)
69 if(gcompg(x
, g
) >= 0) subg(g
, x
);
89 for(j
= x
->deg
; j
>= 0; j
--) {
90 if(!is0(x
->coe
[j
])) break;
92 x
->deg
= (j
>0)? j
: 0;
98 for(j
=0; j
<= x
->deg
; j
++) {
107 giant
*p
= (giant
*)malloc(n
*sizeof(giant
));
110 p
[j
] = newgiant(MAX_DIGS
);
116 newpoly(int coeffs
) {
118 pol
= (poly
) malloc(sizeof(polystruct
));
119 pol
->coe
= (giant
*)newa(coeffs
);
127 j
= (2*Q
+ log_2(MAX_COEFFS
) + 32 + 15)/16;
128 globx
= newgiant(MAX_COEFFS
* j
);
129 globy
= newgiant(MAX_COEFFS
* j
);
131 init_tools(MAX_DIGS
);
132 powx
= newpoly(MAX_COEFFS
);
133 powy
= newpoly(MAX_COEFFS
);
134 kxn
= newpoly(MAX_COEFFS
);
135 kxd
= newpoly(MAX_COEFFS
);
136 kyn
= newpoly(MAX_COEFFS
);
137 kyd
= newpoly(MAX_COEFFS
);
138 txn
= newpoly(MAX_COEFFS
);
139 txd
= newpoly(MAX_COEFFS
);
140 tyn
= newpoly(MAX_COEFFS
);
141 tyd
= newpoly(MAX_COEFFS
);
142 txn1
= newpoly(MAX_COEFFS
);
143 txd1
= newpoly(MAX_COEFFS
);
144 tyn1
= newpoly(MAX_COEFFS
);
145 tyd1
= newpoly(MAX_COEFFS
);
146 nx
= newpoly(MAX_COEFFS
);
147 ny
= newpoly(MAX_COEFFS
);
148 dx
= newpoly(MAX_COEFFS
);
149 dy
= newpoly(MAX_COEFFS
);
150 mn
= newpoly(MAX_COEFFS
);
151 md
= newpoly(MAX_COEFFS
);
152 tmp1
= newpoly(MAX_COEFFS
);
153 tmp2
= newpoly(MAX_COEFFS
);
154 tmp3
= newpoly(MAX_COEFFS
);
155 tmp4
= newpoly(MAX_COEFFS
);
156 mcand
= (giant
*)newa(MAX_COEFFS
);
158 s
[0] = newpoly(MAX_COEFFS
);
160 for(j
=1; j
<=L_MAX
+1; j
++) {
161 s
[j
] = newpoly(j
*(j
+1));
163 smonic
= newpoly(MAX_COEFFS
);
164 /* The next three need extra space for remaindering routine. */
165 qscratch
= newpoly(2*MAX_COEFFS
);
166 rscratch
= newpoly(2*MAX_COEFFS
);
167 pbuff
= newpoly(2*MAX_COEFFS
);
168 pbuff2
= newpoly(MAX_COEFFS
);
169 sscratch
= newpoly(MAX_COEFFS
);
170 tscratch
= newpoly(MAX_COEFFS
);
171 tmp
= newgiant(MAX_DIGS
);
172 err
= newgiant(MAX_DIGS
);
173 coe
= newgiant(MAX_DIGS
);
174 aux
= newgiant(MAX_DIGS
);
175 aux2
= newgiant(MAX_DIGS
);
176 t1
= newgiant(MAX_DIGS
);
177 t2
= newgiant(MAX_DIGS
);
178 t3
= newgiant(MAX_DIGS
);
179 t4
= newgiant(MAX_DIGS
);
180 t5
= newgiant(MAX_DIGS
);
182 p
= newgiant(MAX_DIGS
);
183 a
= newgiant(MAX_DIGS
);
184 b
= newgiant(MAX_DIGS
);
185 magcheck
= newgiant(MAX_DIGS
);
186 precip
= newpoly(MAX_COEFFS
);
190 atoa(giant
*a
, giant
*b
, int n
) {
192 for(j
=0; j
<n
; j
++) gtog(a
[j
], b
[j
]);
200 atoa(x
->coe
, y
->coe
, y
->deg
+1);
207 for(j
=0; j
<= y
->deg
; j
++) {
209 quickmodg(p
, y
->coe
[j
]);
216 if(a
->sign
== 0) return(1);
223 if(x
->deg
== 0 && iszer(x
->coe
[0])) return 1;
244 if(y
->deg
> d
) d
= y
->deg
;
245 for(j
= 0; j
<= d
; j
++) {
246 if((j
<= x
->deg
) && (j
<= y
->deg
)) {
247 addg(x
->coe
[j
], y
->coe
[j
]);
248 quickmodg(p
, y
->coe
[j
]);
251 if((j
<= x
->deg
) && (j
> y
->deg
)) {
252 gtog(x
->coe
[j
], y
->coe
[j
]);
253 quickmodg(p
, y
->coe
[j
]);
267 if(y
->deg
> d
) d
= y
->deg
;
268 for(j
= 0; j
<= d
; j
++) {
269 if((j
<= x
->deg
) && (j
<= y
->deg
)) {
270 subg(x
->coe
[j
], y
->coe
[j
]);
271 quickmodg(p
, y
->coe
[j
]);
274 if((j
<= x
->deg
) && (j
> y
->deg
)) {
275 gtog(x
->coe
[j
], y
->coe
[j
]);
277 quickmodg(p
, y
->coe
[j
]);
287 grammarmulp(poly a
, poly b
)
290 int dega
= a
->deg
, degb
= b
->deg
, deg
= dega
+ degb
;
291 register int d
, kk
, first
, diffa
;
293 for(d
=deg
; d
>=0; d
--) {
296 for(kk
=0; kk
<=d
; kk
++) {
297 if((kk
>degb
)||(kk
<diffa
)) continue;
298 gtog(b
->coe
[kk
], tmp
);
299 mulg(a
->coe
[d
-kk
], tmp
);
306 atoa(mcand
, b
->coe
, deg
+1);
312 atop(giant
*a
, poly x
, int deg
)
313 /* Copy array to poly, with monic option. */
317 atoa(a
, x
->coe
, adeg
);
319 itog(1, x
->coe
[adeg
]);
321 gtog(a
[adeg
], x
->coe
[adeg
]);
327 while((g
->n
[g
->sign
-1] == 0) && (g
->sign
> 0)) --g
->sign
;
331 unstuff_partial(giant g
, poly y
, int words
){
333 for(j
=0; j
< y
->deg
; j
++) {
334 bcopy((g
->n
) + j
*words
, y
->coe
[j
]->n
, words
*sizeof(short));
335 y
->coe
[j
]->sign
= words
;
341 stuff(poly x
, giant g
, int words
) {
342 int deg
= x
->deg
, j
, coedigs
;
344 g
->sign
= words
*(1 + deg
);
345 for(j
=0; j
<= deg
; j
++) {
346 coedigs
= (x
->coe
[j
])->sign
;
347 bcopy(x
->coe
[j
]->n
, (g
->n
) + j
*words
, coedigs
*sizeof(short));
348 bzero((g
->n
) + (j
*words
+coedigs
),
349 sizeof(short)*(words
-coedigs
));
357 binarysegmul(poly x
, poly y
) {
358 int bits
= bitlen(p
), xwords
, ywords
, words
;
360 xwords
= (2*bits
+ log_2(x
->deg
+1) + 32 + 15)/16;
361 ywords
= (2*bits
+ log_2(y
->deg
+1) + 32 + 15)/16;
362 if(xwords
> ywords
) words
= xwords
; else words
= ywords
;
363 if(words
> maxwords
) {
365 // printf("m: %d\n", words);
368 stuff(x
, globx
, words
);
369 stuff(y
, globy
, words
);
371 gtog(y
->coe
[y
->deg
], globx
); /* Save high coeff. */
373 gtog(globx
, y
->coe
[y
->deg
]); /* Move high coeff. */
374 unstuff_partial(globy
, y
, words
);
375 mulg(x
->coe
[x
->deg
], y
->coe
[y
->deg
]); /* resolve high coeff. */
379 binarysegsquare(poly y
) {
380 int bits
= bitlen(p
), words
;
381 words
= (2*bits
+ log_2(y
->deg
+1) + 32 + 15)/16;
382 stuff(y
, globy
, words
);
384 gtog(y
->coe
[y
->deg
], globx
); /* Save high coeff. */
386 gtog(globx
, y
->coe
[y
->deg
]); /* Move high coeff. */
387 unstuff_partial(globy
, y
, words
);
388 mulg(y
->coe
[y
->deg
], y
->coe
[y
->deg
]); /* resolve high coeff. */
394 assess(poly x
, poly y
){
396 for(j
=0; j
<= x
->deg
; j
++) {
397 if(bitlen(x
->coe
[j
]) > max
) max
= bitlen(x
->coe
[j
]);
399 // printf("max: %d ", max);
401 for(j
=0; j
<= y
->deg
; j
++) {
402 if(bitlen(y
->coe
[j
]) > max
) max
= bitlen(y
->coe
[j
]);
404 // printf("%d\n", max);
410 pcompp(poly x
, poly y
) {
412 if(x
->deg
!= y
->deg
) return 1;
413 for(j
=0; j
<= x
->deg
; j
++) {
414 if(gcompg(x
->coe
[j
], y
->coe
[j
])) return 1;
425 int n
, degx
= x
->deg
, degy
= y
->deg
;
429 max_deg = degx; printf("xdeg: %d\n", degx);
433 max_deg = degy; printf("ydeg: %d\n", degy);
436 if((degx
< P_BREAK
) || (degy
< P_BREAK
)) {
441 if(x
==y
) binarysegsquare(y
);
442 else binarysegmul(x
, y
);
447 /* Reverse the coefficients of x. */
448 { int j
, deg
= x
->deg
;
450 for(j
=0; j
<= deg
/2; j
++) {
451 gtog(x
->coe
[deg
-j
], tmp
);
452 gtog(x
->coe
[j
], x
->coe
[deg
-j
]);
453 gtog(tmp
, x
->coe
[j
]);
459 recipp(poly f
, int deg
)
460 /* f := 1/f, via newton method. */
462 int lim
= deg
+ 1, prec
= 1;
464 sscratch
->deg
= 0; itog(1, sscratch
->coe
[0]);
468 if(prec
> lim
) prec
= lim
;
470 ptop(sscratch
, tscratch
);
472 tscratch
->deg
= prec
-1;
474 subg(aux
, tscratch
->coe
[0]);
475 quickmodg(p
, tscratch
->coe
[0]);
476 mulp(sscratch
, tscratch
);
477 tscratch
->deg
= prec
-1;
479 subp(tscratch
, sscratch
);
480 sscratch
->deg
= prec
-1;
488 left_justifyp(poly x
, int start
)
489 /* Left-justify the polynomial, checking from position "start." */
493 for(j
= start
; j
<= x
->deg
; j
++) {
494 if(!is0(x
->coe
[j
])) {
500 for(j
=0; j
<= x
->deg
; j
++) {
501 gtog(x
->coe
[j
+shift
], x
->coe
[j
]);
507 remp(poly x
, poly y
, int mode
)
509 mode = 0 is normal operation,
510 = 1 jams a fixed reciprocal,
511 = 2 uses the fixed reciprocal.
514 int degx
= x
->deg
, degy
= y
->deg
, d
, shift
;
529 case 0: recipp(rscratch
, d
);
531 case 1: recipp(rscratch
, degy
); /* degy -1. */
532 ptop(rscratch
, precip
);
533 rscratch
->deg
= d
; justifyp(rscratch
);
535 case 2: ptop(precip
, rscratch
);
536 rscratch
->deg
= d
; justifyp(rscratch
);
539 /* Next, a limited-precision multiply. */
540 if(d
< degx
) { x
->deg
= d
; justifyp(x
);}
545 x
->deg
= degx
; justifyp(x
);
549 shift
= left_justifyp(y
, d
+1);
550 for(d
= y
->deg
+1; d
<= degx
-shift
; d
++) itog(0, y
->coe
[d
]);
551 y
->deg
= degx
- shift
;
564 scalarmul(giant s
, poly x
) {
566 for(j
=0; j
<= x
->deg
; j
++) {
577 itog(0, s
[0]->coe
[0]);
580 itog(1, s
[1]->coe
[0]);
582 itog(2, s
[2]->coe
[0]);
585 gtog(a
, aux
); mulg(a
, aux
); negg(aux
);
586 gtog(aux
, s
[3]->coe
[0]);
587 gtog(b
, aux
); smulg(12, aux
);
588 gtog(aux
, s
[3]->coe
[1]);
589 gtog(a
, aux
); smulg(6, aux
);
590 gtog(aux
, s
[3]->coe
[2]);
591 itog(0, s
[3]->coe
[3]);
592 itog(3, s
[3]->coe
[4]);
595 gtog(a
, aux
); mulg(a
, aux
); mulg(a
, aux
);
596 gtog(b
, tmp
); mulg(b
, tmp
); smulg(8, tmp
); addg(tmp
, aux
);
598 gtog(aux
, s
[4]->coe
[0]);
599 gtog(b
, aux
); mulg(a
, aux
); smulg(4, aux
); negg(aux
);
600 gtog(aux
, s
[4]->coe
[1]);
601 gtog(a
, aux
); mulg(a
, aux
); smulg(5, aux
); negg(aux
);
602 gtog(aux
, s
[4]->coe
[2]);
603 gtog(b
, aux
); smulg(20, aux
);
604 gtog(aux
, s
[4]->coe
[3]);
605 gtog(a
, aux
); smulg(5, aux
);
606 gtog(aux
, s
[4]->coe
[4]);
607 itog(0, s
[4]->coe
[5]);
608 itog(1, s
[4]->coe
[6]);
610 scalarmul(aux
, s
[4]);
612 itog(1, cubic
->coe
[3]);
613 itog(0, cubic
->coe
[2]);
614 gtog(a
, cubic
->coe
[1]);
615 gtog(b
, cubic
->coe
[0]);
616 for(j
=5; j
<= el
; j
++) {
618 ptop(s
[j
/2 + 2], s
[j
]); mulp(s
[j
/2-1], s
[j
]);
619 polyrem(s
[j
]); mulp(s
[j
/2-1], s
[j
]); polyrem(s
[j
]);
620 ptop(s
[j
/2-2], s
[0]); mulp(s
[j
/2+1], s
[0]); polyrem(s
[0]);
621 mulp(s
[j
/2+1], s
[0]); polyrem(s
[0]);
622 subp(s
[0], s
[j
]); mulp(s
[j
/2], s
[j
]); polyrem(s
[j
]);
623 gtog(p
, aux
); iaddg(1, aux
); gshiftright(1, aux
);
624 scalarmul(aux
, s
[j
]);
626 ptop(s
[(j
-1)/2+2], s
[j
]);
627 mulp(s
[(j
-1)/2], s
[j
]); polyrem(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 ptop(s
[(j
-1)/2-1], s
[0]);
631 mulp(s
[(j
-1)/2 + 1], s
[0]); polyrem(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 if(((j
-1)/2) % 2 == 1) {
635 mulp(cubic
, s
[0]); polyrem(s
[0]);
636 mulp(cubic
, s
[0]); polyrem(s
[0]);
638 mulp(cubic
, s
[j
]); polyrem(s
[j
]);
639 mulp(cubic
, s
[j
]); polyrem(s
[j
]);
641 // polyout(s[1]); polyout(s[3]); polyout(s[0]); polyout(s[j]);
652 mulp(cubic
, smonic
); polyrem(smonic
);
654 gtog(smonic
->coe
[smonic
->deg
], aux
); /* High coeff. */
656 scalarmul(aux
, smonic
); /* s is now monic. */
657 s
[0]->deg
= smonic
->deg
+ 1;
658 for(j
=0; j
<= s
[0]->deg
; j
++) itog(1, s
[0]->coe
[j
]);
660 remp(s
[0], pbuff
, 1); /* Initialize reciprocal of s as precip. */
663 void powerpoly(poly x
, giant n
)
666 ptop(x
, pbuff
); /* x. */
668 mulmod(pbuff2
, pbuff2
); mulmod(pbuff
, pbuff2
); /* x^3. */
673 if(bitval(n
, pos
) != 0) {
678 code
= (bitval(n
, pos
) != 0) * 2 + (bitval(n
, pos
-1) != 0);
680 case 0: mulmod(x
,x
); break;
684 case 2: mulmod(pbuff
, x
);
686 case 3: mulmod(x
,x
); mulmod(pbuff2
, x
); break;
692 mulmod(poly x
, poly y
) {
693 mulp(x
, y
); fullmod(y
);
696 elldoublep(poly n1
, poly d1
, poly m1
, poly c1
, poly n0
, poly d0
,
699 ptop(n1
, mn
); mulmod(n1
, mn
);
700 ptop(mn
, pbuff
); addp(mn
, mn
); addp(pbuff
, mn
);
702 ptop(d1
, pbuff
); mulmod(d1
, pbuff
);
703 scalarmul(a
, pbuff
); addp(pbuff
, mn
);
706 ptop(m1
, md
); addp(md
, md
);
707 mulmod(d1
, md
); mulmod(d1
, md
); mulmod(cubic
, md
);
709 ptop(d1
, n0
); mulmod(mn
, n0
); mulmod(mn
, n0
);
711 ptop(n1
, pbuff
); addp(pbuff
, pbuff
); fullmod(pbuff
);
712 mulmod(md
, pbuff
); mulmod(md
, pbuff
);
713 subp(pbuff
, n0
); fullmod(n0
);
714 ptop(md
, d0
); mulmod(md
, d0
); mulmod(d1
, d0
);
716 ptop(mn
, m0
); mulmod(c1
, m0
);
717 ptop(d0
, pbuff
); mulmod(n1
, pbuff
);
718 ptop(n0
, c0
); mulmod(d1
, c0
); subp(c0
, pbuff
);
721 ptop(m1
, pbuff
); mulmod(md
, pbuff
);
722 mulmod(d1
, pbuff
); mulmod(d0
, pbuff
);
723 subp(pbuff
, m0
); fullmod(m0
);
725 ptop(c1
, c0
); mulmod(md
, c0
); mulmod(d1
, c0
); mulmod(d0
, c0
);
728 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
) {
729 ptop(m2
, mn
); mulmod(c1
, mn
);
730 ptop(m1
, pbuff
); mulmod(c2
, pbuff
);
731 subp(pbuff
, mn
); fullmod(mn
);
732 mulmod(d1
, mn
); mulmod(d2
, mn
);
734 ptop(n2
, md
); mulmod(d1
, md
);
735 ptop(n1
, pbuff
); mulmod(d2
, pbuff
);
736 subp(pbuff
, md
); fullmod(md
);
737 mulmod(c1
, md
); mulmod(c2
, md
);
739 ptop(cubic
, n0
); mulmod(mn
, n0
); mulmod(mn
, n0
);
740 mulmod(d1
, n0
); mulmod(d2
, n0
);
741 ptop(n1
, pbuff
); mulmod(d2
, pbuff
);
742 ptop(n2
, d0
); mulmod(d1
, d0
);
743 addp(d0
, pbuff
); mulmod(md
, pbuff
); mulmod(md
, pbuff
);
744 subp(pbuff
, n0
); fullmod(n0
);
746 ptop(md
, d0
); mulmod(md
, d0
); mulmod(d1
, d0
); mulmod(d2
, d0
);
748 ptop(mn
, m0
); mulmod(c1
, m0
);
749 ptop(d0
, pbuff
); mulmod(n1
, pbuff
);
750 ptop(d1
, c0
); mulmod(n0
, c0
);
751 subp(c0
, pbuff
); fullmod(pbuff
);
753 ptop(m1
, pbuff
); mulmod(md
, pbuff
);
754 mulmod(d0
, pbuff
); mulmod(d1
, pbuff
);
755 subp(pbuff
, m0
); fullmod(m0
);
757 ptop(md
, c0
); mulmod(c1
, c0
); mulmod(d0
, c0
); mulmod(d1
, c0
);
763 for(j
=0; j
<= x
->deg
; j
++) {printf("%d: ",j
); gout(x
->coe
[j
]);}
768 main(int argc
, char **argv
) {
769 int j
, ct
, el
, xmatch
, ymatch
;
771 int T
[L_MAX
], P
[L_MAX
];
773 unsigned int ord
, ordminus
;
775 printf("Initializing...\n"); fflush(stdout
);
778 for(j
=0; j
< L_MAX
; j
++) { /* Array to be used for CRT reconstruction. */
782 printf("Give p, a, b on separate lines:\n"); fflush(stdout
);
783 gin(p
); /* Field prime. */
785 fprintf(stderr
, "p too large, larger than %d bits.\n", Q
);
789 gin(a
); gin(b
); /* Curve parameters. */
792 printf("Checking discriminant for:\nb = ");
794 gtog(a
, t1
); squareg(t1
); modg(p
, t1
); mulg(a
, t1
); modg(p
, t1
);
795 gshiftleft(2, t1
); /* 4 a^3. */
796 gtog(b
, t2
); squareg(t2
); modg(p
, t2
); smulg(27, t2
);
797 addg(t2
, t1
); modg(p
, t1
);
799 printf("Discriminant FAILED\n");
803 printf("Discriminant PASSED\n");
804 printf("Starting sieve process:\n");
807 schain(SIEVE_CUT
+ 1); /* Do first piece of chain, for small-sieving. */
811 for(el
= 2; el
<= L_MAX
; el
+= 1 + (el%2
)) {
812 if(!primeq(el
)) continue;
813 L
= el
; while(L
*el
<= 4) L
*= el
;
814 printf("Resolving Schoof L = %d...\n", L
);
815 P
[ct
] = L
; /* Stuff another prime power. */
817 gtog(magcheck
, tmp
); squareg(tmp
); gshiftright(2, tmp
);
818 if(gcompg(tmp
, p
) > 0) break; /* Done...go to CRT phase. */
819 if((L
> SIEVE_CUT
) && (linit
== 0)) {
824 // printf("s: "); polyout(s[L]);
826 k
= idivg(L
, aux2
); /* p (mod L). */
828 k2
= idivg(el
, aux2
);
829 // printf("power...\n");
830 txd
->deg
= 0; itog(1, txd
->coe
[0]);
831 tyd
->deg
= 0; itog(1, tyd
->coe
[0]);
832 txn
->deg
= 1; itog(0, txn
->coe
[0]); itog(1, txn
->coe
[1]);
836 powerpoly(txn
, aux2
); /* x^p. */
837 // printf("x^p done...\n");
839 powerpoly(powx
, aux2
);
840 // printf("x^p^2 done...\n");
842 gtog(p
, aux2
); itog(1, aux
); subg(aux
, aux2
);
843 gshiftright(1, aux2
); /* aux2 := (p-1)/2. */
844 powerpoly(tyn
, aux2
); /* y^p. */
845 // printf("y^p done...\n");
846 ptop(tyn
, powy
); mulp(tyn
, powy
); fullmod(powy
);
847 mulp(cubic
, powy
); fullmod(powy
);
848 powerpoly(powy
, aux2
);
849 mulp(tyn
, powy
); fullmod(powy
);
850 // printf("Powers done...\n");
852 // printf("pow" ); polyout(powx); polyout(powy);
853 ptop(txn
, txn1
); ptop(txd
, txd1
); /* Save t = 1 case. */
854 ptop(tyn
, tyn1
); ptop(tyd
, tyd1
);
856 (powx, y powy) + k(kxn/kxd, y kyn/kyd) = t(txn/txd, y tyn/tyd)
859 if(k
==1) { ptop(txd
, kxd
); ptop(txd
, kyd
);
862 ptop(s
[k
], kxd
); mulp(s
[k
], kxd
); fullmod(kxd
);
863 if(k%2
==0) { mulp(cubic
, kxd
); fullmod(kxd
); }
864 mulp(kxd
, kxn
); fullmod(kxn
);
865 ptop(s
[k
-1], pbuff
); mulp(s
[k
+1], pbuff
); fullmod(pbuff
);
866 if(k%2
==1) {mulp(cubic
, pbuff
); fullmod(pbuff
); }
867 subp(pbuff
, kxn
); fullmod(kxn
);
869 ptop(s
[k
+2], kyn
); mulp(s
[k
-1], kyn
); fullmod(kyn
);
870 mulp(s
[k
-1], kyn
); fullmod(kyn
);
872 ptop(s
[k
-2], pbuff
); mulp(s
[k
+1], pbuff
); fullmod(pbuff
);
873 mulp(s
[k
+1], pbuff
); fullmod(pbuff
);
874 subp(pbuff
, kyn
); fullmod(kyn
);
876 ptop(s
[k
], kyd
); mulp(s
[k
], kyd
); fullmod(kyd
);
877 mulp(s
[k
], kyd
); fullmod(kyd
);
878 if(k%2
==0) { mulp(cubic
, kyd
); fullmod(kyd
);
879 mulp(cubic
, kyd
); fullmod(kyd
);}
880 itog(4, aux2
); scalarmul(aux2
, kyd
);
882 //printf("kP: "); polyout(kxn); polyout(kxd); polyout(kyn); polyout(kyd);
883 /* Commence t = 0 check. */
884 // printf("Checking t = %d ...\n", 0);
887 ptop(powx
, pbuff
); mulp(kxd
, pbuff
);
894 /* Now check y coords. */
895 if(L
== 2) goto resolve
;
896 ptop(powy
, pbuff
); mulp(kyd
, pbuff
);
901 printf("%d %d\n", L
, 0);
903 if((k2
+ 1 - T
[ct
-1]) % el
== 0) {
904 printf("TILT: %d\n", el
);
912 /* Combine pt1 and pt2. */
913 if((xmatch
== 1) && (ymatch
== 1))
914 elldoublep(powx
, txd
, powy
, txd
, nx
, dx
, ny
, dy
);
916 elladdp(powx
, txd
, powy
, txd
, kxn
, kxd
, kyn
, kyd
, nx
, dx
, ny
, dy
);
918 /* Now {nx/dx, ny/dy} is (fixed) LHS. */
919 // printf("add12: "); polyout(nx); polyout(dx); polyout(ny); polyout(dy);
920 /* Commence t > 0 check. */
921 for(t
=1; t
<= L
/2; t
++) {
922 // printf("Checking t = %d ...\n", t);
923 if(t
> 1) { /* Add (tx1, ty1) to (txn, tyn). */
924 ptop(txn1
, pbuff
); mulmod(txd
, pbuff
);
925 ptop(txn
, powx
); mulmod(txd1
, powx
);
926 subp(powx
, pbuff
); fullmod(pbuff
);
928 elladdp(txn1
, txd1
, tyn1
, tyd1
, txn
, txd
, tyn
, tyd
,
929 tmp1
, tmp2
, tmp3
, tmp4
);
930 else elldoublep(txn
, txd
, tyn
, tyd
,
931 tmp1
, tmp2
, tmp3
, tmp4
);
932 ptop(tmp1
, txn
); ptop(tmp2
, txd
);
933 ptop(tmp3
, tyn
); ptop(tmp4
, tyd
);
935 // printf("tQ: "); polyout(txn); polyout(txd); polyout(tyn); polyout(tyd);
936 /* Next, check {nx/dx, ny/dy} =? {txn/txd, tyn/tyd}. */
937 ptop(nx
, pbuff
); mulmod(txd
, pbuff
);
938 ptop(dx
, powx
); mulmod(txn
, powx
);
939 subp(powx
, pbuff
); fullmod(pbuff
);
940 if(!iszerop(pbuff
)) continue;
942 // printf("y check!\n");
943 ptop(ny
, pbuff
); mulmod(tyd
, pbuff
);
944 ptop(dy
, powx
); mulmod(tyn
, powx
);
945 subp(powx
, pbuff
); fullmod(pbuff
);
947 printf("%d %d\n", L
, t
);
950 printf("%d %d\n", L
, L
-t
);
953 if((k2
+ 1 - T
[ct
-1]) % el
== 0) {
954 printf("TILT: %d\n", el
);
965 /* Now, prime powers P[] and CRT residues T[] are intact. */
966 printf("Prime powers L:\n");
968 for(j
=0; j
< ct
-1; j
++) {
969 printf("%d, ", P
[j
]);
971 printf("%d }\n", P
[ct
-1]);
973 printf("Residues t (mod L):\n");
975 for(j
=0; j
< ct
-1; j
++) {
976 printf("%d, ", T
[j
]);
978 printf("%d }\n", T
[ct
-1]);
980 /* Mathematica algorithm for order:
981 plis = {2^5, 3^3, 5^2, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47};
982 tlis = {1, 26, 4, 2, 4, 11, 6, 5, 19, 22, 10, 16, 7, 22, 11};
983 prod = Apply[Times, plis];
985 invlis = Table[PowerMod[prlis[[q]], -1, plis[[q]]],{q,1,Length[plis]}];
987 t = Mod[tlis . (prlis * invlis), prod];
988 ord = p + 1 - If[t^2 > 4p, t - prod, t]
992 for(j
=0; j
< ct
; j
++) {
996 for(j
=0; j
< 2*ct
; j
++) {
997 if(!ss
[j
]) ss
[j
] = newgiant(MAX_DIGS
);
1000 for(j
=0; j
< ct
; j
++) {
1006 for(j
=0; j
< ct
; j
++) {
1007 gtog(ss
[j
], ss
[j
+ct
]);
1013 for(j
=0; j
< ct
; j
++) {
1024 gtog(p
, t3
); gshiftleft(2, t3
);
1025 if(gcompg(t4
, t3
) > 0) subg(t1
, t2
);
1027 printf("Parameters:\n");
1028 printf("p = "); gout(p
);
1029 printf("a = "); gout(a
);
1030 printf("b = "); gout(b
);
1031 printf("Curve order:\n");
1032 printf("o = "); gout(t5
);
1033 printf("pprob: %d\n", prime_probable(t5
));
1034 printf("Twist order:\n");
1039 printf("pprob: %d\n", prime_probable(t5
));