crypto_bigint/uint/
bit_or.rs

1//! [`Uint`] bitwise OR operations.
2
3use super::Uint;
4use crate::{Limb, Wrapping};
5use core::ops::{BitOr, BitOrAssign};
6use subtle::{Choice, CtOption};
7
8impl<const LIMBS: usize> Uint<LIMBS> {
9    /// Computes bitwise `a & b`.
10    #[inline(always)]
11    pub const fn bitor(&self, rhs: &Self) -> Self {
12        let mut limbs = [Limb::ZERO; LIMBS];
13        let mut i = 0;
14
15        while i < LIMBS {
16            limbs[i] = self.limbs[i].bitor(rhs.limbs[i]);
17            i += 1;
18        }
19
20        Self { limbs }
21    }
22
23    /// Perform wrapping bitwise `OR`.
24    ///
25    /// There's no way wrapping could ever happen.
26    /// This function exists so that all operations are accounted for in the wrapping operations
27    pub const fn wrapping_or(&self, rhs: &Self) -> Self {
28        self.bitor(rhs)
29    }
30
31    /// Perform checked bitwise `OR`, returning a [`CtOption`] which `is_some` always
32    pub fn checked_or(&self, rhs: &Self) -> CtOption<Self> {
33        let result = self.bitor(rhs);
34        CtOption::new(result, Choice::from(1))
35    }
36}
37
38impl<const LIMBS: usize> BitOr for Uint<LIMBS> {
39    type Output = Self;
40
41    fn bitor(self, rhs: Self) -> Uint<LIMBS> {
42        self.bitor(&rhs)
43    }
44}
45
46impl<const LIMBS: usize> BitOr<&Uint<LIMBS>> for Uint<LIMBS> {
47    type Output = Uint<LIMBS>;
48
49    #[allow(clippy::needless_borrow)]
50    fn bitor(self, rhs: &Uint<LIMBS>) -> Uint<LIMBS> {
51        (&self).bitor(rhs)
52    }
53}
54
55impl<const LIMBS: usize> BitOr<Uint<LIMBS>> for &Uint<LIMBS> {
56    type Output = Uint<LIMBS>;
57
58    fn bitor(self, rhs: Uint<LIMBS>) -> Uint<LIMBS> {
59        self.bitor(&rhs)
60    }
61}
62
63impl<const LIMBS: usize> BitOr<&Uint<LIMBS>> for &Uint<LIMBS> {
64    type Output = Uint<LIMBS>;
65
66    fn bitor(self, rhs: &Uint<LIMBS>) -> Uint<LIMBS> {
67        self.bitor(rhs)
68    }
69}
70
71impl<const LIMBS: usize> BitOrAssign for Uint<LIMBS> {
72    fn bitor_assign(&mut self, other: Self) {
73        *self = *self | other;
74    }
75}
76
77impl<const LIMBS: usize> BitOrAssign<&Uint<LIMBS>> for Uint<LIMBS> {
78    fn bitor_assign(&mut self, other: &Self) {
79        *self = *self | other;
80    }
81}
82
83impl<const LIMBS: usize> BitOr for Wrapping<Uint<LIMBS>> {
84    type Output = Self;
85
86    fn bitor(self, rhs: Self) -> Wrapping<Uint<LIMBS>> {
87        Wrapping(self.0.bitor(&rhs.0))
88    }
89}
90
91impl<const LIMBS: usize> BitOr<&Wrapping<Uint<LIMBS>>> for Wrapping<Uint<LIMBS>> {
92    type Output = Wrapping<Uint<LIMBS>>;
93
94    fn bitor(self, rhs: &Wrapping<Uint<LIMBS>>) -> Wrapping<Uint<LIMBS>> {
95        Wrapping(self.0.bitor(&rhs.0))
96    }
97}
98
99impl<const LIMBS: usize> BitOr<Wrapping<Uint<LIMBS>>> for &Wrapping<Uint<LIMBS>> {
100    type Output = Wrapping<Uint<LIMBS>>;
101
102    fn bitor(self, rhs: Wrapping<Uint<LIMBS>>) -> Wrapping<Uint<LIMBS>> {
103        Wrapping(self.0.bitor(&rhs.0))
104    }
105}
106
107impl<const LIMBS: usize> BitOr<&Wrapping<Uint<LIMBS>>> for &Wrapping<Uint<LIMBS>> {
108    type Output = Wrapping<Uint<LIMBS>>;
109
110    fn bitor(self, rhs: &Wrapping<Uint<LIMBS>>) -> Wrapping<Uint<LIMBS>> {
111        Wrapping(self.0.bitor(&rhs.0))
112    }
113}
114
115impl<const LIMBS: usize> BitOrAssign for Wrapping<Uint<LIMBS>> {
116    fn bitor_assign(&mut self, other: Self) {
117        *self = *self | other;
118    }
119}
120
121impl<const LIMBS: usize> BitOrAssign<&Wrapping<Uint<LIMBS>>> for Wrapping<Uint<LIMBS>> {
122    fn bitor_assign(&mut self, other: &Self) {
123        *self = *self | other;
124    }
125}
126
127#[cfg(test)]
128mod tests {
129    use crate::U128;
130
131    #[test]
132    fn checked_or_ok() {
133        let result = U128::ZERO.checked_or(&U128::ONE);
134        assert_eq!(result.unwrap(), U128::ONE);
135    }
136
137    #[test]
138    fn overlapping_or_ok() {
139        let result = U128::MAX.wrapping_or(&U128::ONE);
140        assert_eq!(result, U128::MAX);
141    }
142}