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.
//!
//! Additive commutative groups.
//!
//! An algebraic _additive_ _commutative_ _group_ is an _additive_
//! _group_ `G`, where group addition `+` is required to be
//! _commutative_.
//!
//! # Axioms
//!
//! ```text
//! ∀g, h ∈ G
//!
//! Commutativity: g + h = h + g.
//! ```
//!
//! # References
//!
//! See [references] for a formal definition of an additive commutative
//! group.
//!
#![doc(include = "../../doc/references.md")]

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


///
/// An algebraic _additive_ _commutative_ _group_.
///
pub trait AddComGroup: AddGroup {}


///
/// Laws of additive commutative groups.
///
pub trait AddComGroupLaws: AddComGroup {

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


///
/// Blanket implementation of additive commutative group laws for
/// additive commutative group implementations.
///
impl<G: AddComGroup> AddComGroupLaws for G {}


///
/// Numeric laws of additive commutative groups.
///
pub trait NumAddComGroupLaws: NumEq + AddComGroup {

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


///
/// Blanket implementation of numeric additive commutative group laws
/// for additive commutative group implementations.
///
impl<G: NumEq + AddComGroup> NumAddComGroupLaws for G {}


///
/// Define `AddComGroup` implementations for numeric types.
///
macro_rules! numeric_add_com_group {
  ($type:ty) => {
    impl AddComGroup for $type {}
  };

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


// Signed integers and floats form additive commutative groups.
numeric_add_com_group! {
  i8, i16, i32, i64, i128, isize, f32, f64
}


///
/// 0-tuples form an additive commutative group.
///
impl AddComGroup for () {}


///
/// 1-tuples form an additive commutative group when their items do.
///
impl<A: AddComGroup> AddComGroup for (A,) {}


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


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


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

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


// Array commutative additive group types.
array_add_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;