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
117
118
119
use approx::ApproxEq;
use general::{Operator, Additive, Multiplicative, AbstractGroupAbelian, AbstractMonoid};
use general::wrapper::Wrapper as W;
pub trait AbstractRing<A: Operator = Additive, M: Operator = Multiplicative>:
AbstractGroupAbelian<A> + AbstractMonoid<M> {
fn prop_mul_and_add_are_distributive_approx(args: (Self, Self, Self)) -> bool
where Self: ApproxEq {
let (a, b, c) = args;
let a = || { W::<_, A, M>::new(a.clone()) };
let b = || { W::<_, A, M>::new(b.clone()) };
let c = || { W::<_, A, M>::new(c.clone()) };
relative_eq!(a() * (b() + c()), a() * b() + a() * c()) &&
relative_eq!((b() + c()) * a(), b() * a() + c() * a())
}
fn prop_mul_and_add_are_distributive(args: (Self, Self, Self)) -> bool
where Self: Eq {
let (a, b, c) = args;
let a = || { W::<_, A, M>::new(a.clone()) };
let b = || { W::<_, A, M>::new(b.clone()) };
let c = || { W::<_, A, M>::new(c.clone()) };
(a() * b()) + c() == (a() * b()) + (a() * c()) &&
(b() + c()) * a() == (b() * a()) + (c() * a())
}
}
#[macro_export]
macro_rules! impl_ring(
(<$A:ty, $M:ty> for $($T:ty);* $(;)*) => {
impl_abelian!(<$A> for $($T);*);
impl_monoid!(<$M> for $($T);*);
impl_marker!(AbstractRing<$A, $M>; $($T);*);
}
);
pub trait AbstractRingCommutative<A: Operator = Additive, M: Operator = Multiplicative> : AbstractRing<A, M> {
fn prop_mul_is_commutative_approx(args: (Self, Self)) -> bool
where Self: ApproxEq {
let (a, b) = args;
let a = || { W::<_, A, M>::new(a.clone()) };
let b = || { W::<_, A, M>::new(b.clone()) };
relative_eq!(a() * b(), b() * a())
}
fn prop_mul_is_commutative(args: (Self, Self)) -> bool
where Self: Eq {
let (a, b) = args;
let a = || { W::<_, A, M>::new(a.clone()) };
let b = || { W::<_, A, M>::new(b.clone()) };
a() * b() == b() * a()
}
}
#[macro_export]
macro_rules! impl_ring_commutative(
(<$A:ty, $M:ty> for $($T:ty);* $(;)*) => {
impl_ring!(<$A, $M> for $($T);*);
impl_marker!($crate::general::AbstractRingCommutative<$A, $M>; $($T);*);
}
);
pub trait AbstractField<A: Operator = Additive, M: Operator = Multiplicative>
: AbstractRingCommutative<A, M>
+ AbstractGroupAbelian<M>
{ }
#[macro_export]
macro_rules! impl_field(
(<$A:ty, $M:ty> for $($T:ty);* $(;)*) => {
impl_ring_commutative!(<$A, $M> for $($T);*);
impl_marker!($crate::general::AbstractQuasigroup<$M>; $($T);*);
impl_marker!($crate::general::AbstractLoop<$M>; $($T);*);
impl_marker!($crate::general::AbstractGroup<$M>; $($T);*);
impl_marker!($crate::general::AbstractGroupAbelian<$M>; $($T);*);
impl_marker!($crate::general::AbstractField<$A, $M>; $($T);*);
}
);
impl_ring_commutative!(<Additive, Multiplicative> for i8; i16; i32; i64);
impl_field!(<Additive, Multiplicative> for f32; f64);