205 | | points = [self.point([K(0), one, K(0)], check=True)] |
206 | | |
| 205 | |
| 206 | # start with the points at infinity |
| 207 | P = self.defining_polynomial() |
| 208 | if not P(K(0), K(1), K(0)): |
| 209 | # (0:1:0) is a point on the curve |
| 210 | points = [self.point([K(0), K(1), K(0)], check=True)] |
| 211 | else: |
| 212 | points=[] |
| 213 | if P.degree() > 2: |
| 214 | # P(1, y, 0) = r*y + s |
| 215 | s = P(K(1), K(0), K(0)) |
| 216 | r = P(K(1), K(1), K(0)) - s |
| 217 | if r: # r not zero |
| 218 | points.append(self.point([K(1), -s/r, K(0)], check=True)) |
| 219 | # the case r = 0 need not be considered |
| 220 | elif K.characteristic() == 2: # deg(P) = 2 and char(K) = 2 |
| 221 | # quadratic equation doesn't work in characteristic 2 so use brute force |
| 222 | points += [self.point([K(1), y, K(0)], check=True) for y in K if not P(K(1), y, K(0))] |
| 223 | else: # deg(P) = 2 and char(K) not 2 |
| 224 | # P(1, y, 0) = y^2 + r*y + s |
| 225 | if f.degree() < 2: |
| 226 | s = 0 |
| 227 | else: |
| 228 | s = -f.coeffs()[-1] |
| 229 | if h.degree() < 1: |
| 230 | r = 0 |
| 231 | else: |
| 232 | r = h.coeffs()[-1] |
| 233 | d = r**2/4 - s |
| 234 | if not d: # d = 0 |
| 235 | points.append(self.point([K(1), -r/2, K(0)], check=True)) |
| 236 | elif d.is_square(): |
| 237 | sqrtd = d.sqrt() |
| 238 | points.append(self.point([K(1), -r/2 + sqrtd, K(0)], check=True)) |
| 239 | points.append(self.point([K(1), -r/2 - sqrtd, K(0)], check=True)) |
| 240 | |
279 | | points = [self.point([K(0), one, K(0)], check=True)] |
280 | | |
| 313 | |
| 314 | # start with the points at infinity |
| 315 | P = self.defining_polynomial() |
| 316 | if not P(K(0), K(1), K(0)): |
| 317 | # (0:1:0) is a point on the curve |
| 318 | points = [self.point([K(0), K(1), K(0)], check=True)] |
| 319 | else: |
| 320 | points=[] |
| 321 | if P.degree() > 2: |
| 322 | # P(1, y, 0) = r*y + s |
| 323 | s = P(K(1), K(0), K(0)) |
| 324 | r = P(K(1), K(1), K(0)) - s |
| 325 | if r: # r not zero |
| 326 | points.append(self.point([K(1), -s/r, K(0)], check=True)) |
| 327 | # the case r = 0 need not be considered |
| 328 | elif K.characteristic() == 2: # deg(P) = 2 and char(K) = 2 |
| 329 | # quadratic equation doesn't work in characteristic 2 so use brute force |
| 330 | points += [self.point([K(1), y, K(0)], check=True) for y in K if not P(K(1), y, K(0))] |
| 331 | else: # deg(P) = 2 and char(K) not 2 |
| 332 | # P(1, y, 0) = y^2 + r*y + s |
| 333 | if f.degree() < 2: |
| 334 | s = 0 |
| 335 | else: |
| 336 | s = -f.coeffs()[-1] |
| 337 | if h.degree() < 1: |
| 338 | r = 0 |
| 339 | else: |
| 340 | r = h.coeffs()[-1] |
| 341 | d = r**2/4 - s |
| 342 | sqrtd = square_roots[d] |
| 343 | if not d: # d = 0 |
| 344 | points.append(self.point([K(1), -r/2, K(0)], check=True)) |
| 345 | elif sqrtd is not None: |
| 346 | points.append(self.point([K(1), -r/2 + sqrtd, K(0)], check=True)) |
| 347 | points.append(self.point([K(1), -r/2 - sqrtd, K(0)], check=True)) |
| 348 | |
| 396 | |
| 397 | Conics are allowed (the issue reported at #11800 has been resolved):: |
| 398 | |
| 399 | sage: R.<x> = GF(7)[] |
| 400 | sage: H = HyperellipticCurve(3*x^2 + 5*x + 1) |
| 401 | sage: H.points() |
| 402 | [(0 : 6 : 1), (0 : 1 : 1), (1 : 4 : 1), (1 : 3 : 1), (2 : 4 : 1), (2 : 3 : 1), (3 : 6 : 1), (3 : 1 : 1)] |
| 403 | |
| 404 | The method currently lists points on the plane projective model, that is the closure |
| 405 | in $\mathbb{P}^2$ of the curve defined by $y^2+hy=f$. This means that one point |
| 406 | $(0:1:0)$ at infinity is returned if the degree of the curve is at least 4 and |
| 407 | $\deg(f)>\deg(h)+1$. This point is a singular point of the plane model. Later |
| 408 | implementations may consider a smooth model instead since that would be a more |
| 409 | relevant object. Then, for a curve whose only singularity is at $(0:1:0)$, the point |
| 410 | at infinity would be replaced by a number of rational points of the smooth model. |
| 411 | We illustrate this with an example of a genus 2 hyperelliptic curve:: |
| 412 | |
| 413 | sage: R.<x>=GF(11)[] |
| 414 | sage: H = HyperellipticCurve(x*(x+1)*(x+2)*(x+3)*(x+4)*(x+5)) |
| 415 | sage: H.points() |
| 416 | [(0 : 1 : 0), (0 : 0 : 1), (1 : 7 : 1), (1 : 4 : 1), (5 : 7 : 1), (5 : 4 : 1), (6 : 0 : 1), (7 : 0 : 1), (8 : 0 : 1), (9 : 0 : 1), (10 : 0 : 1)] |
| 417 | |
| 418 | The plane model of the genus 2 hyperelliptic curve in the above example is the curve |
| 419 | in $\mathbb{P}^2$ defined by $y^2z^4=g(x,z)$ where $g(x,z)=x(x+z)(x+2z)(x+3z)(x+4z)(x+5z).$ |
| 420 | This model has one point at infinity $(0:1:0)$ which is also the only singular point of the |
| 421 | plane model. In contrast, the hyperelliptic curve is smooth and imbeds via the equation |
| 422 | $y^2=g(x,z)$ into weighted projected space $\mathbb{P}(1,3,1)$. The latter model has two |
| 423 | points at infinity: $(1:1:0)$ and $(1:-1:0)$. |