add a few tests for monomials and polynomials ops

This commit is contained in:
2026-04-22 10:39:10 +02:00
parent 09a9613870
commit 345bc0f126

View File

@@ -1,13 +1,13 @@
use itertools::Itertools;
use std::fmt::{self, Display};
use std::ops::{Add, Sub, BitXor, Mul};
use std::ops::{Add, BitXor, Mul, Sub};
use crate::fmt::num_to_superscript;
use super::var::{StaticVar, Var};
use crate::fmt::num_to_superscript;
use std::collections::HashMap;
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq)]
pub struct Poly<V: Var> {
mono: HashMap<Mono<V>, i32>,
}
@@ -103,11 +103,9 @@ impl<V: Var, U: Into<V>> FromIterator<(U, u32)> for Mono<V> {
term.sort();
// Check duplicate variables
assert!(
(term[..])
assert!((term[..])
.windows(2)
.all(|window| window[0].0 != window[1].0)
);
.all(|window| window[0].0 != window[1].0));
Mono { term }
}
@@ -223,3 +221,106 @@ impl<V: Var> Sub for Poly<V> {
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mono_contains() {
let a: Mono<StaticVar> = [("x", 2), ("y", 1)].into();
// Lower exponent of same variable is contained
assert!(a.contains(&Mono::from([("x", 1)])));
// Higher exponent of same variable is not contained
assert!(!a.contains(&Mono::from([("x", 3)])));
// Identical monomial is contained
assert!(a.contains(&Mono::from([("x", 2), ("y", 1)])));
// Variable absent from self is not contained
assert!(!a.contains(&Mono::from([("x", 2), ("z", 1)])));
// Subset of variables with lower exponents is contained
assert!(a.contains(&Mono::from([("x", 1), ("y", 1)])));
// Single variable with exact exponent is contained
assert!(a.contains(&Mono::from([("x", 2)])));
// Insufficient exponent in self means not contained
assert!(!Mono::<StaticVar>::from([("x", 1)]).contains(&Mono::from([("x", 2)])));
// Missing variable in self means not contained
assert!(!Mono::<StaticVar>::from([("x", 1), ("y", 1)]).contains(&Mono::from([("x", 2)])));
assert!(!Mono::<StaticVar>::from([("x", 1)]).contains(&Mono::from([("x", 1), ("y", 1)])));
}
#[test]
fn test_mono_mul() {
// Same variable: exponents add
let a: Mono<StaticVar> = [("x", 2)].into();
let b: Mono<StaticVar> = [("x", 3)].into();
assert_eq!(a * b, Mono::from([("x", 5)]));
// Disjoint variables: both appear in result
let a: Mono<StaticVar> = [("x", 2)].into();
let b: Mono<StaticVar> = [("y", 3)].into();
assert_eq!(a * b, Mono::from([("x", 2), ("y", 3)]));
// Mixed: shared and disjoint variables
let a: Mono<StaticVar> = [("x", 1), ("y", 2)].into();
let b: Mono<StaticVar> = [("y", 1), ("z", 3)].into();
assert_eq!(a * b, Mono::from([("x", 1), ("y", 3), ("z", 3)]));
// Commutativity
let a: Mono<StaticVar> = [("x", 2), ("z", 1)].into();
let b: Mono<StaticVar> = [("y", 3)].into();
assert_eq!(a.clone() * b.clone(), b * a);
// Multiply by constant monomial (empty term vec = 1)
let a: Mono<StaticVar> = [("x", 4)].into();
let one: Mono<StaticVar> = Mono { term: vec![] };
assert_eq!(a.clone() * one, a);
}
#[test]
fn test_poly_add() {
// Distinct monomials are collected as separate terms
let a: Poly<StaticVar> = [(1, [("x", 2)]), (2, [("y", 1)])].into();
let b: Poly<StaticVar> = [(3, [("z", 1)])].into();
let expected: Poly<StaticVar> = [(1, [("x", 2)]), (2, [("y", 1)]), (3, [("z", 1)])].into();
assert_eq!(a + b, expected);
// Coefficients of matching monomials are summed
let a: Poly<StaticVar> = [(2, [("x", 1)])].into();
let b: Poly<StaticVar> = [(3, [("x", 1)])].into();
let expected: Poly<StaticVar> = [(5, [("x", 1)])].into();
assert_eq!(a + b, expected);
// Terms that cancel sum to zero are dropped
let a: Poly<StaticVar> = [(1, [("x", 1)])].into();
let b: Poly<StaticVar> = [(-1, [("x", 1)])].into();
let expected: Poly<StaticVar> = Poly::default();
assert_eq!(a + b, expected);
}
#[test]
fn test_poly_sub() {
// Distinct monomials are collected as separate terms with negated rhs coefficients
let a: Poly<StaticVar> = [(3, [("x", 2)])].into();
let b: Poly<StaticVar> = [(1, [("y", 1)])].into();
let expected: Poly<StaticVar> = [(3, [("x", 2)]), (-1, [("y", 1)])].into();
assert_eq!(a - b, expected);
// Coefficients of matching monomials are subtracted
let a: Poly<StaticVar> = [(5, [("x", 1)])].into();
let b: Poly<StaticVar> = [(3, [("x", 1)])].into();
let expected: Poly<StaticVar> = [(2, [("x", 1)])].into();
assert_eq!(a - b, expected);
// Subtracting equal polynomials yields zero
let a: Poly<StaticVar> = [(4, [("x", 2)]), (1, [("y", 1)])].into();
let b: Poly<StaticVar> = [(4, [("x", 2)]), (1, [("y", 1)])].into();
assert_eq!(a - b, Poly::default());
}
}