clifford icon indicating copy to clipboard operation
clifford copied to clipboard

Consider leveraging the numpy printing mechanism

Open eric-wieser opened this issue 4 years ago • 4 comments

We could consider using numpy to round coefficients etc with:

f = np.core.arrayprint._get_format_function(self.value, **np.core.arrayprint._format_options)
# use `f` instead of `round` in `MultiVector.__str__

eric-wieser avatar Sep 11 '20 10:09 eric-wieser

Trying this out:

# copied from MultiVector.__str__, with the above change
def new_str(self) -> str:
    s = ''

    # abs because we handle the minus signs
    fmt = np.core.arrayprint._get_format_function(abs(self.value), **np.core.arrayprint._format_options)

    for grade, name, coeff in zip(self.layout._basis_blade_order.grades, self.layout.names, self.value):
        # if we have nothing yet, don't use + and - as operators but
        # use - as an unary prefix if necessary
        if s:
            seps = (' + ', ' - ')
        else:
            seps = ('', '-')

        # note: these comparisons need to ensure nan is shown, noting that
        # `nan {} x` is always false for all comparisons `{}`.`
        if abs(coeff) < clifford._settings._eps:
            continue  # too small to print
        else:
            if coeff < 0:
                sep = seps[1]
                coeff_str = fmt(-coeff)
            else:
                sep = seps[0]
                coeff_str = fmt(coeff)

            if grade == 0:
                # scalar
                s = '%s%s%s' % (s, sep, coeff_str)
            else:
                # not a scalar
                s = '%s%s(%s^%s)' % (s, sep, coeff_str, name)
    if s:
        # non-zero
        return s
    else:
        # return scalar 0
        return '0'

gives

In [26]: x = 1 + 1.234 * e1 - 1.1 * e12

In [27]: x
Out[27]: 1.0 + (1.234^e1) - (1.1^e12)

In [28]: new_str(x)
Out[28]: '1.    + (1.234^e1) - (1.1  ^e12)'

Note numpy is trying to make all the coefficients the same width, which may or may not be something we care about.

eric-wieser avatar Sep 11 '20 10:09 eric-wieser

With the abs in fmt = np.core.arrayprint._get_format_function(abs(self.value), **np.core.arrayprint._format_options), will this give the correct behaviour for complex .value?

hugohadfield avatar Sep 11 '20 10:09 hugohadfield

Probably not, good point - though coeff < 0 isn't particularly sensible either.

eric-wieser avatar Sep 11 '20 10:09 eric-wieser

Alternative, we could create a subclass of numpy.polynomial.ABCPolyBase and implement _str_term_ascii (and _repr_latex_term) to emit the basis blade names, which would give us the repr for free.

eric-wieser avatar Sep 11 '20 10:09 eric-wieser