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

174 lines, 59 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 # Prevent possible mistakes. Could do this with other operators
23 def __eq__(self, other):
24 # type: (object) -> bool
25 raise AssertionError('Use mops.Equal()')
26
27 def __gt__(self, other):
28 # type: (object) -> bool
29 raise AssertionError('Use functions in mops.py')
30
31 def __ge__(self, other):
32 # type: (object) -> bool
33 raise AssertionError('Use functions in mops.py')
34
35
36ZERO = BigInt(0)
37ONE = BigInt(1)
38MINUS_ONE = BigInt(-1)
39
40
41def ToStr(b):
42 # type: (BigInt) -> str
43 return str(b.i)
44
45
46def FromStr(s, base=10):
47 # type: (str, int) -> BigInt
48 return BigInt(int(s, base))
49
50
51def BigTruncate(b):
52 # type: (BigInt) -> int
53 """Only truncates in C++"""
54 return b.i
55
56
57def IntWiden(i):
58 # type: (int) -> BigInt
59 """Only widens in C++"""
60 return BigInt(i)
61
62
63def FromC(i):
64 # type: (int) -> BigInt
65 """A no-op in C, for RLIM_INFINITY"""
66 return BigInt(i)
67
68
69def FromBool(b):
70 # type: (bool) -> BigInt
71 """Only widens in C++"""
72 return BigInt(1) if b else BigInt(0)
73
74
75def ToFloat(b):
76 # type: (BigInt) -> float
77 """Used by float(42) in Oils"""
78 return float(b.i)
79
80
81def FromFloat(f):
82 # type: (float) -> BigInt
83 """Used by int(3.14) in Oils"""
84 return BigInt(int(f))
85
86
87# Can't use operator overloading
88
89
90def Negate(b):
91 # type: (BigInt) -> BigInt
92 return BigInt(-b.i)
93
94
95def Add(a, b):
96 # type: (BigInt, BigInt) -> BigInt
97 return BigInt(a.i + b.i)
98
99
100def Sub(a, b):
101 # type: (BigInt, BigInt) -> BigInt
102 return BigInt(a.i - b.i)
103
104
105def Mul(a, b):
106 # type: (BigInt, BigInt) -> BigInt
107 return BigInt(a.i * b.i)
108
109
110def Div(a, b):
111 # type: (BigInt, BigInt) -> BigInt
112 """
113 Divide, for positive integers only
114
115 Question: does Oils behave like C remainder when it's positive? Then we
116 could be more efficient with a different layering?
117 """
118 assert a.i >= 0 and b.i >= 0, (a.i, b.i)
119 return BigInt(a.i // b.i)
120
121
122def Rem(a, b):
123 # type: (BigInt, BigInt) -> BigInt
124 """
125 Remainder, for positive integers only
126 """
127 assert a.i >= 0 and b.i >= 0, (a.i, b.i)
128 return BigInt(a.i % b.i)
129
130
131def Equal(a, b):
132 # type: (BigInt, BigInt) -> bool
133 return a.i == b.i
134
135
136def Greater(a, b):
137 # type: (BigInt, BigInt) -> bool
138 return a.i > b.i
139
140
141# GreaterEq, Less, LessEq can all be expressed as the 2 ops above
142
143
144def LShift(a, b):
145 # type: (BigInt, BigInt) -> BigInt
146 """
147 Any semantic issues here? Signed left shift
148 """
149 return BigInt(a.i << b.i)
150
151
152def RShift(a, b):
153 # type: (BigInt, BigInt) -> BigInt
154 return BigInt(a.i >> b.i)
155
156
157def BitAnd(a, b):
158 # type: (BigInt, BigInt) -> BigInt
159 return BigInt(a.i & b.i)
160
161
162def BitOr(a, b):
163 # type: (BigInt, BigInt) -> BigInt
164 return BigInt(a.i | b.i)
165
166
167def BitXor(a, b):
168 # type: (BigInt, BigInt) -> BigInt
169 return BigInt(a.i ^ b.i)
170
171
172def BitNot(a):
173 # type: (BigInt) -> BigInt
174 return BigInt(~a.i)