crypto_bigint/int/
div.rs

1//! [`Int`] division operations.
2
3use core::ops::{Div, DivAssign, Rem, RemAssign};
4
5use subtle::CtOption;
6
7use crate::{CheckedDiv, ConstChoice, ConstCtOption, Int, NonZero, Uint, Wrapping};
8
9/// Checked division operations.
10impl<const LIMBS: usize> Int<LIMBS> {
11    #[inline]
12    /// Base div_rem operation on dividing [`Int`]s.
13    ///
14    /// Computes the quotient and remainder of `self / rhs`.
15    /// Furthermore, returns the signs of `self` and `rhs`.
16    const fn div_rem_base(
17        &self,
18        rhs: &NonZero<Self>,
19    ) -> (Uint<{ LIMBS }>, Uint<{ LIMBS }>, ConstChoice, ConstChoice) {
20        // Step 1: split operands into signs and magnitudes.
21        let (lhs_mag, lhs_sgn) = self.abs_sign();
22        let (rhs_mag, rhs_sgn) = rhs.abs_sign();
23
24        // Step 2. Divide magnitudes
25        // safe to unwrap since rhs is NonZero.
26        let (quotient, remainder) = lhs_mag.div_rem(&rhs_mag);
27
28        (quotient, remainder, lhs_sgn, rhs_sgn)
29    }
30
31    /// Compute the quotient and remainder of `self / rhs`.
32    ///
33    /// Returns `none` for the quotient when `Int::MIN / Int::MINUS_ONE`; that quotient cannot
34    /// be captured in an `Int`.
35    ///
36    /// Example:
37    /// ```
38    /// use crypto_bigint::{I128, NonZero};
39    /// let (quotient, remainder) = I128::from(8).checked_div_rem(&I128::from(3).to_nz().unwrap());
40    /// assert_eq!(quotient.unwrap(), I128::from(2));
41    /// assert_eq!(remainder, I128::from(2));
42    ///
43    /// let (quotient, remainder) = I128::from(-8).checked_div_rem(&I128::from(3).to_nz().unwrap());
44    /// assert_eq!(quotient.unwrap(), I128::from(-2));
45    /// assert_eq!(remainder, I128::from(-2));
46    ///
47    /// let (quotient, remainder) = I128::from(8).checked_div_rem(&I128::from(-3).to_nz().unwrap());
48    /// assert_eq!(quotient.unwrap(), I128::from(-2));
49    /// assert_eq!(remainder, I128::from(2));
50    ///
51    /// let (quotient, remainder) = I128::from(-8).checked_div_rem(&I128::from(-3).to_nz().unwrap());
52    /// assert_eq!(quotient.unwrap(), I128::from(2));
53    /// assert_eq!(remainder, I128::from(-2));
54    /// ```
55    pub const fn checked_div_rem(&self, rhs: &NonZero<Self>) -> (ConstCtOption<Self>, Self) {
56        let (quotient, remainder, lhs_sgn, rhs_sgn) = self.div_rem_base(rhs);
57        let opposing_signs = lhs_sgn.ne(rhs_sgn);
58        (
59            Self::new_from_abs_sign(quotient, opposing_signs),
60            remainder.as_int().wrapping_neg_if(lhs_sgn), // as_int mapping is safe; remainder < 2^{k-1} by construction.
61        )
62    }
63
64    /// Perform checked division, returning a [`CtOption`] which `is_some` if
65    /// - the `rhs != 0`, and
66    /// - `self != MIN` or `rhs != MINUS_ONE`.
67    ///
68    /// Note: this operation rounds towards zero, truncating any fractional part of the exact result.
69    pub fn checked_div(&self, rhs: &Self) -> CtOption<Self> {
70        NonZero::new(*rhs).and_then(|rhs| self.checked_div_rem(&rhs).0.into())
71    }
72
73    /// Computes `self` % `rhs`, returns the remainder.
74    pub const fn rem(&self, rhs: &NonZero<Self>) -> Self {
75        self.checked_div_rem(rhs).1
76    }
77}
78
79/// Vartime checked division operations.
80impl<const LIMBS: usize> Int<LIMBS> {
81    #[inline]
82    /// Variable time equivalent of [Self::div_rem_base]
83    ///
84    /// This is variable only with respect to `rhs`.
85    ///
86    /// When used with a fixed `rhs`, this function is constant-time with respect
87    /// to `self`.
88    const fn div_rem_base_vartime<const RHS_LIMBS: usize>(
89        &self,
90        rhs: &NonZero<Int<RHS_LIMBS>>,
91    ) -> (Uint<LIMBS>, Uint<RHS_LIMBS>, ConstChoice, ConstChoice) {
92        // Step 1: split operands into signs and magnitudes.
93        let (lhs_mag, lhs_sgn) = self.abs_sign();
94        let (rhs_mag, rhs_sgn) = rhs.abs_sign();
95
96        // Step 2. Divide magnitudes
97        // safe to unwrap since rhs is NonZero.
98        let (quotient, remainder) = lhs_mag.div_rem_vartime(&rhs_mag);
99
100        (quotient, remainder, lhs_sgn, rhs_sgn)
101    }
102
103    /// Variable time equivalent of [Self::checked_div_rem]
104    ///
105    /// This is variable only with respect to `rhs`.
106    ///
107    /// When used with a fixed `rhs`, this function is constant-time with respect
108    /// to `self`.
109    pub const fn checked_div_rem_vartime<const RHS_LIMBS: usize>(
110        &self,
111        rhs: &NonZero<Int<RHS_LIMBS>>,
112    ) -> (ConstCtOption<Self>, Int<RHS_LIMBS>) {
113        let (quotient, remainder, lhs_sgn, rhs_sgn) = self.div_rem_base_vartime(rhs);
114        let opposing_signs = lhs_sgn.ne(rhs_sgn);
115        (
116            Self::new_from_abs_sign(quotient, opposing_signs),
117            remainder.as_int().wrapping_neg_if(lhs_sgn), // as_int mapping is safe; remainder < 2^{k-1} by construction.
118        )
119    }
120
121    /// Variable time equivalent of [Self::checked_div]
122    ///
123    /// This is variable only with respect to `rhs`.
124    ///
125    /// When used with a fixed `rhs`, this function is constant-time with respect
126    /// to `self`.
127    pub fn checked_div_vartime<const RHS_LIMBS: usize>(
128        &self,
129        rhs: &Int<RHS_LIMBS>,
130    ) -> CtOption<Self> {
131        NonZero::new(*rhs).and_then(|rhs| self.checked_div_rem_vartime(&rhs).0.into())
132    }
133
134    /// Variable time equivalent of [Self::rem]
135    ///
136    /// This is variable only with respect to `rhs`.
137    ///
138    /// When used with a fixed `rhs`, this function is constant-time with respect
139    /// to `self`.
140    pub const fn rem_vartime<const RHS_LIMBS: usize>(
141        &self,
142        rhs: &NonZero<Int<RHS_LIMBS>>,
143    ) -> Int<RHS_LIMBS> {
144        self.checked_div_rem_vartime(rhs).1
145    }
146}
147
148/// Vartime checked div-floor operations.
149impl<const LIMBS: usize> Int<LIMBS> {
150    /// Variable time equivalent of [Self::checked_div_rem_floor]
151    ///
152    /// This is variable only with respect to `rhs`.
153    ///
154    /// When used with a fixed `rhs`, this function is constant-time with respect
155    /// to `self`.
156    pub const fn checked_div_rem_floor_vartime<const RHS_LIMBS: usize>(
157        &self,
158        rhs: &NonZero<Int<RHS_LIMBS>>,
159    ) -> (ConstCtOption<Self>, Int<RHS_LIMBS>) {
160        let (lhs_mag, lhs_sgn) = self.abs_sign();
161        let (rhs_mag, rhs_sgn) = rhs.abs_sign();
162        let (quotient, remainder) = lhs_mag.div_rem_vartime(&rhs_mag);
163
164        // Modify quotient and remainder when lhs and rhs have opposing signs and the remainder is
165        // non-zero.
166        let opposing_signs = lhs_sgn.xor(rhs_sgn);
167        let modify = remainder.is_nonzero().and(opposing_signs);
168
169        // Increase the quotient by one.
170        let quotient_plus_one = quotient.wrapping_add(&Uint::ONE); // cannot wrap.
171        let quotient = Uint::select(&quotient, &quotient_plus_one, modify);
172
173        // Invert the remainder.
174        let inv_remainder = rhs_mag.0.wrapping_sub(&remainder);
175        let remainder = Uint::select(&remainder, &inv_remainder, modify);
176
177        // Negate output when lhs and rhs have opposing signs.
178        let quotient = Int::new_from_abs_sign(quotient, opposing_signs);
179        let remainder = remainder.as_int().wrapping_neg_if(opposing_signs); // rem always small enough for safe as_int conversion
180
181        (quotient, remainder)
182    }
183
184    /// Variable time equivalent of [Self::checked_div_floor]
185    ///
186    /// This is variable only with respect to `rhs`.
187    ///
188    /// When used with a fixed `rhs`, this function is constant-time with respect
189    /// to `self`.
190    pub fn checked_div_floor_vartime<const RHS_LIMBS: usize>(
191        &self,
192        rhs: &Int<RHS_LIMBS>,
193    ) -> CtOption<Self> {
194        NonZero::new(*rhs).and_then(|rhs| self.checked_div_rem_floor_vartime(&rhs).0.into())
195    }
196}
197
198/// Checked div-floor operations.
199impl<const LIMBS: usize> Int<LIMBS> {
200    /// Perform checked floored division, returning a [`ConstCtOption`] which `is_some` only if
201    /// - the `rhs != 0`, and
202    /// - `self != MIN` or `rhs != MINUS_ONE`.
203    ///
204    /// Note: this operation rounds down.
205    ///
206    /// Example:
207    /// ```
208    /// use crypto_bigint::I128;
209    /// assert_eq!(
210    ///     I128::from(8).checked_div_floor(&I128::from(3)).unwrap(),
211    ///     I128::from(2)
212    /// );
213    /// assert_eq!(
214    ///     I128::from(-8).checked_div_floor(&I128::from(3)).unwrap(),
215    ///     I128::from(-3)
216    /// );
217    /// assert_eq!(
218    ///     I128::from(8).checked_div_floor(&I128::from(-3)).unwrap(),
219    ///     I128::from(-3)
220    /// );
221    /// assert_eq!(
222    ///     I128::from(-8).checked_div_floor(&I128::from(-3)).unwrap(),
223    ///     I128::from(2)
224    /// )
225    /// ```
226    pub fn checked_div_floor(&self, rhs: &Self) -> CtOption<Self> {
227        NonZero::new(*rhs).and_then(|rhs| self.checked_div_rem_floor(&rhs).0.into())
228    }
229
230    /// Perform checked division and mod, returning the quotient and remainder.
231    ///
232    /// The quotient is a [`ConstCtOption`] which `is_some` only if
233    /// - the `rhs != 0`, and
234    /// - `self != MIN` or `rhs != MINUS_ONE`.
235    ///
236    /// Note: this operation rounds down.
237    ///
238    /// Example:
239    /// ```
240    /// use crypto_bigint::I128;
241    ///
242    /// let three = I128::from(3).to_nz().unwrap();
243    /// let (quotient, remainder) = I128::from(8).checked_div_rem_floor(&three);
244    /// assert_eq!(quotient.unwrap(), I128::from(2));
245    /// assert_eq!(remainder, I128::from(2));
246    ///
247    /// let (quotient, remainder) = I128::from(-8).checked_div_rem_floor(&three);
248    /// assert_eq!(quotient.unwrap(), I128::from(-3));
249    /// assert_eq!(remainder, I128::from(-1));
250    ///
251    /// let minus_three = I128::from(-3).to_nz().unwrap();
252    /// let (quotient, remainder) = I128::from(8).checked_div_rem_floor(&minus_three);
253    /// assert_eq!(quotient.unwrap(), I128::from(-3));
254    /// assert_eq!(remainder, I128::from(-1));
255    ///
256    /// let (quotient, remainder) = I128::from(-8).checked_div_rem_floor(&minus_three);
257    /// assert_eq!(quotient.unwrap(), I128::from(2));
258    /// assert_eq!(remainder, I128::from(2));
259    /// ```
260    pub const fn checked_div_rem_floor(&self, rhs: &NonZero<Self>) -> (ConstCtOption<Self>, Self) {
261        let (lhs_mag, lhs_sgn) = self.abs_sign();
262        let (rhs_mag, rhs_sgn) = rhs.abs_sign();
263        let (quotient, remainder) = lhs_mag.div_rem(&rhs_mag);
264
265        // Modify quotient and remainder when lhs and rhs have opposing signs and the remainder is
266        // non-zero.
267        let opposing_signs = lhs_sgn.xor(rhs_sgn);
268        let modify = remainder.is_nonzero().and(opposing_signs);
269
270        // Increase the quotient by one.
271        let quotient_plus_one = quotient.wrapping_add(&Uint::ONE); // cannot wrap.
272        let quotient = Uint::select(&quotient, &quotient_plus_one, modify);
273
274        // Invert the remainder.
275        let inv_remainder = rhs_mag.0.wrapping_sub(&remainder);
276        let remainder = Uint::select(&remainder, &inv_remainder, modify);
277
278        // Negate output when lhs and rhs have opposing signs.
279        let quotient = Int::new_from_abs_sign(quotient, opposing_signs);
280        let remainder = remainder.as_int().wrapping_neg_if(opposing_signs); // rem always small enough for safe as_int conversion
281
282        (quotient, remainder)
283    }
284}
285
286impl<const LIMBS: usize> CheckedDiv for Int<LIMBS> {
287    fn checked_div(&self, rhs: &Int<LIMBS>) -> CtOption<Self> {
288        self.checked_div(rhs)
289    }
290}
291
292impl<const LIMBS: usize> Div<&NonZero<Int<LIMBS>>> for &Int<LIMBS> {
293    type Output = CtOption<Int<LIMBS>>;
294
295    fn div(self, rhs: &NonZero<Int<LIMBS>>) -> Self::Output {
296        *self / *rhs
297    }
298}
299
300impl<const LIMBS: usize> Div<&NonZero<Int<LIMBS>>> for Int<LIMBS> {
301    type Output = CtOption<Int<LIMBS>>;
302
303    fn div(self, rhs: &NonZero<Int<LIMBS>>) -> Self::Output {
304        self / *rhs
305    }
306}
307
308impl<const LIMBS: usize> Div<NonZero<Int<LIMBS>>> for &Int<LIMBS> {
309    type Output = CtOption<Int<LIMBS>>;
310
311    fn div(self, rhs: NonZero<Int<LIMBS>>) -> Self::Output {
312        *self / rhs
313    }
314}
315
316impl<const LIMBS: usize> Div<NonZero<Int<LIMBS>>> for Int<LIMBS> {
317    type Output = CtOption<Int<LIMBS>>;
318
319    fn div(self, rhs: NonZero<Int<LIMBS>>) -> Self::Output {
320        self.checked_div(&rhs)
321    }
322}
323
324impl<const LIMBS: usize> DivAssign<&NonZero<Int<LIMBS>>> for Int<LIMBS> {
325    fn div_assign(&mut self, rhs: &NonZero<Int<LIMBS>>) {
326        *self /= *rhs
327    }
328}
329
330impl<const LIMBS: usize> DivAssign<NonZero<Int<LIMBS>>> for Int<LIMBS> {
331    fn div_assign(&mut self, rhs: NonZero<Int<LIMBS>>) {
332        *self = (*self / rhs).expect("cannot represent positive equivalent of Int::MIN as int");
333    }
334}
335
336impl<const LIMBS: usize> Div<NonZero<Int<LIMBS>>> for Wrapping<Int<LIMBS>> {
337    type Output = Wrapping<Int<LIMBS>>;
338
339    fn div(self, rhs: NonZero<Int<LIMBS>>) -> Self::Output {
340        Wrapping((self.0 / rhs).expect("cannot represent positive equivalent of Int::MIN as int"))
341    }
342}
343
344impl<const LIMBS: usize> Div<NonZero<Int<LIMBS>>> for &Wrapping<Int<LIMBS>> {
345    type Output = Wrapping<Int<LIMBS>>;
346
347    fn div(self, rhs: NonZero<Int<LIMBS>>) -> Self::Output {
348        *self / rhs
349    }
350}
351
352impl<const LIMBS: usize> Div<&NonZero<Int<LIMBS>>> for &Wrapping<Int<LIMBS>> {
353    type Output = Wrapping<Int<LIMBS>>;
354
355    fn div(self, rhs: &NonZero<Int<LIMBS>>) -> Self::Output {
356        *self / *rhs
357    }
358}
359
360impl<const LIMBS: usize> Div<&NonZero<Int<LIMBS>>> for Wrapping<Int<LIMBS>> {
361    type Output = Wrapping<Int<LIMBS>>;
362
363    fn div(self, rhs: &NonZero<Int<LIMBS>>) -> Self::Output {
364        self / *rhs
365    }
366}
367
368impl<const LIMBS: usize> DivAssign<&NonZero<Int<LIMBS>>> for Wrapping<Int<LIMBS>> {
369    fn div_assign(&mut self, rhs: &NonZero<Int<LIMBS>>) {
370        *self = Wrapping(
371            (self.0 / rhs).expect("cannot represent positive equivalent of Int::MIN as int"),
372        );
373    }
374}
375
376impl<const LIMBS: usize> DivAssign<NonZero<Int<LIMBS>>> for Wrapping<Int<LIMBS>> {
377    fn div_assign(&mut self, rhs: NonZero<Int<LIMBS>>) {
378        *self /= &rhs;
379    }
380}
381
382impl<const LIMBS: usize> Rem<&NonZero<Int<LIMBS>>> for &Int<LIMBS> {
383    type Output = Int<LIMBS>;
384
385    fn rem(self, rhs: &NonZero<Int<LIMBS>>) -> Self::Output {
386        *self % *rhs
387    }
388}
389
390impl<const LIMBS: usize> Rem<&NonZero<Int<LIMBS>>> for Int<LIMBS> {
391    type Output = Int<LIMBS>;
392
393    fn rem(self, rhs: &NonZero<Int<LIMBS>>) -> Self::Output {
394        self % *rhs
395    }
396}
397
398impl<const LIMBS: usize> Rem<NonZero<Int<LIMBS>>> for &Int<LIMBS> {
399    type Output = Int<LIMBS>;
400
401    fn rem(self, rhs: NonZero<Int<LIMBS>>) -> Self::Output {
402        *self % rhs
403    }
404}
405
406impl<const LIMBS: usize> Rem<NonZero<Int<LIMBS>>> for Int<LIMBS> {
407    type Output = Int<LIMBS>;
408
409    fn rem(self, rhs: NonZero<Int<LIMBS>>) -> Self::Output {
410        Self::rem(&self, &rhs)
411    }
412}
413
414impl<const LIMBS: usize> RemAssign<&NonZero<Int<LIMBS>>> for Int<LIMBS> {
415    fn rem_assign(&mut self, rhs: &NonZero<Int<LIMBS>>) {
416        *self %= *rhs
417    }
418}
419
420impl<const LIMBS: usize> RemAssign<NonZero<Int<LIMBS>>> for Int<LIMBS> {
421    fn rem_assign(&mut self, rhs: NonZero<Int<LIMBS>>) {
422        *self = *self % rhs;
423    }
424}
425
426impl<const LIMBS: usize> Rem<NonZero<Int<LIMBS>>> for Wrapping<Int<LIMBS>> {
427    type Output = Wrapping<Int<LIMBS>>;
428
429    fn rem(self, rhs: NonZero<Int<LIMBS>>) -> Self::Output {
430        Wrapping(self.0 % rhs)
431    }
432}
433
434impl<const LIMBS: usize> Rem<NonZero<Int<LIMBS>>> for &Wrapping<Int<LIMBS>> {
435    type Output = Wrapping<Int<LIMBS>>;
436
437    fn rem(self, rhs: NonZero<Int<LIMBS>>) -> Self::Output {
438        *self % rhs
439    }
440}
441
442impl<const LIMBS: usize> Rem<&NonZero<Int<LIMBS>>> for &Wrapping<Int<LIMBS>> {
443    type Output = Wrapping<Int<LIMBS>>;
444
445    fn rem(self, rhs: &NonZero<Int<LIMBS>>) -> Self::Output {
446        *self % *rhs
447    }
448}
449
450impl<const LIMBS: usize> Rem<&NonZero<Int<LIMBS>>> for Wrapping<Int<LIMBS>> {
451    type Output = Wrapping<Int<LIMBS>>;
452
453    fn rem(self, rhs: &NonZero<Int<LIMBS>>) -> Self::Output {
454        self % *rhs
455    }
456}
457
458impl<const LIMBS: usize> RemAssign<NonZero<Int<LIMBS>>> for Wrapping<Int<LIMBS>> {
459    fn rem_assign(&mut self, rhs: NonZero<Int<LIMBS>>) {
460        *self %= &rhs;
461    }
462}
463
464impl<const LIMBS: usize> RemAssign<&NonZero<Int<LIMBS>>> for Wrapping<Int<LIMBS>> {
465    fn rem_assign(&mut self, rhs: &NonZero<Int<LIMBS>>) {
466        *self = Wrapping(self.0 % rhs)
467    }
468}
469
470#[cfg(test)]
471mod tests {
472    use crate::{ConstChoice, Int, I128};
473
474    #[test]
475    fn test_checked_div() {
476        let min_plus_one = Int {
477            0: I128::MIN.0.wrapping_add(&I128::ONE.0),
478        };
479
480        // lhs = min
481
482        let result = I128::MIN.checked_div(&I128::MIN);
483        assert_eq!(result.unwrap(), I128::ONE);
484
485        let result = I128::MIN.checked_div(&I128::MINUS_ONE);
486        assert!(bool::from(result.is_none()));
487
488        let result = I128::MIN.checked_div(&I128::ZERO);
489        assert!(bool::from(result.is_none()));
490
491        let result = I128::MIN.checked_div(&I128::ONE);
492        assert_eq!(result.unwrap(), I128::MIN);
493
494        let result = I128::MIN.checked_div(&I128::MAX);
495        assert_eq!(result.unwrap(), I128::MINUS_ONE);
496
497        // lhs = -1
498
499        let result = I128::MINUS_ONE.checked_div(&I128::MIN);
500        assert_eq!(result.unwrap(), I128::ZERO);
501
502        let result = I128::MINUS_ONE.checked_div(&I128::MINUS_ONE);
503        assert_eq!(result.unwrap(), I128::ONE);
504
505        let result = I128::MINUS_ONE.checked_div(&I128::ZERO);
506        assert!(bool::from(result.is_none()));
507
508        let result = I128::MINUS_ONE.checked_div(&I128::ONE);
509        assert_eq!(result.unwrap(), I128::MINUS_ONE);
510
511        let result = I128::MINUS_ONE.checked_div(&I128::MAX);
512        assert_eq!(result.unwrap(), I128::ZERO);
513
514        // lhs = 0
515
516        let result = I128::ZERO.checked_div(&I128::MIN);
517        assert_eq!(result.unwrap(), I128::ZERO);
518
519        let result = I128::ZERO.checked_div(&I128::MINUS_ONE);
520        assert_eq!(result.unwrap(), I128::ZERO);
521
522        let result = I128::ZERO.checked_div(&I128::ZERO);
523        assert!(bool::from(result.is_none()));
524
525        let result = I128::ZERO.checked_div(&I128::ONE);
526        assert_eq!(result.unwrap(), I128::ZERO);
527
528        let result = I128::ZERO.checked_div(&I128::MAX);
529        assert_eq!(result.unwrap(), I128::ZERO);
530
531        // lhs = 1
532
533        let result = I128::ONE.checked_div(&I128::MIN);
534        assert_eq!(result.unwrap(), I128::ZERO);
535
536        let result = I128::ONE.checked_div(&I128::MINUS_ONE);
537        assert_eq!(result.unwrap(), I128::MINUS_ONE);
538
539        let result = I128::ONE.checked_div(&I128::ZERO);
540        assert!(bool::from(result.is_none()));
541
542        let result = I128::ONE.checked_div(&I128::ONE);
543        assert_eq!(result.unwrap(), I128::ONE);
544
545        let result = I128::ONE.checked_div(&I128::MAX);
546        assert_eq!(result.unwrap(), I128::ZERO);
547
548        // lhs = max
549
550        let result = I128::MAX.checked_div(&I128::MIN);
551        assert_eq!(result.unwrap(), I128::ZERO);
552
553        let result = I128::MAX.checked_div(&I128::MINUS_ONE);
554        assert_eq!(result.unwrap(), min_plus_one);
555
556        let result = I128::MAX.checked_div(&I128::ZERO);
557        assert!(bool::from(result.is_none()));
558
559        let result = I128::MAX.checked_div(&I128::ONE);
560        assert_eq!(result.unwrap(), I128::MAX);
561
562        let result = I128::MAX.checked_div(&I128::MAX);
563        assert_eq!(result.unwrap(), I128::ONE);
564    }
565
566    #[test]
567    fn test_checked_div_floor() {
568        assert_eq!(
569            I128::from(8).checked_div_floor(&I128::from(3)).unwrap(),
570            I128::from(2)
571        );
572        assert_eq!(
573            I128::from(-8).checked_div_floor(&I128::from(3)).unwrap(),
574            I128::from(-3)
575        );
576        assert_eq!(
577            I128::from(8).checked_div_floor(&I128::from(-3)).unwrap(),
578            I128::from(-3)
579        );
580        assert_eq!(
581            I128::from(-8).checked_div_floor(&I128::from(-3)).unwrap(),
582            I128::from(2)
583        );
584    }
585
586    #[test]
587    fn test_checked_div_mod_floor() {
588        let (quotient, remainder) =
589            I128::MIN.checked_div_rem_floor(&I128::MINUS_ONE.to_nz().unwrap());
590        assert_eq!(quotient.is_some(), ConstChoice::FALSE);
591        assert_eq!(remainder, I128::ZERO);
592    }
593}