1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#![doc="Defines the commutative ring algebraic structure.

A commutative ring is a ring where the multiplication
operation is commutative.

A commutative ring is a set R equipped with binary operations + and * 
satisfying the following nine axioms:

R is an abelian group under addition, meaning:

* (a + b) + c = a + (b + c) for all a, b, c in R (+ is associative).
* There is an element 0 in R such that a + 0 = a and 0 + a = a for all a in R (0 is the additive identity).
* For each a in R there exists −a in R such that a + (−a) = (−a) + a = 0 (−a is the additive inverse of a).
* a + b = b + a for all a, b in R (+ is commutative).


R is a commutative monoid under multiplication, meaning:

* (a * b) * c = a * (b * c) for all a, b, c in R (* is associative).
* There is an element 1 in R such that a * 1 = a and 1 * a = a for all a in R (1 is the multiplicative identity).[2]
* a * b = b * a for all a, b in R (* is commutative).

Multiplication distributes over addition:

* a * (b + c) = (a * b) + (a * c) for all a, b, c in R (left distributivity).
* (b + c) * a = (b * a) + (c * a) for all a, b, c in R (right distributivity).


References:

* http://en.wikipedia.org/wiki/Algebraic_structure
* http://en.wikipedia.org/wiki/Group_(mathematics)
* http://en.wikipedia.org/wiki/Monoid
* http://en.wikipedia.org/wiki/Ring_(mathematics)

"]

use algebra::structure::monoid::{CommutativeMonoidMulPartial, CommutativeMonoidMul};
use algebra::structure::ring::{RingPartial, Ring};


/// Commutative ring with partial equivalence
pub trait  CommutativeRingPartial : RingPartial 
    + CommutativeMonoidMulPartial
{

    fn prop_multiplication_is_commutative(a : Self, b : Self) -> bool {
        CommutativeMonoidMulPartial::prop_is_commutative(a, b)
    }


    fn check_all_properties(a: Self, b: Self, c : Self)-> bool {
        if !RingPartial::check_all_properties(
            a.clone(), b.clone(), c.clone()) {
            return false;
        }
        if !CommutativeRingPartial::prop_multiplication_is_commutative(a.clone(), b.clone()){
            return false;
        }
        if !CommutativeRingPartial::prop_multiplication_is_commutative(b.clone(), c.clone()){
            return false;
        }
        if !CommutativeRingPartial::prop_multiplication_is_commutative(a.clone(), c.clone()){
            return false;
        }
        true
    }
}

impl<T> CommutativeRingPartial for T where
    T: RingPartial + CommutativeMonoidMulPartial
{}

///////////////////////////////////////////////////////////

/// Commutative ring with full equivalence
pub trait CommutativeRing : CommutativeRingPartial 
    + Ring + CommutativeMonoidMul{
    fn check_all_properties(a: Self, b: Self, c : Self)-> bool {
        CommutativeRingPartial::check_all_properties(a, b, c)
    }
}


impl<T> CommutativeRing for T where
    T: Ring + CommutativeMonoidMul
{

}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_commutative_ring_partial() {
        assert!(CommutativeRingPartial::check_all_properties(2i8, 3i8, 1i8));
        assert!(CommutativeRingPartial::check_all_properties(2i16, 3i16, 1i16));
        assert!(CommutativeRingPartial::check_all_properties(2i32, 3i32, 1i32));
        assert!(CommutativeRingPartial::check_all_properties(2i64, 3i64, 1i64));
        assert!(CommutativeRingPartial::check_all_properties(2f32, 3f32, 1f32));
        assert!(CommutativeRingPartial::check_all_properties(2f64, 3f64, 1f64));
    }

    #[test]
    fn test_commutative_ring() {
        assert!(CommutativeRing::check_all_properties(2i8, 3i8, 1i8));
        assert!(CommutativeRing::check_all_properties(2i16, 3i16, 1i16));
        assert!(CommutativeRing::check_all_properties(2i32, 3i32, 1i32));
        assert!(CommutativeRing::check_all_properties(2i64, 3i64, 1i64));
        // following cannot work
        //assert!(Ring::check_all_properties(2f64, 3f64, 1f64));
        //assert!(Ring::check_all_properties(2u64, 3u64, 1u64));
    }

}