1use crate::core_crypto::prelude::{CastFrom, CastInto, Numeric, SignedNumeric};
2use crate::integer::bigint::static_signed::StaticSignedBigInt;
3use crate::integer::bigint::static_unsigned::StaticUnsignedBigInt;
4use core::ops::{AddAssign, BitAnd, ShlAssign, ShrAssign};
5use std::ops::{BitOrAssign, Not, Shl, Shr, Sub};
6
7pub trait Decomposable:
12 Numeric
13 + BitAnd<Self, Output = Self>
14 + ShrAssign<u32>
15 + Eq
16 + CastFrom<u32>
17 + Shr<u32, Output = Self>
18 + Shl<u32, Output = Self>
19 + BitOrAssign<Self>
20 + Not<Output = Self>
21{
22}
23pub trait Recomposable:
24 Numeric
25 + ShlAssign<u32>
26 + AddAssign<Self>
27 + CastFrom<u32>
28 + BitAnd<Self, Output = Self>
29 + Shl<u32, Output = Self>
30 + Sub<Self, Output = Self>
31{
32 #[must_use]
36 fn recomposable_wrapping_add(self, other: Self) -> Self;
37}
38
39pub trait RecomposableFrom<T>: Recomposable + CastFrom<T> {}
41pub trait DecomposableInto<T>: Decomposable + CastInto<T> {}
42
43macro_rules! impl_recomposable_decomposable {
44 (
45 $($type:ty),* $(,)?
46 ) => {
47 $(
48 impl Decomposable for $type { }
49 impl Recomposable for $type {
50 #[inline]
51 fn recomposable_wrapping_add(self, other: Self) -> Self {
52 self.wrapping_add(other)
53 }
54 }
55 impl RecomposableFrom<u128> for $type { }
56 impl DecomposableInto<u128> for $type { }
57 impl RecomposableFrom<u64> for $type { }
58 impl DecomposableInto<u64> for $type { }
59 impl RecomposableFrom<u8> for $type { }
60 impl DecomposableInto<u8> for $type { }
61 )*
62 };
63}
64
65impl_recomposable_decomposable!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128,);
66
67impl<const N: usize> Decomposable for StaticSignedBigInt<N> {}
68impl<const N: usize> Recomposable for StaticSignedBigInt<N> {
69 #[inline]
70 fn recomposable_wrapping_add(mut self, other: Self) -> Self {
71 self.add_assign(other);
72 self
73 }
74}
75impl<const N: usize> RecomposableFrom<u128> for StaticSignedBigInt<N> {}
76impl<const N: usize> RecomposableFrom<u64> for StaticSignedBigInt<N> {}
77impl<const N: usize> RecomposableFrom<u8> for StaticSignedBigInt<N> {}
78impl<const N: usize> DecomposableInto<u128> for StaticSignedBigInt<N> {}
79impl<const N: usize> DecomposableInto<u64> for StaticSignedBigInt<N> {}
80impl<const N: usize> DecomposableInto<u8> for StaticSignedBigInt<N> {}
81
82impl<const N: usize> Decomposable for StaticUnsignedBigInt<N> {}
83impl<const N: usize> Recomposable for StaticUnsignedBigInt<N> {
84 #[inline]
85 fn recomposable_wrapping_add(mut self, other: Self) -> Self {
86 self.add_assign(other);
87 self
88 }
89}
90impl<const N: usize> RecomposableFrom<u128> for StaticUnsignedBigInt<N> {}
91impl<const N: usize> RecomposableFrom<u64> for StaticUnsignedBigInt<N> {}
92impl<const N: usize> RecomposableFrom<u8> for StaticUnsignedBigInt<N> {}
93impl<const N: usize> DecomposableInto<u128> for StaticUnsignedBigInt<N> {}
94impl<const N: usize> DecomposableInto<u64> for StaticUnsignedBigInt<N> {}
95impl<const N: usize> DecomposableInto<u8> for StaticUnsignedBigInt<N> {}
96
97pub trait RecomposableSignedInteger:
98 RecomposableFrom<u64>
99 + std::ops::Neg<Output = Self>
100 + std::ops::Shr<u32, Output = Self>
101 + std::ops::BitOrAssign<Self>
102 + std::ops::BitOr<Self, Output = Self>
103 + std::ops::Mul<Self, Output = Self>
104 + SignedNumeric
105{
106}
107
108impl RecomposableSignedInteger for i8 {}
109impl RecomposableSignedInteger for i16 {}
110impl RecomposableSignedInteger for i32 {}
111impl RecomposableSignedInteger for i64 {}
112impl RecomposableSignedInteger for i128 {}
113
114impl<const N: usize> RecomposableSignedInteger for StaticSignedBigInt<N> {}
115
116pub trait SignExtendable:
117 std::ops::Shl<u32, Output = Self> + std::ops::Shr<u32, Output = Self> + SignedNumeric
118{
119}
120
121impl<T> SignExtendable for T where T: RecomposableSignedInteger {}
122
123pub(in crate::integer) fn sign_extend_partial_number<T>(unpadded_value: T, num_bits_set: u32) -> T
134where
135 T: SignExtendable,
136{
137 if num_bits_set >= T::BITS as u32 {
138 return unpadded_value;
139 }
140
141 let shift = T::BITS as u32 - num_bits_set;
144 (unpadded_value << shift) >> shift
145}
146
147#[derive(Copy, Clone)]
148#[repr(u32)]
149pub enum PaddingBitValue {
150 Zero = 0,
151 One = 1,
152}
153
154#[derive(Clone)]
155pub struct BlockDecomposer<T> {
156 data: T,
157 bit_mask: T,
158 num_bits_in_mask: u32,
159 num_bits_valid: u32,
160 padding_bit: Option<PaddingBitValue>,
161 limit: Option<T>,
162}
163
164impl<T> BlockDecomposer<T>
165where
166 T: Decomposable,
167{
168 pub fn with_early_stop_at_zero(value: T, bits_per_block: u32) -> Self {
170 Self::new_(value, bits_per_block, Some(T::ZERO), None)
171 }
172
173 pub fn with_padding_bit(value: T, bits_per_block: u32, padding_bit: PaddingBitValue) -> Self {
176 Self::new_(value, bits_per_block, None, Some(padding_bit))
177 }
178
179 pub fn with_block_count(value: T, bits_per_block: u32, block_count: usize) -> Self {
183 let mut decomposer = Self::new(value, bits_per_block);
184 let block_count: u32 = block_count.try_into().unwrap();
185 let num_bits_valid = block_count * bits_per_block;
191 decomposer.num_bits_valid = num_bits_valid;
192 decomposer
193 }
194
195 pub fn new(value: T, bits_per_block: u32) -> Self {
196 Self::new_(value, bits_per_block, None, None)
197 }
198
199 fn new_(
200 value: T,
201 bits_per_block: u32,
202 limit: Option<T>,
203 padding_bit: Option<PaddingBitValue>,
204 ) -> Self {
205 assert!(bits_per_block <= T::BITS as u32);
206 let num_bits_valid = T::BITS as u32;
207
208 let num_bits_in_mask = bits_per_block;
209 let bit_mask = 1_u32.checked_shl(bits_per_block).unwrap() - 1;
210 let bit_mask = T::cast_from(bit_mask);
211
212 Self {
213 data: value,
214 bit_mask,
215 num_bits_in_mask,
216 num_bits_valid,
217 limit,
218 padding_bit,
219 }
220 }
221
222 pub fn iter_as<V>(self) -> std::iter::Map<Self, fn(T) -> V>
225 where
226 V: Numeric,
227 T: CastInto<V>,
228 {
229 assert!(self.num_bits_in_mask <= V::BITS as u32);
230 self.map(CastInto::cast_into)
231 }
232
233 pub fn next_as<V>(&mut self) -> Option<V>
234 where
235 V: CastFrom<T>,
236 {
237 self.next().map(|masked| V::cast_from(masked))
238 }
239
240 pub fn checked_next_as<V>(&mut self) -> Option<V>
241 where
242 V: TryFrom<T>,
243 {
244 self.next().and_then(|masked| V::try_from(masked).ok())
245 }
246}
247
248impl<T> Iterator for BlockDecomposer<T>
249where
250 T: Decomposable,
251{
252 type Item = T;
253
254 fn next(&mut self) -> Option<Self::Item> {
255 if self.num_bits_valid == 0 {
259 return None;
260 }
261
262 if self.limit.is_some_and(|limit| limit == self.data) {
263 return None;
264 }
265
266 let mut masked = self.data & self.bit_mask;
267
268 if self.num_bits_in_mask < T::BITS as u32 {
269 self.data >>= self.num_bits_in_mask;
270 } else {
271 self.data = T::ZERO;
272 }
273
274 if self.num_bits_valid < self.num_bits_in_mask {
275 if let Some(padding_bit) = self.padding_bit {
281 let padding_mask = (self.bit_mask >> self.num_bits_valid) << self.num_bits_valid;
282 masked = masked & !padding_mask;
283
284 let padding_bit = T::cast_from(padding_bit as u32);
285 for i in self.num_bits_valid..self.num_bits_in_mask {
286 masked |= padding_bit << i;
287 }
288 }
289 }
290
291 self.num_bits_valid = self.num_bits_valid.saturating_sub(self.num_bits_in_mask);
292
293 Some(masked)
294 }
295
296 fn size_hint(&self) -> (usize, Option<usize>) {
297 let max_remaining_iter = self.num_bits_valid / self.num_bits_in_mask;
303 let min_remaining_iter = if max_remaining_iter == 0 { 0 } else { 1 };
304 (min_remaining_iter, Some(max_remaining_iter as usize))
305 }
306}
307
308pub struct BlockRecomposer<T> {
309 data: T,
310 bit_mask: T,
311 num_bits_in_block: u32,
312 bit_pos: u32,
313}
314
315impl<T> BlockRecomposer<T>
316where
317 T: Recomposable,
318{
319 pub fn new(bits_per_block: u32) -> Self {
320 let num_bits_in_block = bits_per_block;
321 let bit_pos = 0;
322 let bit_mask = 1_u32.checked_shl(bits_per_block).unwrap() - 1;
323 let bit_mask = T::cast_from(bit_mask);
324
325 Self {
326 data: T::ZERO,
327 bit_mask,
328 num_bits_in_block,
329 bit_pos,
330 }
331 }
332
333 pub fn value(&self) -> T {
334 let is_signed = (T::ONE << (T::BITS as u32 - 1)) < T::ZERO;
335 if self.bit_pos >= (T::BITS as u32 - u32::from(is_signed)) {
336 self.data
337 } else {
338 let valid_mask = (T::ONE << self.bit_pos) - T::ONE;
339 self.data & valid_mask
340 }
341 }
342
343 pub fn unmasked_value(&self) -> T {
344 self.data
345 }
346
347 pub fn add_unmasked<V>(&mut self, block: V) -> bool
348 where
349 T: CastFrom<V>,
350 {
351 let casted_block = T::cast_from(block);
352 self.add(casted_block)
353 }
354
355 pub fn add_masked<V>(&mut self, block: V) -> bool
356 where
357 T: CastFrom<V>,
358 {
359 if self.bit_pos >= T::BITS as u32 {
360 return false;
361 }
362 let casted_block = T::cast_from(block);
363 self.add(casted_block & self.bit_mask)
364 }
365
366 fn add(&mut self, mut block: T) -> bool {
367 if self.bit_pos >= T::BITS as u32 {
368 return false;
369 }
370
371 block <<= self.bit_pos;
372 self.data = self.data.recomposable_wrapping_add(block);
373 self.bit_pos += self.num_bits_in_block;
374
375 true
376 }
377
378 pub fn recompose_unsigned<U>(input: impl Iterator<Item = U>, bits_in_block: u32) -> T
383 where
384 T: RecomposableFrom<U>,
385 {
386 let mut recomposer = Self::new(bits_in_block);
387 for limb in input {
388 if !recomposer.add_unmasked(limb) {
389 break;
390 }
391 }
392
393 recomposer.value()
394 }
395
396 pub fn recompose_unsigned_with_size<U>(
402 input: impl Iterator<Item = U>,
403 bits_in_block: u32,
404 unsigned_integer_size: u32,
405 ) -> T
406 where
407 T: RecomposableFrom<U>,
408 {
409 let mut recomposer = Self::new(bits_in_block);
410 for limb in input {
411 if !recomposer.add_unmasked(limb) {
412 break;
413 }
414 }
415
416 if T::BITS <= unsigned_integer_size as usize {
417 recomposer.value()
418 } else {
419 let mask = (T::ONE << unsigned_integer_size) - T::ONE;
420 recomposer.value() & mask
421 }
422 }
423
424 pub fn recompose_signed<U>(input: impl Iterator<Item = U>, bits_in_block: u32) -> T
429 where
430 T: RecomposableFrom<U> + SignExtendable,
431 {
432 let mut recomposer = Self::new(bits_in_block);
433 for limb in input {
434 if !recomposer.add_unmasked(limb) {
435 break;
436 }
437 }
438
439 sign_extend_partial_number(recomposer.value(), recomposer.bit_pos)
440 }
441
442 pub fn recompose_signed_with_size<U>(
452 input: impl Iterator<Item = U>,
453 bits_in_block: u32,
454 signed_integer_size: u32,
455 ) -> T
456 where
457 T: RecomposableFrom<U> + SignExtendable,
458 {
459 let mut recomposer = Self::new(bits_in_block);
460 for limb in input {
461 if !recomposer.add_unmasked(limb) {
462 break;
463 }
464 }
465
466 sign_extend_partial_number(recomposer.value(), signed_integer_size)
467 }
468}
469
470#[cfg(test)]
471mod tests {
472
473 use super::*;
474
475 #[test]
476 fn test_bit_block_decomposer() {
477 let value = u16::MAX as u32;
478 let bits_per_block = 2;
479 let blocks = BlockDecomposer::new(value, bits_per_block)
480 .iter_as::<u64>()
481 .collect::<Vec<_>>();
482 let expected_blocks = vec![3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0];
483 assert_eq!(expected_blocks, blocks);
484 }
485
486 #[test]
487 fn test_bit_block_decomposer_3() {
488 let bits_per_block = 3;
489
490 let value = -1i8;
491 let blocks = BlockDecomposer::new(value, bits_per_block)
492 .iter_as::<u64>()
493 .collect::<Vec<_>>();
494 let expected_blocks = vec![7, 7, 7];
496 assert_eq!(expected_blocks, blocks);
497
498 let value = i8::MIN;
499 let blocks = BlockDecomposer::new(value, bits_per_block)
500 .iter_as::<u64>()
501 .collect::<Vec<_>>();
502 let expected_blocks = vec![0, 0, 6];
504 assert_eq!(expected_blocks, blocks);
505
506 let value = -1i8;
507 let blocks =
508 BlockDecomposer::with_padding_bit(value, bits_per_block, PaddingBitValue::Zero)
509 .iter_as::<u64>()
510 .collect::<Vec<_>>();
511 let expected_blocks = vec![7, 7, 3];
513 assert_eq!(expected_blocks, blocks);
514 }
515
516 #[test]
517 fn test_bit_block_decomposer_with_block_count() {
518 let bits_per_block = 3;
519 let expected_blocks = [0, 0, 6, 7, 7, 7, 7, 7, 7];
520 let value = i8::MIN;
521 for block_count in 1..expected_blocks.len() {
522 let blocks = BlockDecomposer::with_block_count(value, bits_per_block, block_count)
523 .iter_as::<u64>()
524 .collect::<Vec<_>>();
525 assert_eq!(expected_blocks[..block_count], blocks);
526 }
527
528 let bits_per_block = 3;
529 let expected_blocks = [7, 7, 1, 0, 0, 0, 0, 0, 0];
530 let value = i8::MAX;
531 for block_count in 1..expected_blocks.len() {
532 let blocks = BlockDecomposer::with_block_count(value, bits_per_block, block_count)
533 .iter_as::<u64>()
534 .collect::<Vec<_>>();
535 assert_eq!(expected_blocks[..block_count], blocks);
536 }
537
538 let bits_per_block = 2;
539 let expected_blocks = [0, 0, 0, 2, 3, 3, 3, 3, 3];
540 let value = i8::MIN;
541 for block_count in 1..expected_blocks.len() {
542 let blocks = BlockDecomposer::with_block_count(value, bits_per_block, block_count)
543 .iter_as::<u64>()
544 .collect::<Vec<_>>();
545 assert_eq!(expected_blocks[..block_count], blocks);
546 }
547
548 let bits_per_block = 2;
549 let expected_blocks = [3, 3, 3, 1, 0, 0, 0, 0, 0, 0];
550 let value = i8::MAX;
551 for block_count in 1..expected_blocks.len() {
552 let blocks = BlockDecomposer::with_block_count(value, bits_per_block, block_count)
553 .iter_as::<u64>()
554 .collect::<Vec<_>>();
555 assert_eq!(expected_blocks[..block_count], blocks);
556 }
557 }
558
559 #[test]
560 fn test_bit_block_decomposer_recomposer_carry_handling_in_between() {
561 let value = u16::MAX as u32;
562 let bits_per_block = 2;
563 let mut blocks = BlockDecomposer::new(value, bits_per_block)
564 .iter_as::<u64>()
565 .collect::<Vec<_>>();
566 let expected_blocks = vec![3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0];
567 assert_eq!(expected_blocks, blocks);
568
569 blocks[0] += 2;
571
572 let mut recomposer = BlockRecomposer::new(bits_per_block);
573 for block in blocks {
574 recomposer.add_unmasked(block);
575 }
576 let recomposed: u32 = recomposer.value();
577 assert_eq!(recomposed, value.wrapping_add(2));
578 }
579
580 #[test]
581 fn test_bit_block_decomposer_recomposer_carry_overflow() {
582 let value = u16::MAX;
583 let bits_per_block = 2;
584 let mut blocks = BlockDecomposer::new(value, bits_per_block)
585 .iter_as::<u64>()
586 .collect::<Vec<_>>();
587 let expected_blocks = vec![3, 3, 3, 3, 3, 3, 3, 3];
588 assert_eq!(expected_blocks, blocks);
589
590 blocks[0] += 2;
592
593 let mut recomposer = BlockRecomposer::new(bits_per_block);
594 for block in blocks {
595 recomposer.add_unmasked(block);
596 }
597 let recomposed: u16 = recomposer.value();
598 assert_eq!(recomposed, value.wrapping_add(2));
599 }
600
601 #[test]
602 fn test_bit_block_decomposer_recomposer_carry_bigger_recomposed_type() {
603 let value = u8::MAX as u16;
607 let bits_per_block = 2;
608 let mut blocks = BlockDecomposer::new(value, bits_per_block)
609 .iter_as::<u64>()
610 .take(4)
611 .collect::<Vec<_>>();
612 let expected_blocks = vec![3, 3, 3, 3];
613 assert_eq!(expected_blocks, blocks);
614
615 blocks[0] += 2;
617
618 let mut recomposer = BlockRecomposer::new(bits_per_block);
619 for block in blocks {
620 recomposer.add_unmasked(block);
621 }
622 let recomposed: u16 = recomposer.value();
623 assert_eq!(recomposed, u8::MAX.wrapping_add(2) as u16);
624 }
625
626 #[test]
627 fn test_bit_block_decomposer_round_trip_unsigned() {
628 for i in 0..u32::BITS {
629 let value = (u16::MAX as u32).rotate_left(i);
630 let bits_per_block = 2;
631 let blocks = BlockDecomposer::new(value, bits_per_block)
632 .iter_as::<u64>()
633 .collect::<Vec<_>>();
634
635 let mut recomposer = BlockRecomposer::new(bits_per_block);
636 for block in blocks {
637 recomposer.add_unmasked(block);
638 }
639 let recomposed: u32 = recomposer.value();
640 assert_eq!(recomposed, value);
641 }
642 }
643
644 #[test]
645 fn test_bit_block_decomposer_round_trip_signed() {
646 for i in 0..i32::BITS {
647 let value = (i16::MAX as i32).rotate_left(i);
648 let bits_per_block = 2;
649 let blocks = BlockDecomposer::new(value, bits_per_block).collect::<Vec<_>>();
650
651 let mut recomposer = BlockRecomposer::new(bits_per_block);
652 for block in blocks {
653 recomposer.add_unmasked(block);
654 }
655 let recomposed: i32 = recomposer.value();
656 assert_eq!(recomposed, value);
657 }
658 }
659
660 #[test]
663 fn test_bit_block_decomposer_round_trip_non_multiple_bits_per_block() {
664 for i in 0..u32::BITS {
665 let value = (u16::MAX as u32).rotate_left(i);
666 let bits_per_block = 3;
667 let blocks = BlockDecomposer::new(value, bits_per_block)
668 .iter_as::<u64>()
669 .collect::<Vec<_>>();
670
671 let mut recomposer = BlockRecomposer::new(bits_per_block);
672 for block in blocks {
673 recomposer.add_unmasked(block);
674 }
675 let recomposed: u32 = recomposer.value();
676 assert_eq!(recomposed, value);
677 }
678 }
679}