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;