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 p1 = cgetg(6, t_VEC);
51 77 : gel(p1, 1) = gcopy(r1);
52 77 : gel(p1, 2) = gneg(gadd(gadd(gmul(s0, q2), gmul(s1, q1)), gmul(r0, r2)));
53 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))));
54 77 : gel(p1, 4) = gadd(gmul(gadd(gmul(gadd(gmul(gmulsg(-3, t0), r0), gsqr(s0)), q1), gadd(gmul(gmul(gmulsg(-3, s1), s0), q0), gmul(s1, gsqr(r0)))), q3), gadd(gadd(gmul(gmul(t0, r0), gsqr(q2)), gmul(gadd(gmul(gmul(s1, s0), q1), gadd(gmul(gadd(gmul(gmulsg(-3, t0), r2), gsqr(s1)), q0), gmul(gmul(s0, r0), r2))), q2)), gadd(gadd(gmul(gmul(t0, r2), gsqr(q1)), gmul(gmul(gmul(s1, r0), r2), q1)), gmul(gmul(s0, gsqr(r2)), q0))));
55 77 : gel(p1, 5) = gadd(gadd(gmul(gsub(gadd(gmul(gmulsg(-27, gsqr(t0)), gsqr(q0)), gmul(gsub(gmul(gmul(gmulsg(9, t0), s0), r0), gpowgs(s0, 3)), q0)), gmul(t0, gpowgs(r0, 3))), gsqr(q3)), gmul(gadd(gmul(gadd(gmul(gsub(gmul(gmulsg(9, gsqr(t0)), 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), gsqr(s0)))), q0), gsub(gmul(gmul(t0, gsqr(r0)), r1), gmul(gmul(s1, s0), gsqr(r0))))), q2), gadd(gadd(gadd(gmul(gneg(gsqr(t0)), gpowgs(q1, 3)), gmul(gadd(gmul(gmul(t0, s0), r1), gsub(gmul(gmul(gmulsg(2, t0), s1), r0), gmul(s1, gsqr(s0)))), gsqr(q1))), gmul(gadd(gmul(gadd(gmul(gmul(gmulsg(3, t0), s0), r2), gadd(gmul(gmul(gmulsg(-3, t0), s1), r1), gmul(gmulsg(2, gsqr(s1)), s0))), q0), gadd(gmul(gsub(gmul(gmulsg(2, t0), gsqr(r0)), gmul(gsqr(s0), r0)), r2), gsub(gadd(gmul(gmul(gneg(t0), r0), gsqr(r1)), gmul(gmul(gmul(s1, s0), r0), r1)), gmul(gsqr(s1), gsqr(r0))))), q1)), gadd(gmul(gsub(gmul(gmul(gmulsg(9, t0), s1), r2), gpowgs(s1, 3)), gsqr(q0)), gmul(gadd(gmul(gsub(gmul(gadd(gmul(gmulsg(-3, t0), r0), gsqr(s0)), r1), gmul(gmul(s1, s0), r0)), r2), gadd(gsub(gmul(t0, gpowgs(r1, 3)), gmul(gmul(s1, s0), gsqr(r1))), gmul(gmul(gsqr(s1), r0), r1))), q0)))), q3)), gadd(gadd(gadd(gmul(gmul(gneg(gsqr(t0)), q0), gpowgs(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(gsqr(s1), s0))), q0), gmul(gmul(t0, gsqr(r0)), r2))), gsqr(q2))), gmul(gadd(gadd(gmul(gmul(gmul(gneg(t0), s0), r2), gsqr(q1)), 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), gsqr(s0)), gsqr(r2)), gmul(gsub(gadd(gmul(gneg(t0), gsqr(r1)), gmul(gmul(s1, s0), r1)), gmul(gsqr(s1), r0)), r2)), q0)), q2)), gsub(gadd(gmul(gmul(gmul(gneg(t0), r0), gsqr(r2)), gsqr(q1)), gmul(gmul(gmul(gsub(gmul(t0, r1), gmul(s1, s0)), gsqr(r2)), q0), q1)), gmul(gmul(t0, gpowgs(r2, 3)), gsqr(q0)))));
56 77 : return p1;
57 : }
58 :
59 : /* Input: coefficients of an equation */
60 : /* t0*y^2+(s0*x^2+s1*x+s2)*y+(r0*x^4+r1*x^3+r2*x^2+r3*x+r4)=0 */
61 :
62 : static GEN
63 35 : jac_quart(GEN t0, GEN s0, GEN s1, GEN s2, GEN r0, GEN r1, GEN r2, GEN r3, GEN r4)
64 : {
65 35 : GEN p1 = cgetg(6, t_VEC);
66 35 : gel(p1, 1) = gcopy(s1);
67 35 : gel(p1, 2) = gsub(gmul(gneg(t0), r2), gmul(s0, s2));
68 35 : gel(p1, 3) = gsub(gmul(gmul(gneg(t0), s2), r1), gmul(gmul(t0, s0), r3));
69 35 : gel(p1, 4) = gadd(gadd(gadd(gmul(gneg(gsub(gmul(gmulsg(4, gsqr(t0)), r4), gmul(t0, gsqr(s2)))), r0), gmul(gmul(gsqr(t0), r1), r3)), gmul(gmul(gmul(t0, s0), s2), r2)), gmul(gmul(t0, gsqr(s0)), r4));
70 35 : gel(p1, 5) = gsub(gsub(gsub(gmul(gneg(gadd(gsub(gadd(gmul(gneg(gsub(gmul(gmulsg(4, gpowgs(t0, 3)), r4), gmul(gsqr(t0), gsqr(s2)))), r2), gmul(gpowgs(t0, 3), gsqr(r3))), gmul(gmul(gmul(gsqr(t0), s1), s2), r3)), gmul(gmul(gsqr(t0), gsqr(s1)), r4))), r0), gmul(gmul(gpowgs(t0, 3), gsqr(r1)), r4)), gmul(gsub(gmul(gmul(gmul(gsqr(t0), s0), s2), r3), gmul(gmul(gmul(gsqr(t0), s0), s1), r4)), r1)), gmul(gmul(gmul(gsqr(t0), gsqr(s0)), r2), r4));
71 35 : return p1;
72 : }
73 :
74 : /* Input: coefficients of an equation */
75 : /* (t0*x^2+t1*x+t2)*y^2+(r0*x^2+r1*x+r2)*y+(s0*x^2+s1*x+s2)=0 */
76 :
77 : static GEN
78 7 : jac_biquadr(GEN t0, GEN t1, GEN t2, GEN r0, GEN r1, GEN r2,
79 : GEN s0, GEN s1, GEN s2)
80 : {
81 7 : GEN p1 = cgetg(6, t_VEC);
82 7 : gel(p1, 1) = gcopy(r1);
83 7 : gel(p1, 2) = gneg(gadd(gadd(gadd(gmul(s2, t0), gmul(t2, s0)), gmul(t1, s1)), gmul(r2, r0)));
84 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))));
85 7 : gel(p1, 4) = gadd(gmul(gadd(gmul(gadd(gmul(gmulsg(-4, t2), s2), gsqr(r2)), s0), gadd(gadd(gmul(t2, gsqr(s1)), gmul(gmul(t1, s2), s1)), gmul(gmul(r2, r0), s2))), t0), gadd(gmul(gadd(gmul(gmul(t2, t1), s1), gadd(gmul(gsqr(t1), s2), gmul(gmul(t2, r2), r0))), s0), gadd(gmul(gmul(gmul(t1, r2), r0), s1), gmul(gmul(t2, gsqr(r0)), s2))));
86 7 : gel(p1, 5) = gadd(gadd(gmul(gsub(gmul(gsub(gmul(gmulsg(4, t2), gsqr(s2)), gmul(gsqr(r2), s2)), s0), gmul(gmul(t2, s2), gsqr(s1))), gsqr(t0)), gmul(gadd(gadd(gmul(gsub(gmul(gmulsg(4, gsqr(t2)), s2), gmul(t2, gsqr(r2))), gsqr(s0)), gmul(gadd(gadd(gmul(gneg(gsqr(t2)), gsqr(s1)), gmul(gsub(gmul(gmul(t2, r2), r1), gmul(t1, gsqr(r2))), s1)), gadd(gmul(gneg(gsqr(t1)), gsqr(s2)), gmul(gadd(gmul(gneg(t2), gsqr(r1)), gmul(gmul(t1, r2), r1)), s2))), s0)), gsub(gadd(gmul(gmul(gmul(gneg(t2), r2), r0), gsqr(s1)), gmul(gmul(gmul(gsub(gmul(t2, r1), gmul(t1, r2)), r0), s2), s1)), gmul(gmul(t2, gsqr(r0)), gsqr(s2)))), t0)), gsub(gadd(gmul(gmul(gmul(gneg(t2), gsqr(t1)), s2), gsqr(s0)), gmul(gadd(gmul(gmul(gmul(gmul(gneg(t2), t1), r2), r0), s1), gmul(gadd(gmul(gneg(gsqr(t2)), gsqr(r0)), gmul(gsub(gmul(gmul(t2, t1), r1), gmul(gsqr(t1), r2)), r0)), s2)), s0)), gmul(gmul(gmul(gmul(t2, t1), gsqr(r0)), s2), s1)));
87 7 : return p1;
88 : }
89 :
90 : INLINE long
91 385 : dg(GEN P, long v)
92 : {
93 385 : if (typ(P)!=t_POL || varn(P)!=v || !signe(P))
94 322 : return -1;
95 63 : return degpol(P);
96 : }
97 :
98 : INLINE GEN
99 1638 : co(GEN P, long i, long v)
100 : {
101 1638 : if (typ(P)!=t_POL || varn(P)!=v)
102 574 : return i==0 ? P: gen_0;
103 1064 : if (i>degpol(P)) return gen_0;
104 994 : return gel(P, i+2);
105 : }
106 :
107 : GEN
108 119 : ellfromeqn(GEN P)
109 : {
110 119 : pari_sp av = avma;
111 : long vx, vy, dx, dy, dm;
112 119 : GEN r = gen_0;
113 119 : if (typ(P)!=t_POL) pari_err_TYPE("ellfromeqn",P);
114 119 : vx = varn(P); vy = gvar2(P);
115 119 : if (vy==NO_VARIABLE) pari_err_TYPE("ellfromeqn",P);
116 119 : dx = poldegree(P, vx);
117 119 : dy = poldegree(P, vy);
118 119 : dm = maxss(dx, dy);
119 119 : if (dm == 2)
120 : {
121 7 : GEN p_0 = co(P, 0, vx), p_1 = co(P, 1, vx), p_2 = co(P, 2, vx);
122 7 : r = jac_biquadr(co(p_2, 2, vy), co(p_2, 1, vy), co(p_2, 0, vy),
123 : co(p_1, 2, vy), co(p_1, 1, vy), co(p_1, 0, vy),
124 : co(p_0, 2, vy), co(p_0, 1, vy), co(p_0, 0, vy));
125 : }
126 112 : else if (dm == 3)
127 : {
128 77 : GEN p_0 = co(P, 0, vx), p_1 = co(P, 1, vx),
129 77 : p_2 = co(P, 2, vx), p_3 = co(P, 3, vx);
130 77 : if (dg(p_3, vy) > 0 || dg(p_2, vy) > 1 || dg(p_1, vy) > 2)
131 0 : r = gen_0; /* genus > 1 */
132 : else
133 77 : r = jac_cubic( co(p_3, 0, vy),
134 : co(p_2, 1, vy), co(p_2, 0, vy),
135 : co(p_1, 2, vy), co(p_1, 1, vy), co(p_1, 0, vy),
136 : co(p_0, 3, vy), co(p_0, 2, vy), co(p_0, 1, vy), co(p_0, 0, vy));
137 : }
138 35 : else if (dm == 4 && dx == 2)
139 7 : {
140 7 : GEN p_0 = co(P, 0, vx), p_1 = co(P, 1, vx), p_2 = co(P, 2, vx);
141 7 : if (dg(p_2, vy) > 0 || dg(p_1, vy) > 2)
142 0 : r = gen_0; /* genus > 1 */
143 : else
144 7 : r = jac_quart( co(p_2, 0, vy),
145 : co(p_1, 2, vy), co(p_1, 1, vy), co(p_1, 0, vy),
146 : co(p_0, 4, vy), co(p_0, 3, vy), co(p_0, 2, vy), co(p_0, 1, vy),
147 : co(p_0, 0, vy));
148 : }
149 28 : else if (dm == 4 && dx == 4)
150 : {
151 28 : GEN p_0 = co(P, 0, vx), p_1 = co(P, 1, vx), p_2 = co(P, 2, vx),
152 28 : p_3 = co(P, 3, vx), p_4 = co(P, 4, vx);
153 28 : if (dg(p_4, vy) > 0 || dg(p_3, vy) > 0
154 28 : || dg(p_2, vy) > 1 || dg(p_1, vy) > 1 || dg(p_0, vy) > 2)
155 0 : r = gen_0; /* genus > 1 */
156 : else
157 28 : r = jac_quart(co(p_0, 2, vy),
158 : co(p_2, 1, vy), co(p_1, 1, vy), co(p_0, 1, vy),
159 : co(p_4, 0, vy), co(p_3, 0, vy), co(p_2, 0, vy),
160 : co(p_1, 0, vy), co(p_0, 0, vy));
161 : }
162 119 : if (r==gen_0)
163 0 : pari_err_DOMAIN("ellfromeqn", "genus", "!=", gen_1,P);
164 119 : return gerepileupto(av, r);
165 : }
|