Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

""" 

Hyperelliptic curve constructor 

""" 

from __future__ import absolute_import 

 

#***************************************************************************** 

# Copyright (C) 2006 David Kohel <kohel@maths.usyd.edu> 

# Distributed under the terms of the GNU General Public License (GPL) 

# http://www.gnu.org/licenses/ 

#***************************************************************************** 

 

from sage.schemes.projective.projective_space import ProjectiveSpace 

 

from .hyperelliptic_generic import HyperellipticCurve_generic 

from .hyperelliptic_finite_field import HyperellipticCurve_finite_field 

from .hyperelliptic_rational_field import HyperellipticCurve_rational_field 

from .hyperelliptic_padic_field import HyperellipticCurve_padic_field 

from .hyperelliptic_g2_generic import HyperellipticCurve_g2_generic 

from .hyperelliptic_g2_finite_field import HyperellipticCurve_g2_finite_field 

from .hyperelliptic_g2_rational_field import HyperellipticCurve_g2_rational_field 

from .hyperelliptic_g2_padic_field import HyperellipticCurve_g2_padic_field 

 

from sage.rings.padics.all import is_pAdicField 

 

from sage.rings.rational_field import is_RationalField 

from sage.rings.finite_rings.finite_field_constructor import is_FiniteField 

from sage.rings.polynomial.polynomial_element import is_Polynomial 

 

 

def HyperellipticCurve(f, h=0, names=None, PP=None, check_squarefree=True): 

r""" 

Returns the hyperelliptic curve `y^2 + h y = f`, for 

univariate polynomials `h` and `f`. If `h` 

is not given, then it defaults to 0. 

 

INPUT: 

 

- ``f`` - univariate polynomial 

 

- ``h`` - optional univariate polynomial 

 

- ``names`` (default: ``["x","y"]``) - names for the 

coordinate functions 

 

- ``check_squarefree`` (default: ``True``) - test if 

the input defines a hyperelliptic curve when f is 

homogenized to degree `2g+2` and h to degree 

`g+1` for some g. 

 

.. WARNING:: 

 

When setting ``check_squarefree=False`` or using a base ring that is 

not a field, the output curves are not to be trusted. For example, the 

output of ``is_singular`` is always ``False``, without this being 

properly tested in that case. 

 

.. NOTE:: 

 

The words "hyperelliptic curve" are normally only used for curves of 

genus at least two, but this class allows more general smooth double 

covers of the projective line (conics and elliptic curves), even though 

the class is not meant for those and some outputs may be incorrect. 

 

EXAMPLES: 

 

Basic examples:: 

 

sage: R.<x> = QQ[] 

sage: HyperellipticCurve(x^5 + x + 1) 

Hyperelliptic Curve over Rational Field defined by y^2 = x^5 + x + 1 

sage: HyperellipticCurve(x^19 + x + 1, x-2) 

Hyperelliptic Curve over Rational Field defined by y^2 + (x - 2)*y = x^19 + x + 1 

 

sage: k.<a> = GF(9); R.<x> = k[] 

sage: HyperellipticCurve(x^3 + x - 1, x+a) 

Hyperelliptic Curve over Finite Field in a of size 3^2 defined by y^2 + (x + a)*y = x^3 + x + 2 

 

Characteristic two:: 

 

sage: P.<x> = GF(8,'a')[] 

sage: HyperellipticCurve(x^7+1, x) 

Hyperelliptic Curve over Finite Field in a of size 2^3 defined by y^2 + x*y = x^7 + 1 

sage: HyperellipticCurve(x^8+x^7+1, x^4+1) 

Hyperelliptic Curve over Finite Field in a of size 2^3 defined by y^2 + (x^4 + 1)*y = x^8 + x^7 + 1 

 

sage: HyperellipticCurve(x^8+1, x) 

Traceback (most recent call last): 

... 

ValueError: Not a hyperelliptic curve: highly singular at infinity. 

 

sage: HyperellipticCurve(x^8+x^7+1, x^4) 

Traceback (most recent call last): 

... 

ValueError: Not a hyperelliptic curve: singularity in the provided affine patch. 

 

sage: F.<t> = PowerSeriesRing(FiniteField(2)) 

sage: P.<x> = PolynomialRing(FractionField(F)) 

sage: HyperellipticCurve(x^5+t, x) 

Hyperelliptic Curve over Laurent Series Ring in t over Finite Field of size 2 defined by y^2 + x*y = x^5 + t 

 

We can change the names of the variables in the output:: 

 

sage: k.<a> = GF(9); R.<x> = k[] 

sage: HyperellipticCurve(x^3 + x - 1, x+a, names=['X','Y']) 

Hyperelliptic Curve over Finite Field in a of size 3^2 defined by Y^2 + (X + a)*Y = X^3 + X + 2 

 

This class also allows curves of genus zero or one, which are strictly 

speaking not hyperelliptic:: 

 

sage: P.<x> = QQ[] 

sage: HyperellipticCurve(x^2+1) 

Hyperelliptic Curve over Rational Field defined by y^2 = x^2 + 1 

sage: HyperellipticCurve(x^4-1) 

Hyperelliptic Curve over Rational Field defined by y^2 = x^4 - 1 

sage: HyperellipticCurve(x^3+2*x+2) 

Hyperelliptic Curve over Rational Field defined by y^2 = x^3 + 2*x + 2 

 

Double roots:: 

 

sage: P.<x> = GF(7)[] 

sage: HyperellipticCurve((x^3-x+2)^2*(x^6-1)) 

Traceback (most recent call last): 

... 

ValueError: Not a hyperelliptic curve: singularity in the provided affine patch. 

 

sage: HyperellipticCurve((x^3-x+2)^2*(x^6-1), check_squarefree=False) 

Hyperelliptic Curve over Finite Field of size 7 defined by y^2 = x^12 + 5*x^10 + 4*x^9 + x^8 + 3*x^7 + 3*x^6 + 2*x^4 + 3*x^3 + 6*x^2 + 4*x + 3 

 

The input for a (smooth) hyperelliptic curve of genus `g` should not 

contain polynomials of degree greater than `2g+2`. In the following 

example, the hyperelliptic curve has genus 2 and there exists a model 

`y^2 = F` of degree 6, so the model `y^2 + yh = f` of degree 200 is not 

allowed.:: 

 

sage: P.<x> = QQ[] 

sage: h = x^100 

sage: F = x^6+1 

sage: f = F-h^2/4 

sage: HyperellipticCurve(f, h) 

Traceback (most recent call last): 

... 

ValueError: Not a hyperelliptic curve: highly singular at infinity. 

 

sage: HyperellipticCurve(F) 

Hyperelliptic Curve over Rational Field defined by y^2 = x^6 + 1 

 

An example with a singularity over an inseparable extension of the 

base field:: 

 

sage: F.<t> = GF(5)[] 

sage: P.<x> = F[] 

sage: HyperellipticCurve(x^5+t) 

Traceback (most recent call last): 

... 

ValueError: Not a hyperelliptic curve: singularity in the provided affine patch. 

 

Input with integer coefficients creates objects with the integers 

as base ring, but only checks smoothness over `\QQ`, not over Spec(`\ZZ`). 

In other words, it is checked that the discriminant is non-zero, but it is 

not checked whether the discriminant is a unit in `\ZZ^*`.:: 

 

sage: P.<x> = ZZ[] 

sage: HyperellipticCurve(3*x^7+6*x+6) 

Hyperelliptic Curve over Integer Ring defined by y^2 = 3*x^7 + 6*x + 6 

 

TESTS: 

 

Check that `f` can be a constant (see :trac:`15516`):: 

 

sage: R.<u> = PolynomialRing(Rationals()) 

sage: HyperellipticCurve(-12, u^4 + 7) 

Hyperelliptic Curve over Rational Field defined by y^2 + (x^4 + 7)*y = -12 

 

""" 

