Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
return expr.objectRef(*args)
elif (isinstance(expr, AbstractBinaryOpNode)):
left = substitute_vars(expr.left, var_to_expr_map)
right = substitute_vars(expr.right, var_to_expr_map)
op = expr.op
new_expr = AbstractBinaryOpNode(left, right, op)
return simplify_expr(new_expr)
elif (isinstance(expr, AbstractUnaryOpNode)):
child = substitute_vars(expr.child, var_to_expr_map)
op = expr.op
new_expr = AbstractUnaryOpNode(child, op)
return simplify_expr(new_expr)
elif (isinstance(expr, constructs.Cast)):
typ = expr.typ
return \
constructs.Cast(typ,
substitute_vars(expr.expression, var_to_expr_map))
elif (isinstance(expr, constructs.Select)):
new_cond = substitute_vars(expr.condition, var_to_expr_map)
new_true = substitute_vars(expr.trueExpression, var_to_expr_map)
new_false = substitute_vars(expr.falseExpression, var_to_expr_map)
return constructs.Select(new_cond, new_true, new_false)
elif (isinstance(expr, InbuiltFunction)):
expr = expr.clone()
expr.substitute_vars(var_to_expr_map)
return expr
raise TypeError(type(expr))
if (not (expr.right.has(constructs.Variable)) and \
not (expr.right.has(constructs.Parameter))):
return isAffine(expr.left, include_div, False)
else:
return False
else:
return False
else:
return False
elif (isinstance(expr, AbstractUnaryOpNode)):
return isAffine(expr.child, include_div, include_modulo)
elif (isinstance(expr, constructs.Condition)):
return isAffine(expr.lhs, include_div, include_modulo) and \
isAffine(expr.rhs, include_div, include_modulo)
elif (isinstance(expr,
(constructs.Select, constructs.Cast, InbuiltFunction))):
return False
raise TypeError(type(expr))
assert(isinstance(expr, AbstractExpression))
if (isinstance(expr, Value)):
return expr.typ
elif (isinstance(expr, constructs.Variable)):
return expr.typ
elif (isinstance(expr, constructs.Reference)):
return expr.objectRef.typ
elif (isinstance(expr, AbstractBinaryOpNode)):
left_type = getType(expr.left)
right_type = getType(expr.right)
return result_type(left_type, right_type)
elif (isinstance(expr, AbstractUnaryOpNode)):
return getType(expr.child)
elif (isinstance(expr, constructs.Cast)):
return expr.typ
elif (isinstance(expr, constructs.Select)):
true_type = getType(expr.trueExpression)
false_type = getType(expr.falseExpression)
assert true_type == false_type
return true_type
elif (isinstance(expr, InbuiltFunction)):
return expr.getType()
raise TypeError(type(expr))
return simplify_expr(new_expr)
elif (isinstance(expr, AbstractUnaryOpNode)):
child = substitute_vars(expr.child, var_to_expr_map)
op = expr.op
new_expr = AbstractUnaryOpNode(child, op)
return simplify_expr(new_expr)
elif (isinstance(expr, constructs.Cast)):
typ = expr.typ
return \
constructs.Cast(typ,
substitute_vars(expr.expression, var_to_expr_map))
elif (isinstance(expr, constructs.Select)):
new_cond = substitute_vars(expr.condition, var_to_expr_map)
new_true = substitute_vars(expr.trueExpression, var_to_expr_map)
new_false = substitute_vars(expr.falseExpression, var_to_expr_map)
return constructs.Select(new_cond, new_true, new_false)
elif (isinstance(expr, InbuiltFunction)):
expr = expr.clone()
expr.substitute_vars(var_to_expr_map)
return expr
raise TypeError(type(expr))
return True
else:
return False
elif(include_modulo and expr.op in ['%']):
if (not (expr.right.has(constructs.Variable)) and \
not (expr.right.has(constructs.Parameter))):
return isAffine(expr.left, include_div, False)
else:
return False
else:
return False
else:
return False
elif (isinstance(expr, AbstractUnaryOpNode)):
return isAffine(expr.child, include_div, include_modulo)
elif (isinstance(expr, constructs.Condition)):
return isAffine(expr.lhs, include_div, include_modulo) and \
isAffine(expr.rhs, include_div, include_modulo)
elif (isinstance(expr,
(constructs.Select, constructs.Cast, InbuiltFunction))):
return False
raise TypeError(type(expr))
affine *,/ affine = non-affine
non-affine operand always results in a non-affine expression
Divisions and modulo operators are considered affine if the appropriate
option is specified.
This function is meant to work on straight forward expressions it can be
easily tricked into conservatively saying that the expression is not
affine. For example -x^3 + x^3 will be non affine.
Making the expression anaylsis more robust will require integration with
a symbolic math package.
"""
expr = Value.numericToValue(expr)
assert(isinstance(expr, AbstractExpression)
or isinstance(expr, constructs.Condition))
if (isinstance(expr, Value)):
return (expr.typ is Int) or (include_div and (expr.typ is Rational))
elif (isinstance(expr, constructs.Variable)):
return True
elif (isinstance(expr, constructs.Reference)):
return False
elif (isinstance(expr, AbstractBinaryOpNode)):
left_check = isAffine(expr.left, include_div, include_modulo)
right_check = isAffine(expr.right, include_div, include_modulo)
if (left_check and right_check):
if (expr.op in ['+','-']):
return True
elif(expr.op in ['*']):
if(not (expr.left.has(constructs.Variable) or \
expr.left.has(constructs.Parameter)) or \
not (expr.right.has(constructs.Variable) or \
left_check = isAffine(expr.left, include_div, include_modulo)
right_check = isAffine(expr.right, include_div, include_modulo)
if (left_check and right_check):
if (expr.op in ['+','-']):
return True
elif(expr.op in ['*']):
if(not (expr.left.has(constructs.Variable) or \
expr.left.has(constructs.Parameter)) or \
not (expr.right.has(constructs.Variable) or \
expr.right.has(constructs.Parameter))):
return True
else:
return False
elif(include_div and expr.op in ['/']):
if (not (expr.right.has(constructs.Variable)) and \
not (expr.right.has(constructs.Parameter))):
return True
else:
return False
elif(include_modulo and expr.op in ['%']):
if (not (expr.right.has(constructs.Variable)) and \
not (expr.right.has(constructs.Parameter))):
return isAffine(expr.left, include_div, False)
else:
return False
else:
return False
else:
return False
elif (isinstance(expr, AbstractUnaryOpNode)):
return isAffine(expr.child, include_div, include_modulo)
elif (isinstance(expr, constructs.Condition)):
return (expr.typ is Int) or (include_div and (expr.typ is Rational))
elif (isinstance(expr, constructs.Variable)):
return True
elif (isinstance(expr, constructs.Reference)):
return False
elif (isinstance(expr, AbstractBinaryOpNode)):
left_check = isAffine(expr.left, include_div, include_modulo)
right_check = isAffine(expr.right, include_div, include_modulo)
if (left_check and right_check):
if (expr.op in ['+','-']):
return True
elif(expr.op in ['*']):
if(not (expr.left.has(constructs.Variable) or \
expr.left.has(constructs.Parameter)) or \
not (expr.right.has(constructs.Variable) or \
expr.right.has(constructs.Parameter))):
return True
else:
return False
elif(include_div and expr.op in ['/']):
if (not (expr.right.has(constructs.Variable)) and \
not (expr.right.has(constructs.Parameter))):
return True
else:
return False
elif(include_modulo and expr.op in ['%']):
if (not (expr.right.has(constructs.Variable)) and \
not (expr.right.has(constructs.Parameter))):
return isAffine(expr.left, include_div, False)
else:
return False
else:
def get_affine_var_and_param_coeff(expr):
expr = Value.numericToValue(expr)
if (not isAffine(expr) or \
isinstance(expr, Value) or \
is_constant_expr(expr)):
return {}
elif (isinstance(expr, constructs.Variable)):
return {expr: 1}
elif (isinstance(expr, AbstractBinaryOpNode)):
coeff = {}
left_coeff = get_affine_var_and_param_coeff(expr.left)
right_coeff = get_affine_var_and_param_coeff(expr.right)
if (expr.op == '+'):
coeff = dict((n, left_coeff.get(n, 0) + right_coeff.get(n, 0)) \
for n in set(left_coeff) | set(right_coeff))
elif (expr.op == '-'):
coeff = dict((n, left_coeff.get(n, 0) - right_coeff.get(n, 0)) \
for n in set(left_coeff) | set(right_coeff))
elif (expr.op == '*'):
left_is_constant = is_constant_expr(expr.left, affine=True)
right_is_constant = is_constant_expr(expr.right, affine=True)
#sanity check should be true if the expression is affine
assert(not (left_is_constant and right_is_constant))
def getType(expr):
expr = Value.numericToValue(expr)
assert(isinstance(expr, AbstractExpression))
if (isinstance(expr, Value)):
return expr.typ
elif (isinstance(expr, constructs.Variable)):
return expr.typ
elif (isinstance(expr, constructs.Reference)):
return expr.objectRef.typ
elif (isinstance(expr, AbstractBinaryOpNode)):
left_type = getType(expr.left)
right_type = getType(expr.right)
return result_type(left_type, right_type)
elif (isinstance(expr, AbstractUnaryOpNode)):
return getType(expr.child)
elif (isinstance(expr, constructs.Cast)):
return expr.typ
elif (isinstance(expr, constructs.Select)):
true_type = getType(expr.trueExpression)
false_type = getType(expr.falseExpression)
assert true_type == false_type
return true_type