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!();