Skip to content

Commit f7589bf

Browse files
authored
BoxedUint: impl BitAnd* (#314)
1 parent 2fda5f0 commit f7589bf

6 files changed

Lines changed: 143 additions & 4 deletions

File tree

src/boxed/uint.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Heap-allocated big unsigned integers.
22
33
mod add;
4+
mod bit_and;
45
mod cmp;
56
pub(crate) mod encoding;
67
mod mul;

src/boxed/uint/bit_and.rs

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

src/uint/bit_and.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! [`Uint`] bitwise and operations.
1+
//! [`Uint`] bitwise AND operations.
22
33
use super::Uint;
44
use crate::{Limb, Wrapping};

src/uint/bit_not.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! [`Uint`] bitwise not operations.
1+
//! [`Uint`] bitwise NOT operations.
22
33
use super::Uint;
44
use crate::{Limb, Wrapping};

src/uint/bit_or.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! [`Uint`] bitwise or operations.
1+
//! [`Uint`] bitwise OR operations.
22
33
use super::Uint;
44
use crate::{Limb, Wrapping};

src/uint/bit_xor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! [`Uint`] bitwise xor operations.
1+
//! [`Uint`] bitwise XOR operations.
22
33
use super::Uint;
44
use crate::{Limb, Wrapping};

0 commit comments

Comments
 (0)