-
Notifications
You must be signed in to change notification settings - Fork 0
/
divisors.sage
133 lines (103 loc) · 3.79 KB
/
divisors.sage
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
class Divisor():
def __init__(self, multiplicites, points):
assert len(multiplicites) == len(points)
for m in multiplicites:
assert m in ZZ
# This is not necessary, assuming that every point P in points is defined as E(P)
# for P in points:
# assert P in E
if len(points) >= 1:
self.E = points[0].curve()
for i in range(1,len(points)):
if points[i].curve() != self.E:
raise ValueError("Points must be defined over the same curve")
else:
self.E = None
for i in range(len(multiplicites)-1,-1,-1):
if multiplicites[i] == 0:
multiplicites.pop(i)
points.pop(i)
self.multiplicites = multiplicites
self.points = points
self.degree = sum(multiplicites)
self.support = points
self.repr = {}
for i in range(len(multiplicites)):
self.repr[points[i]] = multiplicites[i]
def __repr__(self):
if len(self.multiplicites) == 0:
return "0"
result = ""
for i in range(len(self.multiplicites)):
if self.multiplicites[i] > 0:
if i > 0:
result += " + "
result += str(self.multiplicites[i])
else:
result += " - " + str(self.multiplicites[i])[1:]
result += "·" + str(self.points[i].xy())
return result
def __add__(self, other):
multiplicites = []
points = []
for key in self.repr.keys():
if key in other.repr.keys():
keysum = self.repr[key] + other.repr[key]
if keysum != 0:
multiplicites.append(keysum)
points.append(key)
else:
multiplicites.append(self.repr[key])
points.append(key)
for key in other.repr.keys():
if key not in self.repr.keys():
multiplicites.append(other.repr[key])
points.append(key)
return Divisor(multiplicites, points)
def __neg__(self):
negative = [-m for m in self.multiplicites]
return Divisor(negative, self.points)
def __sub__(self, other):
return self + (-other)
def __eq__(self, other):
if len(self.multiplicites) != len(other.multiplicites):
return False
for m in self.multiplicites:
if m not in other.multiplicites:
return False
for P in self.points:
if P not in other.points:
return False
return True
def __ne__(self, other):
return not self == other
def is_principal(self):
if self.is_zero():
return True
sum = self.E(0)
for i in range(len(self.multiplicites)):
sum += self.multiplicites[i] * self.points[i]
if sum == self.E(0) and self.degree == 0:
return True
else:
return False
def equivalent(self, other):
D = self - other
return D.is_principal()
def is_zero(self):
return self == Divisor.zero()
@classmethod
def zero(cls):
return Divisor([], [])
def evaluate_function_on_divisor(f, D):
# TODO: Add a check for disjoint supports
# Implement f --> (f), it seems Sage does not support this
result = 1
for i in range(len(D.multiplicites)):
if D.points[i].is_zero():
# homogenize the function and evaluate at the origin in projective space
F = f.numerator().homogenize() / f.denominator().homogenize()
result *= F(0, 1, 0) ^ D.multiplicites[i]
else:
result *= f(D.points[i].xy()) ^ D.multiplicites[i]
return result