From 67e4b5b839b8ec4b1e505ca37c4109ce6122a3b0 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner <inform@tiker.net> Date: Sat, 1 Jun 2013 15:05:41 -0400 Subject: [PATCH] Make many more mappers multivector-aware. Make MVs hashable. --- doc/geometric-algebra.rst | 1 + pymbolic/geometric_algebra.py | 33 +++++++++++++++++++++++++++++---- pymbolic/mapper/__init__.py | 6 ++++++ pymbolic/mapper/evaluator.py | 3 +++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/doc/geometric-algebra.rst b/doc/geometric-algebra.rst index 53e3d5f..e9c5458 100644 --- a/doc/geometric-algebra.rst +++ b/doc/geometric-algebra.rst @@ -35,6 +35,7 @@ Multivectors .. automethod:: rev .. automethod:: invol .. automethod:: dual + .. automethod:: __inv__ .. automethod:: norm_squared .. automethod:: __abs__ .. autoattribute:: I diff --git a/pymbolic/geometric_algebra.py b/pymbolic/geometric_algebra.py index d7957f2..967deef 100644 --- a/pymbolic/geometric_algebra.py +++ b/pymbolic/geometric_algebra.py @@ -421,7 +421,7 @@ class MultiVector(object): def __getinitargs__(self): return (self.data, self.space) - mapper_method = "map_multi_vector" + mapper_method = "map_multivector" # {{{ stringification @@ -438,8 +438,8 @@ class MultiVector(object): except AttributeError: coeff_str = str(coeff) else: - from pymbolic.mapper.stringifier import PREC_TIMES - coeff_str = strifier(coeff, PREC_TIMES) + from pymbolic.mapper.stringifier import PREC_PRODUCT + coeff_str = strifier()(coeff, PREC_PRODUCT) blade_str = self.space.blade_bits_to_str(bits) if not blade_str: @@ -688,11 +688,15 @@ class MultiVector(object): def dual(self): r"""Return the dual of *self*, see (1.2.26) in [HS]. - Often written :math:`\widetilde A`. + Written :math:`\widetilde A` by [HS] and :math:`A^\ast` by [DFW]. """ return self | self.I.rev() + def __inv__(self): + """Return the dual of *self*, see :meth:`dual`.""" + return self.dual() + def norm_squared(self): return self.rev().scalar_product(self) @@ -709,6 +713,14 @@ class MultiVector(object): # {{{ comparisons + @memoize_method + def __hash__(self): + result = hash(self.space) + for bits, coeff in self.data.iteritems(): + result ^= hash(bits) ^ hash(coeff) + + return result + def __nonzero__(self): return bool(self.data) @@ -863,4 +875,17 @@ class MultiVector(object): # }}} + +def componentwise(f, expr): + """Apply function *f* componentwise to object arrays and + :class:`MultiVector` instances. *expr* is also allowed to + be a scalar. + """ + + if isinstance(expr, MultiVector): + return expr.map(f) + + from pytools.obj_array import with_object_array_or_scalar + return with_object_array_or_scalar(f, expr) + # vim: foldmethod=marker diff --git a/pymbolic/mapper/__init__.py b/pymbolic/mapper/__init__.py index cd56ad8..bf3e628 100644 --- a/pymbolic/mapper/__init__.py +++ b/pymbolic/mapper/__init__.py @@ -216,6 +216,9 @@ class CombineMapper(RecursiveMapper): def map_numpy_array(self, expr, *args): return self.combine(self.rec(el) for el in expr.flat) + def map_multivector(self, expr, *args): + return self.combine(self.rec(coeff) for bits, coeff in expr.data.iteritems()) + def map_common_subexpression(self, expr, *args): return self.rec(expr.child, *args) @@ -338,6 +341,9 @@ class IdentityMapper(Mapper): result[i] = self.rec(expr[i]) return result + def map_multivector(self, expr, *args): + return expr.map(lambda ch: self.rec(ch, *args)) + def map_common_subexpression(self, expr, *args, **kwargs): from pymbolic.primitives import is_zero result = self.rec(expr.child, *args, **kwargs) diff --git a/pymbolic/mapper/evaluator.py b/pymbolic/mapper/evaluator.py index c4ef3f6..ec6f93e 100644 --- a/pymbolic/mapper/evaluator.py +++ b/pymbolic/mapper/evaluator.py @@ -147,6 +147,9 @@ class EvaluationMapper(RecursiveMapper): result[i] = self.rec(expr[i]) return result + def map_multivector(self, expr, *args): + return expr.map(lambda ch: self.rec(ch, *args)) + def map_common_subexpression(self, expr): try: return self.common_subexp_cache[expr.child] -- GitLab