1use crate::{
4    private::{Internal, InternalMarker},
5    Bit, NInt, NonZero, PInt, UInt, UTerm, Unsigned, Z0,
6};
7
8pub trait Same<Rhs = Self> {
30    type Output;
32}
33
34impl<T> Same<T> for T {
35    type Output = T;
36}
37
38pub trait Abs {
47    type Output;
49}
50
51impl Abs for Z0 {
52    type Output = Z0;
53}
54
55impl<U: Unsigned + NonZero> Abs for PInt<U> {
56    type Output = Self;
57}
58
59impl<U: Unsigned + NonZero> Abs for NInt<U> {
60    type Output = PInt<U>;
61}
62
63pub trait Pow<Exp> {
72    type Output;
74    fn powi(self, exp: Exp) -> Self::Output;
90}
91
92macro_rules! impl_pow_f {
93    ($t:ty) => {
94        impl Pow<UTerm> for $t {
95            type Output = $t;
96            #[inline]
97            fn powi(self, _: UTerm) -> Self::Output {
98                1.0
99            }
100        }
101
102        impl<U: Unsigned, B: Bit> Pow<UInt<U, B>> for $t {
103            type Output = $t;
104            #[inline]
107            fn powi(self, _: UInt<U, B>) -> Self::Output {
108                let mut exp = <UInt<U, B> as Unsigned>::to_u32();
109                let mut base = self;
110
111                if exp == 0 {
112                    return 1.0;
113                }
114
115                while exp & 1 == 0 {
116                    base *= base;
117                    exp >>= 1;
118                }
119                if exp == 1 {
120                    return base;
121                }
122
123                let mut acc = base.clone();
124                while exp > 1 {
125                    exp >>= 1;
126                    base *= base;
127                    if exp & 1 == 1 {
128                        acc *= base.clone();
129                    }
130                }
131                acc
132            }
133        }
134
135        impl Pow<Z0> for $t {
136            type Output = $t;
137            #[inline]
138            fn powi(self, _: Z0) -> Self::Output {
139                1.0
140            }
141        }
142
143        impl<U: Unsigned + NonZero> Pow<PInt<U>> for $t {
144            type Output = $t;
145            #[inline]
148            fn powi(self, _: PInt<U>) -> Self::Output {
149                let mut exp = U::to_u32();
150                let mut base = self;
151
152                if exp == 0 {
153                    return 1.0;
154                }
155
156                while exp & 1 == 0 {
157                    base *= base;
158                    exp >>= 1;
159                }
160                if exp == 1 {
161                    return base;
162                }
163
164                let mut acc = base.clone();
165                while exp > 1 {
166                    exp >>= 1;
167                    base *= base;
168                    if exp & 1 == 1 {
169                        acc *= base.clone();
170                    }
171                }
172                acc
173            }
174        }
175
176        impl<U: Unsigned + NonZero> Pow<NInt<U>> for $t {
177            type Output = $t;
178
179            #[inline]
180            fn powi(self, _: NInt<U>) -> Self::Output {
181                <$t as Pow<PInt<U>>>::powi(self, PInt::new()).recip()
182            }
183        }
184    };
185}
186
187impl_pow_f!(f32);
188impl_pow_f!(f64);
189
190macro_rules! impl_pow_i {
191    () => ();
192    ($(#[$meta:meta])*  $t: ty $(, $tail:tt)*) => (
193        $(#[$meta])*
194        impl Pow<UTerm> for $t {
195            type Output = $t;
196            #[inline]
197            fn powi(self, _: UTerm) -> Self::Output {
198                1
199            }
200        }
201
202        $(#[$meta])*
203        impl<U: Unsigned, B: Bit> Pow<UInt<U, B>> for $t {
204            type Output = $t;
205            #[inline]
206            fn powi(self, _: UInt<U, B>) -> Self::Output {
207                self.pow(<UInt<U, B> as Unsigned>::to_u32())
208            }
209        }
210
211        $(#[$meta])*
212        impl Pow<Z0> for $t {
213            type Output = $t;
214            #[inline]
215            fn powi(self, _: Z0) -> Self::Output {
216                1
217            }
218        }
219
220        $(#[$meta])*
221        impl<U: Unsigned + NonZero> Pow<PInt<U>> for $t {
222            type Output = $t;
223            #[inline]
224            fn powi(self, _: PInt<U>) -> Self::Output {
225                self.pow(U::to_u32())
226            }
227        }
228
229        impl_pow_i!($($tail),*);
230    );
231}
232
233impl_pow_i!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
234#[cfg(feature = "i128")]
235impl_pow_i!(
236    #[cfg_attr(docsrs, doc(cfg(feature = "i128")))]
237    u128,
238    i128
239);
240
241#[test]
242fn pow_test() {
243    use crate::consts::*;
244    let z0 = Z0::new();
245    let p3 = P3::new();
246
247    let u0 = U0::new();
248    let u3 = U3::new();
249    let n3 = N3::new();
250
251    macro_rules! check {
252        ($x:ident) => {
253            assert_eq!($x.powi(z0), 1);
254            assert_eq!($x.powi(u0), 1);
255
256            assert_eq!($x.powi(p3), $x * $x * $x);
257            assert_eq!($x.powi(u3), $x * $x * $x);
258        };
259        ($x:ident, $f:ident) => {
260            assert!((<$f as Pow<Z0>>::powi(*$x, z0) - 1.0).abs() < ::core::$f::EPSILON);
261            assert!((<$f as Pow<U0>>::powi(*$x, u0) - 1.0).abs() < ::core::$f::EPSILON);
262
263            assert!((<$f as Pow<P3>>::powi(*$x, p3) - $x * $x * $x).abs() < ::core::$f::EPSILON);
264            assert!((<$f as Pow<U3>>::powi(*$x, u3) - $x * $x * $x).abs() < ::core::$f::EPSILON);
265
266            if *$x == 0.0 {
267                assert!(<$f as Pow<N3>>::powi(*$x, n3).is_infinite());
268            } else {
269                assert!(
270                    (<$f as Pow<N3>>::powi(*$x, n3) - 1. / $x / $x / $x).abs()
271                        < ::core::$f::EPSILON
272                );
273            }
274        };
275    }
276
277    for x in &[0i8, -3, 2] {
278        check!(x);
279    }
280    for x in &[0u8, 1, 5] {
281        check!(x);
282    }
283    for x in &[0usize, 1, 5, 40] {
284        check!(x);
285    }
286    for x in &[0isize, 1, 2, -30, -22, 48] {
287        check!(x);
288    }
289    for x in &[0.0f32, 2.2, -3.5, 378.223] {
290        check!(x, f32);
291    }
292    for x in &[0.0f64, 2.2, -3.5, -2387.2, 234.22] {
293        check!(x, f64);
294    }
295}
296
297pub trait Cmp<Rhs = Self> {
311    type Output;
313
314    #[doc(hidden)]
315    fn compare<IM: InternalMarker>(&self, _: &Rhs) -> Self::Output;
316}
317
318#[allow(clippy::len_without_is_empty)]
320pub trait Len {
321    type Output: crate::Unsigned;
323    fn len(&self) -> Self::Output;
325}
326
327pub trait FoldAdd {
329    type Output;
331}
332
333pub trait FoldMul {
335    type Output;
337}
338
339#[test]
340fn fold_test() {
341    use crate::*;
342    assert_eq!(10, <FoldSum::<tarr![U2, U3, U5]>>::to_u32());
343    assert_eq!(30, <FoldProd::<tarr![U2, U3, U5]>>::to_u32());
344}
345
346pub trait PartialDiv<Rhs = Self> {
349    type Output;
351    fn partial_div(self, _: Rhs) -> Self::Output;
353}
354
355pub trait Min<Rhs = Self> {
357    type Output;
359    fn min(self, rhs: Rhs) -> Self::Output;
361}
362
363pub trait Max<Rhs = Self> {
365    type Output;
367    fn max(self, rhs: Rhs) -> Self::Output;
369}
370
371use crate::Compare;
372
373pub trait IsLess<Rhs = Self> {
375    type Output: Bit;
377    #[allow(clippy::wrong_self_convention)]
379    fn is_less(self, rhs: Rhs) -> Self::Output;
380}
381
382use crate::private::IsLessPrivate;
383impl<A, B> IsLess<B> for A
384where
385    A: Cmp<B> + IsLessPrivate<B, Compare<A, B>>,
386{
387    type Output = <A as IsLessPrivate<B, Compare<A, B>>>::Output;
388
389    #[inline]
390    fn is_less(self, rhs: B) -> Self::Output {
391        let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
392        self.is_less_private(rhs, lhs_cmp_rhs)
393    }
394}
395
396pub trait IsEqual<Rhs = Self> {
398    type Output: Bit;
400    #[allow(clippy::wrong_self_convention)]
402    fn is_equal(self, rhs: Rhs) -> Self::Output;
403}
404
405use crate::private::IsEqualPrivate;
406impl<A, B> IsEqual<B> for A
407where
408    A: Cmp<B> + IsEqualPrivate<B, Compare<A, B>>,
409{
410    type Output = <A as IsEqualPrivate<B, Compare<A, B>>>::Output;
411
412    #[inline]
413    fn is_equal(self, rhs: B) -> Self::Output {
414        let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
415        self.is_equal_private(rhs, lhs_cmp_rhs)
416    }
417}
418
419pub trait IsGreater<Rhs = Self> {
421    type Output: Bit;
423    #[allow(clippy::wrong_self_convention)]
425    fn is_greater(self, rhs: Rhs) -> Self::Output;
426}
427
428use crate::private::IsGreaterPrivate;
429impl<A, B> IsGreater<B> for A
430where
431    A: Cmp<B> + IsGreaterPrivate<B, Compare<A, B>>,
432{
433    type Output = <A as IsGreaterPrivate<B, Compare<A, B>>>::Output;
434
435    #[inline]
436    fn is_greater(self, rhs: B) -> Self::Output {
437        let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
438        self.is_greater_private(rhs, lhs_cmp_rhs)
439    }
440}
441
442pub trait IsLessOrEqual<Rhs = Self> {
444    type Output: Bit;
446    #[allow(clippy::wrong_self_convention)]
448    fn is_less_or_equal(self, rhs: Rhs) -> Self::Output;
449}
450
451use crate::private::IsLessOrEqualPrivate;
452impl<A, B> IsLessOrEqual<B> for A
453where
454    A: Cmp<B> + IsLessOrEqualPrivate<B, Compare<A, B>>,
455{
456    type Output = <A as IsLessOrEqualPrivate<B, Compare<A, B>>>::Output;
457
458    #[inline]
459    fn is_less_or_equal(self, rhs: B) -> Self::Output {
460        let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
461        self.is_less_or_equal_private(rhs, lhs_cmp_rhs)
462    }
463}
464
465pub trait IsNotEqual<Rhs = Self> {
467    type Output: Bit;
469    #[allow(clippy::wrong_self_convention)]
471    fn is_not_equal(self, rhs: Rhs) -> Self::Output;
472}
473
474use crate::private::IsNotEqualPrivate;
475impl<A, B> IsNotEqual<B> for A
476where
477    A: Cmp<B> + IsNotEqualPrivate<B, Compare<A, B>>,
478{
479    type Output = <A as IsNotEqualPrivate<B, Compare<A, B>>>::Output;
480
481    #[inline]
482    fn is_not_equal(self, rhs: B) -> Self::Output {
483        let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
484        self.is_not_equal_private(rhs, lhs_cmp_rhs)
485    }
486}
487
488pub trait IsGreaterOrEqual<Rhs = Self> {
490    type Output: Bit;
492    #[allow(clippy::wrong_self_convention)]
494    fn is_greater_or_equal(self, rhs: Rhs) -> Self::Output;
495}
496
497use crate::private::IsGreaterOrEqualPrivate;
498impl<A, B> IsGreaterOrEqual<B> for A
499where
500    A: Cmp<B> + IsGreaterOrEqualPrivate<B, Compare<A, B>>,
501{
502    type Output = <A as IsGreaterOrEqualPrivate<B, Compare<A, B>>>::Output;
503
504    #[inline]
505    fn is_greater_or_equal(self, rhs: B) -> Self::Output {
506        let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
507        self.is_greater_or_equal_private(rhs, lhs_cmp_rhs)
508    }
509}
510
511#[deprecated(since = "1.9.0", note = "use the `op!` macro instead")]
535#[macro_export]
536macro_rules! cmp {
537    ($a:ident < $b:ty) => {
538        <$a as $crate::IsLess<$b>>::Output
539    };
540    ($a:ty, < $b:ty) => {
541        <$a as $crate::IsLess<$b>>::Output
542    };
543
544    ($a:ident == $b:ty) => {
545        <$a as $crate::IsEqual<$b>>::Output
546    };
547    ($a:ty, == $b:ty) => {
548        <$a as $crate::IsEqual<$b>>::Output
549    };
550
551    ($a:ident > $b:ty) => {
552        <$a as $crate::IsGreater<$b>>::Output
553    };
554    ($a:ty, > $b:ty) => {
555        <$a as $crate::IsGreater<$b>>::Output
556    };
557
558    ($a:ident <= $b:ty) => {
559        <$a as $crate::IsLessOrEqual<$b>>::Output
560    };
561    ($a:ty, <= $b:ty) => {
562        <$a as $crate::IsLessOrEqual<$b>>::Output
563    };
564
565    ($a:ident != $b:ty) => {
566        <$a as $crate::IsNotEqual<$b>>::Output
567    };
568    ($a:ty, != $b:ty) => {
569        <$a as $crate::IsNotEqual<$b>>::Output
570    };
571
572    ($a:ident >= $b:ty) => {
573        <$a as $crate::IsGreaterOrEqual<$b>>::Output
574    };
575    ($a:ty, >= $b:ty) => {
576        <$a as $crate::IsGreaterOrEqual<$b>>::Output
577    };
578}
579
580pub trait SquareRoot {
586    type Output;
588}
589
590pub trait Logarithm2 {
596    type Output;
598}
599
600pub trait Gcd<Rhs> {
612    type Output;
614}
615
616pub trait ToInt<T> {
622    fn to_int() -> T;
624    const INT: T;
626}