1use basenum::{ BaseNum, BaseInt, BaseFloat, SignedNum, ApproxEq };
25use std::ops::{ Add, Mul, Sub, Div, Rem, Not, BitAnd, BitOr, BitXor, Shl, Shr };
26use rand::Rand;
27use num::{ Float, One, Zero };
28
29pub trait GenNum<E: BaseNum>
33: Copy
34+ Sized
35+ Clone
36+ One
37+ Zero
38+ Div<Self, Output = Self>
39+ Rem<Self, Output = Self>
40+ Add<E, Output = Self>
41+ Mul<E, Output = Self>
42+ Rand
43{
44    fn from_s(x: E) -> Self;
46
47    fn map<F>(self, f: F) -> Self where F: Fn(E) -> E;
48
49    fn zip<F>(self, y: Self, f: F) -> Self where F: Fn(E, E) -> E;
50
51    fn split<F>(self, f: F) -> (Self, Self) where F: Fn(E) -> (E, E);
52
53    fn map2<F>(self, y: Self, f: F) -> (Self, Self) where F: Fn(E, E) -> (E, E);
54}
55
56macro_rules! impl_GenNum_for_scalar(
57    ($t: ty) => {
58        impl GenNum<$t> for $t {
59            #[inline(always)]
60            fn from_s(x: $t) -> Self {
61                x
62            }
63            #[inline(always)]
64            fn map<F: Fn($t) -> $t>(self, f: F) -> $t {
65                f(self)
66            }
67            #[inline(always)]
68            fn zip<F: Fn($t, $t) -> $t>(self, y: $t, f: F) -> $t {
69                f(self, y)
70            }
71            #[inline(always)]
72            fn split<F: Fn($t) -> ($t, $t)>(self, f: F) -> ($t, $t) {
73                f(self)
74            }
75            #[inline(always)]
76            fn map2<F: Fn($t, $t) -> ($t, $t)>(self, y: $t, f: F) -> ($t, $t) {
77                f(self, y)
78            }
79        }
80    }
81);
82
83pub trait GenInt<I: BaseInt>
85: GenNum<I>
86+ Eq
87+ Not<Output = Self>
88+ BitAnd<Output = Self>
89+ BitOr<Output = Self>
90+ BitXor<Output = Self>
91+ Shl<usize, Output = Self>
92+ Shr<usize, Output = Self>
93{}
94
95pub trait GenIType: GenInt<i32> + SignedNum + Sub<i32, Output = Self> {}
101
102impl_GenNum_for_scalar! { i32 }
103impl GenInt<i32> for i32 {}
104impl GenIType for i32 {}
105
106pub trait GenUType: GenInt<u32> {}
112
113impl_GenNum_for_scalar! { u32 }
114impl GenInt<u32> for u32 {}
115impl GenUType for u32 {}
116
117pub trait GenFloat<F: BaseFloat>
119: GenNum<F>
120+ ApproxEq<BaseType = F>
121+ SignedNum
122+ Sub<F, Output = Self>
123{
124    fn fma(&self, b: &Self, c: &Self) -> Self;
126}
127
128pub trait GenType: GenFloat<f32> {}
129pub trait GenDType: GenFloat<f64> {}
130
131macro_rules! impl_GenFloat_for_scalar(
132    ($t: ty, $gt: ty) => {
133        impl_GenNum_for_scalar! { $t }
134        impl GenFloat<$t> for $t {
135            fn fma(&self, b: &$t, c: &$t) -> $t {
136                Float::mul_add(*self, *b, *c)
137            }
138        }
139        impl $gt for $t {}
140    }
141);
142
143impl_GenFloat_for_scalar! { f32, GenType }
144impl_GenFloat_for_scalar! { f64, GenDType }
145
146pub trait GenBType: Eq {}
148
149impl GenBType for bool {}