Commit 6b90f930 authored by Taddeus Kroes's avatar Taddeus Kroes

Forgot to add numerics rule file in earlier commits (A).

parent 6097dce7
from ..node import ExpressionLeaf as Leaf, TYPE_INTEGER, TYPE_FLOAT, OP_DIV
from ..possibilities import Possibility as P
from .utils import nary_node
def match_divide_numerics(node):
"""
Combine two constants to a single constant in a division, if it does not
lead to a decrease in precision.
Example:
6 / 2 -> 3
3 / 2 -> 3 / 2 # 1.5 would mean a decrease in precision
3.0 / 2 -> 1.5
3 / 2.0 -> 1.5
3.0 / 2.0 -> 1.5
3 / 1.0 -> 3 # Exceptional case: division of integer by 1.0 keeps
# integer precision
"""
assert node.is_op(OP_DIV)
n, d = node
n_int = n.type == TYPE_INTEGER
n_float = n.type == TYPE_FLOAT
d_int = d.type == TYPE_INTEGER
d_float = d.type == TYPE_FLOAT
nv, dv = n.value, d.value
divide = False
if n_int and d_int:
# 6 / 2 -> 3
# 3 / 2 -> 3 / 2
divide = not divmod(nv, dv)[1]
else:
if d_float and dv == 1.0:
# 3 / 1.0 -> 3
dv = 1
# 3.0 / 2 -> 1.5
# 3 / 2.0 -> 1.5
# 3.0 / 2.0 -> 1.5
divide = True
return [P(node, divide_numerics, (nv, dv))] if divide else []
def divide_numerics(root, args):
"""
Combine two constants to a single constant in a division.
Examples:
6 / 2 -> 3
3.0 / 2 -> 1.5
3 / 2.0 -> 1.5
3.0 / 2.0 -> 1.5
3 / 1.0 -> 3
"""
n, d = args
return Leaf(n / d)
def add_numerics(root, args):
"""
Combine two constants to a single constant in an n-ary plus.
Example:
2 + 3 -> 5
"""
n0, n1, c0, c1 = args
scope = root.get_scope()
# Replace the left node with the new expression
scope[scope.index(n0)] = Leaf(c0 + c1)
# Remove the right node
scope.remove(n1)
return nary_node('+', scope)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment