Skip to main content

fixed_bigint/heapless/
bitwise.rs

1//! `BitAnd` / `BitOr` for `HeaplessBigInt` (all four receiver forms each).
2//!
3//! Limb-wise, width-based, `CAP` never enters:
4//! - `BitAnd` → `len = min(a.len, b.len)`: at or above that bound one
5//!   operand is in its zero-tail, so the AND is zero — `min` is
6//!   value-tight and satisfies the zero-tail invariant.
7//! - `BitOr` → `len = max(a.len, b.len)`: OR *sets* bits, so the result
8//!   spans the wider operand; the shorter operand's zero-tail leaves the
9//!   wider operand's limbs unchanged there.
10//!
11//! Both lens are public shape parameters, so the body is identical for
12//! Nct and Ct. `BitAnd` serves Montgomery's `from_montgomery` mask;
13//! `BitOr` serves the sign path's blinding-inverse (`InvertCt`).
14//! `BitXor` is omitted — no consumer needs it.
15
16use super::{HeaplessBigInt, zero};
17use crate::MachineWord;
18use const_num_traits::Personality;
19use core::marker::PhantomData;
20use core::ops::{BitAnd, BitOr};
21
22// Core: `&Self & &Self`. The value + mixed receiver forms delegate here.
23impl<T: MachineWord, const CAP: usize, P: Personality> BitAnd<&HeaplessBigInt<T, CAP, P>>
24    for &HeaplessBigInt<T, CAP, P>
25{
26    type Output = HeaplessBigInt<T, CAP, P>;
27    fn bitand(self, other: &HeaplessBigInt<T, CAP, P>) -> Self::Output {
28        let out_len = core::cmp::min(self.len, other.len);
29        let mut limbs = [zero::<T>(); CAP];
30        let mut i = 0;
31        while i < out_len as usize {
32            limbs[i] = self.limbs[i] & other.limbs[i];
33            i += 1;
34        }
35        HeaplessBigInt {
36            limbs,
37            len: out_len,
38            _p: PhantomData,
39        }
40    }
41}
42
43impl<T: MachineWord, const CAP: usize, P: Personality> BitAnd for HeaplessBigInt<T, CAP, P> {
44    type Output = Self;
45    fn bitand(self, other: Self) -> Self {
46        (&self).bitand(&other)
47    }
48}
49
50impl<T: MachineWord, const CAP: usize, P: Personality> BitAnd<&HeaplessBigInt<T, CAP, P>>
51    for HeaplessBigInt<T, CAP, P>
52{
53    type Output = Self;
54    fn bitand(self, other: &Self) -> Self {
55        (&self).bitand(other)
56    }
57}
58
59impl<T: MachineWord, const CAP: usize, P: Personality> BitAnd<HeaplessBigInt<T, CAP, P>>
60    for &HeaplessBigInt<T, CAP, P>
61{
62    type Output = HeaplessBigInt<T, CAP, P>;
63    fn bitand(self, other: HeaplessBigInt<T, CAP, P>) -> Self::Output {
64        self.bitand(&other)
65    }
66}
67
68// Core: `&Self | &Self`. The value + mixed receiver forms delegate here.
69impl<T: MachineWord, const CAP: usize, P: Personality> BitOr<&HeaplessBigInt<T, CAP, P>>
70    for &HeaplessBigInt<T, CAP, P>
71{
72    type Output = HeaplessBigInt<T, CAP, P>;
73    fn bitor(self, other: &HeaplessBigInt<T, CAP, P>) -> Self::Output {
74        let out_len = core::cmp::max(self.len, other.len);
75        let mut limbs = [zero::<T>(); CAP];
76        let mut i = 0;
77        while i < out_len as usize {
78            limbs[i] = self.limbs[i] | other.limbs[i];
79            i += 1;
80        }
81        HeaplessBigInt {
82            limbs,
83            len: out_len,
84            _p: PhantomData,
85        }
86    }
87}
88
89impl<T: MachineWord, const CAP: usize, P: Personality> BitOr for HeaplessBigInt<T, CAP, P> {
90    type Output = Self;
91    fn bitor(self, other: Self) -> Self {
92        (&self).bitor(&other)
93    }
94}
95
96impl<T: MachineWord, const CAP: usize, P: Personality> BitOr<&HeaplessBigInt<T, CAP, P>>
97    for HeaplessBigInt<T, CAP, P>
98{
99    type Output = Self;
100    fn bitor(self, other: &Self) -> Self {
101        (&self).bitor(other)
102    }
103}
104
105impl<T: MachineWord, const CAP: usize, P: Personality> BitOr<HeaplessBigInt<T, CAP, P>>
106    for &HeaplessBigInt<T, CAP, P>
107{
108    type Output = HeaplessBigInt<T, CAP, P>;
109    fn bitor(self, other: HeaplessBigInt<T, CAP, P>) -> Self::Output {
110        self.bitor(&other)
111    }
112}