crypto_bigint/uint/
concat.rs1use crate::{Concat, Uint};
2
3impl<const LIMBS: usize> Uint<LIMBS> {
4 #[must_use]
7 pub const fn concat<const WIDE_LIMBS: usize>(&self, hi: &Self) -> Uint<WIDE_LIMBS>
8 where
9 Self: Concat<LIMBS, Output = Uint<WIDE_LIMBS>>,
10 {
11 self.concat_resize(hi)
12 }
13
14 #[inline]
17 #[must_use]
18 pub const fn concat_mixed<const HI_LIMBS: usize, const WIDE_LIMBS: usize>(
19 &self,
20 hi: &Uint<HI_LIMBS>,
21 ) -> Uint<WIDE_LIMBS>
22 where
23 Self: Concat<HI_LIMBS, Output = Uint<WIDE_LIMBS>>,
24 {
25 self.concat_resize(hi)
26 }
27
28 #[inline(always)]
32 #[must_use]
33 pub const fn concat_checked<const HI_LIMBS: usize, const WIDE_LIMBS: usize>(
34 &self,
35 hi: &Uint<HI_LIMBS>,
36 ) -> Option<Uint<WIDE_LIMBS>> {
37 if LIMBS + HI_LIMBS == WIDE_LIMBS {
38 Some(self.concat_resize(hi))
39 } else {
40 None
41 }
42 }
43
44 #[inline(always)]
49 #[must_use]
50 pub const fn concat_resize<const HI_LIMBS: usize, const WIDE_LIMBS: usize>(
51 &self,
52 hi: &Uint<HI_LIMBS>,
53 ) -> Uint<WIDE_LIMBS> {
54 let mut res = Uint::ZERO;
55 let len = if LIMBS + HI_LIMBS <= WIDE_LIMBS {
56 LIMBS + HI_LIMBS
57 } else {
58 WIDE_LIMBS
59 };
60 let lo_len = if LIMBS <= len { LIMBS } else { len };
61 let hi_len = len - lo_len;
62 let (res_lo, res_hi) = res.as_mut_uint_ref().split_at_mut(lo_len);
63 res_lo.copy_from(self.as_uint_ref().leading(lo_len));
64 res_hi
65 .leading_mut(hi_len)
66 .copy_from(hi.as_uint_ref().leading(hi_len));
67 res
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use crate::{BitOps, U64, U128, U192, U256, Uint};
74
75 #[test]
76 fn concat() {
77 let hi = U64::from_u64(0x0011223344556677);
78 let lo = U64::from_u64(0x8899aabbccddeeff);
79 assert_eq!(
80 lo.concat(&hi),
81 U128::from_be_hex("00112233445566778899aabbccddeeff")
82 );
83 }
84
85 #[test]
86 fn concat_checked() {
87 let hi = U64::from_u64(0x0011223344556677);
88 let lo = U64::from_u64(0x8899aabbccddeeff);
89 let Some(wide) = lo.concat_checked(&hi) else {
90 panic!("invalid concat")
91 };
92 assert_eq!(wide, U128::from_u128(0x00112233445566778899aabbccddeeff));
93
94 assert!(lo.concat_checked::<{ U64::LIMBS }, 10>(&hi).is_none());
95 }
96
97 #[test]
98 fn concat_resize_small() {
99 let hi = U128::from_u64(0x0011223344556677);
100 let lo = U128::MAX;
101 assert_eq!(lo.concat_resize(&hi), U64::MAX);
102 }
103
104 #[test]
105 fn concat_resize_large() {
106 let hi = U64::from_u64(0x0011223344556677);
107 let lo = U64::from_u64(0x8899aabbccddeeff);
108 assert_eq!(
109 lo.concat_resize(&hi),
110 U256::from_u128(0x00112233445566778899aabbccddeeff)
111 );
112 }
113
114 #[test]
115 fn concat_mixed() {
116 let hi = U64::from_u64(0x0011223344556677);
117 let lo = U128::from_u128(0x8899aabbccddeeff_8899aabbccddeeff);
118 assert_eq!(
119 lo.concat_mixed(&hi),
120 U192::from_be_hex("00112233445566778899aabbccddeeff8899aabbccddeeff")
121 );
122 assert_eq!(
123 hi.concat_mixed(&lo),
124 U192::from_be_hex("8899aabbccddeeff8899aabbccddeeff0011223344556677")
125 );
126 }
127
128 #[test]
129 fn convert() {
130 let res: U128 = U64::ONE.widening_mul(&U64::ONE).into();
131 assert_eq!(res, U128::ONE);
132
133 let res: U128 = U64::ONE.widening_square().into();
134 assert_eq!(res, U128::ONE);
135 }
136
137 #[test]
138 fn infer_sizes() {
139 let wide = U64::ONE.concat(&Uint::ZERO);
140 assert_eq!(wide.bits_precision(), 128);
141 assert_eq!(wide, Uint::ONE);
142
143 let wide = U64::ONE.concat_mixed(&U128::ZERO);
144 assert_eq!(wide.bits_precision(), 192);
145 assert_eq!(wide, Uint::ONE);
146 }
147}