Subtraction.

This commit is contained in:
Simon Forman 2022-10-04 08:47:39 -07:00
parent 6ecf681d3a
commit e2f107d1bb
1 changed files with 30 additions and 5 deletions

View File

@ -1,6 +1,10 @@
import ctypes import ctypes
def is_i32(n):
return -2**31 <= n < 2**31
class OberonInt: class OberonInt:
''' '''
Let's model the Oberon RISC integers, Let's model the Oberon RISC integers,
@ -8,7 +12,7 @@ class OberonInt:
''' '''
def __init__(self, initial=0): def __init__(self, initial=0):
assert -2**31 <= initial < 2**31 assert is_i32(initial)
self.value = ctypes.c_int32(initial) self.value = ctypes.c_int32(initial)
assert self.value.value == initial assert self.value.value == initial
@ -18,15 +22,19 @@ class OberonInt:
''' '''
assert isinstance(other, OberonInt) assert isinstance(other, OberonInt)
n = self.value.value + other.value.value n = self.value.value + other.value.value
carry = not (-2**31 <= n < 2**31) carry = not is_i32(n)
if carry: if carry:
n &= (2**31-1) n &= (2**31-1)
return carry, OberonInt(n) return int(carry), OberonInt(n)
def negate(self): def negate(self):
# Instead of binary ops, just cheat: # Instead of binary ops, just cheat:
return OberonInt(-self.value.value) return OberonInt(-self.value.value)
def sub(self, other):
assert isinstance(other, OberonInt)
return self.add(other.negate())
def __repr__(self): def __repr__(self):
#b = bin(self.value.value & (2**32-1)) #b = bin(self.value.value & (2**32-1))
return f'OberonInt({self.value.value})' return f'OberonInt({self.value.value})'
@ -36,23 +44,40 @@ class OberonInt:
return self.value.value == other.value.value return self.value.value == other.value.value
one = OberonInt(1) obmin, zero, one, obmax = map(OberonInt, (
obmin, zero, obmax = map(OberonInt, (
-(2**31), -(2**31),
0, 0,
1,
2**31-1, 2**31-1,
)) ))
# Addition
carry, z = obmax.add(one) carry, z = obmax.add(one)
assert carry assert carry
assert z == zero assert z == zero
# Negation
negative_one = one.negate() negative_one = one.negate()
carry, m = obmin.add(negative_one) carry, m = obmin.add(negative_one)
assert carry assert carry
assert m == obmax assert m == obmax
# Ergo, subtraction.
carry, m = obmin.sub(one)
assert carry
assert m == obmax
carry, hmm = obmax.add(obmax)
assert carry
assert hmm.value.value == 2**31 - 2
carry, eh = obmax.sub(hmm)
assert not carry
assert eh == one
assert hmm.add(one)[1] == obmax
## if initial >= 2**31: ## if initial >= 2**31:
## raise ValueError(f'too big: {initial!r}') ## raise ValueError(f'too big: {initial!r}')
## if initial < -2**31: ## if initial < -2**31: