/
ordinal.spad
153 lines (128 loc) · 4.5 KB
/
ordinal.spad
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
)abbrev domain SORD SmallOrdinal
++ Author: Waldek Hebisch
++ Description:
++ SmallOrdinal implements ordinal numbers up to epsilon_0. \spad{+}
++ and \spad{*} are "natural" addition and multiplication of ordinals.
++ Available separately are "ordered" operataions.
SmallOrdinal : Join(OrderedAbelianMonoid, SemiRing, CancellationAbelianMonoid,
RetractableTo(NonNegativeInteger), Hashable) with
omega : () -> %
++ omega() is the first infinite ordinal
omegapower : % -> %
++ omegapower(p) returns omega^p
ordinalAdd : (%, %) -> %
++ ordinalAdd(o1, o2) returns sum of o1 and o2 as ordered sets
ordinalMul : (%, %) -> %
++ ordinalMul(o1, o2) returns product of o1 and o2 as ordered sets
ordinalPower : (%, %) -> %
++ ordinalPower(o1, o2) returns o1 to power o2, where power
++ is inductively defined using successive ordinal multiplication
++ from the left
integerPart : % -> NonNegativeInteger
++ integerPart(o) = n when o = l + n and l is a limit ordinal
limitPart : % -> %
++ limitPart(o) = l when o = l + n and l is a limit ordinal
++ and n is a nonnegative integer
"^" : (%, %) -> %
++ o1^o2 returns o1 to power o2, where power is inductively
++ defined using successive natural multiplication from the left
== add
N ==> NonNegativeInteger
PR ==> PolynomialRing(N, %)
Rep := PR
0 == 0$Rep
1 == 1$Rep
omega() == monomial(1$N, 1$%)$Rep
omegapower(p) == monomial(1$N, p)$Rep
zero? p == zero?(p::Rep)$Rep
one? p == p::Rep =$Rep 1
p1 = p2 == p1::Rep =$Rep p2::Rep
hashUpdate!(hs, p) ==
zero?(p) => update!(hs, 6672::SingleInteger)$HashState
hashUpdate!(hs, p::Rep)$Rep
coerce(n : N) : % == monomial(n, 0$%)$Rep
retractIfCan(x : %) : Union(N, "failed") == retractIfCan(x::Rep)$Rep
o1 < o2 ==
p1 := o1::Rep
p2 := o2::Rep
ground?(p1) =>
ground?(p2) =>
ground(p1) <$N ground(p2)
true
if ground?(p2) then
false
else
smaller?(p1, p2)$Rep
p1 + p2 == p1::Rep +$Rep p2::Rep
((p1 : %) * (p2 : %)) : % == p1::Rep *$Rep p2::Rep
subtractIfCan(o1, o2) == subtractIfCan(o1::Rep, o2::Rep)$Rep
ordinalAdd(o1, o2) ==
p1 := o1::Rep
p2 := o2::Rep
e := degree(p2)
e = 0 => p1 + p2
lt : List(Rep) := []
while (degree(p1) >= e) repeat
lt := cons(leadingMonomial(p1), lt)
p1 := reductum(p1)
for t in lt repeat
p2 := t + p2
p2
integerPart(o : %) : N ==
p := o::Rep
while ~ground?(p) repeat p := reductum(p)
ground(p)
limitPart(o : %) : % ==
subtractIfCan(o, integerPart(o)::%)::%
ordinalMul(o1 : %, o2 : %) : % ==
e := degree(o1::Rep)
hi :=
e > 0 => mapExponents((x : %) : % +-> ordinalAdd(e, x),
limitPart(o2)::Rep)$Rep
limitPart(o2)::Rep
lo := o1*integerPart(o2)
hi + lo::Rep
sub_one(o : %) : % ==
ground?(o) =>
n := ground(o)
n = 0 => error "sub_one applied to zero ordinal"
((n - 1) pretend N)::%
o
infinite_power(o1 : %, o2 : %) : % ==
o1 = 0 => 0
o1 = 1 => 1
e1 := degree(o1::Rep)
e1 > 0 => omegapower(ordinalMul(e1, o2))
omegapower(mapExponents(sub_one, o2::Rep)$Rep)
finite_ordinal_power(o : %, n : N) : % ==
n = 0 => 1
n = 1 => o
e := degree(o::Rep)
e = 0 => ((retract(o)@N)^n)::%
n1 := (n - 1) pretend N
ordinalMul(omegapower(e*n1), o)
ordinalPower(o1 : %, o2 : %) : % ==
ordinalMul(infinite_power(o1, limitPart(o2)),
finite_ordinal_power(o1, integerPart(o2)))
(o1 : %)^(o2 : %) ==
infinite_power(o1, limitPart(o2))*o1^integerPart(o2)
coerce(o : %) : OutputForm ==
p := o::Rep
ground?(p) => (ground(p))::OutputForm
l : List OutputForm := []
v := message("omega")
while p ~= 0$Rep repeat
c := leadingCoefficient(p)$Rep
e : % := degree(p)$Rep
p := reductum(p)
co := c::OutputForm
l1 :=
e = 0 => co
if e = 1 then
mon:= v
else mon := v ^ e::OutputForm
c = 1 => mon
co*mon
l := cons(l1, l)
l := reverse!(l)
reduce(_+, l)