un_algebra 0.9.0

Simple implementations of selected abstract algebraic structures--including groups, rings, and fields. Intended for self-study of abstract algebra concepts and not for production use.
//!
//! Multiplicative commutative groups.
//!
//! An algebraic _multiplicative_ _commutative_ _group_ is a
//! _multiplicative_ _group_ `M`, where group multiplication `×` is
//! required to be _commutative_.
//!
//! # Axioms
//!
//! ```text
//! ∀g, h ∈ M
//!
//! Commutativity: g × h = h × g.
//! ```
//!
//! # References
//!
//! See [references] for a formal definition of a multiplicative
//! commutative group.
//!
#![doc(include = "../../doc/references.md")]

use crate::group::*;
use crate::numeric::*;


///
/// An algebraic _multiplicative_ _commutative_ _group_.
///
pub trait MulComGroup: MulGroup {}


///
/// Laws of multiplicative commutative groups.
///
pub trait MulComGroupLaws: MulComGroup {

  /// The _multiplicative_ _commutivity_ axiom.
  fn commutivity(&self, x: &Self) -> bool {
    self.mul(x) == x.mul(self)
  }
}


///
/// Blanket implementation of multiplicative commutative group laws for
/// multiplicative commutative group implementations.
///
impl<G: MulComGroup> MulComGroupLaws for G {}


///
/// Numeric laws of multiplicative commutative groups.
///
pub trait NumMulComGroupLaws: NumEq + MulComGroup {

  /// The _numeric_ _multiplicative_ _commutivity_ axiom.
  fn num_commutivity(&self, x: &Self, eps: &Self::Eps) -> bool {
    self.mul(x).num_eq(&x.mul(self), eps)
  }
}


///
/// Blanket implementation of numeric multiplicative commutative group
/// laws for multiplicative commutative group implementations.
///
impl<G: NumEq + MulComGroup> NumMulComGroupLaws for G {}


///
/// Define `MulComGroup` implementations for floating point types.
/// Probably not needed if Rust had a `Float` super-trait.
///
macro_rules! float_mul_com_group {
  ($type:ty) => {
    impl MulComGroup for $type {}
  };

  ($type:ty, $($others:ty),+) => {
    float_mul_com_group! {$type}
    float_mul_com_group! {$($others),+}
  };
}


// Multiplicative commutative group floating point types.
float_mul_com_group! {
  f32, f64
}


///
/// 0-tuples form a multiplicative commutative group.
///
impl MulComGroup for () {}


///
/// 1-tuples form a multiplicative commutative group when their items
/// do.
///
impl<A: MulComGroup> MulComGroup for (A,) {}


///
/// 2-tuples form a multiplicative commutative group when their items
/// do.
///
impl<A: MulComGroup, B: MulComGroup> MulComGroup for (A, B) {}


///
/// 3-tuples form a multiplicative commutative group when their items
/// do.
///
impl<A: MulComGroup, B: MulComGroup, C: MulComGroup> MulComGroup for (A, B, C) {}


///
/// Define `MulComGroup` implementations for arrays. Maybe not needed if
/// Rust had _const_ _generics_.
///
macro_rules! array_mul_com_group {
  ($size:expr) => {
    impl<T: Copy + MulComGroup> MulComGroup for [T; $size] {}
  };

  ($size:expr, $($others:expr),+) => {
    array_mul_com_group! {$size}
    array_mul_com_group! {$($others),+}
  };
}


// Array commutative multiplicative group types.
array_mul_com_group! {
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
}


// Module unit tests are in a sub-module.
#[cfg(test)]
mod tests;