qfall_math/integer/z/logic/
bit_and.rs

1// Copyright © 2025 Niklas Siemer
2//
3// This file is part of qFALL-math.
4//
5// qFALL-math is free software: you can redistribute it and/or modify it under
6// the terms of the Mozilla Public License Version 2.0 as published by the
7// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.
8
9//! This module contains implementations of the [`BitAnd`] trait.
10
11use crate::{
12    integer::Z,
13    macros::arithmetics::{
14        arithmetic_between_types, arithmetic_trait_borrowed_to_owned,
15        arithmetic_trait_mixed_borrowed_owned,
16    },
17};
18use flint_sys::fmpz::fmpz_and;
19use std::ops::BitAnd;
20
21impl BitAnd for &Z {
22    type Output = Z;
23
24    /// Computes the bit-wise logical `and` of `self` and `other`.
25    ///
26    /// Parameters:
27    /// - `other`: specifies the value to apply the bit-wise logical `and` action to
28    ///   apart from `self`
29    ///
30    /// Returns a new instance of [`Z`] containing the number resulting
31    /// from the bit-wise logical `and` operation performed on `self` and `other`.
32    ///
33    /// # Examples
34    /// ```
35    /// use qfall_math::integer::Z;
36    /// let a = Z::from(5);
37    /// let b = Z::from(7);
38    ///
39    /// let c: Z = &a & &b;
40    /// let d: Z = a & 1;
41    /// let e: Z = b & 15_u64;
42    /// ```
43    fn bitand(self, other: Self) -> Self::Output {
44        let mut out = Z::default();
45        unsafe { fmpz_and(&mut out.value, &self.value, &other.value) };
46        out
47    }
48}
49
50arithmetic_trait_borrowed_to_owned!(BitAnd, bitand, Z, Z, Z);
51arithmetic_trait_mixed_borrowed_owned!(BitAnd, bitand, Z, Z, Z);
52arithmetic_between_types!(BitAnd, bitand, Z, Z, i64 i32 i16 i8 u64 u32 u16 u8);
53
54#[cfg(test)]
55mod test_bitand {
56    use super::Z;
57
58    /// Testing `bitand` for two [`Z`]
59    #[test]
60    fn bitand() {
61        let a: Z = Z::from(42);
62        let b: Z = Z::from(24);
63
64        let c: Z = a & b;
65
66        assert_eq!(Z::from(8), c);
67    }
68
69    /// Testing `bitand` for two borrowed [`Z`]
70    #[test]
71    fn bitand_borrow() {
72        let a: Z = Z::from(42);
73        let b: Z = Z::from(24);
74
75        let c: Z = &a & &b;
76
77        assert_eq!(Z::from(8), c);
78    }
79
80    /// Testing `bitand` for borrowed [`Z`] and [`Z`]
81    #[test]
82    fn bitand_first_borrowed() {
83        let a: Z = Z::from(42);
84        let b: Z = Z::from(24);
85
86        let c: Z = &a & b;
87
88        assert_eq!(Z::from(8), c);
89    }
90
91    /// Testing `bitand` for [`Z`] and borrowed [`Z`]
92    #[test]
93    fn bitand_second_borrowed() {
94        let a: Z = Z::from(42);
95        let b: Z = Z::from(24);
96
97        let c: Z = a & &b;
98
99        assert_eq!(Z::from(8), c);
100    }
101
102    /// Testing `bitand` for large numbers
103    #[test]
104    fn bitand_large_numbers() {
105        let a: Z = Z::from(u64::MAX);
106        let b: Z = Z::from(-221319874);
107        let c: Z = Z::from(i64::MIN);
108        let d_cmp = Z::from(18446744073488231742_u64);
109        let e_cmp = Z::from(9223372036854775808_u64);
110
111        let d: Z = &a & b;
112        let e: Z = a & c;
113
114        assert_eq!(d_cmp, d);
115        assert_eq!(e_cmp, e);
116    }
117
118    /// Testing `bitand` between different types
119    #[test]
120    #[allow(clippy::op_ref)]
121    fn availability() {
122        let a: Z = Z::from(42);
123        let b: u64 = 1;
124        let c: u32 = 1;
125        let d: u16 = 1;
126        let e: u8 = 1;
127        let f: i64 = 1;
128        let g: i32 = 1;
129        let h: i16 = 1;
130        let i: i8 = 1;
131
132        let _: Z = &a & &b;
133        let _: Z = &a & &c;
134        let _: Z = &a & &d;
135        let _: Z = &a & &e;
136        let _: Z = &a & &f;
137        let _: Z = &a & &g;
138        let _: Z = &a & &h;
139        let _: Z = &a & &i;
140
141        let _: Z = &b & &a;
142        let _: Z = &c & &a;
143        let _: Z = &d & &a;
144        let _: Z = &e & &a;
145        let _: Z = &f & &a;
146        let _: Z = &g & &a;
147        let _: Z = &h & &a;
148        let _: Z = &i & &a;
149
150        let _: Z = &a & b;
151        let _: Z = &a & c;
152        let _: Z = &a & d;
153        let _: Z = &a & e;
154        let _: Z = &a & f;
155        let _: Z = &a & g;
156        let _: Z = &a & h;
157        let _: Z = &a & i;
158
159        let _: Z = &b & Z::from(42);
160        let _: Z = &c & Z::from(42);
161        let _: Z = &d & Z::from(42);
162        let _: Z = &e & Z::from(42);
163        let _: Z = &f & Z::from(42);
164        let _: Z = &g & Z::from(42);
165        let _: Z = &h & Z::from(42);
166        let _: Z = &i & Z::from(42);
167
168        let _: Z = Z::from(42) & &b;
169        let _: Z = Z::from(42) & &c;
170        let _: Z = Z::from(42) & &d;
171        let _: Z = Z::from(42) & &e;
172        let _: Z = Z::from(42) & &f;
173        let _: Z = Z::from(42) & &g;
174        let _: Z = Z::from(42) & &h;
175        let _: Z = Z::from(42) & &i;
176
177        let _: Z = b & &a;
178        let _: Z = c & &a;
179        let _: Z = d & &a;
180        let _: Z = e & &a;
181        let _: Z = f & &a;
182        let _: Z = g & &a;
183        let _: Z = h & &a;
184        let _: Z = i & &a;
185
186        let _: Z = Z::from(42) & b;
187        let _: Z = Z::from(42) & c;
188        let _: Z = Z::from(42) & d;
189        let _: Z = Z::from(42) & e;
190        let _: Z = Z::from(42) & f;
191        let _: Z = Z::from(42) & g;
192        let _: Z = Z::from(42) & h;
193        let _: Z = Z::from(42) & i;
194
195        let _: Z = b & Z::from(42);
196        let _: Z = c & Z::from(42);
197        let _: Z = d & Z::from(42);
198        let _: Z = e & Z::from(42);
199        let _: Z = f & Z::from(42);
200        let _: Z = g & Z::from(42);
201        let _: Z = h & Z::from(42);
202        let _: Z = i & Z::from(42);
203    }
204}