Skip to content

Commit

Permalink
Implement _make_scalar in terms of _make_grade (pygae#95)
Browse files Browse the repository at this point in the history
This eliminates some special-casing in _make_mv and _make_spinor

Note that to avoid making pygaegh-81 worse, we now need to expicitly only allow strings
  • Loading branch information
eric-wieser authored and utensil committed Dec 1, 2019
1 parent e46f829 commit 09ecbd1
Showing 1 changed file with 31 additions and 33 deletions.
64 changes: 31 additions & 33 deletions galgebra/mv.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import copy
import numbers
from operator import itemgetter, mul, add
import operator
from functools import reduce, cmp_to_key

from sympy import (
Expand Down Expand Up @@ -173,20 +173,23 @@ def characterise_Mv(self):
@staticmethod
def _make_grade(ga, __name_or_coeffs, __grade, **kwargs):
""" Make a pure grade multivector. """
def add_superscript(root, s):
if not s:
return root
return '{}__{}'.format(root, s)
grade = __grade
if utils.isstr(__name_or_coeffs):
name = __name_or_coeffs
root = name + '__'
if isinstance(kwargs['f'], bool) and not kwargs['f']: #Is a constant mulitvector function
return sum([Symbol(root + super_script, real=True) * base
return sum([Symbol(add_superscript(name, super_script), real=True) * base
for (super_script, base) in zip(ga.blade_super_scripts[grade], ga.blades[grade])])

else:
if isinstance(kwargs['f'], bool): #Is a multivector function of all coordinates
return sum([Function(root + super_script, real=True)(*ga.coords) * base
return sum([Function(add_superscript(name, super_script), real=True)(*ga.coords) * base
for (super_script, base) in zip(ga.blade_super_scripts[grade], ga.blades[grade])])
else: #Is a multivector function of tuple kwargs['f'] variables
return sum([Function(root + super_script, real=True)(*kwargs['f']) * base
return sum([Function(add_superscript(name, super_script), real=True)(*kwargs['f']) * base
for (super_script, base) in zip(ga.blade_super_scripts[grade], ga.blades[grade])])
elif isinstance(__name_or_coeffs, (list, tuple)):
coeffs = __name_or_coeffs
Expand All @@ -203,14 +206,7 @@ def _make_scalar(ga, __name_or_value, **kwargs):
""" Make a scalar multivector """
if utils.isstr(__name_or_value):
name = __name_or_value
if 'f' in kwargs and isinstance(kwargs['f'],bool):
if kwargs['f']:
return Function(name)(*ga.coords)
else:
return Symbol(name, real=True)
else:
if 'f' in kwargs and isinstance(kwargs['f'],tuple):
return Function(name)(*kwargs['f'])
return Mv._make_grade(ga, name, 0, **kwargs)
else:
value = __name_or_value
return value
Expand All @@ -233,28 +229,30 @@ def _make_pseudo(ga, __name_or_coeffs, **kwargs):
@staticmethod
def _make_mv(ga, __name, **kwargs):
""" Make a general (2**n components) multivector """
tmp = Mv._make_scalar(ga, __name, **kwargs)
for grade in ga.n_range:
tmp += Mv._make_grade(ga, __name, grade + 1, **kwargs)
return tmp
if not isinstance(__name, str):
raise TypeError("Must be a string")
return reduce(operator.add, (
Mv._make_grade(ga, __name, grade, **kwargs)
for grade in range(ga.n + 1)
))

@staticmethod
def _make_spinor(ga, __name, **kwargs):
""" Make a general even (spinor) multivector """
tmp = Mv._make_scalar(ga, __name, **kwargs)
for grade in ga.n_range:
if (grade + 1) % 2 == 0:
tmp += Mv._make_grade(ga, __name, grade + 1, **kwargs)
return tmp
if not isinstance(__name, str):
raise TypeError("Must be a string")
return reduce(operator.add, (
Mv._make_grade(ga, __name, grade, **kwargs)
for grade in range(0, ga.n + 1, 2)
))

@staticmethod
def _make_odd(ga, __name_or_coeffs, **kwargs):
""" Make a general odd multivector """
tmp = S(0)
for grade in ga.n_range:
if (grade + 1) % 2 == 1:
tmp += Mv._make_grade(ga, __name_or_coeffs, grade + 1, **kwargs)
return tmp
return reduce(operator.add, (
Mv._make_grade(ga, __name_or_coeffs, grade, **kwargs)
for grade in range(1, ga.n + 1, 2)
), S(0)) # base case needed in case n == 0

# aliases
_make_grade2 = _make_bivector
Expand Down Expand Up @@ -305,7 +303,7 @@ def __init__(self, *args, **kwargs):
self.obj = make_func(self.Ga, *make_args, **kwargs)
elif isinstance(args[1], int): # args[1] = r (integer) Construct grade r multivector
if args[1] == 0:
# make_grade does not work for scalars (gh-82)
# _make_scalar interprets its coefficient argument differently
make_args = list(args)
make_args.pop(1)
self.obj = Mv._make_scalar(self.Ga, *make_args, **kwargs)
Expand Down Expand Up @@ -567,7 +565,7 @@ def Mv_str(self):
for arg in args:
c, nc = arg.args_cnc()
if len(c) > 0:
c = reduce(mul, c)
c = reduce(operator.mul, c)
else:
c = S(1)
if len(nc) > 0:
Expand All @@ -584,7 +582,7 @@ def Mv_str(self):
if grade0 != S(0):
terms[-1] = (grade0, S(1), -1)
terms = list(terms.items())
sorted_terms = sorted(terms, key=itemgetter(0)) # sort via base indexes
sorted_terms = sorted(terms, key=operator.itemgetter(0)) # sort via base indexes

s = str(sorted_terms[0][1][0] * sorted_terms[0][1][1])
if printer.GaPrinter.fmt == 3:
Expand Down Expand Up @@ -654,7 +652,7 @@ def append_plus(c_str):
for arg in args:
c, nc = arg.args_cnc(split_1=False)
if len(c) > 0:
c = reduce(mul, c)
c = reduce(operator.mul, c)
else:
c = S(1)
if len(nc) > 0:
Expand All @@ -672,7 +670,7 @@ def append_plus(c_str):
terms[-1] = (grade0, S(1), 0)
terms = list(terms.items())

sorted_terms = sorted(terms, key=itemgetter(0)) # sort via base indexes
sorted_terms = sorted(terms, key=operator.itemgetter(0)) # sort via base indexes

if len(sorted_terms) == 1 and sorted_terms[0][1][2] == 0: # scalar
return printer.latex(printer.coef_simplify(sorted_terms[0][1][0]))
Expand Down Expand Up @@ -1327,7 +1325,7 @@ def list(self):
if index not in indexes:
key_coefs.append((S(0), index))

key_coefs = sorted(key_coefs, key=itemgetter(1))
key_coefs = sorted(key_coefs, key=operator.itemgetter(1))
coefs = [x[0] for x in key_coefs]
return coefs

Expand Down

0 comments on commit 09ecbd1

Please sign in to comment.