use crate::ring::Polynomial;
#[inline]
fn a() -> Polynomial {
Polynomial::var(0)
}
#[inline]
fn b() -> Polynomial {
Polynomial::var(1)
}
#[inline]
fn c() -> Polynomial {
Polynomial::var(2)
}
#[inline]
fn d() -> Polynomial {
Polynomial::var(3)
}
pub fn add_associative() -> bool {
a().add(&b()).add(&c()).canonical_eq(&a().add(&b().add(&c())))
}
pub fn add_commutative() -> bool {
a().add(&b()).canonical_eq(&b().add(&a()))
}
pub fn mul_associative() -> bool {
a().mul(&b()).mul(&c()).canonical_eq(&a().mul(&b().mul(&c())))
}
pub fn mul_commutative() -> bool {
a().mul(&b()).canonical_eq(&b().mul(&a()))
}
pub fn left_distributive() -> bool {
a().mul(&b().add(&c())).canonical_eq(&a().mul(&b()).add(&a().mul(&c())))
}
pub fn additive_identity() -> bool {
a().add(&Polynomial::constant(0)).canonical_eq(&a())
}
pub fn multiplicative_identity() -> bool {
a().mul(&Polynomial::constant(1)).canonical_eq(&a())
}
pub fn karatsuba_expand() -> bool {
let lhs = a().add(&b()).mul(&c().add(&d()));
let rhs = a()
.mul(&c())
.add(&a().mul(&d()))
.add(&b().mul(&c()))
.add(&b().mul(&d()));
lhs.canonical_eq(&rhs)
}
pub fn all_word_ring_laws_certified() -> bool {
add_associative()
&& add_commutative()
&& mul_associative()
&& mul_commutative()
&& left_distributive()
&& additive_identity()
&& multiplicative_identity()
&& karatsuba_expand()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn word_ring_laws_are_kernel_certified() {
assert!(add_associative(), "additive associativity in ℤ/2ⁿ");
assert!(add_commutative(), "additive commutativity in ℤ/2ⁿ");
assert!(mul_associative(), "multiplicative associativity in ℤ/2ⁿ");
assert!(mul_commutative(), "multiplicative commutativity in ℤ/2ⁿ");
assert!(left_distributive(), "left distributivity in ℤ/2ⁿ");
assert!(additive_identity(), "additive identity in ℤ/2ⁿ");
assert!(multiplicative_identity(), "multiplicative identity in ℤ/2ⁿ");
assert!(karatsuba_expand(), "Karatsuba/gauss expansion in ℤ/2ⁿ");
assert!(all_word_ring_laws_certified(), "the combined gate");
}
#[test]
fn wrong_word_ring_identities_are_not_certified() {
assert!(
!a().add(&b()).canonical_eq(&a().mul(&b())),
"sum must not be certified equal to product"
);
assert!(
!a()
.mul(&b().add(&c()))
.canonical_eq(&a().mul(&b()).add(&c())),
"a broken distributive law must not be certified"
);
assert!(
!a()
.add(&b())
.mul(&c().add(&d()))
.canonical_eq(&a().mul(&c()).add(&b().mul(&d()))),
"dropping the cross terms must not be certified"
);
}
}