def binary_operator(self, other): if isinstance(self, NumericalExpression): self_expr, other_expr, new_inputs = self.build_binary_op( op, other, ) return NumExprFilter( "({left}) {op} ({right})".format( left=self_expr, op=op, right=other_expr, ), new_inputs, ) elif isinstance(other, NumericalExpression): # NumericalExpression overrides numerical ops to correctly handle # merging of inputs. Look up and call the appropriate # right-binding operator with ourself as the input. return commuted_method_getter(other)(self) elif isinstance(other, Filter): if self is other: return NumExprFilter( "x_0 {op} x_0".format(op=op), (self, ), ) return NumExprFilter( "x_0 {op} x_1".format(op=op), (self, other), ) elif isinstance(other, int): # Note that this is true for bool as well return NumExprFilter( "x_0 {op} ({constant})".format(op=op, constant=int(other)), binds=(self, ), ) raise BadBinaryOperator(op, self, other)
def reflected_binary_operator(self, other): if isinstance(self, NumericalExpression): self_expr, other_expr, new_inputs = self.build_binary_op( op, other ) return NumExprFactor( "({left}) {op} ({right})".format( left=other_expr, right=self_expr, op=op, ), new_inputs, dtype=binop_return_dtype(op, other.dtype, self.dtype) ) # Only have to handle the numeric case because in all other valid cases # the corresponding left-binding method will be called. elif isinstance(other, Number): return NumExprFactor( "{constant} {op} x_0".format(op=op, constant=other), binds=(self,), dtype=binop_return_dtype(op, other.dtype, self.dtype), ) raise BadBinaryOperator(op, other, self)
def binary_operator(self, other): # This can't be hoisted up a scope because the types returned by # binop_return_type aren't defined when the top-level function is # invoked in the class body of Factor. return_type = binop_return_type(op) if isinstance(self, NumExprFactor): self_expr, other_expr, new_inputs = self.build_binary_op( op, other, ) return return_type( "({left}) {op} ({right})".format( left=self_expr, op=op, right=other_expr, ), new_inputs, dtype=binop_return_dtype(op, self.dtype, other.dtype), ) elif isinstance(other, NumExprFactor): # NumericalExpression overrides ops to correctly handle merging of # inputs. Look up and call the appropriate reflected operator with # ourself as the input. return commuted_method_getter(other)(self) elif isinstance(other, Term): if self is other: return return_type( "x_0 {op} x_0".format(op=op), (self, ), dtype=binop_return_dtype(op, self.dtype, other.dtype), ) return return_type( "x_0 {op} x_1".format(op=op), (self, other), dtype=binop_return_dtype(op, self.dtype, other.dtype), ) elif isinstance(other, Number): return return_type( "x_0 {op} ({constant})".format(op=op, constant=other), binds=(self, ), # .dtype access is safe here because coerce_numbers_to_my_dtype # will convert any input numbers to numpy equivalents. dtype=binop_return_dtype(op, self.dtype, other.dtype)) raise BadBinaryOperator(op, self, other)