OILS / mycpp / mops.py View on Github | oilshell.org

203 lines, 70 significant
1"""
2Math operations, e.g. for arbitrary precision integers
3
4They are currently int64_t, rather than C int, but we want to upgrade to
5heap-allocated integers.
6
7Regular int ops can use the normal operators + - * /, or maybe i_add() if we
8really want. Does that make code gen harder or worse?
9
10Float ops could be + - * / too, but it feels nicer to develop a formal
11interface?
12"""
13from __future__ import print_function
14
15
16class BigInt(object):
17
18 def __init__(self, i):
19 # type: (int) -> None
20 self.i = i
21
22 def __eq__(self, other):
23 # type: (object) -> bool
24
25 # Disabled check
26 # Prevent possible mistakes. Could do this with other operators
27 # raise AssertionError('Use mops.Equal()')
28
29 if not isinstance(other, BigInt):
30 raise AssertionError()
31
32 # Used for hashing
33 return self.i == other.i
34
35 def __gt__(self, other):
36 # type: (object) -> bool
37 raise AssertionError('Use functions in mops.py')
38
39 def __ge__(self, other):
40 # type: (object) -> bool
41 raise AssertionError('Use functions in mops.py')
42
43 def __hash__(self):
44 # type: () -> int
45 """For dict lookups."""
46 return hash(self.i)
47
48
49ZERO = BigInt(0)
50ONE = BigInt(1)
51MINUS_ONE = BigInt(-1)
52MINUS_TWO = BigInt(-2) # for printf
53
54
55def ToStr(b):
56 # type: (BigInt) -> str
57 return str(b.i)
58
59
60def ToOctal(b):
61 # type: (BigInt) -> str
62 return '%o' % b.i
63
64
65def ToHexUpper(b):
66 # type: (BigInt) -> str
67 return '%X' % b.i
68
69
70def ToHexLower(b):
71 # type: (BigInt) -> str
72 return '%x' % b.i
73
74
75def FromStr(s, base=10):
76 # type: (str, int) -> BigInt
77 return BigInt(int(s, base))
78
79
80def BigTruncate(b):
81 # type: (BigInt) -> int
82 """Only truncates in C++"""
83 return b.i
84
85
86def IntWiden(i):
87 # type: (int) -> BigInt
88 """Only widens in C++"""
89 return BigInt(i)
90
91
92def FromC(i):
93 # type: (int) -> BigInt
94 """A no-op in C, for RLIM_INFINITY"""
95 return BigInt(i)
96
97
98def FromBool(b):
99 # type: (bool) -> BigInt
100 """Only widens in C++"""
101 return BigInt(1) if b else BigInt(0)
102
103
104def ToFloat(b):
105 # type: (BigInt) -> float
106 """Used by float(42) in Oils"""
107 return float(b.i)
108
109
110def FromFloat(f):
111 # type: (float) -> BigInt
112 """Used by int(3.14) in Oils"""
113 return BigInt(int(f))
114
115
116# Can't use operator overloading
117
118
119def Negate(b):
120 # type: (BigInt) -> BigInt
121 return BigInt(-b.i)
122
123
124def Add(a, b):
125 # type: (BigInt, BigInt) -> BigInt
126 return BigInt(a.i + b.i)
127
128
129def Sub(a, b):
130 # type: (BigInt, BigInt) -> BigInt
131 return BigInt(a.i - b.i)
132
133
134def Mul(a, b):
135 # type: (BigInt, BigInt) -> BigInt
136 return BigInt(a.i * b.i)
137
138
139def Div(a, b):
140 # type: (BigInt, BigInt) -> BigInt
141 """
142 Divide, for positive integers only
143
144 Question: does Oils behave like C remainder when it's positive? Then we
145 could be more efficient with a different layering?
146 """
147 assert a.i >= 0 and b.i >= 0, (a.i, b.i)
148 return BigInt(a.i // b.i)
149
150
151def Rem(a, b):
152 # type: (BigInt, BigInt) -> BigInt
153 """
154 Remainder, for positive integers only
155 """
156 assert a.i >= 0 and b.i >= 0, (a.i, b.i)
157 return BigInt(a.i % b.i)
158
159
160def Equal(a, b):
161 # type: (BigInt, BigInt) -> bool
162 return a.i == b.i
163
164
165def Greater(a, b):
166 # type: (BigInt, BigInt) -> bool
167 return a.i > b.i
168
169
170# GreaterEq, Less, LessEq can all be expressed as the 2 ops above
171
172
173def LShift(a, b):
174 # type: (BigInt, BigInt) -> BigInt
175 """
176 Any semantic issues here? Signed left shift
177 """
178 return BigInt(a.i << b.i)
179
180
181def RShift(a, b):
182 # type: (BigInt, BigInt) -> BigInt
183 return BigInt(a.i >> b.i)
184
185
186def BitAnd(a, b):
187 # type: (BigInt, BigInt) -> BigInt
188 return BigInt(a.i & b.i)
189
190
191def BitOr(a, b):
192 # type: (BigInt, BigInt) -> BigInt
193 return BigInt(a.i | b.i)
194
195
196def BitXor(a, b):
197 # type: (BigInt, BigInt) -> BigInt
198 return BigInt(a.i ^ b.i)
199
200
201def BitNot(a):
202 # type: (BigInt) -> BigInt
203 return BigInt(~a.i)