use general::{Monoid, GroupAbelian, Additive, Multiplicative};
use general::Wrapper as W;
use cmp::ApproxEq;
pub trait Ring
: GroupAbelian<Additive>
+ Monoid<Multiplicative>
{
fn prop_mul_and_add_are_distributive(args: (Self, Self, Self)) -> bool
where Self: ApproxEq {
let (a, b, c) = (|| W(args.0.clone()), || W(args.1.clone()), || W(args.2.clone()));
((a() * b()) + c()).approx_eq(&((a() * b()) + (a() * c()))) &&
((b() + c()) * a()).approx_eq(&((b() * a()) + (c() * a())))
}
}
impl_marker!(Ring; i8, i16, i32, i64, f32, f64);
pub trait RingCommutative : Ring
{
fn prop_mul_is_commutative(args: (Self, Self)) -> bool
where Self: ApproxEq {
let (a, b) = (|| W(args.0.clone()), || W(args.1.clone()));
(a() * b()).approx_eq(&(b() * a()))
}
}
impl_marker!(RingCommutative; i8, i16, i32, i64, f32, f64);
pub trait Field
: RingCommutative
+ GroupAbelian<Multiplicative>
{}
impl_marker!(Field; f32, f64);