rithm/
traits.rs

1use std::ops::Neg;
2
3use traiter::numbers::Signed;
4
5use crate::constants::UNDEFINED_DIVISION_ERROR_MESSAGE;
6
7pub trait TryDivAsFloat<Divisor, Output> {
8    type Error;
9
10    fn try_div_as_float(self, divisor: Divisor)
11        -> Result<Output, Self::Error>;
12}
13
14macro_rules! try_div_integer_as_float_impl {
15    ($($integer:ty)+ => $float:ty) => {
16        $(
17            impl TryDivAsFloat<Self, $float> for $integer {
18                type Error = &'static str;
19
20                #[inline]
21                fn try_div_as_float(self, divisor: Self) -> Result<$float, Self::Error> {
22                    if divisor == 0 {
23                        Err(UNDEFINED_DIVISION_ERROR_MESSAGE)
24                    } else {
25                        Ok((self as $float) / (divisor as $float))
26                    }
27                }
28            }
29        )+
30    }
31}
32
33try_div_integer_as_float_impl!(
34    u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize => f32
35);
36try_div_integer_as_float_impl!(
37    u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize => f64
38);
39
40pub trait DoublePrecision: Sized {
41    type Result: From<Self>;
42}
43
44impl DoublePrecision for i8 {
45    type Result = i16;
46}
47
48impl DoublePrecision for i16 {
49    type Result = i32;
50}
51
52impl DoublePrecision for i32 {
53    type Result = i64;
54}
55
56impl DoublePrecision for i64 {
57    type Result = i128;
58}
59
60impl DoublePrecision for u8 {
61    type Result = u16;
62}
63
64impl DoublePrecision for u16 {
65    type Result = u32;
66}
67
68impl DoublePrecision for u32 {
69    type Result = u64;
70}
71
72impl DoublePrecision for u64 {
73    type Result = u128;
74}
75
76pub trait HasSignBit {
77    const RESULT: bool;
78}
79
80impl HasSignBit for i8 {
81    const RESULT: bool = true;
82}
83
84impl HasSignBit for i16 {
85    const RESULT: bool = true;
86}
87
88impl HasSignBit for i32 {
89    const RESULT: bool = true;
90}
91
92impl HasSignBit for i64 {
93    const RESULT: bool = true;
94}
95
96impl HasSignBit for i128 {
97    const RESULT: bool = true;
98}
99
100impl HasSignBit for isize {
101    const RESULT: bool = true;
102}
103
104impl HasSignBit for u8 {
105    const RESULT: bool = false;
106}
107
108impl HasSignBit for u16 {
109    const RESULT: bool = false;
110}
111
112impl HasSignBit for u32 {
113    const RESULT: bool = false;
114}
115
116impl HasSignBit for u64 {
117    const RESULT: bool = false;
118}
119
120impl HasSignBit for u128 {
121    const RESULT: bool = false;
122}
123
124impl HasSignBit for usize {
125    const RESULT: bool = false;
126}
127
128pub trait MantissaDigits {
129    const MANTISSA_DIGITS: usize;
130}
131
132macro_rules! float_mantissa_digits_impl {
133    ($($float:ty)*) => ($(
134        impl MantissaDigits for $float {
135            const MANTISSA_DIGITS: usize = <$float>::MANTISSA_DIGITS as usize;
136        }
137    )*)
138}
139
140float_mantissa_digits_impl!(f32 f64);
141
142pub trait MaxExp {
143    const MAX_EXP: i32;
144}
145
146macro_rules! float_max_exp_impl {
147    ($($float:ty)*) => ($(
148        impl MaxExp for $float {
149            const MAX_EXP: i32 = <$float>::MAX_EXP;
150        }
151    )*)
152}
153
154float_max_exp_impl!(f32 f64);
155
156pub trait MinExp {
157    #[allow(dead_code)]
158    const MIN_EXP: i32;
159}
160
161macro_rules! float_min_exp_impl {
162    ($($float:ty)*) => ($(
163        impl MinExp for $float {
164            const MIN_EXP: i32 = <$float>::MIN_EXP;
165        }
166    )*)
167}
168
169float_min_exp_impl!(f32 f64);
170
171pub trait Oppose {
172    type Result: Copy + Neg<Output = Self::Result> + Signed;
173}
174
175impl Oppose for i8 {
176    type Result = i8;
177}
178
179impl Oppose for i16 {
180    type Result = i16;
181}
182
183impl Oppose for i32 {
184    type Result = i32;
185}
186
187impl Oppose for i64 {
188    type Result = i64;
189}
190
191impl Oppose for i128 {
192    type Result = i128;
193}
194
195impl Oppose for isize {
196    type Result = isize;
197}
198
199impl Oppose for u8 {
200    type Result = i8;
201}
202
203impl Oppose for u16 {
204    type Result = i16;
205}
206
207impl Oppose for u32 {
208    type Result = i32;
209}
210
211impl Oppose for u64 {
212    type Result = i64;
213}
214
215impl Oppose for u128 {
216    type Result = i128;
217}
218
219impl Oppose for usize {
220    type Result = isize;
221}
222
223pub trait UncheckedToInt<Int> {
224    unsafe fn unchecked_to_int(self) -> Int;
225}
226
227macro_rules! impl_float_unchecked_to_int_impl {
228    ($float:ty => $($integer:ty)+) => {
229        $(
230            impl UncheckedToInt<$integer> for $float {
231                #[inline(always)]
232                unsafe fn unchecked_to_int(self) -> $integer {
233                    self.to_int_unchecked::<$integer>()
234                }
235            }
236        )+
237    }
238}
239
240impl_float_unchecked_to_int_impl!(
241    f32 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize
242);
243impl_float_unchecked_to_int_impl!(
244    f64 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize
245);
246
247pub(crate) trait WrappingSub<Subtrahend = Self> {
248    type Output;
249
250    fn wrapping_sub(self, subtrahend: Subtrahend) -> Self::Output;
251}
252
253macro_rules! integer_wrapping_sub_impl {
254    ($($integer:ty)*) => ($(
255        impl WrappingSub for $integer {
256            type Output = $integer;
257
258            #[inline(always)]
259            fn wrapping_sub(self, subtrahend: Self) -> Self::Output {
260                <$integer>::wrapping_sub(self, subtrahend)
261            }
262        }
263    )*)
264}
265
266integer_wrapping_sub_impl!(
267    i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize
268);
269
270pub type DoublePrecisionOf<T> = <T as DoublePrecision>::Result;
271pub type OppositionOf<T> = <T as Oppose>::Result;