crypto_bigint/uint/
lcm.rs1use crate::{Concat, NonZero, Uint};
4
5impl<const LIMBS: usize> Uint<LIMBS> {
6 #[must_use]
8 pub const fn lcm<const WIDE_LIMBS: usize>(&self, rhs: &Self) -> Uint<WIDE_LIMBS>
9 where
10 Self: Concat<LIMBS, Output = Uint<WIDE_LIMBS>>,
11 {
12 let self_is_nz = self.is_nonzero();
13 let rhs_is_nz = rhs.is_nonzero();
14
15 let gcd_nz = NonZero(self.gcd(&Uint::select(&Uint::ONE, rhs, rhs_is_nz)));
16
17 let lcm = self.wrapping_div(&gcd_nz).concatenating_mul(rhs);
18
19 Uint::select(&Uint::ZERO, &lcm, self_is_nz.and(rhs_is_nz))
20 }
21}
22
23#[cfg(test)]
24mod tests {
25 mod lcm {
26 use crate::{Concat, U64, U128, U256, U512, U1024, U2048, U4096, U8192, Uint};
27
28 fn test<const LIMBS: usize, const WIDE_LIMBS: usize>(
29 lhs: Uint<LIMBS>,
30 rhs: Uint<LIMBS>,
31 target: Uint<WIDE_LIMBS>,
32 ) where
33 Uint<LIMBS>: Concat<LIMBS, Output = Uint<WIDE_LIMBS>>,
34 {
35 assert_eq!(lhs.lcm(&rhs), target);
36 }
37
38 fn run_tests<const LIMBS: usize, const WIDE_LIMBS: usize>()
39 where
40 Uint<LIMBS>: Concat<LIMBS, Output = Uint<WIDE_LIMBS>>,
41 {
42 test(Uint::<LIMBS>::ZERO, Uint::ZERO, Uint::<WIDE_LIMBS>::ZERO);
43 test(Uint::<LIMBS>::ZERO, Uint::ONE, Uint::<WIDE_LIMBS>::ZERO);
44 test(Uint::<LIMBS>::ZERO, Uint::MAX, Uint::<WIDE_LIMBS>::ZERO);
45 test(Uint::<LIMBS>::ONE, Uint::ZERO, Uint::<WIDE_LIMBS>::ZERO);
46 test(Uint::<LIMBS>::ONE, Uint::ONE, Uint::<WIDE_LIMBS>::ONE);
47 test(
48 Uint::<LIMBS>::ONE,
49 Uint::MAX,
50 Uint::<LIMBS>::MAX.resize::<WIDE_LIMBS>(),
51 );
52 test(Uint::<LIMBS>::MAX, Uint::ZERO, Uint::<WIDE_LIMBS>::ZERO);
53 test(
54 Uint::<LIMBS>::MAX,
55 Uint::ONE,
56 Uint::<LIMBS>::MAX.resize::<WIDE_LIMBS>(),
57 );
58 test(
59 Uint::<LIMBS>::MAX,
60 Uint::MAX,
61 Uint::<LIMBS>::MAX.resize::<WIDE_LIMBS>(),
62 );
63 }
64
65 #[test]
66 fn lcm_sizes() {
67 run_tests::<{ U64::LIMBS }, { U128::LIMBS }>();
68 run_tests::<{ U128::LIMBS }, { U256::LIMBS }>();
69 run_tests::<{ U256::LIMBS }, { U512::LIMBS }>();
70 run_tests::<{ U512::LIMBS }, { U1024::LIMBS }>();
71 if cfg!(not(miri)) {
72 run_tests::<{ U1024::LIMBS }, { U2048::LIMBS }>();
73 run_tests::<{ U2048::LIMBS }, { U4096::LIMBS }>();
74 run_tests::<{ U4096::LIMBS }, { U8192::LIMBS }>();
75 }
76 }
77 }
78}