# Attempt at basic math with limited ops. (5.00)
# Can use:
# Bitwise operations (and, or, xor, not, shift).
# Addition and subtraction by one.
# Negation.
# Comparison against zero.
# @see nHFxFx, UCiqyi
def wordsize2s(x, y):
if x == 0 and y == 0:
return 2
return 1 + wordsize2s(abs(x) >> 1, abs(y) >> 1)
def to2s(x, n):
m = (1<<n) - 1
y = abs(x) & m
return y if x >= 0 else ((y - 1) ^ m)
def from2s(x, n):
m = (1<<n) - 1
x = x & m
s = x >> (n-1)
return x if s == 0 else -((x ^ m) + 1)
def unsigned_add(a, b):
if b == 0:
return a
return unsigned_add(a ^ b, (a & b) << 1)
# Math public.
def flipsign(a, b):
return -a if b < 0 else a
def add(a, b):
n = wordsize2s(a, b)
return from2s(unsigned_add(to2s(a, n), to2s(b, n)), n)
def sub(a, b):
return add(a, -b)
def mul(a, b):
a = flipsign(a, b)
b = abs(b)
if b == 0:
return 0
if b&1 == 0:
return mul(a << 1, b >> 1)
return add(a, mul(a, b - 1))
def exp(a, b):
if b < 0:
raise ValueError("domain error")
if b == 0:
return 1
if b&1 == 0:
return exp(mul(a, a), b >> 1)
return mul(a, exp(a, b - 1))
# Test.
n = 25
for y in range(-n, n):
for x in range(-n, n):
assert add(x, y) == (x + y), "Bad add"
assert sub(x, y) == (x - y), "Bad sub"
assert mul(x, y) == (x * y), "Bad mul"
assert y < 0 or exp(x, y) == (x ** y), "Bad exp"
n = 13
for y in range(1, n):
print("".join(format(mul(x, y), "4d") for x in range(1, n)))
IyBBdHRlbXB0IGF0IGJhc2ljIG1hdGggd2l0aCBsaW1pdGVkIG9wcy4gKDUuMDApCiMgQ2FuIHVzZToKIyAgQml0d2lzZSBvcGVyYXRpb25zIChhbmQsIG9yLCB4b3IsIG5vdCwgc2hpZnQpLgojICBBZGRpdGlvbiBhbmQgc3VidHJhY3Rpb24gYnkgb25lLgojICBOZWdhdGlvbi4KIyAgQ29tcGFyaXNvbiBhZ2FpbnN0IHplcm8uCiMgQHNlZSBuSEZ4RngsIFVDaXF5aQoKZGVmIHdvcmRzaXplMnMoeCwgeSk6CiAgICBpZiB4ID09IDAgYW5kIHkgPT0gMDoKICAgICAgICByZXR1cm4gMgogICAgcmV0dXJuIDEgKyB3b3Jkc2l6ZTJzKGFicyh4KSA+PiAxLCBhYnMoeSkgPj4gMSkKCmRlZiB0bzJzKHgsIG4pOgogICAgbSA9ICgxPDxuKSAtIDEKICAgIHkgPSBhYnMoeCkgJiBtCiAgICByZXR1cm4geSBpZiB4ID49IDAgZWxzZSAoKHkgLSAxKSBeIG0pCgpkZWYgZnJvbTJzKHgsIG4pOgogICAgbSA9ICgxPDxuKSAtIDEKICAgIHggPSB4ICYgbQogICAgcyA9IHggPj4gKG4tMSkKICAgIHJldHVybiB4IGlmIHMgPT0gMCBlbHNlIC0oKHggXiBtKSArIDEpCgpkZWYgdW5zaWduZWRfYWRkKGEsIGIpOgogICAgaWYgYiA9PSAwOgogICAgICAgIHJldHVybiBhCiAgICByZXR1cm4gdW5zaWduZWRfYWRkKGEgXiBiLCAoYSAmIGIpIDw8IDEpCgojIE1hdGggcHVibGljLgoKZGVmIGZsaXBzaWduKGEsIGIpOgogICAgcmV0dXJuIC1hIGlmIGIgPCAwIGVsc2UgYQoKZGVmIGFkZChhLCBiKToKICAgIG4gPSB3b3Jkc2l6ZTJzKGEsIGIpCiAgICByZXR1cm4gZnJvbTJzKHVuc2lnbmVkX2FkZCh0bzJzKGEsIG4pLCB0bzJzKGIsIG4pKSwgbikKCmRlZiBzdWIoYSwgYik6CiAgICByZXR1cm4gYWRkKGEsIC1iKQoKZGVmIG11bChhLCBiKToKICAgIGEgPSBmbGlwc2lnbihhLCBiKQogICAgYiA9IGFicyhiKQogICAgaWYgYiA9PSAwOgogICAgICAgIHJldHVybiAwCiAgICBpZiBiJjEgPT0gMDoKICAgICAgICByZXR1cm4gbXVsKGEgPDwgMSwgYiA+PiAxKQogICAgcmV0dXJuIGFkZChhLCBtdWwoYSwgYiAtIDEpKQoKZGVmIGV4cChhLCBiKToKICAgIGlmIGIgPCAwOgogICAgICAgIHJhaXNlIFZhbHVlRXJyb3IoImRvbWFpbiBlcnJvciIpCiAgICBpZiBiID09IDA6CiAgICAgICAgcmV0dXJuIDEKICAgIGlmIGImMSA9PSAwOgogICAgICAgIHJldHVybiBleHAobXVsKGEsIGEpLCBiID4+IDEpCiAgICByZXR1cm4gbXVsKGEsIGV4cChhLCBiIC0gMSkpCgojIFRlc3QuCgpuID0gMjUKZm9yIHkgaW4gcmFuZ2UoLW4sIG4pOgogICAgZm9yIHggaW4gcmFuZ2UoLW4sIG4pOgogICAgICAgIGFzc2VydCBhZGQoeCwgeSkgPT0gKHggKyB5KSwgIkJhZCBhZGQiCiAgICAgICAgYXNzZXJ0IHN1Yih4LCB5KSA9PSAoeCAtIHkpLCAiQmFkIHN1YiIKICAgICAgICBhc3NlcnQgbXVsKHgsIHkpID09ICh4ICogeSksICJCYWQgbXVsIgogICAgICAgIGFzc2VydCB5IDwgMCBvciBleHAoeCwgeSkgPT0gKHggKiogeSksICJCYWQgZXhwIgoKbiA9IDEzCmZvciB5IGluIHJhbmdlKDEsIG4pOgogICAgcHJpbnQoIiIuam9pbihmb3JtYXQobXVsKHgsIHkpLCAiNGQiKSBmb3IgeCBpbiByYW5nZSgxLCBuKSkp