# F is the discriminant; use this for the type check 

# rather than f and h, one of which might be constant. 

F = h**2 + 4*f 

if not is_Polynomial(F): 

raise TypeError("Arguments f (= %s) and h (= %s) must be polynomials" % (f, h)) 

P = F.parent() 

f = P(f) 

h = P(h) 

df = f.degree() 

dh_2 = 2*h.degree() 

if dh_2 < df: 

g = (df-1)//2 

else: 

g = (dh_2-1)//2 

if check_squarefree: 

# Assuming we are working over a field, this checks that after 

# resolving the singularity at infinity, we get a smooth double cover 

# of P^1. 

if P(2) == 0: 

# characteristic 2 

if h == 0: 

raise ValueError("In characteristic 2, argument h (= %s) must be non-zero."%h) 

if h[g+1] == 0 and f[2*g+1]**2 == f[2*g+2]*h[g]**2: 

raise ValueError("Not a hyperelliptic curve: " \ 

"highly singular at infinity.") 

should_be_coprime = [h, f*h.derivative()**2+f.derivative()**2] 

else: 

# characteristic not 2 

if not F.degree() in [2*g+1, 2*g+2]: 

raise ValueError("Not a hyperelliptic curve: " \ 

"highly singular at infinity.") 

should_be_coprime = [F, F.derivative()] 

try: 

smooth = should_be_coprime[0].gcd(should_be_coprime[1]).degree()==0 

except (AttributeError, NotImplementedError, TypeError): 

try: 

smooth = should_be_coprime[0].resultant(should_be_coprime[1])!=0 

except (AttributeError, NotImplementedError, TypeError): 

raise NotImplementedError("Cannot determine whether " \ 

"polynomials %s have a common root. Use " \ 

"check_squarefree=False to skip this check." % \ 

should_be_coprime) 

if not smooth: 

raise ValueError("Not a hyperelliptic curve: " \ 

"singularity in the provided affine patch.") 

R = P.base_ring() 

PP = ProjectiveSpace(2, R) 

if names is None: 

names = ["x","y"] 

if is_FiniteField(R): 

if g == 2: 

return HyperellipticCurve_g2_finite_field(PP, f, h, names=names, genus=g) 

else: 

return HyperellipticCurve_finite_field(PP, f, h, names=names, genus=g) 

elif is_RationalField(R): 

if g == 2: 

return HyperellipticCurve_g2_rational_field(PP, f, h, names=names, genus=g) 

else: 

return HyperellipticCurve_rational_field(PP, f, h, names=names, genus=g) 

elif is_pAdicField(R): 

if g == 2: 

return HyperellipticCurve_g2_padic_field(PP, f, h, names=names, genus=g) 

else: 

return HyperellipticCurve_padic_field(PP, f, h, names=names, genus=g) 

else: 

if g == 2: 

return HyperellipticCurve_g2_generic(PP, f, h, names=names, genus=g) 

else: 

return HyperellipticCurve_generic(PP, f, h, names=names, genus=g)