devela/num/int/wrapper/
impl_modulo.rs

1// devela::num::int::wrapper::impl_modulo
2//
3//! Implements modulo-related methods for [`Int`].
4//
5// TOC
6// - signed|unsigned:
7//   - modulo (uc)
8//   - modulo_cycles (uc)
9//   - modulo_add (uc)
10//   - modulo_add_cycles (uc)
11//   - modulo_add_inv (uc)
12//   - modulo_sub (uc)
13//   - modulo_sub_cycles (uc)
14//   - modulo_mul (uc)
15//   - modulo_mul_cycles (uc)
16//   - modulo_mul_inv (uc)
17//   - modulo_div (uc)
18
19#[cfg(any(feature = "_int_isize", feature = "_int_usize"))]
20use crate::isize_up;
21#[cfg(feature = "_int_usize")]
22use crate::usize_up;
23use crate::{
24    cif, iif, paste, Int,
25    NumError::{NonZeroRequired, Overflow},
26    NumResult as Result, ValueQuant,
27};
28#[cfg(_int_i··)]
29use crate::{unwrap, NumError::NoInverse};
30
31// helper function to be called from the cold path branch when modulus == 0.
32#[cold] #[inline(never)] #[cfg(_int··)] #[rustfmt::skip]
33const fn cold_err_zero<T>() -> Result<T> { Err(NonZeroRequired) }
34// helper function to be called from the cold path branch for rare i128 overflow.
35#[cold] #[inline(never)] #[cfg(_int_i··)] #[rustfmt::skip]
36const fn cold_err_overflow<T>() -> Result<T> { Err(Overflow(None)) }
37
38/// Helper macro to deal with the case when we can't upcast (i.e. for 128-bits).
39///
40/// $op:  an overloadable operator (+, -, *, /)
41/// $fn:  the corresponding function (add, sub, mul, div)
42/// $lhs: the left hand side operator
43/// $rhs: the right hand side operator
44/// $is_up: whether we've upcasted (Y) or not (N), known at compile-time
45///
46/// # Features
47/// Uses `unsafe_hint` for performance optimizations with upcasted arithmetic.
48#[rustfmt::skip] #[allow(unused_macros)]
49macro_rules! upcastop {
50    // this is used for checked versions
51    (err $op:tt $fn:ident($lhs:expr, $rhs:expr) $is_up:ident) => { paste! {
52        if cif!(same($is_up, Y)) { // can't overflow if upcasted
53            #[cfg(any(feature = "safe_num", not(feature = "unsafe_hint")))]
54            { $lhs $op $rhs }
55            #[cfg(all(not(feature = "safe_num"), feature = "unsafe_hint"))]
56            // SAFETY: can't overflow if upcasted
57            unsafe { $lhs.[<unchecked_ $fn>]($rhs) }
58
59        } else { // otherwise do the checked operation:
60            if let Some(result) = $lhs.[<checked_ $fn>]($rhs) {
61                result } else { return Err(Overflow(None));
62            }
63        }
64    }};
65    // this is used for checked versions that don't need to calculate cycles
66    (reduce_err $op:tt $fn:ident($lhs:expr, $rhs:expr) % $modulus:expr, $is_up:ident) => { paste! {
67        if cif!(same($is_up, Y)) { // can't overflow if upcasted
68            #[cfg(any(feature = "safe_num", not(feature = "unsafe_hint")))]
69            { $lhs $op $rhs }
70            #[cfg(all(not(feature = "safe_num"), feature = "unsafe_hint"))]
71            // SAFETY: can't overflow if upcasted
72            unsafe { $lhs.[<unchecked_ $fn>]($rhs) }
73
74        } else { // otherwise reduce each operand before the checked operation:
75            if let Some(result) = ($lhs % $modulus).[<checked_ $fn>]($rhs % $modulus) {
76                result } else { return Err(Overflow(None));
77            }
78        }
79    }};
80    // this is used for unchecked versions that don't need to calculate cycles
81    (reduce $op:tt $fn:ident($lhs:expr, $rhs:expr) % $modulus:expr, $is_up:ident) => { paste! {
82        if cif!(same($is_up, Y)) { // can't overflow if upcasted
83            #[cfg(any(feature = "safe_num", not(feature = "unsafe_hint")))]
84            { $lhs $op $rhs }
85            #[cfg(all(not(feature = "safe_num"), feature = "unsafe_hint"))]
86            // SAFETY: can't overflow if upcasted
87            unsafe { $lhs.[<unchecked_ $fn>]($rhs) }
88
89        } else { // otherwise reduce each operand before the unchecked operation:
90            ($lhs % $modulus) $op ($rhs % $modulus)
91        }
92    }};
93}
94
95/// Implements modulo-related methods for [`Int`].
96///
97/// # Args
98/// $t:     the input/output type
99/// $cap:   the capability feature that enables the given implementation. E.g "_int_u8"
100/// $up:    the upcasted type to do the operations on (the ones that can overflow) E.g. u16
101/// $iup:   the signed upcasted type for some methods. E.g. i16
102/// $icap:  the feature that enables some methods related to `$iup`. E.g "_int_i16"
103/// $is_up: [Y|N]. `Y` if bitsize of $up|$iup > $t; `N` if bitsize $up|$iup == $t
104///
105/// $d:   the doclink suffix for the method name
106macro_rules! impl_modulo {
107    () => {
108        impl_modulo![signed
109            (i8    :"_int_i8",    i16      :Y |""),
110            (i16   :"_int_i16",   i32      :Y |"-1"),
111            (i32   :"_int_i32",   i64      :Y |"-2"),
112            (i64   :"_int_i64",   i128     :Y |"-3"),
113            (i128  :"_int_i128",  i128     :N |"-4"),
114            (isize :"_int_isize", isize_up :Y |"-5")
115        ];
116        impl_modulo![unsigned
117            (u8   :"_int_u8",   u16|i16   :"_int_i16"  :Y |"-6"),
118            (u16  :"_int_u16",  u32|i32   :"_int_i32"  :Y |"-7"),
119            (u32  :"_int_u32",  u64|i64   :"_int_i64"  :Y |"-8"),
120            (u64  :"_int_u64",  u128|i128 :"_int_i128" :Y |"-9"),
121            (u128 :"_int_u128", u128|i128 :"_int_i128" :N |"-10")
122        ];
123        #[cfg(target_pointer_width = "32")]
124        impl_modulo![unsigned (usize :"_int_usize", usize_up|isize_up :"_int_i64"  :Y |"-11")];
125        #[cfg(target_pointer_width = "64")]
126        impl_modulo![unsigned (usize :"_int_usize", usize_up|isize_up :"_int_i128" :Y |"-11")];
127    };
128    (signed $( ($t:ty : $cap:literal, $up:ty:$is_up:ident |$d:literal) ),+) => {
129        $( impl_modulo![@signed ($t:$cap, $up:$is_up |$d)]; )+
130    };
131    (unsigned $(
132        ($t:ty : $cap:literal, $up:ty | $iup:ty : $icap:literal : $is_up:ident |$d:literal)
133    ),+ ) => {
134        $( impl_modulo![@unsigned ($t:$cap, $up|$iup:$icap :$is_up |$d)]; )+
135    };
136    (
137    // implements signed ops
138    @signed ($t:ty : $cap:literal, $up:ty:$is_up:ident |$d:literal) ) => { paste! {
139        #[doc = crate::doc_availability!(feature = $cap)]
140        ///
141        #[doc = "# Integer modulo related methods for `" $t "`\n\n"]
142        #[doc = "- [modulo](#method.modulo" $d
143            ") *([uc](#method.modulo_unchecked" $d ")*)"]
144        #[doc = "- [modulo_cycles](#method.modulo_cycles" $d
145            ") *([uc](#method.modulo_cycles_unchecked" $d "))*"]
146        //
147        #[doc = "- [modulo_add](#method.modulo_add" $d
148            ") *([uc](#method.modulo_add_unchecked" $d "))*"]
149        #[doc = "- [modulo_add_cycles](#method.modulo_add_cycles" $d
150            ") *([uc](#method.modulo_add_cycles_unchecked" $d "))*"]
151        #[doc = "- [modulo_add_inv](#method.modulo_add_inv" $d
152            ") *([uc](#method.modulo_add_inv_unchecked" $d "))*"]
153        //
154        #[doc = "- [modulo_sub](#method.modulo_sub" $d
155            ") *([uc](#method.modulo_sub_unchecked" $d "))*"]
156        #[doc = "- [modulo_sub_cycles](#method.modulo_add_cycles" $d
157            ") *([uc](#method.modulo_sub_cycles_unchecked" $d "))*"]
158        //
159        #[doc = "- [modulo_mul](#method.modulo_mul" $d
160            ") *([uc](#method.modulo_mul_unchecked" $d "))*"]
161        #[doc = "- [modulo_mul_cycles](#method.modulo_mul_cycles" $d
162            ") *([uc](#method.modulo_mul_cycles_unchecked" $d "))*"]
163        #[doc = "- [modulo_mul_inv](#method.modulo_mul_inv" $d
164            ") *([uc](#method.modulo_mul_inv_unchecked" $d "))*"]
165        //
166        #[doc = "- [modulo_div](#method.modulo_div" $d
167            ") *([uc](#method.modulo_div_unchecked" $d "))*"]
168        ///
169        #[cfg(feature = $cap )]
170        impl Int<$t> {
171            /* modulo (signed) */
172
173            /// Computes the non-negative modulo of `self` over |`modulus`|.
174            ///
175            /// The result is non-negative and less than the absolute value of `modulus`,
176            /// i.e., in the range $ [0, |\text{modulus}|) $.
177            ///
178            #[doc = "Performs operations internally as [`" $up "`]."]
179            ///
180            /// # Errors
181            /// Returns [`NonZeroRequired`] if `modulus == 0`, and for `i128`
182            /// it could also return [`Overflow`].
183            ///
184            /// # Examples
185            /// ```
186            /// # use devela::{Int, NumResult, NumError};
187            /// # fn main() -> NumResult<()> {
188            /// let m = 3;
189            #[doc = "assert_eq![Int(-4_" $t ").modulo(m)?, 2];"]
190            #[doc = "assert_eq![Int(-3_" $t ").modulo(m)?, 0];"]
191            #[doc = "assert_eq![Int(-2_" $t ").modulo(m)?, 1];"]
192            #[doc = "assert_eq![Int(-1_" $t ").modulo(m)?, 2];"]
193            #[doc = "assert_eq![Int( 0_" $t ").modulo(m)?, 0];"]
194            #[doc = "assert_eq![Int( 1_" $t ").modulo(m)?, 1];"]
195            #[doc = "assert_eq![Int( 2_" $t ").modulo(m)?, 2];"]
196            #[doc = "assert_eq![Int( 3_" $t ").modulo(m)?, 0];"]
197            #[doc = "assert_eq![Int( 4_" $t ").modulo(m)?, 1];"]
198            ///
199            #[doc = "assert_eq![Int(" $t "::MAX).modulo(" $t "::MIN)?, " $t "::MAX];"]
200            #[doc = "assert_eq![Int(" $t "::MIN).modulo(" $t "::MAX)?, " $t "::MAX - 1];"]
201            #[doc = "assert_eq![Int(" $t "::MIN).modulo(" $t "::MIN)?, 0];"]
202            /// # #[cfg(feature = "_int_i64")]
203            #[doc = "assert![Int(i64::MIN).modulo(-1).is_ok()];"]
204            ///
205            #[doc = "assert_eq![Int(1_" $t ").modulo(0), Err(NumError::NonZeroRequired)];"]
206            /// # #[cfg(feature = "_int_i128")]
207            #[doc = "assert_eq![Int(i128::MIN).modulo(-1), Err(NumError::Overflow(None))];"]
208            /// # Ok(()) }
209            /// ```
210            pub const fn modulo(self, modulus: $t) -> Result<Int<$t>> {
211                if modulus == 0 {
212                    cold_err_zero()
213                } else {
214                    let (v, m) = (self.0 as $up, modulus as $up);
215                    if let Some(v) = v.checked_rem_euclid(m) {
216                        Ok(Int(v as $t))
217                    } else {
218                        cold_err_overflow()
219                    }
220                }
221            }
222
223            /// Computes the non-negative modulo of `self` over |`modulus`|, unchecked version.
224            ///
225            /// The result is non-negative and less than the absolute value of `modulus`,
226            /// i.e., in the range $ [0, |\text{modulus}|) $.
227            ///
228            #[doc = "Performs operations internally as [`" $up "`]."]
229            ///
230            /// # Panics
231            /// Panics if `modulus == 0`, and for `i128` it could also panic on overflow.
232            ///
233            /// # Examples
234            /// ```
235            /// # use devela::Int;
236            /// let m = 3;
237            #[doc = "assert_eq![Int(-4_" $t ").modulo_unchecked(m), 2];"]
238            #[doc = "assert_eq![Int(-3_" $t ").modulo_unchecked(m), 0];"]
239            #[doc = "assert_eq![Int(-2_" $t ").modulo_unchecked(m), 1];"]
240            #[doc = "assert_eq![Int(-1_" $t ").modulo_unchecked(m), 2];"]
241            #[doc = "assert_eq![Int( 0_" $t ").modulo_unchecked(m), 0];"]
242            #[doc = "assert_eq![Int( 1_" $t ").modulo_unchecked(m), 1];"]
243            #[doc = "assert_eq![Int( 2_" $t ").modulo_unchecked(m), 2];"]
244            #[doc = "assert_eq![Int( 3_" $t ").modulo_unchecked(m), 0];"]
245            #[doc = "assert_eq![Int( 4_" $t ").modulo_unchecked(m), 1];"]
246            #[doc = "assert_eq![Int( 4_" $t ").modulo_unchecked(-m), 1];"]
247            ///
248            #[doc = "assert_eq![Int(" $t "::MAX).modulo_unchecked(" $t "::MAX - 1), 1];"]
249            #[doc = "assert_eq![Int(" $t "::MAX).modulo_unchecked(" $t "::MAX), 0];"]
250            #[doc = "assert_eq![Int(" $t "::MAX).modulo_unchecked(" $t "::MIN), " $t "::MAX];"]
251            #[doc = "assert_eq![Int(" $t "::MIN).modulo_unchecked(" $t "::MAX), " $t "::MAX - 1];"]
252            #[doc = "assert_eq![Int(" $t "::MIN).modulo_unchecked(" $t "::MIN), 0];"]
253            ///
254            /// # #[cfg(feature = "_int_i64")]
255            #[doc = "assert_eq![Int(i64::MIN).modulo_unchecked(-1), 0];"]
256            /// ```
257            /// ```should_panic
258            /// # use devela::Int;
259            #[cfg(feature = "_int_i128")]
260            #[doc = "let _ = Int(i128::MIN).modulo_unchecked(-1); // i128 could overflow"]
261            /// ```
262            /// ```should_panic
263            /// # use devela::Int;
264            #[doc = "let _ = Int(1_" $t ").modulo_unchecked(0); // panics if modulus == 0"]
265            /// ```
266            pub const fn modulo_unchecked(self, modulus: $t) -> Int<$t> {
267                let (v, m) = (self.0 as $up, modulus as $up);
268                Int(v.rem_euclid(m) as $t)
269            }
270
271            /* modulo cycles (signed) */
272
273            /// Computes the non-negative modulo of `self` over |`modulus`|,
274            /// and the number of cycles the result is reduced.
275            ///
276            #[doc = "Performs operations internally as [`" $up "`]."]
277            ///
278            /// # Errors
279            /// Returns [`NonZeroRequired`] if `modulus == 0`, and for `i128`
280            /// if `self == MIN && modulus == ±1` it can return [`Overflow`].
281            ///
282            /// # Examples
283            /// ```
284            /// # use devela::{Int, NumResult, NumError};
285            /// # fn main() -> NumResult<()> {
286            /// let m = 3;
287            #[doc = "assert_eq![Int(-3_" $t ").modulo_cycles(m)?, (0, 1)];"]
288            #[doc = "assert_eq![Int(-2_" $t ").modulo_cycles(m)?, (1, 0)];"]
289            #[doc = "assert_eq![Int(-1_" $t ").modulo_cycles(m)?, (2, 0)];"]
290            #[doc = "assert_eq![Int( 0_" $t ").modulo_cycles(m)?, (0, 0)];"]
291            #[doc = "assert_eq![Int( 1_" $t ").modulo_cycles(m)?, (1, 0)];"]
292            #[doc = "assert_eq![Int( 2_" $t ").modulo_cycles(m)?, (2, 0)];"]
293            #[doc = "assert_eq![Int( 3_" $t ").modulo_cycles(m)?, (0, 1)];"]
294            /// # Ok(()) }
295            /// ```
296            pub const fn modulo_cycles(self, modulus: $t) -> Result<ValueQuant<Int<$t>, Int<$t>>> {
297                if modulus == 0 {
298                    cold_err_zero()
299                } else {
300                    let (orig, m) = (self.0 as $up, modulus as $up);
301                    if let Some(v) = orig.checked_rem_euclid(m) {
302                        let modulo = Int(v as $t);
303                        let times = Int(((orig / m) as $t).abs());
304                        Ok(ValueQuant::new(modulo, times))
305                    } else {
306                        cold_err_overflow()
307                    }
308                }
309            }
310
311            /// Computes the non-negative modulo of `self` over |`modulus`|,
312            /// and the number of cycles the result is reduced,
313            /// unchecked version.
314            ///
315            #[doc = "Performs operations internally as [`" $up "`]."]
316            ///
317            /// # Panics
318            /// Panics if `modulus == 0`, and for `i128` it can also panic
319            /// if `self == MIN && modulus == ±1`.
320            pub const fn modulo_cycles_unchecked(self, modulus: $t) -> ValueQuant<Int<$t>, Int<$t>> {
321                let (v, m) = (self.0 as $up, modulus as $up);
322                let modulo = Int(v.rem_euclid(m) as $t);
323                let times = Int(((v / m) as $t).abs());
324                ValueQuant::new(modulo, times)
325            }
326
327            /* modulo add (signed) */
328
329            /// Computes the non-negative modulo of `self + other` over |`modulus`|.
330            ///
331            #[doc = "Performs operations internally as [`" $up "`]."]
332            ///
333            /// # Features
334            /// Uses `unsafe_hint` for performance optimizations with upcasted arithmetic.
335            ///
336            /// # Errors
337            /// Returns [`NonZeroRequired`] if `modulus == 0`, and for `i128`
338            /// it could also return [`Overflow`].
339            ///
340            /// # Examples
341            /// ```
342            /// # use devela::{Int, NumResult, NumError};
343            /// # fn main() -> NumResult<()> {
344            /// let m = 3;
345            #[doc = "assert_eq![Int(4_" $t ").modulo_add(-4, m)?, 0];"]
346            #[doc = "assert_eq![Int(4_" $t ").modulo_add(-3, m)?, 1];"]
347            #[doc = "assert_eq![Int(4_" $t ").modulo_add(-2, m)?, 2];"]
348            #[doc = "assert_eq![Int(4_" $t ").modulo_add(-1, m)?, 0];"]
349            #[doc = "assert_eq![Int(4_" $t ").modulo_add( 0, m)?, 1];"]
350            #[doc = "assert_eq![Int(4_" $t ").modulo_add( 1, m)?, 2];"]
351            #[doc = "assert_eq![Int(4_" $t ").modulo_add( 2, m)?, 0];"]
352            #[doc = "assert_eq![Int(4_" $t ").modulo_add( 3, m)?, 1];"]
353            #[doc = "assert_eq![Int(4_" $t ").modulo_add( 4, m)?, 2];"]
354            /// # Ok(()) }
355            /// ```
356            pub const fn modulo_add(self, other: $t, modulus: $t) -> Result<Int<$t>> {
357                if modulus == 0 {
358                    cold_err_zero()
359                } else {
360                    let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
361                    let sum = upcastop![reduce_err +add(a, b) % m, $is_up];
362                    if let Some(v) = sum.checked_rem_euclid(m) { // TODO:TEST
363                        Ok(Int(v as $t))
364                    } else {
365                        cold_err_overflow()
366                    }
367                }
368            }
369
370            /// Computes the non-negative modulo of `self + other` over |`modulus`|,
371            /// unchecked version.
372            ///
373            #[doc = "Performs operations internally as [`" $up "`]."]
374            ///
375            /// # Features
376            /// Uses `unsafe_hint` for performance optimizations with upcasted arithmetic.
377            ///
378            /// # Panics
379            /// Panics if `modulus == 0`, and for `i128` it could also panic on overflow.
380            pub const fn modulo_add_unchecked(self, other: $t, modulus: $t) -> Int<$t> {
381                let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
382                let sum = upcastop![reduce +add(a, b) % m, $is_up];
383                Int(sum.rem_euclid(m) as $t)
384            }
385
386            /* modulo add cycles (signed) */
387
388            /// Computes the non-negative modulo of `self + other` over |`modulus`|,
389            /// and the number of cycles the result is reduced.
390            ///
391            #[doc = "Performs operations internally as [`" $up "`]."]
392            ///
393            /// # Features
394            /// Uses `unsafe_hint` for performance optimizations with upcasted arithmetic.
395            ///
396            /// # Errors
397            /// Returns [`NonZeroRequired`] if `modulus == 0`, and for `i128`
398            /// it can also return [`Overflow`], more probably than in
399            /// [`modulo_add`][Self::modulo_add] since we can't reduce
400            /// the operands beforehand in order to calculate *times*.
401            ///
402            /// # Examples
403            /// ```
404            /// # use devela::{Int, NumResult, NumError};
405            /// # fn main() -> NumResult<()> {
406            /// let m = 3;
407            #[doc = "assert_eq![Int(4_" $t ").modulo_add_cycles(-4, m)?, (0, 0)];"]
408            #[doc = "assert_eq![Int(4_" $t ").modulo_add_cycles(-3, m)?, (1, 0)];"]
409            #[doc = "assert_eq![Int(4_" $t ").modulo_add_cycles(-2, m)?, (2, 0)];"]
410            #[doc = "assert_eq![Int(4_" $t ").modulo_add_cycles(-1, m)?, (0, 1)];"]
411            #[doc = "assert_eq![Int(4_" $t ").modulo_add_cycles( 0, m)?, (1, 1)];"]
412            #[doc = "assert_eq![Int(4_" $t ").modulo_add_cycles( 1, m)?, (2, 1)];"]
413            #[doc = "assert_eq![Int(4_" $t ").modulo_add_cycles( 2, m)?, (0, 2)];"]
414            #[doc = "assert_eq![Int(4_" $t ").modulo_add_cycles( 3, m)?, (1, 2)];"]
415            #[doc = "assert_eq![Int(4_" $t ").modulo_add_cycles( 4, m)?, (2, 2)];"]
416            /// # Ok(()) }
417            /// ```
418            pub const fn modulo_add_cycles(self, other: $t, modulus: $t)
419                -> Result<ValueQuant<Int<$t>, Int<$t>>> {
420                if modulus == 0 {
421                    cold_err_zero()
422                } else {
423                    let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
424                    // not reducing for i128 makes overflow more likely,
425                    // but we can't if we want to calculate `times`.
426                    let sum = upcastop![err +add(a, b) $is_up];
427                    if let Some(v) = sum.checked_rem_euclid(m) {
428                        let modulo = Int(v as $t);
429                        let times = Int(((sum / m) as $t).abs());
430                        Ok(ValueQuant::new(modulo, times))
431                    } else {
432                        cold_err_overflow()
433                    }
434                }
435            }
436
437            /// Computes the non-negative modulo of `self + other` over |`modulus`|,
438            /// and the number of cycles the result is reduced,
439            /// unchecked version.
440            ///
441            #[doc = "Performs operations internally as [`" $up "`]."]
442            ///
443            /// # Features
444            /// Uses `unsafe_hint` for performance optimizations with upcasted arithmetic.
445            ///
446            /// # Panics
447            /// Panics if `modulus == 0`, and for `i128` it can also panic on overflow,
448            /// more probably than in [`modulo_add_unchecked`][Self::modulo_add_unchecked]
449            /// since we can't reduce the operands beforehand in order to calculate *times*.
450            pub const fn modulo_add_cycles_unchecked(self, other: $t, modulus: $t)
451                -> ValueQuant<Int<$t>, Int<$t>> {
452                let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
453                // not reducing for i128 makes overflow more likely,
454                // but we can't if we want to calculate `times`.
455                let sum = a + b;
456                let modulo = sum.rem_euclid(m) as $t;
457                let times = ((sum / m) as $t).abs();
458                ValueQuant::new(Int(modulo), Int(times))
459            }
460
461            /* modulo add inverse (signed) */
462
463            /// Calculates the modular additive inverse.
464            ///
465            /// The modular additive inverse of *self* modulo *modulus*
466            /// is an integer *b* such that $ a+b \equiv 0 (\mod m) $.
467            ///
468            /// The modular multiplicative inverse always exists and is simply
469            /// `modulus - self` if `self != 0`, or 0 otherwise.
470            ///
471            /// # Errors
472            /// Returns [`NonZeroRequired`] if `modulus == 0`.
473            ///
474            /// # Examples
475            /// ```
476            /// # use devela::{Int, NumResult, NumError};
477            /// # fn main() -> NumResult<()> {
478            /// let m = 3;
479            #[doc = "assert_eq![Int(-4_" $t ").modulo_add_inv(m)?, 1];"]
480            #[doc = "assert_eq![Int(-3_" $t ").modulo_add_inv(m)?, 0];"]
481            #[doc = "assert_eq![Int(-2_" $t ").modulo_add_inv(m)?, 2];"]
482            #[doc = "assert_eq![Int(-1_" $t ").modulo_add_inv(m)?, 1];"]
483            #[doc = "assert_eq![Int( 0_" $t ").modulo_add_inv(m)?, 0];"]
484            #[doc = "assert_eq![Int( 1_" $t ").modulo_add_inv(m)?, 2];"]
485            #[doc = "assert_eq![Int( 2_" $t ").modulo_add_inv(m)?, 1];"]
486            #[doc = "assert_eq![Int( 3_" $t ").modulo_add_inv(m)?, 0];"]
487            /// # Ok(()) }
488            /// ```
489            pub const fn modulo_add_inv(self, modulus: $t) -> Result<Int<$t>> {
490                if modulus == 0 {
491                    cold_err_zero()
492                } else {
493                    let rem = (self.0.rem_euclid(modulus));
494                    iif![rem == 0; Ok(Int(0)); Ok(Int(modulus - rem))]
495                }
496            }
497
498            /// Calculates the modular additive inverse,
499            /// unchecked version.
500            ///
501            /// The modular additive inverse of *self* modulo *modulus*
502            /// is an integer *b* such that $ a+b \equiv 0 (\mod m) $.
503            ///
504            /// The modular multiplicative inverse always exists and is simply
505            /// `modulus - self` if `self != 0`, or 0 otherwise.
506            ///
507            /// # Panics
508            /// Panics if `modulus == 0`.
509            pub const fn modulo_add_inv_unchecked(self, modulus: $t) -> Int<$t> {
510                let rem = (self.0.rem_euclid(modulus));
511                iif![rem == 0; Int(0); Int(modulus - rem)]
512            }
513
514            /* modulo sub (signed) */
515
516            /// Computes the modulo of `self - other` over |`modulus`|.
517            ///
518            #[doc = "Performs operations internally as [`" $up "`]."]
519            ///
520            /// # Features
521            /// Uses `unsafe_hint` for performance optimizations with upcasted arithmetic.
522            ///
523            /// # Errors
524            /// Returns [`NonZeroRequired`] if `modulus == 0`.
525            ///
526            /// # Examples
527            /// ```
528            /// # use devela::{Int, NumResult, NumError};
529            /// # fn main() -> NumResult<()> {
530            /// let m = 3;
531            #[doc = "assert_eq![Int(4_" $t ").modulo_sub(-4, m)?, 2];"]
532            #[doc = "assert_eq![Int(4_" $t ").modulo_sub(-3, m)?, 1];"]
533            #[doc = "assert_eq![Int(4_" $t ").modulo_sub(-2, m)?, 0];"]
534            #[doc = "assert_eq![Int(4_" $t ").modulo_sub(-1, m)?, 2];"]
535            #[doc = "assert_eq![Int(4_" $t ").modulo_sub( 0, m)?, 1];"]
536            #[doc = "assert_eq![Int(4_" $t ").modulo_sub( 1, m)?, 0];"]
537            #[doc = "assert_eq![Int(4_" $t ").modulo_sub( 2, m)?, 2];"]
538            #[doc = "assert_eq![Int(4_" $t ").modulo_sub( 3, m)?, 1];"]
539            #[doc = "assert_eq![Int(4_" $t ").modulo_sub( 4, m)?, 0];"]
540            /// # Ok(()) }
541            /// ```
542            pub const fn modulo_sub(self, other: $t, modulus: $t) -> Result<Int<$t>> {
543                if modulus == 0 {
544                    cold_err_zero()
545                } else {
546                    let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
547                    let res = upcastop![reduce_err -sub(a, b) % m, $is_up];
548                    Ok(Int(res.rem_euclid(m) as $t))
549                }
550            }
551
552            /// Computes the modulo of `self - other` over |`modulus`|,
553            /// unchecked version.
554            ///
555            #[doc = "Performs operations internally as [`" $up "`]."]
556            ///
557            /// # Features
558            /// Uses `unsafe_hint` for performance optimizations with upcasted arithmetic.
559            ///
560            /// # Panics
561            /// Panics if `modulus == 0`.
562            pub const fn modulo_sub_unchecked(self, other: $t, modulus: $t) -> Int<$t> {
563                let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
564                let res = upcastop![reduce -sub(a, b) % m, $is_up];
565                Int(res.rem_euclid(m) as $t)
566            }
567
568            /* modulo sub cycles (signed) */
569
570            /// Computes the non-negative modulo of `self - other` over |`modulus`|,
571            /// and the number of cycles the result is reduced.
572            ///
573            #[doc = "Performs operations internally as [`" $up "`]."]
574            ///
575            /// # Features
576            /// Uses `unsafe_hint` for performance optimizations with upcasted arithmetic.
577            ///
578            /// # Errors
579            /// Returns [`NonZeroRequired`] if `modulus == 0`, and for `i128`
580            /// it can also return [`Overflow`] (unlike [`modulo_sub`][Self::modulo_sub])
581            /// since we can't reduce the operands beforehand in order to calculate *times*.
582            ///
583            /// # Examples
584            /// ```
585            /// # use devela::{Int, NumResult, NumError};
586            /// # fn main() -> NumResult<()> {
587            /// let m = 3;
588            #[doc = "assert_eq![Int(4_" $t ").modulo_sub_cycles(-4, m)?, (2, 2)];"]
589            #[doc = "assert_eq![Int(4_" $t ").modulo_sub_cycles(-3, m)?, (1, 2)];"]
590            #[doc = "assert_eq![Int(4_" $t ").modulo_sub_cycles(-2, m)?, (0, 2)];"]
591            #[doc = "assert_eq![Int(4_" $t ").modulo_sub_cycles(-1, m)?, (2, 1)];"]
592            #[doc = "assert_eq![Int(4_" $t ").modulo_sub_cycles( 0, m)?, (1, 1)];"]
593            #[doc = "assert_eq![Int(4_" $t ").modulo_sub_cycles( 1, m)?, (0, 1)];"]
594            #[doc = "assert_eq![Int(4_" $t ").modulo_sub_cycles( 2, m)?, (2, 0)];"]
595            #[doc = "assert_eq![Int(4_" $t ").modulo_sub_cycles( 3, m)?, (1, 0)];"]
596            #[doc = "assert_eq![Int(4_" $t ").modulo_sub_cycles( 4, m)?, (0, 0)];"]
597            /// # Ok(()) }
598            /// ```
599            pub const fn modulo_sub_cycles(self, other: $t, modulus: $t)
600                -> Result<ValueQuant<Int<$t>, Int<$t>>> {
601                if modulus == 0 {
602                    cold_err_zero()
603                } else {
604                    let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
605                    // not reducing for i128 makes overflow more likely,
606                    // but we can't if we want to calculate `times`.
607                    let res = upcastop![err -sub(a, b) $is_up];
608                    let modulo = Int(res.rem_euclid(m) as $t);
609                    let times = Int(((res / m) as $t).abs());
610                    Ok(ValueQuant::new(modulo, times))
611                }
612            }
613
614            /// Computes the non-negative modulo of `self - other` over |`modulus`|,
615            /// and the number of cycles the result is reduced,
616            /// unchecked version.
617            ///
618            #[doc = "Performs operations internally as [`" $up "`]."]
619            ///
620            /// # Panics
621            /// Panics if `modulus == 0`, and for `i128` it can also panic on overflow,
622            /// more probably than in [`modulo_sub_unchecked`][Self::modulo_sub_unchecked]
623            /// since we can't reduce the operands beforehand in order to calculate *times*.
624            #[must_use]
625            pub const fn modulo_sub_cycles_unchecked(self, other: $t, modulus: $t)
626                -> (Int<$t>, Int<$t>) {
627                let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
628                // not reducing for i128 makes overflow more likely,
629                // but we can't if we want to calculate `times`.
630                let res = a - b;
631                let modulo = res.rem_euclid(m) as $t;
632                let times = ((res / m) as $t).abs();
633                (Int(modulo), Int(times))
634            }
635
636            /* modulo mul (signed) */
637
638            /// Computes the non-negative modulo of `self + other` over |`modulus`|.
639            ///
640            #[doc = "Performs operations internally as [`" $up "`]."]
641            ///
642            /// # Features
643            /// Uses `unsafe_hint` for performance optimizations with upcasted arithmetic.
644            ///
645            /// # Errors
646            /// Returns [`NonZeroRequired`] if `modulus == 0`, and for `i128`
647            /// it could also return [`Overflow`].
648            ///
649            /// # Examples
650            /// ```
651            /// # use devela::{Int, NumResult, NumError};
652            /// # fn main() -> NumResult<()> {
653            /// let m = 3;
654            #[doc = "assert_eq![Int(4_" $t ").modulo_mul(-4, m)?, 2];"]
655            #[doc = "assert_eq![Int(4_" $t ").modulo_mul(-3, m)?, 0];"]
656            #[doc = "assert_eq![Int(4_" $t ").modulo_mul(-2, m)?, 1];"]
657            #[doc = "assert_eq![Int(4_" $t ").modulo_mul(-1, m)?, 2];"]
658            #[doc = "assert_eq![Int(4_" $t ").modulo_mul( 0, m)?, 0];"]
659            #[doc = "assert_eq![Int(4_" $t ").modulo_mul( 1, m)?, 1];"]
660            #[doc = "assert_eq![Int(4_" $t ").modulo_mul( 2, m)?, 2];"]
661            #[doc = "assert_eq![Int(4_" $t ").modulo_mul( 3, m)?, 0];"]
662            #[doc = "assert_eq![Int(4_" $t ").modulo_mul( 4, m)?, 1];"]
663            /// # Ok(()) }
664            /// ```
665            pub const fn modulo_mul(self, other: $t, modulus: $t) -> Result<Int<$t>> {
666                if modulus == 0 {
667                    cold_err_zero()
668                } else {
669                    let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
670                    let sum = upcastop![reduce_err *mul(a, b) % m, $is_up];
671                    if let Some(v) = sum.checked_rem_euclid(m) { // TODO:TEST
672                        Ok(Int(v as $t))
673                    } else {
674                        cold_err_overflow()
675                    }
676                }
677            }
678
679            /// Computes the non-negative modulo of `self + other` over |`modulus`|,
680            /// unchecked version.
681            ///
682            #[doc = "Performs operations internally as [`" $up "`]."]
683            ///
684            /// # Features
685            /// Uses `unsafe_hint` for performance optimizations with upcasted arithmetic.
686            ///
687            /// # Panics
688            /// Panics if `modulus == 0`, and for `i128` it could also panic on overflow.
689            pub const fn modulo_mul_unchecked(self, other: $t, modulus: $t) -> Int<$t> {
690                let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
691                let sum = upcastop![reduce *mul(a, b) % m, $is_up];
692                Int(sum.rem_euclid(m) as $t)
693            }
694
695            /* modulo mul cycles (signed) */
696
697            /// Computes the non-negative modulo of `self + other` over |`modulus`|,
698            /// and the number of cycles the result is reduced.
699            ///
700            #[doc = "Performs operations internally as [`" $up "`]."]
701            ///
702            /// # Features
703            /// Uses `unsafe_hint` for performance optimizations with upcasted arithmetic.
704            ///
705            /// # Errors
706            /// Returns [`NonZeroRequired`] if `modulus == 0`, and for `i128`
707            /// it can also return [`Overflow`], more probably than in
708            /// [`modulo_mul`][Self::modulo_mul] since we can't reduce
709            /// the operands beforehand in order to calculate *times*.
710            ///
711            /// # Examples
712            /// ```
713            /// # use devela::{Int, NumResult, NumError};
714            /// # fn main() -> NumResult<()> {
715            /// let m = 3;
716            #[doc = "assert_eq![Int(4_" $t ").modulo_mul_cycles(-4, m)?, (2, 5)];"]
717            #[doc = "assert_eq![Int(4_" $t ").modulo_mul_cycles(-3, m)?, (0, 4)];"]
718            #[doc = "assert_eq![Int(4_" $t ").modulo_mul_cycles(-2, m)?, (1, 2)];"]
719            #[doc = "assert_eq![Int(4_" $t ").modulo_mul_cycles(-1, m)?, (2, 1)];"]
720            #[doc = "assert_eq![Int(4_" $t ").modulo_mul_cycles( 0, m)?, (0, 0)];"]
721            #[doc = "assert_eq![Int(4_" $t ").modulo_mul_cycles( 1, m)?, (1, 1)];"]
722            #[doc = "assert_eq![Int(4_" $t ").modulo_mul_cycles( 2, m)?, (2, 2)];"]
723            #[doc = "assert_eq![Int(4_" $t ").modulo_mul_cycles( 3, m)?, (0, 4)];"]
724            #[doc = "assert_eq![Int(4_" $t ").modulo_mul_cycles( 4, m)?, (1, 5)];"]
725            /// # Ok(()) }
726            /// ```
727            pub const fn modulo_mul_cycles(self, other: $t, modulus: $t)
728                -> Result<ValueQuant<Int<$t>, Int<$t>>> {
729                if modulus == 0 {
730                    cold_err_zero()
731                } else {
732                    let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
733                    // not reducing for i128 makes overflow more likely,
734                    // but we can't if we want to calculate `times`.
735                    let sum = upcastop![err *mul(a, b) $is_up];
736                    if let Some(v) = sum.checked_rem_euclid(m) {
737                        let modulo = Int(v as $t);
738                        let times = Int(((sum / m) as $t).abs());
739                        Ok(ValueQuant::new(modulo, times))
740                    } else {
741                        cold_err_overflow()
742                    }
743                }
744            }
745
746            /// Computes the non-negative modulo of `self + other` over |`modulus`|,
747            /// and the number of cycles the result is reduced,
748            /// unchecked version.
749            ///
750            #[doc = "Performs operations internally as [`" $up "`]."]
751            ///
752            /// # Panics
753            /// Panics if `modulus == 0`, and for `i128` it can also panic on overflow,
754            /// more probably than in [`modulo_mul_unchecked`][Self::modulo_mul_unchecked]
755            /// since we can't reduce the operands beforehand in order to calculate *times*.
756            pub const fn modulo_mul_cycles_unchecked(self, other: $t, modulus: $t)
757                -> ValueQuant<Int<$t>, Int<$t>> {
758                let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
759                // not reducing for i128 makes overflow more likely,
760                // but we can't if we want to calculate `times`.
761                let sum = a + b;
762                let modulo = sum.rem_euclid(m) as $t;
763                let times = ((sum / m) as $t).abs();
764                ValueQuant::new(Int(modulo), Int(times))
765            }
766
767            /* modulo mul inv (signed) */
768
769            /// Calculates the modular multiplicative inverse.
770            ///
771            /// The modular multiplicative inverse of *self* modulo *modulus*
772            /// is an integer *b* such that $ ab \equiv 1 (\mod m) $.
773            ///
774            /// The modular multiplicative inverse exists only if `self` and
775            /// `modulus` are coprime, meaning their greatest common divisor is 1.
776            ///
777            /// # Errors
778            /// Returns [`NonZeroRequired`] if `modulus == 0`,
779            /// or [`NoInverse`] if there's no inverse.
780            ///
781            /// # Examples
782            /// ```
783            /// # use devela::{Int, NumResult, NumError};
784            /// # fn main() -> NumResult<()> {
785            /// let m = 5;
786            #[doc = "assert_eq![Int(-4_" $t ").modulo_mul_inv(m)?, 4];"]
787            #[doc = "assert_eq![Int(-3_" $t ").modulo_mul_inv(m)?, 2];"]
788            #[doc = "assert_eq![Int(-2_" $t ").modulo_mul_inv(m)?, 3];"]
789            #[doc = "assert_eq![Int(-1_" $t ").modulo_mul_inv(m)?, 1];"]
790            #[doc = "assert_eq![Int( 0_" $t ").modulo_mul_inv(m), Err(NumError::NoInverse)];"]
791            #[doc = "assert_eq![Int( 1_" $t ").modulo_mul_inv(m)?, 1];"]
792            #[doc = "assert_eq![Int( 2_" $t ").modulo_mul_inv(m)?, 3];"]
793            #[doc = "assert_eq![Int( 3_" $t ").modulo_mul_inv(m)?, 2];"]
794            #[doc = "assert_eq![Int( 4_" $t ").modulo_mul_inv(m)?, 4];"]
795            /// # Ok(()) }
796            /// ```
797            pub const fn modulo_mul_inv(self, modulus: $t) -> Result<Int<$t>> {
798                if modulus == 0 {
799                    cold_err_zero()
800                } else {
801                    let (gcd, x, _) = self.gcd_ext(modulus).as_tuple_copy();
802                    if gcd.0 != 1 {
803                        Err(NoInverse)
804                    } else {
805                        Ok(Int(x.0.rem_euclid(modulus)))
806                    }
807                }
808            }
809
810            /// Calculates the modular multiplicative inverse,
811            /// unchecked version.
812            ///
813            /// The modular multiplicative inverse of *self* modulo *modulus*
814            /// is an integer *b* such that $ ab \equiv 1 (\mod m) $.
815            ///
816            /// The modular multiplicative inverse exists only if `self` and
817            /// `modulus` are coprime, meaning their greatest common divisor is 1.
818            ///
819            /// # Panics
820            /// Panics if `modulus == 0`, and if there's no inverse.
821            pub const fn modulo_mul_inv_unchecked(self, modulus: $t) -> Int<$t> {
822                let (gcd, x, _) = self.gcd_ext(modulus).as_tuple_copy();
823                if gcd.0 != 1 {
824                    panic!["No inverse"];
825                } else {
826                    Int(x.0.rem_euclid(modulus))
827                }
828            }
829
830            /* modulo div (signed) */
831
832            /// Computes `self / other` over |`modulus`|.
833            ///
834            #[doc = "Performs operations internally as [`" $up "`]."]
835            ///
836            /// $a / b \mod m$ is equivalent to $a * b^{-1} \mod m$,
837            /// where $b^{-1}$ is the modular multiplicative inverse
838            /// of $b$ modulo $m$.
839            ///
840            /// # Errors
841            /// Returns [`NonZeroRequired`] if `modulus == 0`,
842            /// and [`NoInverse`] if there's no multiplicative inverse of `other`.
843            ///
844            /// # Examples
845            /// ```
846            /// # use devela::{Int, NumResult, NumError};
847            /// # fn main() -> NumResult<()> {
848            /// let m = 3;
849            #[doc = "assert_eq![Int(-4_" $t ").modulo_div(2, m)?, 1];"]
850            #[doc = "assert_eq![Int(-3_" $t ").modulo_div(2, m)?, 0];"]
851            #[doc = "assert_eq![Int(-2_" $t ").modulo_div(2, m)?, 2];"]
852            #[doc = "assert_eq![Int(-1_" $t ").modulo_div(2, m)?, 1];"]
853            #[doc = "assert_eq![Int( 0_" $t ").modulo_div(2, m)?, 0];"]
854            #[doc = "assert_eq![Int( 1_" $t ").modulo_div(2, m)?, 2];"]
855            #[doc = "assert_eq![Int( 2_" $t ").modulo_div(2, m)?, 1];"]
856            #[doc = "assert_eq![Int( 3_" $t ").modulo_div(2, m)?, 0];"]
857            #[doc = "assert_eq![Int( 4_" $t ").modulo_div(2, m)?, 2];"]
858            /// # Ok(()) }
859            /// ```
860            pub const fn modulo_div(self, other: $t, modulus: $t) -> Result<Int<$t>> {
861                if modulus == 0 {
862                    cold_err_zero()
863                } else {
864                    let inverse = unwrap![ok? Int(other).modulo_mul_inv(modulus)];
865                    self.modulo_mul(inverse.0, modulus)
866                }
867            }
868
869            /// Computes `self / other` over |`modulus`|,
870            /// unchecked version.
871            ///
872            #[doc = "Performs operations internally as [`" $up "`]."]
873            ///
874            /// # Panics
875            /// Panics if `modulus == 0`,
876            /// and if there's no multiplicative inverse of `other`.
877            pub const fn modulo_div_unchecked(self, other: $t, modulus: $t) -> Int<$t> {
878                let inverse = Int(other).modulo_mul_inv_unchecked(modulus);
879                self.modulo_mul_unchecked(inverse.0, modulus)
880            }
881        }
882    }};
883    (
884    // implements unsigned ops
885    @unsigned
886         ($t:ty : $cap:literal, $up:ty | $iup:ty : $icap:literal : $is_up:ident |$d:literal)
887    ) => { paste! {
888        #[doc = crate::doc_availability!(feature = $cap)]
889        ///
890        #[doc = "# Integer modulo related methods for `" $t "`\n\n"]
891        #[doc = "- [modulo](#method.modulo" $d
892            ") *([uc](#method.modulo_unchecked" $d ")*)"]
893        #[doc = "- [modulo_cycles](#method.modulo_cycles" $d
894            ") *([uc](#method.modulo_cycles_unchecked" $d "))*"]
895        //
896        #[doc = "- [modulo_add](#method.modulo_add" $d
897            ") *([uc](#method.modulo_add_unchecked" $d "))*"]
898        #[doc = "- [modulo_add_cycles](#method.modulo_add_cycles" $d
899            ") *([uc](#method.modulo_add_cycles_unchecked" $d "))*"]
900        #[doc = "- [modulo_add_inv](#method.modulo_add_inv" $d
901            ") *([uc](#method.modulo_add_inv_unchecked" $d "))*"]
902        //
903        #[doc = "- [modulo_sub](#method.modulo_sub" $d
904            ") *([uc](#method.modulo_sub_unchecked" $d "))*"]
905        #[doc = "- [modulo_sub_cycles](#method.modulo_sub_cycles" $d
906            ") *([uc](#method.modulo_sub_cycles_unchecked" $d "))*"]
907        //
908        #[doc = "- [modulo_mul](#method.modulo_mul" $d
909            ") *([uc](#method.modulo_mul_unchecked" $d "))*"]
910        #[doc = "- [modulo_mul_cycles](#method.modulo_mul_cycles" $d
911            ") *([uc](#method.modulo_mul_cycles_unchecked" $d "))*"]
912        #[doc = "- [modulo_mul_inv](#method.modulo_mul_inv" $d
913            ") *([uc](#method.modulo_mul_inv_unchecked" $d "))*"]
914        //
915        #[doc = "- [modulo_div](#method.modulo_div" $d
916            ") *([uc](#method.modulo_div_unchecked" $d "))*"]
917        ///
918        #[cfg(feature = $cap )]
919        impl Int<$t> {
920            /* modulo (unsigned) */
921
922            /// Computes the non-negative modulo of `self` over `modulus`.
923            ///
924            /// The result is less than the value of `modulus`,
925            /// i.e., in the range $ [0, \text{modulus}) $.
926            ///
927            /// # Errors
928            /// Returns [`NonZeroRequired`] if `modulus == 0`.
929            ///
930            /// # Examples
931            /// ```
932            /// # use devela::{Int, NumResult, NumError};
933            /// # fn main() -> NumResult<()> {
934            /// let m = 3;
935            #[doc = "assert_eq![Int(0_" $t ").modulo(m)?, 0];"]
936            #[doc = "assert_eq![Int(1_" $t ").modulo(m)?, 1];"]
937            #[doc = "assert_eq![Int(2_" $t ").modulo(m)?, 2];"]
938            #[doc = "assert_eq![Int(3_" $t ").modulo(m)?, 0];"]
939            #[doc = "assert_eq![Int(4_" $t ").modulo(m)?, 1];"]
940            /// # Ok(()) }
941            /// ```
942            pub const fn modulo(self, modulus: $t) -> Result<Int<$t>> {
943                if modulus == 0 {
944                    cold_err_zero()
945                } else {
946                    Ok(Int(self.0 % modulus))
947                }
948            }
949
950            /// Computes the non-negative modulo of `self` over `modulus`, unchecked version.
951            ///
952            /// The result is less than the value of `modulus`,
953            /// i.e., in the range $ [0, \text{modulus}) $.
954            ///
955            /// # Panics
956            /// Panics if `modulus == 0`.
957            ///
958            /// # Examples
959            /// ```
960            /// # use devela::Int;
961            /// let m = 3;
962            #[doc = "assert_eq![Int(0_" $t ").modulo_unchecked(m), 0];"]
963            #[doc = "assert_eq![Int(1_" $t ").modulo_unchecked(m), 1];"]
964            #[doc = "assert_eq![Int(2_" $t ").modulo_unchecked(m), 2];"]
965            #[doc = "assert_eq![Int(3_" $t ").modulo_unchecked(m), 0];"]
966            #[doc = "assert_eq![Int(4_" $t ").modulo_unchecked(m), 1];"]
967            /// ```
968            pub const fn modulo_unchecked(self, modulus: $t) -> Int<$t> {
969                Int(self.0 % modulus)
970            }
971
972            /* modulo cycles (unsigned) */
973
974            /// Computes the non-negative modulo of `self` over `modulus`,
975            /// and the number of cycles it is reduced.
976            ///
977            /// # Errors
978            /// Returns [`NonZeroRequired`] if `modulus == 0`.
979            ///
980            /// # Examples
981            /// ```
982            /// # use devela::{Int, NumResult, NumError};
983            /// # fn main() -> NumResult<()> {
984            /// let m = 3;
985            #[doc = "assert_eq![Int(0_" $t ").modulo_cycles(m)?, (0, 0)];"]
986            #[doc = "assert_eq![Int(1_" $t ").modulo_cycles(m)?, (1, 0)];"]
987            #[doc = "assert_eq![Int(2_" $t ").modulo_cycles(m)?, (2, 0)];"]
988            #[doc = "assert_eq![Int(3_" $t ").modulo_cycles(m)?, (0, 1)];"]
989            /// # Ok(()) }
990            /// ```
991            pub const fn modulo_cycles(self, modulus: $t) -> Result<ValueQuant<Int<$t>, Int<$t>>> {
992                if modulus == 0 {
993                    cold_err_zero()
994                } else {
995                    Ok(ValueQuant::new(Int(self.0 % modulus), Int(self.0 / modulus)))
996                }
997            }
998
999            /// Computes the non-negative modulo of `self` over `modulus`,
1000            /// and the number of cycles it is reduced,
1001            /// unchecked version.
1002            ///
1003            /// # Panics
1004            /// Panics if `modulus == 0`.
1005            ///
1006            /// # Examples
1007            /// ```
1008            /// # use devela::Int;
1009            /// let m = 3;
1010            #[doc = "assert_eq![Int(0_" $t ").modulo_cycles_unchecked(m), (0, 0)];"]
1011            #[doc = "assert_eq![Int(1_" $t ").modulo_cycles_unchecked(m), (1, 0)];"]
1012            #[doc = "assert_eq![Int(2_" $t ").modulo_cycles_unchecked(m), (2, 0)];"]
1013            #[doc = "assert_eq![Int(3_" $t ").modulo_cycles_unchecked(m), (0, 1)];"]
1014            /// ```
1015            pub const fn modulo_cycles_unchecked(self, modulus: $t)
1016                -> ValueQuant<Int<$t>, Int<$t>> {
1017                ValueQuant::new(Int(self.0 % modulus), Int(self.0 / modulus))
1018            }
1019
1020            /* modulo add (unsigned) */
1021
1022            /// Computes the modulo of `self + other` over `modulus`.
1023            ///
1024            #[doc = "Performs operations internally as [`" $up "`]."]
1025            ///
1026            /// # Features
1027            /// Uses `unsafe_hint` for performance optimizations with upcasted arithmetic.
1028            ///
1029            /// # Errors
1030            /// Returns [`NonZeroRequired`] if `modulus == 0`, and for `u128`
1031            /// it could also return [`Overflow`].
1032            ///
1033            /// # Examples
1034            /// ```
1035            /// # use devela::{Int, NumResult, NumError};
1036            /// # fn main() -> NumResult<()> {
1037            /// let m = 3;
1038            #[doc = "assert_eq![Int(4_" $t ").modulo_add(0, m)?, 1];"]
1039            #[doc = "assert_eq![Int(4_" $t ").modulo_add(1, m)?, 2];"]
1040            #[doc = "assert_eq![Int(4_" $t ").modulo_add(2, m)?, 0];"]
1041            #[doc = "assert_eq![Int(4_" $t ").modulo_add(3, m)?, 1];"]
1042            #[doc = "assert_eq![Int(4_" $t ").modulo_add(4, m)?, 2];"]
1043            /// # Ok(()) }
1044            /// ```
1045            pub const fn modulo_add(self, other: $t, modulus: $t) -> Result<Int<$t>> {
1046                if modulus == 0 {
1047                    cold_err_zero()
1048                } else {
1049                    let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
1050                    let sum = upcastop![reduce_err +add(a, b) % m, $is_up];
1051                    Ok((Int((sum % m) as $t)))
1052                }
1053            }
1054
1055            /// Computes the modulo of `self + other` over `modulus`,
1056            /// unchecked version.
1057            ///
1058            #[doc = "Performs operations internally as [`" $up "`]."]
1059            ///
1060            /// # Features
1061            /// Uses `unsafe_hint` for performance optimizations with upcasted arithmetic.
1062            ///
1063            /// # Panics
1064            /// Panics if `modulus == 0`, and for `u128` it could also panic on overflow.
1065            pub const fn modulo_add_unchecked(self, other: $t, modulus: $t) -> Int<$t> {
1066                let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
1067                let sum = upcastop![reduce +add(a, b) % m, $is_up];
1068                Int((sum % m) as $t)
1069            }
1070
1071            /* modulo add cycles (unsigned) */
1072
1073            /// Computes the modulo of `self + other` over `modulus`,
1074            /// and the number of cycles the result is reduced.
1075            ///
1076            #[doc = "Performs operations internally as [`" $up "`]."]
1077            ///
1078            /// # Features
1079            /// Uses `unsafe_hint` for performance optimizations with upcasted arithmetic.
1080            ///
1081            /// # Errors
1082            /// Returns [`NonZeroRequired`] if `modulus == 0`, and for `u128`
1083            /// it can also return [`Overflow`], more probably than in
1084            /// [`modulo_add`][Self::modulo_add] since we can't reduce
1085            /// the operands beforehand in order to calculate *times*.
1086            ///
1087            /// # Examples
1088            /// ```
1089            /// # use devela::{Int, NumResult, NumError};
1090            /// # fn main() -> NumResult<()> {
1091            /// let m = 3;
1092            #[doc = "assert_eq![Int(4_" $t ").modulo_add_cycles(0, m)?, (1, 1)];"]
1093            #[doc = "assert_eq![Int(4_" $t ").modulo_add_cycles(1, m)?, (2, 1)];"]
1094            #[doc = "assert_eq![Int(4_" $t ").modulo_add_cycles(2, m)?, (0, 2)];"]
1095            #[doc = "assert_eq![Int(4_" $t ").modulo_add_cycles(3, m)?, (1, 2)];"]
1096            #[doc = "assert_eq![Int(4_" $t ").modulo_add_cycles(4, m)?, (2, 2)];"]
1097            /// # Ok(()) }
1098            /// ```
1099            pub const fn modulo_add_cycles(self, other: $t, modulus: $t)
1100                -> Result<ValueQuant<Int<$t>, Int<$t>>> {
1101                if modulus == 0 {
1102                    cold_err_zero()
1103                } else {
1104                    let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
1105                    // not reducing for u128 makes overflow more likely,
1106                    // but we can't if we want to calculate `times`.
1107                    let sum = upcastop![err +add(a, b) $is_up];
1108                    let modulo = Int((sum % m) as $t);
1109                    let times = Int((sum / m) as $t);
1110                    Ok(ValueQuant::new(modulo, times))
1111                }
1112            }
1113
1114            /// Computes the modulo of `self + other` over `modulus`,
1115            /// and the number of cycles the result is reduced,
1116            /// unchecked version.
1117            ///
1118            #[doc = "Performs operations internally as [`" $up "`]."]
1119            ///
1120            /// # Panics
1121            /// Panics if `modulus == 0`, and for `u128` it can also panic on overflow,
1122            /// more probably than in [`modulo_add_unchecked`][Self::modulo_add_unchecked]
1123            /// since we can't reduce the operands beforehand in order to calculate *times*.
1124            pub const fn modulo_add_cycles_unchecked(self, other: $t, modulus: $t)
1125                -> ValueQuant<Int<$t>, Int<$t>> {
1126                let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
1127                // not reducing for u128 makes overflow more likely,
1128                // but we can't if we want to calculate `times`.
1129                let sum = a + b;
1130                let modulo = Int((sum % m) as $t);
1131                let times = Int((sum / m) as $t);
1132                ValueQuant::new(modulo, times)
1133            }
1134
1135            /* modulo add inverse (unsigned) */
1136
1137            /// Calculates the modular additive inverse.
1138            ///
1139            /// The modular additive inverse of *self* modulo *modulus*
1140            /// is an integer *b* such that $ a+b \equiv 0 (\mod m) $.
1141            ///
1142            /// The modular multiplicative inverse always exists and is simply
1143            /// `modulus - self` if `self != 0`, or 0 otherwise.
1144            ///
1145            /// # Errors
1146            /// Returns [`NonZeroRequired`] if `modulus == 0`.
1147            ///
1148            /// # Examples
1149            /// ```
1150            /// # use devela::{Int, NumResult, NumError};
1151            /// # fn main() -> NumResult<()> {
1152            /// let m = 3;
1153            #[doc = "assert_eq![Int(0_" $t ").modulo_add_inv(m)?, 0];"]
1154            #[doc = "assert_eq![Int(1_" $t ").modulo_add_inv(m)?, 2];"]
1155            #[doc = "assert_eq![Int(2_" $t ").modulo_add_inv(m)?, 1];"]
1156            #[doc = "assert_eq![Int(3_" $t ").modulo_add_inv(m)?, 0];"]
1157            /// # Ok(()) }
1158            /// ```
1159            pub const fn modulo_add_inv(self, modulus: $t) -> Result<Int<$t>> {
1160                if modulus == 0 {
1161                    cold_err_zero()
1162                } else {
1163                    let rem = (self.0.rem_euclid(modulus));
1164                    iif![rem == 0; Ok(Int(0)); Ok(Int(modulus - rem))]
1165                }
1166            }
1167
1168            /// Calculates the modular additive inverse,
1169            /// unchecked version.
1170            ///
1171            /// The modular additive inverse of *self* modulo *modulus*
1172            /// is an integer *b* such that $ a+b \equiv 0 (\mod m) $.
1173            ///
1174            /// The modular multiplicative inverse always exists and is simply
1175            /// `modulus - self` if `self != 0`, or 0 otherwise.
1176            ///
1177            /// # Panics
1178            /// Panics if `modulus == 0`.
1179            pub const fn modulo_add_inv_unchecked(self, modulus: $t) -> Int<$t> {
1180                let rem = (self.0.rem_euclid(modulus));
1181                iif![rem == 0; Int(0); Int(modulus - rem)]
1182            }
1183
1184            /* modulo sub (unsigned) */
1185
1186            /// Computes the modulo of `self - other` over `modulus`.
1187            ///
1188            /// # Errors
1189            /// Returns [`NonZeroRequired`] if `modulus == 0`, and it can also
1190            /// return [`Overflow`] if the result would be a negative value.
1191            ///
1192            /// # Examples
1193            /// ```
1194            /// # use devela::{Int, NumResult, NumError};
1195            /// # fn main() -> NumResult<()> {
1196            /// let m = 3;
1197            #[doc = "assert_eq![Int(4_" $t ").modulo_sub(0, m)?, 1];"]
1198            #[doc = "assert_eq![Int(4_" $t ").modulo_sub(1, m)?, 0];"]
1199            #[doc = "assert_eq![Int(4_" $t ").modulo_sub(2, m)?, 2];"]
1200            #[doc = "assert_eq![Int(4_" $t ").modulo_sub(3, m)?, 1];"]
1201            #[doc = "assert_eq![Int(4_" $t ").modulo_sub(4, m)?, 0];"]
1202            /// # Ok(()) }
1203            /// ```
1204            pub const fn modulo_sub(self, other: $t, modulus: $t) -> Result<Int<$t>> {
1205                if modulus == 0 {
1206                    cold_err_zero()
1207                } else {
1208                    if let Some(res) = self.0.checked_sub(other) {
1209                        Ok(Int(res % modulus))
1210                    } else {
1211                        Err(Overflow(None))
1212                    }
1213                }
1214            }
1215
1216            /// Computes the modulo of `self - other` over `modulus`,
1217            /// unchecked version.
1218            ///
1219            /// # Panics
1220            /// Panics if `modulus == 0`, and if the result would be a negative value.
1221            pub const fn modulo_sub_unchecked(self, other: $t, modulus: $t) -> Int<$t> {
1222                Int(((self.0 - other) % modulus))
1223            }
1224
1225            /* modulo sub cycles (unsigned) */
1226
1227            /// Computes the modulo of `self - other` over `modulus`,
1228            /// and the number of cycles the result is reduced.
1229            ///
1230            /// # Errors
1231            /// Returns [`NonZeroRequired`] if `modulus == 0`, and it can also
1232            /// return [`Overflow`] if the result would be a negative value.
1233            ///
1234            /// # Examples
1235            /// ```
1236            /// # use devela::{Int, NumResult, NumError};
1237            /// # fn main() -> NumResult<()> {
1238            /// let m = 3;
1239            #[doc = "assert_eq![Int(4_" $t ").modulo_sub_cycles(0, m)?, (1, 1)];"]
1240            #[doc = "assert_eq![Int(4_" $t ").modulo_sub_cycles(1, m)?, (0, 1)];"]
1241            #[doc = "assert_eq![Int(4_" $t ").modulo_sub_cycles(2, m)?, (2, 0)];"]
1242            #[doc = "assert_eq![Int(4_" $t ").modulo_sub_cycles(3, m)?, (1, 0)];"]
1243            #[doc = "assert_eq![Int(4_" $t ").modulo_sub_cycles(4, m)?, (0, 0)];"]
1244            /// # Ok(()) }
1245            /// ```
1246            pub const fn modulo_sub_cycles(self, other: $t, modulus: $t)
1247                -> Result<ValueQuant<Int<$t>, Int<$t>>> {
1248                if modulus == 0 {
1249                    cold_err_zero()
1250                } else {
1251                    if let Some(res) = self.0.checked_sub(other) {
1252                        let modulo = Int((res % modulus) as $t);
1253                        let times = Int((res / modulus) as $t);
1254                        Ok(ValueQuant::new(modulo, times))
1255                    } else {
1256                        Err(Overflow(None))
1257                    }
1258                }
1259            }
1260
1261            /// Computes the modulo of `self - other` over `modulus`,
1262            /// and the number of cycles the result is reduced,
1263            /// unchecked version.
1264            ///
1265            /// # Panics
1266            /// Panics if `modulus == 0`, and if the result would be a negative value.
1267            pub const fn modulo_sub_cycles_unchecked(self, other: $t, modulus: $t)
1268                -> ValueQuant<Int<$t>, Int<$t>> {
1269                let res = self.0 - other;
1270                let modulo = Int((res % modulus) as $t);
1271                let times = Int((res / modulus) as $t);
1272                ValueQuant::new(modulo, times)
1273            }
1274
1275            /* modulo mul (unsigned) */
1276
1277            /// Computes the modulo of `self + other` over `modulus`.
1278            ///
1279            #[doc = "Performs operations internally as [`" $up "`]."]
1280            ///
1281            /// # Features
1282            /// Uses `unsafe_hint` for performance optimizations with upcasted arithmetic.
1283            ///
1284            /// # Errors
1285            /// Returns [`NonZeroRequired`] if `modulus == 0`, and for `u128`
1286            /// it could also return [`Overflow`].
1287            ///
1288            /// # Examples
1289            /// ```
1290            /// # use devela::{Int, NumResult, NumError};
1291            /// # fn main() -> NumResult<()> {
1292            /// let m = 3;
1293            #[doc = "assert_eq![Int(4_" $t ").modulo_mul(0, m)?, 0];"]
1294            #[doc = "assert_eq![Int(4_" $t ").modulo_mul(1, m)?, 1];"]
1295            #[doc = "assert_eq![Int(4_" $t ").modulo_mul(2, m)?, 2];"]
1296            #[doc = "assert_eq![Int(4_" $t ").modulo_mul(3, m)?, 0];"]
1297            #[doc = "assert_eq![Int(4_" $t ").modulo_mul(4, m)?, 1];"]
1298            /// # Ok(()) }
1299            /// ```
1300            pub const fn modulo_mul(self, other: $t, modulus: $t) -> Result<Int<$t>> {
1301                if modulus == 0 {
1302                    cold_err_zero()
1303                } else {
1304                    let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
1305                    let sum = upcastop![reduce_err *mul(a, b) % m, $is_up];
1306                    Ok((Int((sum % m) as $t)))
1307                }
1308            }
1309
1310            /// Computes the modulo of `self + other` over `modulus`,
1311            /// unchecked version.
1312            ///
1313            #[doc = "Performs operations internally as [`" $up "`]."]
1314            ///
1315            /// # Features
1316            /// Uses `unsafe_hint` for performance optimizations with upcasted arithmetic.
1317            ///
1318            /// # Panics
1319            /// Panics if `modulus == 0`, and for `u128` it could also panic on overflow.
1320            pub const fn modulo_mul_unchecked(self, other: $t, modulus: $t) -> Int<$t> {
1321                let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
1322                let sum = upcastop![reduce *mul(a, b) % m, $is_up];
1323                Int((sum % m) as $t)
1324            }
1325
1326            /* modulo mul cycles (unsigned) */
1327
1328            /// Computes the modulo of `self + other` over `modulus`,
1329            /// and the number of cycles the result is reduced.
1330            ///
1331            #[doc = "Performs operations internally as [`" $up "`]."]
1332            ///
1333            /// # Features
1334            /// Uses `unsafe_hint` for performance optimizations with upcasted arithmetic.
1335            ///
1336            /// # Errors
1337            /// Returns [`NonZeroRequired`] if `modulus == 0`, and for `u128`
1338            /// it can also return [`Overflow`], more probably than in
1339            /// [`modulo_mul`][Self::modulo_mul] since we can't reduce
1340            /// the operands beforehand in order to calculate *times*.
1341            ///
1342            /// # Examples
1343            /// ```
1344            /// # use devela::{Int, NumResult, NumError};
1345            /// # fn main() -> NumResult<()> {
1346            /// let m = 3;
1347            #[doc = "assert_eq![Int(4_" $t ").modulo_mul_cycles(0, m)?, (0, 0)];"]
1348            #[doc = "assert_eq![Int(4_" $t ").modulo_mul_cycles(1, m)?, (1, 1)];"]
1349            #[doc = "assert_eq![Int(4_" $t ").modulo_mul_cycles(2, m)?, (2, 2)];"]
1350            #[doc = "assert_eq![Int(4_" $t ").modulo_mul_cycles(3, m)?, (0, 4)];"]
1351            #[doc = "assert_eq![Int(4_" $t ").modulo_mul_cycles(4, m)?, (1, 5)];"]
1352            /// # Ok(()) }
1353            /// ```
1354            pub const fn modulo_mul_cycles(self, other: $t, modulus: $t)
1355                -> Result<ValueQuant<Int<$t>, Int<$t>>> {
1356                if modulus == 0 {
1357                    cold_err_zero()
1358                } else {
1359                    let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
1360                    // not reducing for u128 makes overflow more likely,
1361                    // but we can't if we want to calculate `times`.
1362                    let sum = upcastop![err *mul(a, b) $is_up];
1363                    let modulo = Int((sum % m) as $t);
1364                    let times = Int((sum / m) as $t);
1365                    Ok(ValueQuant::new(modulo, times))
1366                }
1367            }
1368
1369            /// Computes the modulo of `self + other` over `modulus`,
1370            /// and the number of cycles the result is reduced,
1371            /// unchecked version.
1372            ///
1373            #[doc = "Performs operations internally as [`" $up "`]."]
1374            ///
1375            /// # Panics
1376            /// Panics if `modulus == 0`, and for `u128` it can also panic on overflow,
1377            /// more probably than in [`modulo_mul_unchecked`][Self::modulo_mul_unchecked]
1378            /// since we can't reduce the operands beforehand in order to calculate *times*.
1379            pub const fn modulo_mul_cycles_unchecked(self, other: $t, modulus: $t)
1380                -> ValueQuant<Int<$t>, Int<$t>> {
1381                let (a, b, m) = (self.0 as $up, other as $up, modulus as $up);
1382                // not reducing for u128 makes overflow more likely,
1383                // but we can't if we want to calculate `times`.
1384                let sum = a + b;
1385                let modulo = Int((sum % m) as $t);
1386                let times = Int((sum / m) as $t);
1387                ValueQuant::new(modulo, times)
1388            }
1389
1390            /* modulo mul inv (unsigned) */
1391
1392            /// Calculates the modular multiplicative inverse.
1393            ///
1394            #[doc = "Performs operations internally as [`" $iup "`]."]
1395            ///
1396            /// The modular multiplicative inverse of *a* modulo *m*
1397            /// is an integer *b* such that $ ab \equiv 1 (\mod m) $.
1398            ///
1399            /// The modular multiplicative inverse exists only if `self` and
1400            /// `modulus` are coprime, meaning their greatest common divisor is 1.
1401            ///
1402            /// # Errors
1403            /// Returns [`NonZeroRequired`] if `modulus == 0`,
1404            /// [`NoInverse`] if there's no inverse,
1405            /// and for `u128` it could return [`Overflow`] when casting
1406            /// in the [`gcd_ext`][Self::gcd_ext] calculation.
1407            ///
1408            /// # Examples
1409            /// ```
1410            /// # use devela::{Int, NumResult, NumError};
1411            /// # fn main() -> NumResult<()> {
1412            /// let m = 5;
1413            #[doc = "assert_eq![Int(0_" $t ").modulo_mul_inv(m), Err(NumError::NoInverse)];"]
1414            #[doc = "assert_eq![Int(1_" $t ").modulo_mul_inv(m)?, 1];"]
1415            #[doc = "assert_eq![Int(2_" $t ").modulo_mul_inv(m)?, 3];"]
1416            #[doc = "assert_eq![Int(3_" $t ").modulo_mul_inv(m)?, 2];"]
1417            #[doc = "assert_eq![Int(4_" $t ").modulo_mul_inv(m)?, 4];"]
1418            /// # Ok(()) }
1419            /// ```
1420            #[cfg(all(feature = $icap, feature = "cast"))]
1421            #[cfg_attr(feature = "nightly_doc", doc(cfg(all(feature = $icap, feature = "cast"))))]
1422            pub const fn modulo_mul_inv(self, modulus: $t) -> Result<Int<$t>> {
1423                if modulus == 0 {
1424                    cold_err_zero()
1425                } else {
1426                    let (gcd, x, _) = unwrap![ok? self.gcd_ext(modulus)].as_tuple_copy();
1427                    if gcd.0 != 1 {
1428                        Err(NoInverse)
1429                    } else {
1430                        Ok(Int((x.0.rem_euclid(modulus as $iup) as $t)))
1431                    }
1432                }
1433            }
1434
1435            /// Calculates the modular multiplicative inverse,
1436            /// unchecked version.
1437            ///
1438            #[doc = "Performs operations internally as [`" $iup "`]."]
1439            ///
1440            /// The modular multiplicative inverse of *a* modulo *m*
1441            /// is an integer *b* such that $ ab \equiv 1 (\mod m) $.
1442            ///
1443            /// The modular multiplicative inverse exists only if `self` and
1444            /// `modulus` are coprime, meaning their greatest common divisor is 1.
1445            ///
1446            /// # Panics
1447            /// Panics if `modulus == 0`, if there's no inverse,
1448            /// and for `u128` it could overflow when casting
1449            /// in the [`gcd_ext`][Self::gcd_ext] calculation.
1450            #[cfg(all(feature = $icap, feature = "cast"))]
1451            #[cfg_attr(feature = "nightly_doc", doc(cfg(all(feature = $icap, feature = "cast"))))]
1452            pub const fn modulo_mul_inv_unchecked(self, modulus: $t) -> Int<$t> {
1453                let (gcd, x, _) = unwrap![ok self.gcd_ext(modulus)].as_tuple_copy();
1454                if gcd.0 != 1 {
1455                    panic!["no inverse"]; // CHECK without checking
1456                } else {
1457                    Int((x.0.rem_euclid(modulus as $iup) as $t))
1458                }
1459            }
1460
1461            /* modulo div (unsigned) */
1462
1463            /// Computes `self / other` over `modulus`.
1464            ///
1465            #[doc = "Performs operations internally as [`" $iup "`]."]
1466            ///
1467            /// $a / b \mod m$ is equivalent to $a * b^{-1} \mod m$,
1468            /// where $b^{-1}$ is the modular multiplicative inverse
1469            /// of $b$ modulo $m$.
1470            /// # Errors
1471            /// Returns [`NonZeroRequired`] if `modulus == 0`,
1472            /// [`NoInverse`] if there's no multiplicative inverse of `other`,
1473            /// and for `u128` it could return [`Overflow`] when casting
1474            /// in the [`gcd_ext`][Self::gcd_ext] calculation.
1475            ///
1476            /// # Examples
1477            /// ```
1478            /// # use devela::{Int, NumResult, NumError};
1479            /// # fn main() -> NumResult<()> {
1480            /// let m = 3;
1481            #[doc = "assert_eq![Int(0_" $t ").modulo_div(2, m)?, 0];"]
1482            #[doc = "assert_eq![Int(1_" $t ").modulo_div(2, m)?, 2];"]
1483            #[doc = "assert_eq![Int(2_" $t ").modulo_div(2, m)?, 1];"]
1484            #[doc = "assert_eq![Int(3_" $t ").modulo_div(2, m)?, 0];"]
1485            #[doc = "assert_eq![Int(4_" $t ").modulo_div(2, m)?, 2];"]
1486            /// # Ok(()) }
1487            /// ```
1488            #[cfg(all(feature = $icap, feature = "cast"))]
1489            #[cfg_attr(feature = "nightly_doc", doc(cfg(all(feature = $icap, feature = "cast"))))]
1490            pub const fn modulo_div(self, other: $t, modulus: $t) -> Result<Int<$t>> {
1491                if modulus == 0 {
1492                    cold_err_zero()
1493                } else {
1494                    let inverse = unwrap![ok? Int(other).modulo_mul_inv(modulus)];
1495                    self.modulo_mul(inverse.0, modulus)
1496                }
1497            }
1498
1499            /// Computes `self / other` over `modulus`,
1500            /// unchecked version.
1501            ///
1502            #[doc = "Performs operations internally as [`" $iup "`]."]
1503            ///
1504            /// # Panics
1505            /// Panics if `modulus == 0`,
1506            /// if there's no multiplicative inverse of `other`.
1507            /// and for `u128` it could overflow when casting
1508            /// in the [`gcd_ext`][Self::gcd_ext] calculation.
1509            #[cfg(all(feature = $icap, feature = "cast"))]
1510            #[cfg_attr(feature = "nightly_doc", doc(cfg(all(feature = $icap, feature = "cast"))))]
1511            pub const fn modulo_div_unchecked(self, other: $t, modulus: $t) -> Int<$t> {
1512                let inverse = Int(other).modulo_mul_inv_unchecked(modulus);
1513                self.modulo_mul_unchecked(inverse.0, modulus)
1514            }
1515        }
1516    }};
1517}
1518impl_modulo!();