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

168 lines, 57 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 FromBool(b):
64 # type: (bool) -> BigInt
65 """Only widens in C++"""
66 return BigInt(1) if b else BigInt(0)
67
68
69def ToFloat(b):
70 # type: (BigInt) -> float
71 """Used by float(42) in Oils"""
72 return float(b.i)
73
74
75def FromFloat(f):
76 # type: (float) -> BigInt
77 """Used by int(3.14) in Oils"""
78 return BigInt(int(f))
79
80
81# Can't use operator overloading
82
83
84def Negate(b):
85 # type: (BigInt) -> BigInt
86 return BigInt(-b.i)
87
88
89def Add(a, b):
90 # type: (BigInt, BigInt) -> BigInt
91 return BigInt(a.i + b.i)
92
93
94def Sub(a, b):
95 # type: (BigInt, BigInt) -> BigInt
96 return BigInt(a.i - b.i)
97
98
99def Mul(a, b):
100 # type: (BigInt, BigInt) -> BigInt
101 return BigInt(a.i * b.i)
102
103
104def Div(a, b):
105 # type: (BigInt, BigInt) -> BigInt
106 """
107 Divide, for positive integers only
108
109 Question: does Oils behave like C remainder when it's positive? Then we
110 could be more efficient with a different layering?
111 """
112 assert a.i >= 0 and b.i >= 0, (a.i, b.i)
113 return BigInt(a.i // b.i)
114
115
116def Rem(a, b):
117 # type: (BigInt, BigInt) -> BigInt
118 """
119 Remainder, for positive integers only
120 """
121 assert a.i >= 0 and b.i >= 0, (a.i, b.i)
122 return BigInt(a.i % b.i)
123
124
125def Equal(a, b):
126 # type: (BigInt, BigInt) -> bool
127 return a.i == b.i
128
129
130def Greater(a, b):
131 # type: (BigInt, BigInt) -> bool
132 return a.i > b.i
133
134
135# GreaterEq, Less, LessEq can all be expressed as the 2 ops above
136
137
138def LShift(a, b):
139 # type: (BigInt, BigInt) -> BigInt
140 """
141 Any semantic issues here? Signed left shift
142 """
143 return BigInt(a.i << b.i)
144
145
146def RShift(a, b):
147 # type: (BigInt, BigInt) -> BigInt
148 return BigInt(a.i >> b.i)
149
150
151def BitAnd(a, b):
152 # type: (BigInt, BigInt) -> BigInt
153 return BigInt(a.i & b.i)
154
155
156def BitOr(a, b):
157 # type: (BigInt, BigInt) -> BigInt
158 return BigInt(a.i | b.i)
159
160
161def BitXor(a, b):
162 # type: (BigInt, BigInt) -> BigInt
163 return BigInt(a.i ^ b.i)
164
165
166def BitNot(a):
167 # type: (BigInt) -> BigInt
168 return BigInt(~a.i)