Module loda.runtime.operations
Evaluate operations.
Expand source code
# -*- coding: utf-8 -*-
"""Evaluate operations."""
from loda.lang import Operation
import math
def add(a, b):
"""Addition."""
if a == None or b == None:
return None
return a + b
def sub(a, b):
"""Subtraction."""
if a == None or b == None:
return None
return a - b
def trn(a, b):
"""Truncated Subtraction."""
if a == None or b == None:
return None
return max(a - b, 0)
def mul(a, b):
"""Multiplication."""
if a == None or b == None:
return None
return a * b
def div(a, b):
"""Division."""
if a == None or b == None or b == 0:
return None
s = 1 if (a < 0) == (b < 0) else -1
return s * (abs(a) // abs(b))
def dif(a, b):
"""Conditional Division."""
if a == None or b == None:
return None
if b == 0:
return a
d = div(a, b)
return d if a == mul(b, d) else a
def mod(a, b):
"""Modulus (Remainder)."""
if a == None or b == None or b == 0:
return None
return a - mul(b, div(a, b))
def pow(a, b):
"""Power."""
if a == None or b == None:
return None
if a == 0:
if b > 0:
return 0 # 0^(positive number)
elif b == 0:
return 1 # 0^0
else:
return None # 0^(negative number) => inf
elif a == 1:
return 1 # 1^x is always 1
elif a == -1:
return 1 if mod(b, 2) == 0 else -1 # (-1)^x
else:
if b < 0:
return 0
else:
return a**b
def gcd(a, b):
"""Greatest Common Divisor."""
if a == None or b == None:
return None
return math.gcd(a, b)
def bin(n, k):
"""Binomial Coefficient."""
if n == None or k == None:
return None
# check for negative arguments: https://arxiv.org/pdf/1105.3689.pdf
sign = 1
if n < 0: # Theorem 2.1
if k >= 0:
sign = 1 if mod(k, 2) == 0 else -1
n = sub(k, add(n, 1))
elif n >= k:
sign = 1 if mod(sub(n, k), 2) == 0 else -1
m = n
n = sub(0, add(k, 1))
k = sub(m, k)
else:
return 0
if k < 0 or n < k: # 1.2
return 0
if n < mul(k, 2):
k = sub(n, k)
# main calculation
r = 1
for i in range(k):
r = mul(r, sub(n, i))
r = div(r, add(i, 1))
if r == None:
break
return mul(sign, r)
def cmp(a, b):
"""Comparison."""
if a == None or b == None:
return None
return 1 if a == b else 0
def min(a, b):
"""Minimum."""
if a == None or b == None:
return None
return a if a < b else b
def max(a, b):
"""Maximum."""
if a == None or b == None:
return None
return a if a > b else b
def exec_arithmetic(t: Operation.Type, a, b):
"""Execute an arithmetic operation."""
if t == Operation.Type.MOV:
return b
elif t == Operation.Type.ADD:
return add(a, b)
elif t == Operation.Type.SUB:
return sub(a, b)
elif t == Operation.Type.TRN:
return trn(a, b)
elif t == Operation.Type.MUL:
return mul(a, b)
elif t == Operation.Type.DIV:
return div(a, b)
elif t == Operation.Type.DIF:
return dif(a, b)
elif t == Operation.Type.MOD:
return mod(a, b)
elif t == Operation.Type.POW:
return pow(a, b)
elif t == Operation.Type.GCD:
return gcd(a, b)
elif t == Operation.Type.BIN:
return bin(a, b)
elif t == Operation.Type.CMP:
return cmp(a, b)
elif t == Operation.Type.MIN:
return min(a, b)
elif t == Operation.Type.MAX:
return max(a, b)
else:
raise ValueError("operation type not arithmetic: {}".format(t))
Functions
def add(a, b)
-
Addition.
Expand source code
def add(a, b): """Addition.""" if a == None or b == None: return None return a + b
def bin(n, k)
-
Binomial Coefficient.
Expand source code
def bin(n, k): """Binomial Coefficient.""" if n == None or k == None: return None # check for negative arguments: https://arxiv.org/pdf/1105.3689.pdf sign = 1 if n < 0: # Theorem 2.1 if k >= 0: sign = 1 if mod(k, 2) == 0 else -1 n = sub(k, add(n, 1)) elif n >= k: sign = 1 if mod(sub(n, k), 2) == 0 else -1 m = n n = sub(0, add(k, 1)) k = sub(m, k) else: return 0 if k < 0 or n < k: # 1.2 return 0 if n < mul(k, 2): k = sub(n, k) # main calculation r = 1 for i in range(k): r = mul(r, sub(n, i)) r = div(r, add(i, 1)) if r == None: break return mul(sign, r)
def cmp(a, b)
-
Comparison.
Expand source code
def cmp(a, b): """Comparison.""" if a == None or b == None: return None return 1 if a == b else 0
def dif(a, b)
-
Conditional Division.
Expand source code
def dif(a, b): """Conditional Division.""" if a == None or b == None: return None if b == 0: return a d = div(a, b) return d if a == mul(b, d) else a
def div(a, b)
-
Division.
Expand source code
def div(a, b): """Division.""" if a == None or b == None or b == 0: return None s = 1 if (a < 0) == (b < 0) else -1 return s * (abs(a) // abs(b))
def exec_arithmetic(t: Operation.Type, a, b)
-
Execute an arithmetic operation.
Expand source code
def exec_arithmetic(t: Operation.Type, a, b): """Execute an arithmetic operation.""" if t == Operation.Type.MOV: return b elif t == Operation.Type.ADD: return add(a, b) elif t == Operation.Type.SUB: return sub(a, b) elif t == Operation.Type.TRN: return trn(a, b) elif t == Operation.Type.MUL: return mul(a, b) elif t == Operation.Type.DIV: return div(a, b) elif t == Operation.Type.DIF: return dif(a, b) elif t == Operation.Type.MOD: return mod(a, b) elif t == Operation.Type.POW: return pow(a, b) elif t == Operation.Type.GCD: return gcd(a, b) elif t == Operation.Type.BIN: return bin(a, b) elif t == Operation.Type.CMP: return cmp(a, b) elif t == Operation.Type.MIN: return min(a, b) elif t == Operation.Type.MAX: return max(a, b) else: raise ValueError("operation type not arithmetic: {}".format(t))
def gcd(a, b)
-
Greatest Common Divisor.
Expand source code
def gcd(a, b): """Greatest Common Divisor.""" if a == None or b == None: return None return math.gcd(a, b)
def max(a, b)
-
Maximum.
Expand source code
def max(a, b): """Maximum.""" if a == None or b == None: return None return a if a > b else b
def min(a, b)
-
Minimum.
Expand source code
def min(a, b): """Minimum.""" if a == None or b == None: return None return a if a < b else b
def mod(a, b)
-
Modulus (Remainder).
Expand source code
def mod(a, b): """Modulus (Remainder).""" if a == None or b == None or b == 0: return None return a - mul(b, div(a, b))
def mul(a, b)
-
Multiplication.
Expand source code
def mul(a, b): """Multiplication.""" if a == None or b == None: return None return a * b
def pow(a, b)
-
Power.
Expand source code
def pow(a, b): """Power.""" if a == None or b == None: return None if a == 0: if b > 0: return 0 # 0^(positive number) elif b == 0: return 1 # 0^0 else: return None # 0^(negative number) => inf elif a == 1: return 1 # 1^x is always 1 elif a == -1: return 1 if mod(b, 2) == 0 else -1 # (-1)^x else: if b < 0: return 0 else: return a**b
def sub(a, b)
-
Subtraction.
Expand source code
def sub(a, b): """Subtraction.""" if a == None or b == None: return None return a - b
def trn(a, b)
-
Truncated Subtraction.
Expand source code
def trn(a, b): """Truncated Subtraction.""" if a == None or b == None: return None return max(a - b, 0)