pub struct SparseMultivariatePolynomial<D: Domain, O: MonomialOrder = Grevlex> { /* private fields */ }Expand description
A sparse multivariate polynomial with coefficients in a domain D and
monomial ordering O.
§Example
use ocas_domain::{IntegerDomain, Integer};
use ocas_poly::sparse::Grevlex;
use ocas_poly::SparseMultivariatePolynomial;
let domain = IntegerDomain;
let p = SparseMultivariatePolynomial::<IntegerDomain, Grevlex>::from_terms(
domain,
2,
vec![(vec![1, 0], Integer::from(2)), (vec![0, 1], Integer::from(3))],
);
let q = SparseMultivariatePolynomial::<IntegerDomain, Grevlex>::from_terms(
domain,
2,
vec![(vec![1, 0], Integer::from(1)), (vec![0, 0], Integer::from(1))],
);
let r = p.mul(&q);
assert_eq!(r.coeff(&[1, 0]), Integer::from(2));
assert_eq!(r.coeff(&[0, 1]), Integer::from(3));
assert_eq!(r.coeff(&[2, 0]), Integer::from(2));Implementations§
Source§impl<D: Domain, O: MonomialOrder> SparseMultivariatePolynomial<D, O>
impl<D: Domain, O: MonomialOrder> SparseMultivariatePolynomial<D, O>
Sourcepub fn new(domain: D, n_vars: usize) -> Self
pub fn new(domain: D, n_vars: usize) -> Self
Create the zero polynomial in n_vars variables over domain.
Sourcepub fn from_terms(
domain: D,
n_vars: usize,
terms: Vec<(Vec<usize>, D::Element)>,
) -> Self
pub fn from_terms( domain: D, n_vars: usize, terms: Vec<(Vec<usize>, D::Element)>, ) -> Self
Create a polynomial from a list of (exponent vector, coefficient) pairs.
Zero coefficients and empty terms are dropped automatically.
§Example
use ocas_domain::{IntegerDomain, Integer};
use ocas_poly::sparse::Grevlex;
use ocas_poly::SparseMultivariatePolynomial;
let domain = IntegerDomain;
let p = SparseMultivariatePolynomial::<IntegerDomain, Grevlex>::from_terms(
domain,
2,
vec![(vec![1, 0], Integer::from(2)), (vec![0, 1], Integer::from(3))],
);
assert_eq!(p.n_terms(), 2);
assert_eq!(p.coeff(&[1, 0]), Integer::from(2));Sourcepub fn terms_ref(&self) -> &HashMap<SmallVec<[usize; 4]>, D::Element>
pub fn terms_ref(&self) -> &HashMap<SmallVec<[usize; 4]>, D::Element>
Return a reference to the internal term map (exponent → coefficient).
Sourcepub fn set_term_external(&mut self, exp: Vec<usize>, coeff: D::Element)
pub fn set_term_external(&mut self, exp: Vec<usize>, coeff: D::Element)
Set the coefficient of a monomial (public version of set_term).
Zero coefficients remove the term.
Sourcepub fn total_degree(&self) -> Option<usize>
pub fn total_degree(&self) -> Option<usize>
Return the total degree, or None for the zero polynomial.
Sourcepub fn coeff(&self, exp: &[usize]) -> D::Element
pub fn coeff(&self, exp: &[usize]) -> D::Element
Return the coefficient of the given monomial, or zero if absent.
Sourcepub fn add(&self, other: &Self) -> Self
pub fn add(&self, other: &Self) -> Self
Add another polynomial.
Panics if the polynomials have different numbers of variables.
Sourcepub fn sub(&self, other: &Self) -> Self
pub fn sub(&self, other: &Self) -> Self
Subtract another polynomial.
Panics if the polynomials have different numbers of variables.
Sourcepub fn mul_scalar(&self, scalar: &D::Element) -> Self
pub fn mul_scalar(&self, scalar: &D::Element) -> Self
Multiply by a scalar coefficient.
Sourcepub fn mul(&self, other: &Self) -> Self
pub fn mul(&self, other: &Self) -> Self
Multiply two polynomials.
Panics if the polynomials have different numbers of variables.
Sourcepub fn sorted_terms(&self) -> Vec<(&SmallVec<[usize; 4]>, &D::Element)>
pub fn sorted_terms(&self) -> Vec<(&SmallVec<[usize; 4]>, &D::Element)>
Return the terms sorted according to the monomial ordering.
Sourcepub fn leading_term(&self) -> Option<(&SmallVec<[usize; 4]>, &D::Element)>
pub fn leading_term(&self) -> Option<(&SmallVec<[usize; 4]>, &D::Element)>
Return the leading term (exponent_vector, coefficient) or None
for the zero polynomial.
This scans the HashMap in O(n) without allocating — faster than
sorted_terms() for repeated calls during reduction.
Sourcepub fn leading_monomial(&self) -> Option<&SmallVec<[usize; 4]>>
pub fn leading_monomial(&self) -> Option<&SmallVec<[usize; 4]>>
Return the leading monomial (exponent vector) or None.
Sourcepub fn leading_coeff(&self) -> Option<&D::Element>
pub fn leading_coeff(&self) -> Option<&D::Element>
Return the leading coefficient or None.
Sourcepub fn mul_monomial(&self, exp: &[usize]) -> Self
pub fn mul_monomial(&self, exp: &[usize]) -> Self
Multiply every term’s exponent vector by exp element-wise.
Panics if exp.len() != self.n_vars.
Sourcepub fn reduce(&self, basis: &[Self]) -> Self
pub fn reduce(&self, basis: &[Self]) -> Self
Reduce self by the given basis (a list of polynomials).
Implements multivariate polynomial division: repeatedly look for a
basis element whose leading monomial divides the current leading
monomial, subtract the appropriate multiple, or else move the leading
term into the remainder. Requires that div on the domain succeeds
(i.e. the domain is effectively a field).
Sourcepub fn spoly(&self, other: &Self) -> Self
pub fn spoly(&self, other: &Self) -> Self
Compute the S-polynomial of self and other:
S(f, g) = f·lc(g)·x^(lcm-lm(f)) - g·lc(f)·x^(lcm-lm(g))
Sourcepub fn content(&self) -> D::Elementwhere
D: EuclideanDomain,
pub fn content(&self) -> D::Elementwhere
D: EuclideanDomain,
Compute the content: the GCD of all coefficients.
For the zero polynomial the content is zero.
§Example
use ocas_domain::{Integer, IntegerDomain};
use ocas_poly::SparseMultivariatePolynomial;
use ocas_poly::Lex;
let p = SparseMultivariatePolynomial::<_, Lex>::from_terms(
IntegerDomain, 1,
vec![(vec![2], Integer::from(6)), (vec![1], Integer::from(9)), (vec![0], Integer::from(3))],
);
assert_eq!(p.content(), Integer::from(3));Sourcepub fn primitive_part(&self) -> Selfwhere
D: EuclideanDomain,
pub fn primitive_part(&self) -> Selfwhere
D: EuclideanDomain,
Return the primitive part: self / content.
The result has content 1 (or is zero).
§Example
use ocas_domain::{Integer, IntegerDomain};
use ocas_poly::SparseMultivariatePolynomial;
use ocas_poly::Lex;
let p = SparseMultivariatePolynomial::<_, Lex>::from_terms(
IntegerDomain, 1,
vec![(vec![2], Integer::from(6)), (vec![0], Integer::from(3))],
);
let pp = p.primitive_part();
// After dividing by content=3: 2*x^2 + 1
assert_eq!(pp.coeff(&[2]), Integer::from(2));
assert_eq!(pp.coeff(&[0]), Integer::from(1));Sourcepub fn div_exact(&self, divisor: &Self) -> Self
pub fn div_exact(&self, divisor: &Self) -> Self
Divide this polynomial by another, assuming the division is exact (no remainder).
Each term of self is divided by the corresponding factor from
divisor. This is used in rational-function canonicalization where
the GCD is known to divide both numerator and denominator.
§Panics
Panics if the division is not exact.
Sourcepub fn degree_in(&self, var_index: usize) -> usize
pub fn degree_in(&self, var_index: usize) -> usize
Return the degree of this polynomial in the given variable.
Returns 0 for the zero polynomial (by convention) or if the variable does not appear.
Sourcepub fn max_exp(&self) -> Option<&SmallVec<[usize; 4]>>
pub fn max_exp(&self) -> Option<&SmallVec<[usize; 4]>>
Return the exponent vector of the leading monomial, or None for zero.
This is an alias for leading_monomial that
matches the Symbolica naming convention used in the F4 algorithm.
Sourcepub fn max_coeff(&self) -> Option<&D::Element>
pub fn max_coeff(&self) -> Option<&D::Element>
Return the leading coefficient, or None for zero.
This is an alias for leading_coeff that
matches the Symbolica naming convention used in the F4 algorithm.
Sourcepub fn exponents_iter(&self) -> impl Iterator<Item = &SmallVec<[usize; 4]>>
pub fn exponents_iter(&self) -> impl Iterator<Item = &SmallVec<[usize; 4]>>
Iterate over all exponent vectors in sorted order (descending by the monomial ordering).
The F4 algorithm uses this to enumerate every monomial in a polynomial for symbolic preprocessing.
Sourcepub fn make_monic_inplace(&mut self) -> bool
pub fn make_monic_inplace(&mut self) -> bool
Divide every term by the leading coefficient, making the polynomial
monic. Returns false if the polynomial is zero or the leading
coefficient has no inverse.
Sourcepub fn zero_with_capacity(&self, _cap: usize) -> Self
pub fn zero_with_capacity(&self, _cap: usize) -> Self
Create a zero polynomial with the same domain and variable count.
This is identical to zero but named to match the
Symbolica convention used in F4 code.
Sourcepub fn append_monomial(&mut self, coeff: D::Element, exp: &[usize])
pub fn append_monomial(&mut self, coeff: D::Element, exp: &[usize])
Append a single monomial term coeff * x^exp.
If the monomial already exists, the coefficients are summed. Zero coefficients remove the term.
Sourcepub fn eval(&self, var_index: usize, value: &D::Element) -> Self
pub fn eval(&self, var_index: usize, value: &D::Element) -> Self
Evaluate the polynomial by substituting value for variable var_index.
Returns a polynomial in one fewer variable (all remaining variables
keep their relative order). If var_index is the only variable, the
result is a zero-variable (constant) polynomial.
§Example
use ocas_domain::{Integer, IntegerDomain};
use ocas_poly::SparseMultivariatePolynomial;
use ocas_poly::Lex;
let p = SparseMultivariatePolynomial::<_, Lex>::from_terms(
IntegerDomain, 2,
vec![
(vec![1, 1], Integer::from(1)), // x*y
(vec![0, 1], Integer::from(2)), // 2*y
],
);
// Substitute x=3: result = 3*y + 2*y = 5*y
let r = p.eval(0, &Integer::from(3));
assert_eq!(r.coeff(&[1]), Integer::from(5));Source§impl SparseMultivariatePolynomial<IntegerDomain, Lex>
impl SparseMultivariatePolynomial<IntegerDomain, Lex>
Sourcepub fn factor(&self) -> Vec<(Self, usize)>
pub fn factor(&self) -> Vec<(Self, usize)>
Factor this bivariate integer polynomial into irreducible factors with multiplicities.
The current implementation treats the polynomial as univariate in the first variable $x$ with coefficients in $\mathbb{Z}[y]$ and uses Wang’s Hensel-lifting algorithm. It succeeds when the leading coefficient in $x$ is an integer constant.
§Example
use ocas_domain::{Integer, IntegerDomain};
use ocas_poly::SparseMultivariatePolynomial;
use ocas_poly::Lex;
// (x^2 + y + 1)(x + y + 2)
let f = SparseMultivariatePolynomial::<_, Lex>::from_terms(
IntegerDomain, 2,
vec![
(vec![3, 0], Integer::from(1)),
(vec![2, 1], Integer::from(1)),
(vec![2, 0], Integer::from(2)),
(vec![1, 1], Integer::from(1)),
(vec![1, 0], Integer::from(1)),
(vec![0, 2], Integer::from(1)),
(vec![0, 1], Integer::from(3)),
(vec![0, 0], Integer::from(2)),
],
);
let factors = f.factor();
assert!(factors.len() >= 2);Source§impl SparseMultivariatePolynomial<FiniteField, Lex>
impl SparseMultivariatePolynomial<FiniteField, Lex>
Sourcepub fn factor(&self) -> Vec<(Self, usize)>
pub fn factor(&self) -> Vec<(Self, usize)>
Factor this bivariate polynomial over a prime finite field into irreducible factors with multiplicities.
The current implementation treats the polynomial as univariate in the first variable $x$ with coefficients in $\mathbb{F}_p[y]$ and uses Hensel lifting. It succeeds when the leading coefficient in $x$ is a field constant and the polynomial is square-free (or the derivative in $x$ is non-zero).
Trait Implementations§
Source§impl<D: Clone + Domain, O: Clone + MonomialOrder> Clone for SparseMultivariatePolynomial<D, O>
impl<D: Clone + Domain, O: Clone + MonomialOrder> Clone for SparseMultivariatePolynomial<D, O>
Source§fn clone(&self) -> SparseMultivariatePolynomial<D, O>
fn clone(&self) -> SparseMultivariatePolynomial<D, O>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<D: Debug + Domain, O: Debug + MonomialOrder> Debug for SparseMultivariatePolynomial<D, O>
impl<D: Debug + Domain, O: Debug + MonomialOrder> Debug for SparseMultivariatePolynomial<D, O>
impl<D: Eq + Domain, O: Eq + MonomialOrder> Eq for SparseMultivariatePolynomial<D, O>
Source§impl<D: PartialEq + Domain, O: PartialEq + MonomialOrder> PartialEq for SparseMultivariatePolynomial<D, O>
impl<D: PartialEq + Domain, O: PartialEq + MonomialOrder> PartialEq for SparseMultivariatePolynomial<D, O>
Source§fn eq(&self, other: &SparseMultivariatePolynomial<D, O>) -> bool
fn eq(&self, other: &SparseMultivariatePolynomial<D, O>) -> bool
self and other values to be equal, and is used by ==.