typenum/
int.rs

1//! Type-level signed integers.
2//!
3//!
4//! Type **operators** implemented:
5//!
6//! From `core::ops`: `Add`, `Sub`, `Mul`, `Div`, and `Rem`.
7//! From `typenum`: `Same`, `Cmp`, and `Pow`.
8//!
9//! Rather than directly using the structs defined in this module, it is recommended that
10//! you import and use the relevant aliases from the [consts](../consts/index.html) module.
11//!
12//! Note that operators that work on the underlying structure of the number are
13//! intentionally not implemented. This is because this implementation of signed integers
14//! does *not* use twos-complement, and implementing them would require making arbitrary
15//! choices, causing the results of such operators to be difficult to reason about.
16//!
17//! # Example
18//! ```rust
19//! use std::ops::{Add, Div, Mul, Rem, Sub};
20//! use typenum::{Integer, N3, P2};
21//!
22//! assert_eq!(<N3 as Add<P2>>::Output::to_i32(), -1);
23//! assert_eq!(<N3 as Sub<P2>>::Output::to_i32(), -5);
24//! assert_eq!(<N3 as Mul<P2>>::Output::to_i32(), -6);
25//! assert_eq!(<N3 as Div<P2>>::Output::to_i32(), -1);
26//! assert_eq!(<N3 as Rem<P2>>::Output::to_i32(), -1);
27//! ```
28
29pub use crate::marker_traits::Integer;
30use crate::{
31    bit::{Bit, B0, B1},
32    consts::{N1, P1, U0, U1},
33    private::{Internal, InternalMarker, PrivateDivInt, PrivateIntegerAdd, PrivateRem},
34    uint::{UInt, Unsigned},
35    Cmp, Equal, Greater, Less, NonZero, Pow, PowerOfTwo, ToInt, Zero,
36};
37use core::ops::{Add, Div, Mul, Neg, Rem, Sub};
38
39/// Type-level signed integers with positive sign.
40#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)]
41pub struct PInt<U: Unsigned + NonZero> {
42    pub(crate) n: U,
43}
44
45/// Type-level signed integers with negative sign.
46#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)]
47pub struct NInt<U: Unsigned + NonZero> {
48    pub(crate) n: U,
49}
50
51impl<U: Unsigned + NonZero> PInt<U> {
52    /// Instantiates a singleton representing this strictly positive integer.
53    #[inline]
54    pub fn new() -> PInt<U> {
55        PInt::default()
56    }
57}
58
59impl<U: Unsigned + NonZero> NInt<U> {
60    /// Instantiates a singleton representing this strictly negative integer.
61    #[inline]
62    pub fn new() -> NInt<U> {
63        NInt::default()
64    }
65}
66
67/// The type-level signed integer 0.
68#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)]
69pub struct Z0;
70
71impl Z0 {
72    /// Instantiates a singleton representing the integer 0.
73    #[inline]
74    pub fn new() -> Z0 {
75        Z0
76    }
77}
78
79impl<U: Unsigned + NonZero> NonZero for PInt<U> {}
80impl<U: Unsigned + NonZero> NonZero for NInt<U> {}
81impl Zero for Z0 {}
82
83impl<U: Unsigned + NonZero + PowerOfTwo> PowerOfTwo for PInt<U> {}
84
85impl Integer for Z0 {
86    const I8: i8 = 0;
87    const I16: i16 = 0;
88    const I32: i32 = 0;
89    const I64: i64 = 0;
90    #[cfg(feature = "i128")]
91    const I128: i128 = 0;
92    const ISIZE: isize = 0;
93
94    #[inline]
95    fn to_i8() -> i8 {
96        0
97    }
98    #[inline]
99    fn to_i16() -> i16 {
100        0
101    }
102    #[inline]
103    fn to_i32() -> i32 {
104        0
105    }
106    #[inline]
107    fn to_i64() -> i64 {
108        0
109    }
110    #[cfg(feature = "i128")]
111    #[inline]
112    fn to_i128() -> i128 {
113        0
114    }
115    #[inline]
116    fn to_isize() -> isize {
117        0
118    }
119}
120
121impl<U: Unsigned + NonZero> Integer for PInt<U> {
122    const I8: i8 = U::I8;
123    const I16: i16 = U::I16;
124    const I32: i32 = U::I32;
125    const I64: i64 = U::I64;
126    #[cfg(feature = "i128")]
127    const I128: i128 = U::I128;
128    const ISIZE: isize = U::ISIZE;
129
130    #[inline]
131    fn to_i8() -> i8 {
132        <U as Unsigned>::to_i8()
133    }
134    #[inline]
135    fn to_i16() -> i16 {
136        <U as Unsigned>::to_i16()
137    }
138    #[inline]
139    fn to_i32() -> i32 {
140        <U as Unsigned>::to_i32()
141    }
142    #[inline]
143    fn to_i64() -> i64 {
144        <U as Unsigned>::to_i64()
145    }
146    #[cfg(feature = "i128")]
147    #[inline]
148    fn to_i128() -> i128 {
149        <U as Unsigned>::to_i128()
150    }
151    #[inline]
152    fn to_isize() -> isize {
153        <U as Unsigned>::to_isize()
154    }
155}
156
157// Simply negating the result of e.g. `U::I8` will result in overflow for `std::i8::MIN`. Instead,
158// we use the fact that `U: NonZero` by subtracting one from the `U::U8` before negating.
159impl<U: Unsigned + NonZero> Integer for NInt<U> {
160    const I8: i8 = -((U::U8 - 1) as i8) - 1;
161    const I16: i16 = -((U::U16 - 1) as i16) - 1;
162    const I32: i32 = -((U::U32 - 1) as i32) - 1;
163    const I64: i64 = -((U::U64 - 1) as i64) - 1;
164    #[cfg(feature = "i128")]
165    const I128: i128 = -((U::U128 - 1) as i128) - 1;
166    const ISIZE: isize = -((U::USIZE - 1) as isize) - 1;
167
168    #[inline]
169    fn to_i8() -> i8 {
170        Self::I8
171    }
172    #[inline]
173    fn to_i16() -> i16 {
174        Self::I16
175    }
176    #[inline]
177    fn to_i32() -> i32 {
178        Self::I32
179    }
180    #[inline]
181    fn to_i64() -> i64 {
182        Self::I64
183    }
184    #[cfg(feature = "i128")]
185    #[inline]
186    fn to_i128() -> i128 {
187        Self::I128
188    }
189    #[inline]
190    fn to_isize() -> isize {
191        Self::ISIZE
192    }
193}
194
195// ---------------------------------------------------------------------------------------
196// Neg
197
198/// `-Z0 = Z0`
199impl Neg for Z0 {
200    type Output = Z0;
201    #[inline]
202    fn neg(self) -> Self::Output {
203        Z0
204    }
205}
206
207/// `-PInt = NInt`
208impl<U: Unsigned + NonZero> Neg for PInt<U> {
209    type Output = NInt<U>;
210    #[inline]
211    fn neg(self) -> Self::Output {
212        NInt::new()
213    }
214}
215
216/// `-NInt = PInt`
217impl<U: Unsigned + NonZero> Neg for NInt<U> {
218    type Output = PInt<U>;
219    #[inline]
220    fn neg(self) -> Self::Output {
221        PInt::new()
222    }
223}
224
225// ---------------------------------------------------------------------------------------
226// Add
227
228/// `Z0 + I = I`
229impl<I: Integer> Add<I> for Z0 {
230    type Output = I;
231    #[inline]
232    fn add(self, rhs: I) -> Self::Output {
233        rhs
234    }
235}
236
237/// `PInt + Z0 = PInt`
238impl<U: Unsigned + NonZero> Add<Z0> for PInt<U> {
239    type Output = PInt<U>;
240    #[inline]
241    fn add(self, _: Z0) -> Self::Output {
242        PInt::new()
243    }
244}
245
246/// `NInt + Z0 = NInt`
247impl<U: Unsigned + NonZero> Add<Z0> for NInt<U> {
248    type Output = NInt<U>;
249    #[inline]
250    fn add(self, _: Z0) -> Self::Output {
251        NInt::new()
252    }
253}
254
255/// `P(Ul) + P(Ur) = P(Ul + Ur)`
256impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Add<PInt<Ur>> for PInt<Ul>
257where
258    Ul: Add<Ur>,
259    <Ul as Add<Ur>>::Output: Unsigned + NonZero,
260{
261    type Output = PInt<<Ul as Add<Ur>>::Output>;
262    #[inline]
263    fn add(self, _: PInt<Ur>) -> Self::Output {
264        PInt::new()
265    }
266}
267
268/// `N(Ul) + N(Ur) = N(Ul + Ur)`
269impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Add<NInt<Ur>> for NInt<Ul>
270where
271    Ul: Add<Ur>,
272    <Ul as Add<Ur>>::Output: Unsigned + NonZero,
273{
274    type Output = NInt<<Ul as Add<Ur>>::Output>;
275    #[inline]
276    fn add(self, _: NInt<Ur>) -> Self::Output {
277        NInt::new()
278    }
279}
280
281/// `P(Ul) + N(Ur)`: We resolve this with our `PrivateAdd`
282impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Add<NInt<Ur>> for PInt<Ul>
283where
284    Ul: Cmp<Ur> + PrivateIntegerAdd<<Ul as Cmp<Ur>>::Output, Ur>,
285{
286    type Output = <Ul as PrivateIntegerAdd<<Ul as Cmp<Ur>>::Output, Ur>>::Output;
287    #[inline]
288    fn add(self, rhs: NInt<Ur>) -> Self::Output {
289        let lhs = self.n;
290        let rhs = rhs.n;
291        let lhs_cmp_rhs = lhs.compare::<Internal>(&rhs);
292        lhs.private_integer_add(lhs_cmp_rhs, rhs)
293    }
294}
295
296/// `N(Ul) + P(Ur)`: We resolve this with our `PrivateAdd`
297// We just do the same thing as above, swapping Lhs and Rhs
298impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Add<PInt<Ur>> for NInt<Ul>
299where
300    Ur: Cmp<Ul> + PrivateIntegerAdd<<Ur as Cmp<Ul>>::Output, Ul>,
301{
302    type Output = <Ur as PrivateIntegerAdd<<Ur as Cmp<Ul>>::Output, Ul>>::Output;
303    #[inline]
304    fn add(self, rhs: PInt<Ur>) -> Self::Output {
305        let lhs = self.n;
306        let rhs = rhs.n;
307        let rhs_cmp_lhs = rhs.compare::<Internal>(&lhs);
308        rhs.private_integer_add(rhs_cmp_lhs, lhs)
309    }
310}
311
312/// `P + N = 0` where `P == N`
313impl<N: Unsigned, P: Unsigned> PrivateIntegerAdd<Equal, N> for P {
314    type Output = Z0;
315
316    #[inline]
317    fn private_integer_add(self, _: Equal, _: N) -> Self::Output {
318        Z0
319    }
320}
321
322/// `P + N = Positive` where `P > N`
323impl<N: Unsigned, P: Unsigned> PrivateIntegerAdd<Greater, N> for P
324where
325    P: Sub<N>,
326    <P as Sub<N>>::Output: Unsigned + NonZero,
327{
328    type Output = PInt<<P as Sub<N>>::Output>;
329
330    #[inline]
331    fn private_integer_add(self, _: Greater, n: N) -> Self::Output {
332        PInt { n: self - n }
333    }
334}
335
336/// `P + N = Negative` where `P < N`
337impl<N: Unsigned, P: Unsigned> PrivateIntegerAdd<Less, N> for P
338where
339    N: Sub<P>,
340    <N as Sub<P>>::Output: Unsigned + NonZero,
341{
342    type Output = NInt<<N as Sub<P>>::Output>;
343
344    #[inline]
345    fn private_integer_add(self, _: Less, n: N) -> Self::Output {
346        NInt { n: n - self }
347    }
348}
349
350// ---------------------------------------------------------------------------------------
351// Sub
352
353/// `Z0 - Z0 = Z0`
354impl Sub<Z0> for Z0 {
355    type Output = Z0;
356    #[inline]
357    fn sub(self, _: Z0) -> Self::Output {
358        Z0
359    }
360}
361
362/// `Z0 - P = N`
363impl<U: Unsigned + NonZero> Sub<PInt<U>> for Z0 {
364    type Output = NInt<U>;
365    #[inline]
366    fn sub(self, _: PInt<U>) -> Self::Output {
367        NInt::new()
368    }
369}
370
371/// `Z0 - N = P`
372impl<U: Unsigned + NonZero> Sub<NInt<U>> for Z0 {
373    type Output = PInt<U>;
374    #[inline]
375    fn sub(self, _: NInt<U>) -> Self::Output {
376        PInt::new()
377    }
378}
379
380/// `PInt - Z0 = PInt`
381impl<U: Unsigned + NonZero> Sub<Z0> for PInt<U> {
382    type Output = PInt<U>;
383    #[inline]
384    fn sub(self, _: Z0) -> Self::Output {
385        PInt::new()
386    }
387}
388
389/// `NInt - Z0 = NInt`
390impl<U: Unsigned + NonZero> Sub<Z0> for NInt<U> {
391    type Output = NInt<U>;
392    #[inline]
393    fn sub(self, _: Z0) -> Self::Output {
394        NInt::new()
395    }
396}
397
398/// `P(Ul) - N(Ur) = P(Ul + Ur)`
399impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Sub<NInt<Ur>> for PInt<Ul>
400where
401    Ul: Add<Ur>,
402    <Ul as Add<Ur>>::Output: Unsigned + NonZero,
403{
404    type Output = PInt<<Ul as Add<Ur>>::Output>;
405    #[inline]
406    fn sub(self, _: NInt<Ur>) -> Self::Output {
407        PInt::new()
408    }
409}
410
411/// `N(Ul) - P(Ur) = N(Ul + Ur)`
412impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Sub<PInt<Ur>> for NInt<Ul>
413where
414    Ul: Add<Ur>,
415    <Ul as Add<Ur>>::Output: Unsigned + NonZero,
416{
417    type Output = NInt<<Ul as Add<Ur>>::Output>;
418    #[inline]
419    fn sub(self, _: PInt<Ur>) -> Self::Output {
420        NInt::new()
421    }
422}
423
424/// `P(Ul) - P(Ur)`: We resolve this with our `PrivateAdd`
425impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Sub<PInt<Ur>> for PInt<Ul>
426where
427    Ul: Cmp<Ur> + PrivateIntegerAdd<<Ul as Cmp<Ur>>::Output, Ur>,
428{
429    type Output = <Ul as PrivateIntegerAdd<<Ul as Cmp<Ur>>::Output, Ur>>::Output;
430    #[inline]
431    fn sub(self, rhs: PInt<Ur>) -> Self::Output {
432        let lhs = self.n;
433        let rhs = rhs.n;
434        let lhs_cmp_rhs = lhs.compare::<Internal>(&rhs);
435        lhs.private_integer_add(lhs_cmp_rhs, rhs)
436    }
437}
438
439/// `N(Ul) - N(Ur)`: We resolve this with our `PrivateAdd`
440// We just do the same thing as above, swapping Lhs and Rhs
441impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Sub<NInt<Ur>> for NInt<Ul>
442where
443    Ur: Cmp<Ul> + PrivateIntegerAdd<<Ur as Cmp<Ul>>::Output, Ul>,
444{
445    type Output = <Ur as PrivateIntegerAdd<<Ur as Cmp<Ul>>::Output, Ul>>::Output;
446    #[inline]
447    fn sub(self, rhs: NInt<Ur>) -> Self::Output {
448        let lhs = self.n;
449        let rhs = rhs.n;
450        let rhs_cmp_lhs = rhs.compare::<Internal>(&lhs);
451        rhs.private_integer_add(rhs_cmp_lhs, lhs)
452    }
453}
454
455// ---------------------------------------------------------------------------------------
456// Mul
457
458/// `Z0 * I = Z0`
459impl<I: Integer> Mul<I> for Z0 {
460    type Output = Z0;
461    #[inline]
462    fn mul(self, _: I) -> Self::Output {
463        Z0
464    }
465}
466
467/// `P * Z0 = Z0`
468impl<U: Unsigned + NonZero> Mul<Z0> for PInt<U> {
469    type Output = Z0;
470    #[inline]
471    fn mul(self, _: Z0) -> Self::Output {
472        Z0
473    }
474}
475
476/// `N * Z0 = Z0`
477impl<U: Unsigned + NonZero> Mul<Z0> for NInt<U> {
478    type Output = Z0;
479    #[inline]
480    fn mul(self, _: Z0) -> Self::Output {
481        Z0
482    }
483}
484
485/// P(Ul) * P(Ur) = P(Ul * Ur)
486impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Mul<PInt<Ur>> for PInt<Ul>
487where
488    Ul: Mul<Ur>,
489    <Ul as Mul<Ur>>::Output: Unsigned + NonZero,
490{
491    type Output = PInt<<Ul as Mul<Ur>>::Output>;
492    #[inline]
493    fn mul(self, _: PInt<Ur>) -> Self::Output {
494        PInt::new()
495    }
496}
497
498/// N(Ul) * N(Ur) = P(Ul * Ur)
499impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Mul<NInt<Ur>> for NInt<Ul>
500where
501    Ul: Mul<Ur>,
502    <Ul as Mul<Ur>>::Output: Unsigned + NonZero,
503{
504    type Output = PInt<<Ul as Mul<Ur>>::Output>;
505    #[inline]
506    fn mul(self, _: NInt<Ur>) -> Self::Output {
507        PInt::new()
508    }
509}
510
511/// P(Ul) * N(Ur) = N(Ul * Ur)
512impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Mul<NInt<Ur>> for PInt<Ul>
513where
514    Ul: Mul<Ur>,
515    <Ul as Mul<Ur>>::Output: Unsigned + NonZero,
516{
517    type Output = NInt<<Ul as Mul<Ur>>::Output>;
518    #[inline]
519    fn mul(self, _: NInt<Ur>) -> Self::Output {
520        NInt::new()
521    }
522}
523
524/// N(Ul) * P(Ur) = N(Ul * Ur)
525impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Mul<PInt<Ur>> for NInt<Ul>
526where
527    Ul: Mul<Ur>,
528    <Ul as Mul<Ur>>::Output: Unsigned + NonZero,
529{
530    type Output = NInt<<Ul as Mul<Ur>>::Output>;
531    #[inline]
532    fn mul(self, _: PInt<Ur>) -> Self::Output {
533        NInt::new()
534    }
535}
536
537// ---------------------------------------------------------------------------------------
538// Div
539
540/// `Z0 / I = Z0` where `I != 0`
541impl<I: Integer + NonZero> Div<I> for Z0 {
542    type Output = Z0;
543    #[inline]
544    fn div(self, _: I) -> Self::Output {
545        Z0
546    }
547}
548
549macro_rules! impl_int_div {
550    ($A:ident, $B:ident, $R:ident) => {
551        /// `$A<Ul> / $B<Ur> = $R<Ul / Ur>`
552        impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Div<$B<Ur>> for $A<Ul>
553        where
554            Ul: Cmp<Ur>,
555            $A<Ul>: PrivateDivInt<<Ul as Cmp<Ur>>::Output, $B<Ur>>,
556        {
557            type Output = <$A<Ul> as PrivateDivInt<<Ul as Cmp<Ur>>::Output, $B<Ur>>>::Output;
558            #[inline]
559            fn div(self, rhs: $B<Ur>) -> Self::Output {
560                let lhs_cmp_rhs = self.n.compare::<Internal>(&rhs.n);
561                self.private_div_int(lhs_cmp_rhs, rhs)
562            }
563        }
564        impl<Ul, Ur> PrivateDivInt<Less, $B<Ur>> for $A<Ul>
565        where
566            Ul: Unsigned + NonZero,
567            Ur: Unsigned + NonZero,
568        {
569            type Output = Z0;
570
571            #[inline]
572            fn private_div_int(self, _: Less, _: $B<Ur>) -> Self::Output {
573                Z0
574            }
575        }
576        impl<Ul, Ur> PrivateDivInt<Equal, $B<Ur>> for $A<Ul>
577        where
578            Ul: Unsigned + NonZero,
579            Ur: Unsigned + NonZero,
580        {
581            type Output = $R<U1>;
582
583            #[inline]
584            fn private_div_int(self, _: Equal, _: $B<Ur>) -> Self::Output {
585                $R { n: U1::new() }
586            }
587        }
588        impl<Ul, Ur> PrivateDivInt<Greater, $B<Ur>> for $A<Ul>
589        where
590            Ul: Unsigned + NonZero + Div<Ur>,
591            Ur: Unsigned + NonZero,
592            <Ul as Div<Ur>>::Output: Unsigned + NonZero,
593        {
594            type Output = $R<<Ul as Div<Ur>>::Output>;
595
596            #[inline]
597            fn private_div_int(self, _: Greater, d: $B<Ur>) -> Self::Output {
598                $R { n: self.n / d.n }
599            }
600        }
601    };
602}
603
604impl_int_div!(PInt, PInt, PInt);
605impl_int_div!(PInt, NInt, NInt);
606impl_int_div!(NInt, PInt, NInt);
607impl_int_div!(NInt, NInt, PInt);
608
609// ---------------------------------------------------------------------------------------
610// PartialDiv
611
612use crate::{PartialDiv, Quot};
613
614impl<M, N> PartialDiv<N> for M
615where
616    M: Integer + Div<N> + Rem<N, Output = Z0>,
617{
618    type Output = Quot<M, N>;
619    #[inline]
620    fn partial_div(self, rhs: N) -> Self::Output {
621        self / rhs
622    }
623}
624
625// ---------------------------------------------------------------------------------------
626// Cmp
627
628/// 0 == 0
629impl Cmp<Z0> for Z0 {
630    type Output = Equal;
631
632    #[inline]
633    fn compare<IM: InternalMarker>(&self, _: &Z0) -> Self::Output {
634        Equal
635    }
636}
637
638/// 0 > -X
639impl<U: Unsigned + NonZero> Cmp<NInt<U>> for Z0 {
640    type Output = Greater;
641
642    #[inline]
643    fn compare<IM: InternalMarker>(&self, _: &NInt<U>) -> Self::Output {
644        Greater
645    }
646}
647
648/// 0 < X
649impl<U: Unsigned + NonZero> Cmp<PInt<U>> for Z0 {
650    type Output = Less;
651
652    #[inline]
653    fn compare<IM: InternalMarker>(&self, _: &PInt<U>) -> Self::Output {
654        Less
655    }
656}
657
658/// X > 0
659impl<U: Unsigned + NonZero> Cmp<Z0> for PInt<U> {
660    type Output = Greater;
661
662    #[inline]
663    fn compare<IM: InternalMarker>(&self, _: &Z0) -> Self::Output {
664        Greater
665    }
666}
667
668/// -X < 0
669impl<U: Unsigned + NonZero> Cmp<Z0> for NInt<U> {
670    type Output = Less;
671
672    #[inline]
673    fn compare<IM: InternalMarker>(&self, _: &Z0) -> Self::Output {
674        Less
675    }
676}
677
678/// -X < Y
679impl<P: Unsigned + NonZero, N: Unsigned + NonZero> Cmp<PInt<P>> for NInt<N> {
680    type Output = Less;
681
682    #[inline]
683    fn compare<IM: InternalMarker>(&self, _: &PInt<P>) -> Self::Output {
684        Less
685    }
686}
687
688/// X > - Y
689impl<P: Unsigned + NonZero, N: Unsigned + NonZero> Cmp<NInt<N>> for PInt<P> {
690    type Output = Greater;
691
692    #[inline]
693    fn compare<IM: InternalMarker>(&self, _: &NInt<N>) -> Self::Output {
694        Greater
695    }
696}
697
698/// X <==> Y
699impl<Pl: Cmp<Pr> + Unsigned + NonZero, Pr: Unsigned + NonZero> Cmp<PInt<Pr>> for PInt<Pl> {
700    type Output = <Pl as Cmp<Pr>>::Output;
701
702    #[inline]
703    fn compare<IM: InternalMarker>(&self, rhs: &PInt<Pr>) -> Self::Output {
704        self.n.compare::<Internal>(&rhs.n)
705    }
706}
707
708/// -X <==> -Y
709impl<Nl: Unsigned + NonZero, Nr: Cmp<Nl> + Unsigned + NonZero> Cmp<NInt<Nr>> for NInt<Nl> {
710    type Output = <Nr as Cmp<Nl>>::Output;
711
712    #[inline]
713    fn compare<IM: InternalMarker>(&self, rhs: &NInt<Nr>) -> Self::Output {
714        rhs.n.compare::<Internal>(&self.n)
715    }
716}
717
718// ---------------------------------------------------------------------------------------
719// Rem
720
721/// `Z0 % I = Z0` where `I != 0`
722impl<I: Integer + NonZero> Rem<I> for Z0 {
723    type Output = Z0;
724    #[inline]
725    fn rem(self, _: I) -> Self::Output {
726        Z0
727    }
728}
729
730macro_rules! impl_int_rem {
731    ($A:ident, $B:ident, $R:ident) => {
732        /// `$A<Ul> % $B<Ur> = $R<Ul % Ur>`
733        impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Rem<$B<Ur>> for $A<Ul>
734        where
735            Ul: Rem<Ur>,
736            $A<Ul>: PrivateRem<<Ul as Rem<Ur>>::Output, $B<Ur>>,
737        {
738            type Output = <$A<Ul> as PrivateRem<<Ul as Rem<Ur>>::Output, $B<Ur>>>::Output;
739            #[inline]
740            fn rem(self, rhs: $B<Ur>) -> Self::Output {
741                self.private_rem(self.n % rhs.n, rhs)
742            }
743        }
744        impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> PrivateRem<U0, $B<Ur>> for $A<Ul> {
745            type Output = Z0;
746
747            #[inline]
748            fn private_rem(self, _: U0, _: $B<Ur>) -> Self::Output {
749                Z0
750            }
751        }
752        impl<Ul, Ur, U, B> PrivateRem<UInt<U, B>, $B<Ur>> for $A<Ul>
753        where
754            Ul: Unsigned + NonZero,
755            Ur: Unsigned + NonZero,
756            U: Unsigned,
757            B: Bit,
758        {
759            type Output = $R<UInt<U, B>>;
760
761            #[inline]
762            fn private_rem(self, urem: UInt<U, B>, _: $B<Ur>) -> Self::Output {
763                $R { n: urem }
764            }
765        }
766    };
767}
768
769impl_int_rem!(PInt, PInt, PInt);
770impl_int_rem!(PInt, NInt, PInt);
771impl_int_rem!(NInt, PInt, NInt);
772impl_int_rem!(NInt, NInt, NInt);
773
774// ---------------------------------------------------------------------------------------
775// Pow
776
777/// 0^0 = 1
778impl Pow<Z0> for Z0 {
779    type Output = P1;
780    #[inline]
781    fn powi(self, _: Z0) -> Self::Output {
782        P1::new()
783    }
784}
785
786/// 0^P = 0
787impl<U: Unsigned + NonZero> Pow<PInt<U>> for Z0 {
788    type Output = Z0;
789    #[inline]
790    fn powi(self, _: PInt<U>) -> Self::Output {
791        Z0
792    }
793}
794
795/// 0^N = 0
796impl<U: Unsigned + NonZero> Pow<NInt<U>> for Z0 {
797    type Output = Z0;
798    #[inline]
799    fn powi(self, _: NInt<U>) -> Self::Output {
800        Z0
801    }
802}
803
804/// 1^N = 1
805impl<U: Unsigned + NonZero> Pow<NInt<U>> for P1 {
806    type Output = P1;
807    #[inline]
808    fn powi(self, _: NInt<U>) -> Self::Output {
809        P1::new()
810    }
811}
812
813/// (-1)^N = 1 if N is even
814impl<U: Unsigned> Pow<NInt<UInt<U, B0>>> for N1 {
815    type Output = P1;
816    #[inline]
817    fn powi(self, _: NInt<UInt<U, B0>>) -> Self::Output {
818        P1::new()
819    }
820}
821
822/// (-1)^N = -1 if N is odd
823impl<U: Unsigned> Pow<NInt<UInt<U, B1>>> for N1 {
824    type Output = N1;
825    #[inline]
826    fn powi(self, _: NInt<UInt<U, B1>>) -> Self::Output {
827        N1::new()
828    }
829}
830
831/// P^0 = 1
832impl<U: Unsigned + NonZero> Pow<Z0> for PInt<U> {
833    type Output = P1;
834    #[inline]
835    fn powi(self, _: Z0) -> Self::Output {
836        P1::new()
837    }
838}
839
840/// N^0 = 1
841impl<U: Unsigned + NonZero> Pow<Z0> for NInt<U> {
842    type Output = P1;
843    #[inline]
844    fn powi(self, _: Z0) -> Self::Output {
845        P1::new()
846    }
847}
848
849/// P(Ul)^P(Ur) = P(Ul^Ur)
850impl<Ul: Unsigned + NonZero, Ur: Unsigned + NonZero> Pow<PInt<Ur>> for PInt<Ul>
851where
852    Ul: Pow<Ur>,
853    <Ul as Pow<Ur>>::Output: Unsigned + NonZero,
854{
855    type Output = PInt<<Ul as Pow<Ur>>::Output>;
856    #[inline]
857    fn powi(self, _: PInt<Ur>) -> Self::Output {
858        PInt::new()
859    }
860}
861
862/// N(Ul)^P(Ur) = P(Ul^Ur) if Ur is even
863impl<Ul: Unsigned + NonZero, Ur: Unsigned> Pow<PInt<UInt<Ur, B0>>> for NInt<Ul>
864where
865    Ul: Pow<UInt<Ur, B0>>,
866    <Ul as Pow<UInt<Ur, B0>>>::Output: Unsigned + NonZero,
867{
868    type Output = PInt<<Ul as Pow<UInt<Ur, B0>>>::Output>;
869    #[inline]
870    fn powi(self, _: PInt<UInt<Ur, B0>>) -> Self::Output {
871        PInt::new()
872    }
873}
874
875/// N(Ul)^P(Ur) = N(Ul^Ur) if Ur is odd
876impl<Ul: Unsigned + NonZero, Ur: Unsigned> Pow<PInt<UInt<Ur, B1>>> for NInt<Ul>
877where
878    Ul: Pow<UInt<Ur, B1>>,
879    <Ul as Pow<UInt<Ur, B1>>>::Output: Unsigned + NonZero,
880{
881    type Output = NInt<<Ul as Pow<UInt<Ur, B1>>>::Output>;
882    #[inline]
883    fn powi(self, _: PInt<UInt<Ur, B1>>) -> Self::Output {
884        NInt::new()
885    }
886}
887
888// ---------------------------------------------------------------------------------------
889// Gcd
890use crate::{Gcd, Gcf};
891
892impl Gcd<Z0> for Z0 {
893    type Output = Z0;
894}
895
896impl<U> Gcd<PInt<U>> for Z0
897where
898    U: Unsigned + NonZero,
899{
900    type Output = PInt<U>;
901}
902
903impl<U> Gcd<Z0> for PInt<U>
904where
905    U: Unsigned + NonZero,
906{
907    type Output = PInt<U>;
908}
909
910impl<U> Gcd<NInt<U>> for Z0
911where
912    U: Unsigned + NonZero,
913{
914    type Output = PInt<U>;
915}
916
917impl<U> Gcd<Z0> for NInt<U>
918where
919    U: Unsigned + NonZero,
920{
921    type Output = PInt<U>;
922}
923
924impl<U1, U2> Gcd<PInt<U2>> for PInt<U1>
925where
926    U1: Unsigned + NonZero + Gcd<U2>,
927    U2: Unsigned + NonZero,
928    Gcf<U1, U2>: Unsigned + NonZero,
929{
930    type Output = PInt<Gcf<U1, U2>>;
931}
932
933impl<U1, U2> Gcd<PInt<U2>> for NInt<U1>
934where
935    U1: Unsigned + NonZero + Gcd<U2>,
936    U2: Unsigned + NonZero,
937    Gcf<U1, U2>: Unsigned + NonZero,
938{
939    type Output = PInt<Gcf<U1, U2>>;
940}
941
942impl<U1, U2> Gcd<NInt<U2>> for PInt<U1>
943where
944    U1: Unsigned + NonZero + Gcd<U2>,
945    U2: Unsigned + NonZero,
946    Gcf<U1, U2>: Unsigned + NonZero,
947{
948    type Output = PInt<Gcf<U1, U2>>;
949}
950
951impl<U1, U2> Gcd<NInt<U2>> for NInt<U1>
952where
953    U1: Unsigned + NonZero + Gcd<U2>,
954    U2: Unsigned + NonZero,
955    Gcf<U1, U2>: Unsigned + NonZero,
956{
957    type Output = PInt<Gcf<U1, U2>>;
958}
959
960// ---------------------------------------------------------------------------------------
961// Min
962use crate::{Max, Maximum, Min, Minimum};
963
964impl Min<Z0> for Z0 {
965    type Output = Z0;
966    #[inline]
967    fn min(self, _: Z0) -> Self::Output {
968        self
969    }
970}
971
972impl<U> Min<PInt<U>> for Z0
973where
974    U: Unsigned + NonZero,
975{
976    type Output = Z0;
977    #[inline]
978    fn min(self, _: PInt<U>) -> Self::Output {
979        self
980    }
981}
982
983impl<U> Min<NInt<U>> for Z0
984where
985    U: Unsigned + NonZero,
986{
987    type Output = NInt<U>;
988    #[inline]
989    fn min(self, rhs: NInt<U>) -> Self::Output {
990        rhs
991    }
992}
993
994impl<U> Min<Z0> for PInt<U>
995where
996    U: Unsigned + NonZero,
997{
998    type Output = Z0;
999    #[inline]
1000    fn min(self, rhs: Z0) -> Self::Output {
1001        rhs
1002    }
1003}
1004
1005impl<U> Min<Z0> for NInt<U>
1006where
1007    U: Unsigned + NonZero,
1008{
1009    type Output = NInt<U>;
1010    #[inline]
1011    fn min(self, _: Z0) -> Self::Output {
1012        self
1013    }
1014}
1015
1016impl<Ul, Ur> Min<PInt<Ur>> for PInt<Ul>
1017where
1018    Ul: Unsigned + NonZero + Min<Ur>,
1019    Ur: Unsigned + NonZero,
1020    Minimum<Ul, Ur>: Unsigned + NonZero,
1021{
1022    type Output = PInt<Minimum<Ul, Ur>>;
1023    #[inline]
1024    fn min(self, rhs: PInt<Ur>) -> Self::Output {
1025        PInt {
1026            n: self.n.min(rhs.n),
1027        }
1028    }
1029}
1030
1031impl<Ul, Ur> Min<PInt<Ur>> for NInt<Ul>
1032where
1033    Ul: Unsigned + NonZero,
1034    Ur: Unsigned + NonZero,
1035{
1036    type Output = NInt<Ul>;
1037    #[inline]
1038    fn min(self, _: PInt<Ur>) -> Self::Output {
1039        self
1040    }
1041}
1042
1043impl<Ul, Ur> Min<NInt<Ur>> for PInt<Ul>
1044where
1045    Ul: Unsigned + NonZero,
1046    Ur: Unsigned + NonZero,
1047{
1048    type Output = NInt<Ur>;
1049    #[inline]
1050    fn min(self, rhs: NInt<Ur>) -> Self::Output {
1051        rhs
1052    }
1053}
1054
1055impl<Ul, Ur> Min<NInt<Ur>> for NInt<Ul>
1056where
1057    Ul: Unsigned + NonZero + Max<Ur>,
1058    Ur: Unsigned + NonZero,
1059    Maximum<Ul, Ur>: Unsigned + NonZero,
1060{
1061    type Output = NInt<Maximum<Ul, Ur>>;
1062    #[inline]
1063    fn min(self, rhs: NInt<Ur>) -> Self::Output {
1064        NInt {
1065            n: self.n.max(rhs.n),
1066        }
1067    }
1068}
1069
1070// ---------------------------------------------------------------------------------------
1071// Max
1072
1073impl Max<Z0> for Z0 {
1074    type Output = Z0;
1075    #[inline]
1076    fn max(self, _: Z0) -> Self::Output {
1077        self
1078    }
1079}
1080
1081impl<U> Max<PInt<U>> for Z0
1082where
1083    U: Unsigned + NonZero,
1084{
1085    type Output = PInt<U>;
1086    #[inline]
1087    fn max(self, rhs: PInt<U>) -> Self::Output {
1088        rhs
1089    }
1090}
1091
1092impl<U> Max<NInt<U>> for Z0
1093where
1094    U: Unsigned + NonZero,
1095{
1096    type Output = Z0;
1097    #[inline]
1098    fn max(self, _: NInt<U>) -> Self::Output {
1099        self
1100    }
1101}
1102
1103impl<U> Max<Z0> for PInt<U>
1104where
1105    U: Unsigned + NonZero,
1106{
1107    type Output = PInt<U>;
1108    #[inline]
1109    fn max(self, _: Z0) -> Self::Output {
1110        self
1111    }
1112}
1113
1114impl<U> Max<Z0> for NInt<U>
1115where
1116    U: Unsigned + NonZero,
1117{
1118    type Output = Z0;
1119    #[inline]
1120    fn max(self, rhs: Z0) -> Self::Output {
1121        rhs
1122    }
1123}
1124
1125impl<Ul, Ur> Max<PInt<Ur>> for PInt<Ul>
1126where
1127    Ul: Unsigned + NonZero + Max<Ur>,
1128    Ur: Unsigned + NonZero,
1129    Maximum<Ul, Ur>: Unsigned + NonZero,
1130{
1131    type Output = PInt<Maximum<Ul, Ur>>;
1132    #[inline]
1133    fn max(self, rhs: PInt<Ur>) -> Self::Output {
1134        PInt {
1135            n: self.n.max(rhs.n),
1136        }
1137    }
1138}
1139
1140impl<Ul, Ur> Max<PInt<Ur>> for NInt<Ul>
1141where
1142    Ul: Unsigned + NonZero,
1143    Ur: Unsigned + NonZero,
1144{
1145    type Output = PInt<Ur>;
1146    #[inline]
1147    fn max(self, rhs: PInt<Ur>) -> Self::Output {
1148        rhs
1149    }
1150}
1151
1152impl<Ul, Ur> Max<NInt<Ur>> for PInt<Ul>
1153where
1154    Ul: Unsigned + NonZero,
1155    Ur: Unsigned + NonZero,
1156{
1157    type Output = PInt<Ul>;
1158    #[inline]
1159    fn max(self, _: NInt<Ur>) -> Self::Output {
1160        self
1161    }
1162}
1163
1164impl<Ul, Ur> Max<NInt<Ur>> for NInt<Ul>
1165where
1166    Ul: Unsigned + NonZero + Min<Ur>,
1167    Ur: Unsigned + NonZero,
1168    Minimum<Ul, Ur>: Unsigned + NonZero,
1169{
1170    type Output = NInt<Minimum<Ul, Ur>>;
1171    #[inline]
1172    fn max(self, rhs: NInt<Ur>) -> Self::Output {
1173        NInt {
1174            n: self.n.min(rhs.n),
1175        }
1176    }
1177}
1178
1179// -----------------------------------------
1180// ToInt
1181
1182impl ToInt<i8> for Z0 {
1183    #[inline]
1184    fn to_int() -> i8 {
1185        Self::I8
1186    }
1187}
1188
1189impl ToInt<i16> for Z0 {
1190    #[inline]
1191    fn to_int() -> i16 {
1192        Self::I16
1193    }
1194}
1195
1196impl ToInt<i32> for Z0 {
1197    #[inline]
1198    fn to_int() -> i32 {
1199        Self::I32
1200    }
1201}
1202
1203impl ToInt<i64> for Z0 {
1204    #[inline]
1205    fn to_int() -> i64 {
1206        Self::I64
1207    }
1208}
1209
1210// negative numbers
1211
1212impl<U> ToInt<i8> for NInt<U>
1213where
1214    U: Unsigned + NonZero,
1215{
1216    #[inline]
1217    fn to_int() -> i8 {
1218        Self::I8
1219    }
1220}
1221
1222impl<U> ToInt<i16> for NInt<U>
1223where
1224    U: Unsigned + NonZero,
1225{
1226    #[inline]
1227    fn to_int() -> i16 {
1228        Self::I16
1229    }
1230}
1231
1232impl<U> ToInt<i32> for NInt<U>
1233where
1234    U: Unsigned + NonZero,
1235{
1236    #[inline]
1237    fn to_int() -> i32 {
1238        Self::I32
1239    }
1240}
1241
1242impl<U> ToInt<i64> for NInt<U>
1243where
1244    U: Unsigned + NonZero,
1245{
1246    #[inline]
1247    fn to_int() -> i64 {
1248        Self::I64
1249    }
1250}
1251
1252// positive numbers
1253
1254impl<U> ToInt<i8> for PInt<U>
1255where
1256    U: Unsigned + NonZero,
1257{
1258    #[inline]
1259    fn to_int() -> i8 {
1260        Self::I8
1261    }
1262}
1263
1264impl<U> ToInt<i16> for PInt<U>
1265where
1266    U: Unsigned + NonZero,
1267{
1268    #[inline]
1269    fn to_int() -> i16 {
1270        Self::I16
1271    }
1272}
1273
1274impl<U> ToInt<i32> for PInt<U>
1275where
1276    U: Unsigned + NonZero,
1277{
1278    #[inline]
1279    fn to_int() -> i32 {
1280        Self::I32
1281    }
1282}
1283
1284impl<U> ToInt<i64> for PInt<U>
1285where
1286    U: Unsigned + NonZero,
1287{
1288    #[inline]
1289    fn to_int() -> i64 {
1290        Self::I64
1291    }
1292}
1293
1294#[cfg(test)]
1295mod tests {
1296    use crate::{consts::*, Integer, ToInt};
1297
1298    #[test]
1299    fn to_ix_min() {
1300        assert_eq!(N128::to_i8(), ::core::i8::MIN);
1301        assert_eq!(N32768::to_i16(), ::core::i16::MIN);
1302    }
1303
1304    #[test]
1305    fn int_toint_test() {
1306        // i8
1307        assert_eq!(0_i8, Z0::to_int());
1308        assert_eq!(1_i8, P1::to_int());
1309        assert_eq!(2_i8, P2::to_int());
1310        assert_eq!(3_i8, P3::to_int());
1311        assert_eq!(4_i8, P4::to_int());
1312        assert_eq!(-1_i8, N1::to_int());
1313        assert_eq!(-2_i8, N2::to_int());
1314        assert_eq!(-3_i8, N3::to_int());
1315        assert_eq!(-4_i8, N4::to_int());
1316
1317        // i16
1318        assert_eq!(0_i16, Z0::to_int());
1319        assert_eq!(1_i16, P1::to_int());
1320        assert_eq!(2_i16, P2::to_int());
1321        assert_eq!(3_i16, P3::to_int());
1322        assert_eq!(4_i16, P4::to_int());
1323        assert_eq!(-1_i16, N1::to_int());
1324        assert_eq!(-2_i16, N2::to_int());
1325        assert_eq!(-3_i16, N3::to_int());
1326        assert_eq!(-4_i16, N4::to_int());
1327
1328        // i32
1329        assert_eq!(0_i32, Z0::to_int());
1330        assert_eq!(1_i32, P1::to_int());
1331        assert_eq!(2_i32, P2::to_int());
1332        assert_eq!(3_i32, P3::to_int());
1333        assert_eq!(4_i32, P4::to_int());
1334        assert_eq!(-1_i32, N1::to_int());
1335        assert_eq!(-2_i32, N2::to_int());
1336        assert_eq!(-3_i32, N3::to_int());
1337        assert_eq!(-4_i32, N4::to_int());
1338
1339        // i64
1340        assert_eq!(0_i64, Z0::to_int());
1341        assert_eq!(1_i64, P1::to_int());
1342        assert_eq!(2_i64, P2::to_int());
1343        assert_eq!(3_i64, P3::to_int());
1344        assert_eq!(4_i64, P4::to_int());
1345        assert_eq!(-1_i64, N1::to_int());
1346        assert_eq!(-2_i64, N2::to_int());
1347        assert_eq!(-3_i64, N3::to_int());
1348        assert_eq!(-4_i64, N4::to_int());
1349    }
1350}