Tripling-oriented Doche/Icart/Kohel coordinates represent an affine point (x,y) on a tripling-oriented Doche/Icart/Kohel-form elliptic curve y^2 = x^3 + 3a(x+1)^2 as (X:Y:Z:ZZ) satisfying Y^2 = X^3 + 3aZ^2(X+Z^2)^2 and ZZ = Z^2. Here (X:Y:Z:ZZ) = (s^2 X:s^3 Y:sZ:s^2 ZZ) for all nonzero s.
Speed records:
The following commands for the Magma computer-algebra system check various addition formulas for tripling-oriented Doche/Icart/Kohel coordinates.
Tripling-oriented Doche/Icart/Kohel scaling.
K<a,X1,Y1,X2,Y2>:=FieldOfFractions(PolynomialRing(Rationals(),5));
R<Z1,Z2>:=PolynomialRing(K,2);
S:=quo<R|Y1^2-X1^3-3*a*Z1^2*(X1+Z1^2)^2,Y2^2-X2^3-3*a*Z2^2*(X2+Z2^2)^2>;
// here are the formulas:
A:=1/Z1;
AA:=A^2;
X2:=X1*AA;
Y2:=Y1*AA*A;
Z2:=1;
// check:
x1:=X1/Z1^2; y1:=Y1/Z1^3;
S!(y1^2-x1^3-3*a*(x1+1)^2);
x2:=X2/Z2^2; y2:=Y2/Z2^3;
S!(y2^2-x2^3-3*a*(x2+1)^2);
S!(Z2-1);
S!(x2-x1); S!(y2-y1);
Tripling-oriented Doche/Icart/Kohel addition (11M+6S+1D+13add+2times2+1times3+1times8+1times16) matches traditional addition. S,M counts stated in the literature: 11M + 6S in 2007 Bernstein/Birkner/Lange/Peters.
2006 Doche/Icart/Kohel, page 199, top display, Z2 set to 1, affine only:
K<a,x1,x2>:=FieldOfFractions(PolynomialRing(Rationals(),3));
R<y1,y2>:=PolynomialRing(K,2);
S:=quo<R|y1^2-x1^3-3*a*(x1+1)^2,y2^2-x2^3-3*a*(x2+1)^2>;
X1:=x1; Y1:=y1; Z1:=1;
X2:=x2; Y2:=y2; Z2:=1;
// here are the formulas:
// uncached:
A:=X1;
B:=Y1;
C:=X2-A;
D:=Y2-B;
Z3:=C;
E:=Z3^2;
F:=C^2;
G:=C*F;
H:=A*F;
X3:=D^2-G-3*a*E-2*H;
Y3:=D*(H-X3)-B*G;
Z3Z3:=E;
// back to affine:
Z3Z3-Z3^2;
x3:=X3/Z3^2; y3:=Y3/Z3^3;
S!(y3^2-x3^3-3*a*(x3+1)^2);
// versus traditional affine formulas:
x1:=X1/Z1^2; y1:=Y1/Z1^3;
x2:=X2/Z2^2; y2:=Y2/Z2^3;
lambda:=(y2-y1)/(x2-x1);
r3:=lambda^2-3*a-x1-x2; s3:=lambda*(x1-r3)-y1;
// check the answer:
S!(x3-r3); S!(y3-s3);
Simplified, projectified:
K<a,X1,Y1,X2,Y2>:=FieldOfFractions(PolynomialRing(Rationals(),5));
R<Z1,Z2>:=PolynomialRing(K,2);
S:=quo<R|Y1^2-X1^3-3*a*Z1^2*(X1+Z1^2)^2,Y2^2-X2^3-3*a*Z2^2*(X2+Z2^2)^2>;
x1:=X1/Z1^2; y1:=Y1/Z1^3;
S!(y1^2-x1^3-3*a*(x1+1)^2);
x2:=X2/Z2^2; y2:=Y2/Z2^3;
S!(y2^2-x2^3-3*a*(x2+1)^2);
// here are the formulas:
D:=Y2/Z2^3-Y1/Z1^3;
Z3:=X2/Z2^2-X1/Z1^2;
X3:=D^2-Z3^3-3*a*Z3^2-2*Z3^2*X1/Z1^2;
Y3:=D*(Z3^2*X1/Z1^2-X3)-Z3^3*Y1/Z1^3;
// back to affine:
x3:=X3/Z3^2; y3:=Y3/Z3^3;
S!(y3^2-x3^3-3*a*(x3+1)^2);
// versus traditional affine formulas:
lambda:=(y2-y1)/(x2-x1);
r3:=lambda^2-3*a-x1-x2; s3:=lambda*(x1-r3)-y1;
// check the answer:
S!(x3-r3); S!(y3-s3);
Denominators cleared:
K<a,X1,Y1,X2,Y2>:=FieldOfFractions(PolynomialRing(Rationals(),5));
R<Z1,Z2>:=PolynomialRing(K,2);
S:=quo<R|Y1^2-X1^3-3*a*Z1^2*(X1+Z1^2)^2,Y2^2-X2^3-3*a*Z2^2*(X2+Z2^2)^2>;
x1:=X1/Z1^2; y1:=Y1/Z1^3;
S!(y1^2-x1^3-3*a*(x1+1)^2);
x2:=X2/Z2^2; y2:=Y2/Z2^3;
S!(y2^2-x2^3-3*a*(x2+1)^2);
// here are the formulas:
A:=X2*Z1^2-X1*Z2^2;
B:=Y2*Z1^3-Y1*Z2^3;
X3:=B^2-A^3-Z1^2*Z2^2*3*a*A^2-Z2^2*2*A^2*X1;
Y3:=B*(Z2^2*A^2*X1-X3)-Z2^3*A^3*Y1;
Z3:=Z1*Z2*A;
// back to affine:
x3:=X3/Z3^2; y3:=Y3/Z3^3;
S!(y3^2-x3^3-3*a*(x3+1)^2);
// versus traditional affine formulas:
lambda:=(y2-y1)/(x2-x1);
r3:=lambda^2-3*a-x1-x2; s3:=lambda*(x1-r3)-y1;
// check the answer:
S!(x3-r3); S!(y3-s3);
Common subexpressions eliminated,
13M + 4S + 1D + 7add + 1times2 + 1times3:
K<a,X1,Y1,X2,Y2>:=FieldOfFractions(PolynomialRing(Rationals(),5));
R<Z1,Z2>:=PolynomialRing(K,2);
S:=quo<R|Y1^2-X1^3-3*a*Z1^2*(X1+Z1^2)^2,Y2^2-X2^3-3*a*Z2^2*(X2+Z2^2)^2>;
x1:=X1/Z1^2; y1:=Y1/Z1^3;
S!(y1^2-x1^3-3*a*(x1+1)^2);
x2:=X2/Z2^2; y2:=Y2/Z2^3;
S!(y2^2-x2^3-3*a*(x2+1)^2);
// already provided as part of input:
Z1Z1:=Z1^2;
Z2Z2:=Z2^2;
// here are the formulas:
A:=X2*Z1Z1-X1*Z2Z2;
B:=Y2*Z1*Z1Z1-Y1*Z2*Z2Z2;
C:=Z2*A;
CC:=C^2;
D:=X1*CC;
Z3:=Z1*C;
E:=Z3^2;
X3:=B^2-A*A^2-3*a*E-2*D;
Y3:=B*(D-X3)-Y1*C*CC;
Z3Z3:=E;
// back to affine:
Z3Z3-Z3^2;
x3:=X3/Z3^2; y3:=Y3/Z3^3;
S!(y3^2-x3^3-3*a*(x3+1)^2);
// versus traditional affine formulas:
lambda:=(y2-y1)/(x2-x1);
r3:=lambda^2-3*a-x1-x2; s3:=lambda*(x1-r3)-y1;
// check the answer:
S!(x3-r3); S!(y3-s3);
2007 Bernstein/Birkner/Lange/Peters,
11M + 6S + 1D + 13add + 2times2 + 1times3 + 1times8 + 1times16:
K<a,X1,Y1,X2,Y2>:=FieldOfFractions(PolynomialRing(Rationals(),5));
R<Z1,Z2>:=PolynomialRing(K,2);
S:=quo<R|Y1^2-X1^3-3*a*Z1^2*(X1+Z1^2)^2,Y2^2-X2^3-3*a*Z2^2*(X2+Z2^2)^2>;
x1:=X1/Z1^2; y1:=Y1/Z1^3;
S!(y1^2-x1^3-3*a*(x1+1)^2);
x2:=X2/Z2^2; y2:=Y2/Z2^3;
S!(y2^2-x2^3-3*a*(x2+1)^2);
// already provided as part of input:
Z1Z1:=Z1^2;
Z2Z2:=Z2^2;
// cached:
Z2Z2Z2:=Z2*Z2Z2;
// uncached:
Z1Z1Z1:=Z1*Z1Z1;
A:=X2*Z1Z1-X1*Z2Z2;
B:=Y2*Z1Z1Z1-Y1*Z2Z2Z2;
AA:=A^2;
C:=(Z2+A)^2-Z2Z2-AA;
CC:=C^2;
CC8:=8*CC;
D:=X1*CC8;
Z3:=(Z1+C)^2-Z1Z1-CC;
E:=Z3^2;
X3:=16*(B^2-A*AA)-D-3*a*E;
Y3:=2*B*(D-2*X3)-Y1*C*CC8;
Z3Z3:=E;
// back to affine:
Z3Z3-Z3^2;
x3:=X3/Z3^2; y3:=Y3/Z3^3;
S!(y3^2-x3^3-3*a*(x3+1)^2);
// versus traditional affine formulas:
lambda:=(y2-y1)/(x2-x1);
r3:=lambda^2-3*a-x1-x2; s3:=lambda*(x1-r3)-y1;
// check the answer:
S!(x3-r3); S!(y3-s3);
Tripling-oriented Doche/Icart/Kohel mixed addition (7M+4S+1D+10add+3times2+1times3+1times4) matches traditional addition. S,M,D counts stated in the literature: 8M+3S+1D in 2006 Doche/Icart/Kohel ("8M+3S to compute an addition. If u is a random element in the field, then an extra multiplication is required"). 7M+4S+1D in 2007 Bernstein/Lange.
2006 Doche/Icart/Kohel, page 199, top display, roles of 1 and 2 reversed, 8M+3S+1D+7add+1times2+1times3:
K<a,X1,Y1,X2>:=FieldOfFractions(PolynomialRing(Rationals(),4));
R<Z1,Y2>:=PolynomialRing(K,2);
Z2:=1;
S:=quo<R|Y1^2-X1^3-3*a*Z1^2*(X1+Z1^2)^2,Y2^2-X2^3-3*a*Z2^2*(X2+Z2^2)^2>;
// here are the formulas:
// already provided as part of input:
Z1Z1:=Z1^2;
// uncached:
A:=X2*Z1Z1;
B:=Y2*Z1Z1*Z1;
C:=X1-A;
D:=Y1-B;
Z3:=Z1*C;
E:=Z3^2;
F:=C^2;
G:=C*F;
H:=A*F;
X3:=D^2-G-3*a*E-2*H;
Y3:=D*(H-X3)-B*G;
Z3Z3:=E;
// back to affine:
Z3Z3-Z3^2;
x3:=X3/Z3^2; y3:=Y3/Z3^3;
S!(y3^2-x3^3-3*a*(x3+1)^2);
// versus traditional affine formulas:
x1:=X1/Z1^2; y1:=Y1/Z1^3;
x2:=X2/Z2^2; y2:=Y2/Z2^3;
lambda:=(y2-y1)/(x2-x1);
r3:=lambda^2-3*a-x1-x2; s3:=lambda*(x1-r3)-y1;
// check the answer:
S!(x3-r3); S!(y3-s3);
2007 Bernstein/Birkner/Lange/Peters,
7M+4S+1D+10add+3times2+1times3+1times4:
K<a,X1,Y1,X2>:=FieldOfFractions(PolynomialRing(Rationals(),4));
R<Z1,Y2>:=PolynomialRing(K,2);
Z2:=1;
S:=quo<R|Y1^2-X1^3-3*a*Z1^2*(X1+Z1^2)^2,Y2^2-X2^3-3*a*Z2^2*(X2+Z2^2)^2>;
// here are the formulas:
// already provided as part of input:
Z1Z1:=Z1^2;
// uncached:
A:=X2*Z1Z1;
B:=Y2*Z1Z1*Z1;
C:=X1-A;
D:=2*(Y1-B);
F:=C^2;
F4:=4*F;
Z3:=(Z1+C)^2-Z1Z1-F;
E:=Z3^2;
G:=C*F4;
H:=A*F4;
X3:=D^2-G-2*H-3*a*E;
Y3:=D*(H-X3)-2*B*G;
Z3Z3:=E;
// back to affine:
Z3Z3-Z3^2;
x3:=X3/Z3^2; y3:=Y3/Z3^3;
S!(y3^2-x3^3-3*a*(x3+1)^2);
// versus traditional affine formulas:
x1:=X1/Z1^2; y1:=Y1/Z1^3;
x2:=X2/Z2^2; y2:=Y2/Z2^3;
lambda:=(y2-y1)/(x2-x1);
r3:=lambda^2-3*a-x1-x2; s3:=lambda*(x1-r3)-y1;
// check the answer:
S!(x3-r3); S!(y3-s3);
Tripling-oriented Doche/Icart/Kohel addition with Z1=1 and Z2=1 (4M + 2S + 1D + 7add + 4times2 + 1times3 + 1times4) matches traditional addition. S,M,D counts stated in the literature: 8M+3S+1D in 2007 Bernstein/Lange.
2007 Bernstein/Birkner/Lange/Peters, 4M + 2S + 1D + 7add + 4times2 + 1times3 + 1times4:
K<a,X1,Y1,X2>:=FieldOfFractions(PolynomialRing(Rationals(),4));
R<Z1,Y2>:=PolynomialRing(K,2);
Z1:=1; Z2:=1;
S:=quo<R|Y1^2-X1^3-3*a*Z1^2*(X1+Z1^2)^2,Y2^2-X2^3-3*a*Z2^2*(X2+Z2^2)^2>;
// here are the formulas:
// uncached:
C:=X1-X2;
D:=2*(Y1-Y2);
F:=C^2;
F4:=4*F;
Z3:=2*C;
G:=C*F4;
H:=X2*F4;
X3:=D^2-G-2*H-3*a*F4;
Y3:=D*(H-X3)-2*Y2*G;
Z3Z3:=F4;
// back to affine:
Z3Z3-Z3^2;
x3:=X3/Z3^2; y3:=Y3/Z3^3;
S!(y3^2-x3^3-3*a*(x3+1)^2);
// versus traditional affine formulas:
x1:=X1/Z1^2; y1:=Y1/Z1^3;
x2:=X2/Z2^2; y2:=Y2/Z2^3;
lambda:=(y2-y1)/(x2-x1);
r3:=lambda^2-3*a-x1-x2; s3:=lambda*(x1-r3)-y1;
// check the answer:
S!(x3-r3); S!(y3-s3);
Tripling-oriented Doche/Icart/Kohel doubling (2M + 7S + 2D + 12add + 3times2 + 2times3 + 1times8) matches traditional doubling. S,M,D counts stated in the literature: 4M+5S+2D in 2006 Doche/Icart/Kohel ("4M+5S as long as we neglect multiplications by u, otherwise a doubling can be obtained with 6M+4S"; no explanation of the 4S). 2M+7S+2D in 2007 Bernstein/Birkner/Lange/Peters.
2006 Doche/Icart/Kohel, page 198, bottom display, corrected by 2007 Bernstein/Birkner/Lange/Peters to incorporate the missing -3a term:
K<a,x1>:=FieldOfFractions(PolynomialRing(Rationals(),2));
R<y1>:=PolynomialRing(K,1);
S:=quo<R|y1^2-x1^3-3*a*(x1+1)^2>;
x2:=x1; y2:=y1;
X1:=x1; Y1:=y1; Z1:=1;
// already provided as part of input:
Z1Z1:=Z1^2;
// here are the formulas:
// warning: 2006 Doche/Icart/Kohel is missing -3*a*Z3Z3
A:=Y1*Z1;
Z3:=2*A;
B:=4*Y1^2*X1;
C:=B+6*a*A^2;
Z3Z3:=4*A^2;
D:=3*X1^2;
E:=D+6*a*Z1Z1*(Z1Z1+X1);
X3:=E^2-2*B-3*a*Z3Z3;
Y3:=E*(B-X3)-8*Y1^4;
// back to affine:
S!(Z3Z3-Z3^2);
x3:=X3/Z3^2; y3:=Y3/Z3^3;
S!(y3^2-x3^3-3*a*(x3+1)^2);
// versus traditional affine formulas:
lambda:=(3*x1^2+6*a*x1+6*a)/(2*y1);
r3:=lambda^2-3*a-2*x1; s3:=lambda*(x1-r3)-y1;
// check the answer:
S!(x3-r3); S!(y3-s3);
2006 Doche/Icart/Kohel, page 198, bottom display,
corrected by 2007 Bernstein/Birkner/Lange/Peters to incorporate the missing -3a term:
K<a,X1,Y1>:=FieldOfFractions(PolynomialRing(Rationals(),3));
R<Z1>:=PolynomialRing(K,1);
S:=quo<R|Y1^2-X1^3-3*a*Z1^2*(X1+Z1^2)^2>;
x1:=X1/Z1^2; y1:=Y1/Z1^3;
// already provided as part of input:
Z1Z1:=Z1^2;
// here are the formulas:
// warning: 2006 Doche/Icart/Kohel is missing -3*a*Z3Z3
A:=Y1*Z1;
Z3:=2*A;
B:=4*Y1^2*X1;
C:=B+6*a*A^2;
Z3Z3:=4*A^2;
D:=3*X1^2;
E:=D+6*a*Z1Z1*(Z1Z1+X1);
X3:=E^2-2*B-3*a*Z3Z3;
Y3:=E*(B-X3)-8*Y1^4;
// back to affine:
S!(Z3Z3-Z3^2);
x3:=X3/Z3^2; y3:=Y3/Z3^3;
S!(y3^2-x3^3-3*a*(x3+1)^2);
// versus traditional affine formulas:
lambda:=(3*x1^2+6*a*x1+6*a)/(2*y1);
r3:=lambda^2-3*a-2*x1; s3:=lambda*(x1-r3)-y1;
// check the answer:
S!(x3-r3); S!(y3-s3);
2006 Doche/Icart/Kohel, page 198, bottom display,
corrected by 2007 Bernstein/Birkner/Lange/Peters to incorporate the missing -3a term,
unused C eliminated,
common subexpressions eliminated,
4M + 5S + 2D + 6add + 2times2 + 2times3 + 1times4 + 1times6 + 1times8:
K<a,X1,Y1>:=FieldOfFractions(PolynomialRing(Rationals(),3));
R<Z1>:=PolynomialRing(K,1);
S:=quo<R|Y1^2-X1^3-3*a*Z1^2*(X1+Z1^2)^2>;
x1:=X1/Z1^2; y1:=Y1/Z1^3;
// already provided as part of input:
Z1Z1:=Z1^2;
// here are the formulas:
Y1Y1:=Y1^2;
A:=Y1*Z1;
Z3:=2*A;
B:=4*Y1Y1*X1;
Z3Z3:=Z3^2;
D:=3*X1^2;
E:=D+6*a*Z1Z1*(Z1Z1+X1);
X3:=E^2-2*B-3*a*Z3Z3;
Y3:=E*(B-X3)-8*Y1Y1^2;
// back to affine:
S!(Z3Z3-Z3^2);
x3:=X3/Z3^2; y3:=Y3/Z3^3;
S!(y3^2-x3^3-3*a*(x3+1)^2);
// versus traditional affine formulas:
lambda:=(3*x1^2+6*a*x1+6*a)/(2*y1);
r3:=lambda^2-3*a-2*x1; s3:=lambda*(x1-r3)-y1;
// check the answer:
S!(x3-r3); S!(y3-s3);
2007 Bernstein/Birkner/Lange/Peters,
2M + 7S + 2D + 12add + 3times2 + 2times3 + 1times8:
K<a,X1,Y1>:=FieldOfFractions(PolynomialRing(Rationals(),3));
R<Z1>:=PolynomialRing(K,1);
S:=quo<R|Y1^2-X1^3-3*a*Z1^2*(X1+Z1^2)^2>;
x1:=X1/Z1^2; y1:=Y1/Z1^3;
// already provided as part of input:
Z1Z1:=Z1^2;
// here are the formulas:
A:=X1^2;
B:=2*a*Z1Z1*(X1+Z1Z1);
C:=3*(A+B);
D:=Y1^2;
E:=D^2;
Z3:=(Y1+Z1)^2-D-Z1Z1;
Z3Z3:=Z3^2;
F:=2*((X1+D)^2-A-E);
X3:=C^2-3*a*Z3Z3-2*F;
Y3:=C*(F-X3)-8*E;
// back to affine:
S!(Z3Z3-Z3^2);
x3:=X3/Z3^2; y3:=Y3/Z3^3;
S!(y3^2-x3^3-3*a*(x3+1)^2);
// versus traditional affine formulas:
lambda:=(3*x1^2+6*a*x1+6*a)/(2*y1);
r3:=lambda^2-3*a-2*x1; s3:=lambda*(x1-r3)-y1;
// check the answer:
S!(x3-r3); S!(y3-s3);
Tripling-oriented Doche/Icart/Kohel doubling with Z1=1 (1M + 5S + 2D + 9add + 4times2 + 2times3 + 1times4+ 1times8) matches traditional doubling. S,M,D counts stated in the literature: 1M + 5S + 2D in 2007 Bernstein/Lange.
K<a,X1,Y1>:=FieldOfFractions(PolynomialRing(Rationals(),3));
R<Z1>:=PolynomialRing(K,1);
S:=quo<R|Y1^2-X1^3-3*a*Z1^2*(X1+Z1^2)^2>;
Z1:=1;
x1:=X1/Z1^2; y1:=Y1/Z1^3;
// here are the formulas:
A:=X1^2;
B:=2*a*(X1+1);
C:=3*(A+B);
D:=Y1^2;
E:=D^2;
Z3:=2*Y1;
Z3Z3:=4*D;
F:=2*((X1+D)^2-A-E);
X3:=C^2-3*a*Z3Z3-2*F;
Y3:=C*(F-X3)-8*E;
// back to affine:
S!(Z3Z3-Z3^2);
x3:=X3/Z3^2; y3:=Y3/Z3^3;
S!(y3^2-x3^3-3*a*(x3+1)^2);
// versus traditional affine formulas:
lambda:=(3*x1^2+6*a*x1+6*a)/(2*y1);
r3:=lambda^2-3*a-2*x1; s3:=lambda*(x1-r3)-y1;
// check the answer:
S!(x3-r3); S!(y3-s3);
Tripling-oriented Doche/Icart/Kohel tripling (6M+6S+2D+7add+4times3+2times4+1times9) matches traditional tripling. S,M,D counts stated in the literature: 6M+6S+2D in 2006 Doche/Icart/Kohel ("6M+6S ... a multiplication by u is negligible. Otherwise, 8M+6S are necessary"). 6M+6S+2D in 2007 Bernstein/Birkner/Lange/Peters; thanks to Hisil for comments.
2006 Doche/Icart/Kohel, page 198, middle display:
K<a,x1>:=FieldOfFractions(PolynomialRing(Rationals(),2));
R<y1>:=PolynomialRing(K,1);
S:=quo<R|y1^2-x1^3-3*a*(x1+1)^2>;
x2:=x1; y2:=y1;
X1:=x1; Y1:=y1; Z1:=1;
// already provided as part of input:
Z1Z1:=Z1^2;
// here are the formulas:
A:=(X1+3*Z1Z1)^2;
B:=a*Z1Z1*A;
Xt:=Y1^2+B;
Yt:=Y1*(Y1^2-3*B);
Zt:=X1*Z1;
C:=Zt^2;
D:=((4*a-9)*C-Xt)^2;
E:=-3*a*C*D;
X3:=(Yt^2+E);
Y3:=Yt*(X3-4*E);
Z3:=3*Xt*Zt;
Z3Z3:=Z3^2;
// back to affine:
S!(Z3Z3-Z3^2);
x3:=X3/Z3^2; y3:=Y3/Z3^3;
S!(y3^2-x3^3-3*a*(x3+1)^2);
// versus traditional affine formulas:
lambda:=(3*x1^2+6*a*x1+6*a)/(2*y1);
r2:=lambda^2-3*a-2*x1; s2:=lambda*(x1-r2)-y1;
lambda:=(s2-y1)/(r2-x1);
r3:=lambda^2-3*a-x1-r2; s3:=lambda*(x1-r3)-y1;
// check the answer:
S!(x3-r3); S!(y3-s3);
2006 Doche/Icart/Kohel, page 198, middle display:
K<a,X1,Y1>:=FieldOfFractions(PolynomialRing(Rationals(),3));
R<Z1>:=PolynomialRing(K,1);
S:=quo<R|Y1^2-X1^3-3*a*Z1^2*(X1+Z1^2)^2>;
x1:=X1/Z1^2; y1:=Y1/Z1^3;
// already provided as part of input:
Z1Z1:=Z1^2;
// here are the formulas:
A:=(X1+3*Z1Z1)^2;
B:=a*Z1Z1*A;
Xt:=Y1^2+B;
Yt:=Y1*(Y1^2-3*B);
Zt:=X1*Z1;
C:=Zt^2;
D:=((4*a-9)*C-Xt)^2;
E:=-3*a*C*D;
X3:=(Yt^2+E);
Y3:=Yt*(X3-4*E);
Z3:=3*Xt*Zt;
Z3Z3:=Z3^2;
// back to affine:
S!(Z3Z3-Z3^2);
x3:=X3/Z3^2; y3:=Y3/Z3^3;
S!(y3^2-x3^3-3*a*(x3+1)^2);
// versus traditional affine formulas:
lambda:=(3*x1^2+6*a*x1+6*a)/(2*y1);
r2:=lambda^2-3*a-2*x1; s2:=lambda*(x1-r2)-y1;
lambda:=(s2-y1)/(r2-x1);
r3:=lambda^2-3*a-x1-r2; s3:=lambda*(x1-r3)-y1;
// check the answer:
S!(x3-r3); S!(y3-s3);
2006 Doche/Icart/Kohel, page 198, middle display,
common subexpressions eliminated,
6M + 6S + 2D + 7add + 4times3 + 2times4 + 1times9:
K<a,X1,Y1>:=FieldOfFractions(PolynomialRing(Rationals(),3));
R<Z1>:=PolynomialRing(K,1);
S:=quo<R|Y1^2-X1^3-3*a*Z1^2*(X1+Z1^2)^2>;
x1:=X1/Z1^2; y1:=Y1/Z1^3;
// already provided as part of input:
Z1Z1:=Z1^2;
// here are the formulas:
Y1Y1:=Y1^2;
A:=(X1+3*Z1Z1)^2;
B:=a*Z1Z1*A;
Xt:=Y1Y1+B;
Yt:=Y1*(Y1Y1-3*B);
Zt:=X1*Z1;
C:=Zt^2;
Ca:=a*C;
E:=3*Ca*(4*Ca-9*C-Xt)^2;
X3:=Yt^2-E;
Y3:=Yt*(X3+4*E);
Z3:=3*Xt*Zt;
Z3Z3:=Z3^2;
// back to affine:
S!(Z3Z3-Z3^2);
x3:=X3/Z3^2; y3:=Y3/Z3^3;
S!(y3^2-x3^3-3*a*(x3+1)^2);
// versus traditional affine formulas:
lambda:=(3*x1^2+6*a*x1+6*a)/(2*y1);
r2:=lambda^2-3*a-2*x1; s2:=lambda*(x1-r2)-y1;
lambda:=(s2-y1)/(r2-x1);
r3:=lambda^2-3*a-x1-r2; s3:=lambda*(x1-r3)-y1;
// check the answer:
S!(x3-r3); S!(y3-s3);