Support for Polynomial-Real Scalar Division
In extending Minterpy capabilities to carry out polynomial arithmetics (see Issue #142 (closed)), we should support polynomial division by scalar (real) numbers. Polynomials are closed under division by a scalar, meaning that the result division by scalar is also a polynomial having the same multi-index set.
Dividing a polynomial in a given basis with a scalar would divide all the coefficients with the scalar and this rule is universal and it applies to all polynomial basis without controversies.
For instance, polynomial in the Lagrange basis:
>>> mi = mp.MultiIndexSet.from_degree(2, 2, 1.0)
>>> coeffs = np.arange(1, len(mi) + 1, dtype=np.float_)
>>> lag_poly = mp.LagrangePolynomial(mi, coeffs)
>>> lag_poly.coeffs
array([1., 2., 3., 4., 5., 6.])
Division a scalar
>>> lag_poly_2 = lag_poly / 5
>>> lag_poly_2.coeffs
array([ 0.2, 0.4, 0.6, 0.8, 1.0, 1.2])
The same rule applies to all the other bases.
Additional properties that might be useful for testing:
- Order of multiplication should matter, so if
a
andp
are scalar and polynomial, respectively thenp / a
should not be the same asa / p
. In fact,a / p
will require an implementation of polynomial-polynomial division which is not going to happen in the foreseeable future. - Division by multiplicative identity, i.e.,
p / 1
should give a polynomial equal in value.
Note that, although division by a scalar is also carried in polynomial transformation (i.e., multiplied polynomial in a given basis is equal to multiplied polynomial in another basis transformed to the former basis), exact equality check may fail because some precision may be lost during the transformation.
For instance,
>>> mi = mp.MultiIndexSet.from_degree(2, 2, 1.0)
>>> coeffs = np.arange(1, len(mi) + 1, dtype=np.float_)
>>> lag_poly = mp.LagrangePolynomial(mi, coeffs)
>>> nwt_poly = mp.LagrangeToNewton(lag_poly)()
The two polynomials above are the same but in different bases. Now:
>>> lag_poly = lag_poly / 5
>>> nwt_poly = nwt_poly / 5
>>> lag_poly_2 = mp.NewtonToLagrange(nwt_poly)()
>>> lag_poly == lag_poly_2
False
This is to be expected, because the transformation from Newton to Lagrange may not be (most probably not be) exact. However, a test via np.allclose
on the coefficients directly should return True
. ==
represents exact equality check by convention.
This issue is part of refactoring and extending the support for arithmetic operations involving polynomial (see Issue #142 (closed)).
Notes on implementation
Because the division by a scalar rule applies to all concrete classes of polynomials, the implementation may be put directly in MultivariatePolynomialSingleABC
.