def _coeff_det(coeff, j): return Product((coeff if j % 2 == 0 else -coeff, Call(self, (_minor(array, 0, j), ))))
def parse_postfix(self, pstate, min_precedence, left_exp): import pymbolic.primitives as primitives import pymbolic.parser as p did_something = False next_tag = pstate.next_tag() if next_tag is p._openpar and p._PREC_CALL > min_precedence: pstate.advance() pstate.expect_not_end() if next_tag is p._closepar: pstate.advance() left_exp = primitives.Call(left_exp, ()) else: args = self.parse_expression(pstate) if not isinstance(args, tuple): args = (args, ) pstate.expect(p._closepar) pstate.advance() if left_exp == primitives.Variable("matrix"): left_exp = np.array(list(list(row) for row in args)) else: left_exp = primitives.Call(left_exp, args) did_something = True elif next_tag is p._openbracket and p._PREC_CALL > min_precedence: pstate.advance() pstate.expect_not_end() left_exp = primitives.Subscript(left_exp, self.parse_expression(pstate)) pstate.expect(p._closebracket) pstate.advance() did_something = True elif next_tag is p._dot and p._PREC_CALL > min_precedence: pstate.advance() pstate.expect(p._identifier) left_exp = primitives.Lookup(left_exp, pstate.next_str()) pstate.advance() did_something = True elif next_tag is p._plus and p._PREC_PLUS > min_precedence: pstate.advance() left_exp += self.parse_expression(pstate, p._PREC_PLUS) did_something = True elif next_tag is p._minus and p._PREC_PLUS > min_precedence: pstate.advance() left_exp -= self.parse_expression(pstate, p._PREC_PLUS) did_something = True elif next_tag is p._times and p._PREC_TIMES > min_precedence: pstate.advance() left_exp *= self.parse_expression(pstate, p._PREC_TIMES) did_something = True elif next_tag is p._over and p._PREC_TIMES > min_precedence: pstate.advance() from pymbolic.primitives import Quotient left_exp = Quotient(left_exp, self.parse_expression(pstate, p._PREC_TIMES)) did_something = True elif next_tag is self.power_sym and p._PREC_POWER > min_precedence: pstate.advance() exponent = self.parse_expression(pstate, p._PREC_POWER) if left_exp == np.e: from pymbolic.primitives import Call, Variable left_exp = Call(Variable("exp"), (exponent, )) else: left_exp **= exponent did_something = True elif next_tag is p._comma and p._PREC_COMMA > min_precedence: # The precedence makes the comma left-associative. pstate.advance() if pstate.is_at_end() or pstate.next_tag() is p._closepar: left_exp = (left_exp, ) else: new_el = self.parse_expression(pstate, p._PREC_COMMA) if isinstance(left_exp, tuple) \ and not isinstance(left_exp, FinalizedTuple): left_exp = left_exp + (new_el, ) else: left_exp = (left_exp, new_el) did_something = True return left_exp, did_something
def _arithmetic_op(self, other, op): """ Registers a substitution rule that performs ``(self) op (other)`` element-wise for the arrays. :mod:`numpy` broadcasting rules are followed while performing these operations. :return: An instance of :class:`ArraySymbol` corresponding to the registered substitution for the element-wise operation. """ assert op in ['+', '-', '*', '/', '<', '<=', '>', '>='] assert self.stack == other.stack def _apply_op(var1, var2): if op == '+': return var1 + var2, self.dtype if op == '-': return var1 - var2, self.dtype if op == '*': return var1 * var2, self.dtype if op == '/': return var1 / var2, self.dtype if op == '<': return var1.lt(var2), np.int if op == '<=': return var1.le(var2), np.int if op == '>': return var1.gt(var2), np.int if op == '>=': return var1.ge(var2), np.int raise RuntimeError() if isinstance(other, Number): inames = tuple( self.stack.name_generator(based_on='i') for _ in self.shape) rhs, dtype = _apply_op( Call(function=Variable(self.name), parameters=tuple(Variable(iname) for iname in inames)), other) subst_name = self.stack.name_generator(based_on='subst') self.stack.register_substitution( lp.SubstitutionRule(subst_name, inames, rhs)) return self.copy(name=subst_name, dtype=dtype) elif isinstance(other, ArraySymbol): if self.shape == other.shape: inames = tuple( self.stack.name_generator(based_on='i') for _ in self.shape) rhs, dtype = _apply_op( Variable(self.name)(*tuple( Variable(iname) for iname in inames)), Variable(other.name)(*tuple( Variable(iname) for iname in inames))) subst_name = self.stack.name_generator(based_on='subst') self.stack.register_substitution( lp.SubstitutionRule(subst_name, inames, rhs)) return self.copy(name=subst_name, dtype=dtype) else: left = self right = other new_left_shape = self.shape[:] new_right_shape = other.shape[:] if len(left.shape) > len(right.shape): new_right_shape = ((1, ) * (len(left.shape) - len(right.shape)) + new_right_shape) if len(left.shape) < len(right.shape): new_left_shape = ((1, ) * (len(right.shape) - len(left.shape)) + new_left_shape) # now both have the same shapes # let compute the shape of these guys new_shape = [1] * len(new_left_shape) for i, (left_len, right_len) in enumerate( zip(new_left_shape, new_right_shape)): if left_len == right_len: new_shape[i] = left_len else: if left_len != 1 and right_len != 1: raise ValueError("Cannot be broadcasted.") else: new_shape[i] = left_len * right_len new_shape = tuple(new_shape) if new_shape != left.shape: subst_name = self.stack.name_generator(based_on="subst") inames = tuple( self.stack.name_generator(based_on="i") for _ in new_left_shape) def _empty_if_zero(_idx): if _idx == (0, ): return () return _idx indices = _empty_if_zero( tuple( Variable(iname) if axis_len != 1 else 0 for iname, axis_len in zip( inames[-len(left.shape):], left.shape))) rule = lp.SubstitutionRule(subst_name, inames, Variable(left.name)(*indices)) self.stack.register_substitution(rule) new_left = left.copy(name=subst_name, shape=new_shape, dim_tags=None, order=left.order) else: new_left = left if new_shape != right.shape: subst_name = self.stack.name_generator(based_on="subst") inames = tuple( self.stack.name_generator(based_on="i") for _ in new_right_shape) def _empty_if_zero(_idx): if _idx == (0, ): return () return _idx indices = _empty_if_zero( tuple( Variable(iname) if axis_len != 1 else 0 for iname, axis_len in zip( inames[-len(right.shape):], right.shape))) rule = lp.SubstitutionRule(subst_name, inames, Variable(right.name)(*indices)) self.stack.register_substitution(rule) new_right = right.copy(name=subst_name, shape=new_shape, dim_tags=None, order=right.order) else: new_right = right return new_left._arithmetic_op(new_right, op) else: raise NotImplementedError('__mul__ for', type(other))