Refactor Constant Scalar Polynomial Multiplication for All Instances of Polynomials
Constant scalar polynomial is a polynomial with a single multi-index element of (0, \ldots, 0) (for Newton, canonical, Chebyshev the element corresponds to the constant term). Currently, multiplication of an arbitrary polynomial with a constant scalar polynomial is handled in a rather quick-and-dirty hack. The multiplication is carried out by _scalar_mul()
method with the coefficient of the constant scalar polynomial set as the scalar to the method.
This causes consistency in polynomial-polynomial multiplication. For instance, the convention of polynomial-polynomial multiplication is if one polynomial is of the higher dimension than the other, the resulting polynomial should have the higher dimension. This convention is violated by the hack.
>>> nwt_poly_1 = mp.NewtonPolynomial.from_degree(4, 0, 1.0, coeffs=10.0) # constant scalar polynomial
>>> nwt_poly_2 = mp.NewtonPolynomial.from_degree(3, 2, 2.0)
>>> nwt_poly_2.coeffs = np.random.rand(len(nwt_poly_2.multi_index))
>>> nwt_poly_1 * nwt_poly_2 == nwt_poly_2 * 10.0
False
This is because:
>>> nwt_poly_2.spatial_dimension, (nwt_poly_1 * nwt_poly_2).spatial_dimension
(3, 4)
Furthermore, multiplication in the Newton and Chebyshev basis may not be identical with the scalar multiplication using the same scalar because the transformation between the Lagrange coefficients to the corresponding coefficients. Again the error induced by the transformation is small but even that is still unsatisfactory for a simple scalar multiplication.
Consider the following example:
Furthermore, while scalar multiplication operation currently supports in-place operation (explicitly via __imul__
and only for scalars), keeping the promise that the instance will be mutated in-place consistently is difficult and may be currently unnecessary anyway. I would propose via the resolution of this issue to remove the in-place operation support for scalar multiplication. By default, the statement *=
will fall back to __mul__()
. If __imul__()
is not implemented so a new instance will always be created and assign to the previous variable.
This issue is part of refactoring and extending the support for arithmetic operations involving polynomial (see Issue #142 (closed)).