Line data Source code
1 : /* Copyright (C) 2015 The PARI group.
2 :
3 : This file is part of the PARI/GP package.
4 :
5 : PARI/GP is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 2 of the License, or (at your option) any later
8 : version. It is distributed in the hope that it will be useful, but WITHOUT
9 : ANY WARRANTY WHATSOEVER.
10 :
11 : Check the License for details. You should have received a copy of it, along
12 : with the package; see the file 'COPYING'. If not, write to the Free Software
13 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14 :
15 : #include "pari.h"
16 : #include "paripriv.h"
17 :
18 : /* This file is a C version by Bill Allombert of a GP script by
19 : Fernando Rodriguez-Villegas */
20 :
21 : /* --------------- GP code --------------------------------------- */
22 : /* http://www.ma.utexas.edu/users/villegas/cnt/jacobians.gp */
23 : /* */
24 : /* Description: Compute long Weierstrass equation for genus 1 curve */
25 : /* given by a plane curve */
26 : /* */
27 : /* Original Author: Fernando Rodriguez-Villegas */
28 : /* villegas@math.utexas.edu */
29 : /* University of Texas at Austin */
30 : /* */
31 : /* Created: Tue Jun 7 2005 */
32 : /* */
33 : /*----------------------------------------------------------------- */
34 :
35 : /* The mathematic behind this is described in
36 : On the Jacobians of plane cubics,
37 : Artin, Michael and Rodriguez-Villegas, Fernando and Tate, John,
38 : Advances in Mathematics, 198, 2005, 1, 366--382
39 : DOI: 10.1016/j.aim.2005.06.004
40 : URL: http://dx.doi.org/10.1016/j.aim.2005.06.004
41 : PDF: http://www.sciencedirect.com/science/article/pii/S0001870805001775
42 : */
43 :
44 : /* Input: coefficients of a cubic */
45 : /*t0*y^3+(s1+s0*x)*y^2 +(r2+r1*x+r0*x^2)*y+(q3+q2*x+q1*x^2+q0*x^3)=0*/
46 :
47 : static GEN
48 77 : jac_cubic(GEN t0, GEN s0, GEN s1, GEN r0, GEN r1, GEN r2, GEN q0, GEN q1, GEN q2, GEN q3)
49 : {
50 77 : GEN t0_2 = gsqr(t0);
51 77 : GEN s0_2 = gsqr(s0), s0_3 = gmul(s0, s0_2);
52 77 : GEN s1_2 = gsqr(s1), s1_3 = gmul(s1, s1_2);
53 77 : GEN r0_2 = gsqr(r0), r0_3 = gmul(r0, r0_2);
54 77 : GEN r1_2 = gsqr(r1), r1_3 = gmul(r1, r1_2);
55 77 : GEN r2_2 = gsqr(r2), r2_3 = gmul(r2, r2_2);
56 77 : GEN q0_2 = gsqr(q0);
57 77 : GEN q1_2 = gsqr(q1), q1_3 = gmul(q1, q1_2);
58 77 : GEN q2_2 = gsqr(q2), q2_3 = gmul(q2, q2_2);
59 77 : GEN q3_2 = gsqr(q3);
60 77 : GEN p1 = cgetg(6, t_VEC);
61 77 : gel(p1, 1) = r1;
62 77 : gel(p1, 2) = gneg(gadd(gadd(gmul(s0, q2), gmul(s1, q1)), gmul(r0, r2)));
63 77 : gel(p1, 3) = gadd(gmul(gsub(gmul(gmulsg(9, t0), q0), gmul(s0, r0)), q3), gadd(gmul(gsub(gmul(gneg(t0), q1), gmul(s1, r0)), q2), gsub(gmul(gmul(gneg(s0), r2), q1), gmul(gmul(s1, r2), q0))));
64 77 : gel(p1, 4) = gadd(gmul(gadd(gmul(gadd(gmul(gmulsg(-3, t0), r0), s0_2), q1), gadd(gmul(gmul(gmulsg(-3, s1), s0), q0), gmul(s1, r0_2))), q3), gadd(gadd(gmul(gmul(t0, r0), q2_2), gmul(gadd(gmul(gmul(s1, s0), q1), gadd(gmul(gadd(gmul(gmulsg(-3, t0), r2), s1_2), q0), gmul(gmul(s0, r0), r2))), q2)), gadd(gadd(gmul(gmul(t0, r2), q1_2), gmul(gmul(gmul(s1, r0), r2), q1)), gmul(gmul(s0, r2_2), q0))));
65 77 : gel(p1, 5) = gadd(gadd(gmul(gsub(gadd(gmul(gmulsg(-27, t0_2), q0_2), gmul(gsub(gmul(gmul(gmulsg(9, t0), s0), r0), s0_3), q0)), gmul(t0, r0_3)), q3_2), gmul(gadd(gmul(gadd(gmul(gsub(gmul(gmulsg(9, t0_2), q0), gmul(gmul(t0, s0), r0)), q1), gadd(gmul(gadd(gmul(gmul(gmulsg(-3, t0), s0), r1), gadd(gmul(gmul(gmulsg(3, t0), s1), r0), gmul(gmulsg(2, s1), s0_2))), q0), gsub(gmul(gmul(t0, r0_2), r1), gmul(gmul(s1, s0), r0_2)))), q2), gadd(gadd(gadd(gmul(gneg(t0_2), q1_3), gmul(gadd(gmul(gmul(t0, s0), r1), gsub(gmul(gmul(gmulsg(2, t0), s1), r0), gmul(s1, s0_2))), q1_2)), gmul(gadd(gmul(gadd(gmul(gmul(gmulsg(3, t0), s0), r2), gadd(gmul(gmul(gmulsg(-3, t0), s1), r1), gmul(gmulsg(2, s1_2), s0))), q0), gadd(gmul(gsub(gmul(gmulsg(2, t0), r0_2), gmul(s0_2, r0)), r2), gsub(gadd(gmul(gmul(gneg(t0), r0), r1_2), gmul(gmul(gmul(s1, s0), r0), r1)), gmul(s1_2, r0_2)))), q1)), gadd(gmul(gsub(gmul(gmul(gmulsg(9, t0), s1), r2), s1_3), q0_2), gmul(gadd(gmul(gsub(gmul(gadd(gmul(gmulsg(-3, t0), r0), s0_2), r1), gmul(gmul(s1, s0), r0)), r2), gadd(gsub(gmul(t0, r1_3), gmul(gmul(s1, s0), r1_2)), gmul(gmul(s1_2, r0), r1))), q0)))), q3)), gadd(gadd(gadd(gmul(gmul(gneg(t0_2), q0), q2_3), gmul(gadd(gmul(gmul(gmul(gneg(t0), s1), r0), q1), gsub(gmul(gadd(gmul(gmul(gmulsg(2, t0), s0), r2), gsub(gmul(gmul(t0, s1), r1), gmul(s1_2, s0))), q0), gmul(gmul(t0, r0_2), r2))), q2_2)), gmul(gadd(gadd(gmul(gmul(gmul(gneg(t0), s0), r2), q1_2), gmul(gadd(gmul(gmul(gmul(gneg(t0), s1), r2), q0), gmul(gsub(gmul(gmul(t0, r0), r1), gmul(gmul(s1, s0), r0)), r2)), q1)), gmul(gadd(gmul(gsub(gmul(gmulsg(2, t0), r0), s0_2), r2_2), gmul(gsub(gadd(gmul(gneg(t0), r1_2), gmul(gmul(s1, s0), r1)), gmul(s1_2, r0)), r2)), q0)), q2)), gsub(gadd(gmul(gmul(gmul(gneg(t0), r0), r2_2), q1_2), gmul(gmul(gmul(gsub(gmul(t0, r1), gmul(s1, s0)), r2_2), q0), q1)), gmul(gmul(t0, r2_3), q0_2))));
66 77 : return p1;
67 : }
68 :
69 : /* Input: coefficients of an equation */
70 : /* t0*y^2+(s0*x^2+s1*x+s2)*y+(r0*x^4+r1*x^3+r2*x^2+r3*x+r4)=0 */
71 :
72 : static GEN
73 35 : jac_quart(GEN t0, GEN s0, GEN s1, GEN s2, GEN r0, GEN r1, GEN r2, GEN r3, GEN r4)
74 : {
75 35 : GEN t0_2 = gsqr(t0), t0_3 = gmul(t0, t0_2);
76 35 : GEN s0_2 = gsqr(s0);
77 35 : GEN s1_2 = gsqr(s1);
78 35 : GEN s2_2 = gsqr(s2);
79 35 : GEN r1_2 = gsqr(r1);
80 35 : GEN r3_2 = gsqr(r3);
81 35 : GEN p1 = cgetg(6, t_VEC);
82 35 : gel(p1, 1) = s1;
83 35 : gel(p1, 2) = gsub(gmul(gneg(t0), r2), gmul(s0, s2));
84 35 : gel(p1, 3) = gsub(gmul(gmul(gneg(t0), s2), r1), gmul(gmul(t0, s0), r3));
85 35 : gel(p1, 4) = gadd(gadd(gadd(gmul(gneg(gsub(gmul(gmulsg(4, t0_2), r4), gmul(t0, s2_2))), r0), gmul(gmul(t0_2, r1), r3)), gmul(gmul(gmul(t0, s0), s2), r2)), gmul(gmul(t0, s0_2), r4));
86 35 : gel(p1, 5) = gsub(gsub(gsub(gmul(gneg(gadd(gsub(gadd(gmul(gneg(gsub(gmul(gmulsg(4, t0_3), r4), gmul(t0_2, s2_2))), r2), gmul(t0_3, r3_2)), gmul(gmul(gmul(t0_2, s1), s2), r3)), gmul(gmul(t0_2, s1_2), r4))), r0), gmul(gmul(t0_3, r1_2), r4)), gmul(gsub(gmul(gmul(gmul(t0_2, s0), s2), r3), gmul(gmul(gmul(t0_2, s0), s1), r4)), r1)), gmul(gmul(gmul(t0_2, s0_2), r2), r4));
87 35 : return p1;
88 : }
89 :
90 : /* Input: coefficients of an equation */
91 : /* (t0*x^2+t1*x+t2)*y^2+(r0*x^2+r1*x+r2)*y+(s0*x^2+s1*x+s2)=0 */
92 :
93 : static GEN
94 7 : jac_biquadr(GEN t0, GEN t1, GEN t2, GEN r0, GEN r1, GEN r2,
95 : GEN s0, GEN s1, GEN s2)
96 : {
97 7 : GEN t0_2 = gsqr(t0);
98 7 : GEN t1_2 = gsqr(t1);
99 7 : GEN t2_2 = gsqr(t2);
100 7 : GEN s0_2 = gsqr(s0);
101 7 : GEN s1_2 = gsqr(s1);
102 7 : GEN s2_2 = gsqr(s2);
103 7 : GEN r0_2 = gsqr(r0);
104 7 : GEN r1_2 = gsqr(r1);
105 7 : GEN r2_2 = gsqr(r2);
106 7 : GEN p1 = cgetg(6, t_VEC);
107 7 : gel(p1, 1) = r1;
108 7 : gel(p1, 2) = gneg(gadd(gadd(gadd(gmul(s2, t0), gmul(t2, s0)), gmul(t1, s1)), gmul(r2, r0)));
109 7 : gel(p1, 3) = gadd(gmul(gmul(gneg(r2), s1), t0), gadd(gmul(gmul(gneg(t1), r2), s0), gsub(gmul(gmul(gneg(t2), r0), s1), gmul(gmul(t1, r0), s2))));
110 7 : gel(p1, 4) = gadd(gmul(gadd(gmul(gadd(gmul(gmulsg(-4, t2), s2), r2_2), s0), gadd(gadd(gmul(t2, s1_2), gmul(gmul(t1, s2), s1)), gmul(gmul(r2, r0), s2))), t0), gadd(gmul(gadd(gmul(gmul(t2, t1), s1), gadd(gmul(t1_2, s2), gmul(gmul(t2, r2), r0))), s0), gadd(gmul(gmul(gmul(t1, r2), r0), s1), gmul(gmul(t2, r0_2), s2))));
111 7 : gel(p1, 5) = gadd(gadd(gmul(gsub(gmul(gsub(gmul(gmulsg(4, t2), s2_2), gmul(r2_2, s2)), s0), gmul(gmul(t2, s2), s1_2)), t0_2), gmul(gadd(gadd(gmul(gsub(gmul(gmulsg(4, t2_2), s2), gmul(t2, r2_2)), s0_2), gmul(gadd(gadd(gmul(gneg(t2_2), s1_2), gmul(gsub(gmul(gmul(t2, r2), r1), gmul(t1, r2_2)), s1)), gadd(gmul(gneg(t1_2), s2_2), gmul(gadd(gmul(gneg(t2), r1_2), gmul(gmul(t1, r2), r1)), s2))), s0)), gsub(gadd(gmul(gmul(gmul(gneg(t2), r2), r0), s1_2), gmul(gmul(gmul(gsub(gmul(t2, r1), gmul(t1, r2)), r0), s2), s1)), gmul(gmul(t2, r0_2), s2_2))), t0)), gsub(gadd(gmul(gmul(gmul(gneg(t2), t1_2), s2), s0_2), gmul(gadd(gmul(gmul(gmul(gmul(gneg(t2), t1), r2), r0), s1), gmul(gadd(gmul(gneg(t2_2), r0_2), gmul(gsub(gmul(gmul(t2, t1), r1), gmul(t1_2, r2)), r0)), s2)), s0)), gmul(gmul(gmul(gmul(t2, t1), r0_2), s2), s1)));
112 7 : return p1;
113 : }
114 :
115 : INLINE long
116 385 : dg(GEN P, long v)
117 : {
118 385 : if (typ(P)!=t_POL || varn(P)!=v || !signe(P))
119 322 : return -1;
120 63 : return degpol(P);
121 : }
122 :
123 : INLINE GEN
124 1638 : co(GEN P, long i, long v)
125 : {
126 1638 : if (typ(P)!=t_POL || varn(P)!=v)
127 574 : return i==0 ? P: gen_0;
128 1064 : if (i>degpol(P)) return gen_0;
129 994 : return gel(P, i+2);
130 : }
131 :
132 : GEN
133 119 : ellfromeqn(GEN P)
134 : {
135 119 : pari_sp av = avma;
136 : long vx, vy, dx, dy, dm;
137 119 : GEN r = gen_0;
138 119 : if (typ(P)!=t_POL) pari_err_TYPE("ellfromeqn",P);
139 119 : vx = varn(P); vy = gvar2(P);
140 119 : if (vy==NO_VARIABLE) pari_err_TYPE("ellfromeqn",P);
141 119 : dx = poldegree(P, vx);
142 119 : dy = poldegree(P, vy);
143 119 : dm = maxss(dx, dy);
144 119 : if (dm == 2)
145 : {
146 7 : GEN p_0 = co(P, 0, vx), p_1 = co(P, 1, vx), p_2 = co(P, 2, vx);
147 7 : r = jac_biquadr(co(p_2, 2, vy), co(p_2, 1, vy), co(p_2, 0, vy),
148 : co(p_1, 2, vy), co(p_1, 1, vy), co(p_1, 0, vy),
149 : co(p_0, 2, vy), co(p_0, 1, vy), co(p_0, 0, vy));
150 : }
151 112 : else if (dm == 3)
152 : {
153 77 : GEN p_0 = co(P, 0, vx), p_1 = co(P, 1, vx),
154 77 : p_2 = co(P, 2, vx), p_3 = co(P, 3, vx);
155 77 : if (dg(p_3, vy) > 0 || dg(p_2, vy) > 1 || dg(p_1, vy) > 2)
156 0 : r = gen_0; /* genus > 1 */
157 : else
158 77 : r = jac_cubic( co(p_3, 0, vy),
159 : co(p_2, 1, vy), co(p_2, 0, vy),
160 : co(p_1, 2, vy), co(p_1, 1, vy), co(p_1, 0, vy),
161 : co(p_0, 3, vy), co(p_0, 2, vy), co(p_0, 1, vy), co(p_0, 0, vy));
162 : }
163 35 : else if (dm == 4 && dx == 2)
164 7 : {
165 7 : GEN p_0 = co(P, 0, vx), p_1 = co(P, 1, vx), p_2 = co(P, 2, vx);
166 7 : if (dg(p_2, vy) > 0 || dg(p_1, vy) > 2)
167 0 : r = gen_0; /* genus > 1 */
168 : else
169 7 : r = jac_quart( co(p_2, 0, vy),
170 : co(p_1, 2, vy), co(p_1, 1, vy), co(p_1, 0, vy),
171 : co(p_0, 4, vy), co(p_0, 3, vy), co(p_0, 2, vy), co(p_0, 1, vy),
172 : co(p_0, 0, vy));
173 : }
174 28 : else if (dm == 4 && dx == 4)
175 : {
176 28 : GEN p_0 = co(P, 0, vx), p_1 = co(P, 1, vx), p_2 = co(P, 2, vx),
177 28 : p_3 = co(P, 3, vx), p_4 = co(P, 4, vx);
178 28 : if (dg(p_4, vy) > 0 || dg(p_3, vy) > 0
179 28 : || dg(p_2, vy) > 1 || dg(p_1, vy) > 1 || dg(p_0, vy) > 2)
180 0 : r = gen_0; /* genus > 1 */
181 : else
182 28 : r = jac_quart(co(p_0, 2, vy),
183 : co(p_2, 1, vy), co(p_1, 1, vy), co(p_0, 1, vy),
184 : co(p_4, 0, vy), co(p_3, 0, vy), co(p_2, 0, vy),
185 : co(p_1, 0, vy), co(p_0, 0, vy));
186 : }
187 119 : if (r==gen_0)
188 0 : pari_err_DOMAIN("ellfromeqn", "genus", "!=", gen_1,P);
189 119 : return gerepilecopy(av, r);
190 : }
|