divisor.sage 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. DIV_POINT = 1
  2. DIV_FUNC = 2
  3. class Divisor:
  4. def __init__(self, field):
  5. self.field = field
  6. self._div = []
  7. def __call__(self, Px, Py, Pz=1):
  8. K = self.field
  9. # Convert to base field
  10. Px, Py, Pz = K(Px), K(Py), K(Pz)
  11. # Normalize coordinates
  12. if Pz > 0:
  13. Px /= Pz
  14. Py /= Pz
  15. Pz = 1
  16. P = (Px, Py, Pz)
  17. D = Divisor(K)
  18. D._div += [(DIV_POINT, 1, P)]
  19. return D
  20. def div(self, f):
  21. K = self.field
  22. D = Divisor(K)
  23. D._div += [(DIV_FUNC, 1, f)]
  24. return D
  25. def _clean(self):
  26. self._div = [(type_id, self._deg_obj(P), P)
  27. for type_id, P in self._objs()]
  28. self._div = [(type_id, n, P) for type_id, n, P in self._div if n != 0]
  29. def _deg_obj(self, P):
  30. return sum(n for type_id, n, Q in self._div if P == Q)
  31. def _objs(self):
  32. return set((type_id, P) for type_id, _, P in self._div)
  33. def __add__(self, other):
  34. K = self.field
  35. D = Divisor(K)
  36. D._div = self._div[:] + other._div[:]
  37. D._clean()
  38. return D
  39. def __sub__(self, other):
  40. K = self.field
  41. D = self + -1*other
  42. return D
  43. def __mul__(self, n):
  44. K = self.field
  45. D = Divisor(K)
  46. D._div = [(type_id, n*m, P) for type_id, m, P in self._div]
  47. return D
  48. __rmul__ = __mul__
  49. def __repr__(self):
  50. out = ""
  51. if not self._div:
  52. out += "0"
  53. for i, (type_id, n, obj) in enumerate(self._div):
  54. assert n != 0
  55. if i > 0:
  56. if n > 0:
  57. out += " + "
  58. else:
  59. out += " - "
  60. else:
  61. if n < 0:
  62. out += "-"
  63. assert type_id in (DIV_POINT, DIV_FUNC)
  64. if abs(n) > 1:
  65. out += f"{abs(n)}"
  66. if type_id == DIV_POINT:
  67. out += self._format_point(obj)
  68. elif type_id == DIV_FUNC:
  69. out += f" div({obj})"
  70. return out
  71. def _format_point(self, P):
  72. Px, Py, Pz = P
  73. assert Pz in (0, 1)
  74. if Pz == 0:
  75. return f"[∞]"
  76. return f"[({Px}, {Py})]"
  77. def deg(self):
  78. return sum(n for _, n, _ in self._div)
  79. def supp(self):
  80. return set(P for _, _, P in self._div)
  81. K.<x, y> = GF(47)[]
  82. D = Divisor(K)
  83. D = 4*D(2, 3) + D(2, 4) + 2*D(0, 1, 0) + 4*D.div(x^2 + y)
  84. E = 6*D(4, 2) - 6*D(6, 3) + 6*D(6, 3)
  85. #D -= 4*D.div(x^2 + y)
  86. #E -= 6*D(4, 2)
  87. print(f"D = {D}")
  88. print(f"E = {E}")
  89. print(f"D + E = {D + E}")
  90. print(f"6E = {6*E}")
  91. print(f"deg(D) = {D.deg()}")
  92. print(f"supp(D) = {D.supp()}")
  93. print(f"deg(E) = {E.deg()}")
  94. print(f"supp(E) = {E.supp()}")