Skip to content

Commit 262c38b

Browse files
committed
Add templated bitwise AND block with tests (refs #161)
1 parent d48ecc6 commit 262c38b

File tree

4 files changed

+93
-1
lines changed

4 files changed

+93
-1
lines changed

blocks/basic/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ add_library(
1212
include/gnuradio-4.0/basic/SignalGenerator.hpp
1313
include/gnuradio-4.0/basic/StreamToDataSet.hpp
1414
include/gnuradio-4.0/basic/SyncBlock.hpp
15-
include/gnuradio-4.0/basic/Trigger.hpp)
15+
include/gnuradio-4.0/basic/Trigger.hpp
16+
include/gnuradio-4.0/basic/And.hpp)
1617
target_link_libraries(gr-basic INTERFACE gnuradio-core gnuradio-algorithm)
1718
target_include_directories(gr-basic INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/>
1819
$<INSTALL_INTERFACE:include/>)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#ifndef AND_HPP
2+
#define AND_HPP
3+
4+
#include <gnuradio-4.0/Block.hpp>
5+
#include <gnuradio-4.0/BlockRegistry.hpp>
6+
7+
namespace gr::basic {
8+
9+
GR_REGISTER_BLOCK(gr::basic::And, [uint8_t, int16_t, int32_t])
10+
11+
template<typename T>
12+
requires std::is_arithmetic_v<T>
13+
struct And : Block<And<T>> {
14+
using Description = Doc<"@brief Performs a bitwise AND operation on two inputs, producing one output stream.">;
15+
16+
PortIn<T> in1;
17+
PortIn<T> in2;
18+
PortOut<T> out;
19+
20+
GR_MAKE_REFLECTABLE(And, in1, in2, out);
21+
22+
[[nodiscard]] constexpr T processOne(T input1, T input2) const noexcept {
23+
return input1 & input2;
24+
}
25+
};
26+
27+
} // namespace gr::blocks
28+
29+
#endif // AND_HPP

blocks/basic/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ add_ut_test(qa_Selector)
33
add_ut_test(qa_sources)
44
add_ut_test(qa_DataSink)
55
add_ut_test(qa_TriggerBlocks)
6+
add_ut_test(qa_And)
67

78
if(ENABLE_BLOCK_REGISTRY AND ENABLE_BLOCK_PLUGINS)
89
add_ut_test(qa_BasicKnownBlocks)

blocks/basic/test/qa_And.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#include <boost/ut.hpp>
2+
#include <gnuradio-4.0/basic/And.hpp>
3+
// #include <limits>
4+
5+
using namespace gr::basic;
6+
using namespace boost::ut;
7+
8+
const suite AndTests = [] {
9+
"Bitwise AND operations"_test = [] {
10+
And<uint8_t> andBlock;
11+
// Basic bitwise AND operation
12+
expect(eq(andBlock.processOne(0xFF, 0x0F), 0x0F)); // 0xFF & 0x0F = 0x0F
13+
expect(eq(andBlock.processOne(0x00, 0xFF), 0x00));
14+
expect(eq(andBlock.processOne(0xAB, 0x22), 0x22));
15+
};
16+
17+
"Edge cases"_test = [] {
18+
And<uint8_t> andBlock;
19+
// Edge cases for boundary values (max and min values)
20+
expect(eq(andBlock.processOne(0xFF, 0xFF), 0xFF)); // 0xFF & 0xFF = 0xFF
21+
expect(eq(andBlock.processOne(0x00, 0x00), 0x00)); // 0x00 & 0x00 = 0x00
22+
};
23+
24+
"int16_t support"_test = [] {
25+
And<int16_t> andBlock;
26+
// Test with int16_t values
27+
expect(eq(andBlock.processOne(0x7FFF, 0x00FF), 0x00FF)); // 0x7FFF & 0x00FF = 0x0101
28+
expect(eq(andBlock.processOne(static_cast<int16_t>(-1), static_cast<int16_t>(0xAABB)), static_cast<int16_t>(0xAABB))); // -1 & 0xAABB = 0xAABB
29+
};
30+
31+
"int32_t support"_test = [] {
32+
And<int32_t> andBlock;
33+
// Test bitwise AND on int32_t values (max and min values)
34+
expect(eq(andBlock.processOne(0xFFFF, 0x0F0F), 0x0F0F)); // 0xFFFF (1111111111111111) & 0x0F0F (0000111100001111) = 0x0F0F
35+
expect(eq(andBlock.processOne(-1, 0x0000), 0x0000)); // -1 & 0x0000 = 0x0000
36+
};
37+
38+
"Boundary cases"_test = [] {
39+
And<int32_t> andBlock;
40+
// Boundary test cases for int32_t limits
41+
expect(eq(andBlock.processOne(std::numeric_limits<int32_t>::max(), std::numeric_limits<int32_t>::min()), 0)); // MAX & MIN = 0
42+
expect(eq(andBlock.processOne(std::numeric_limits<int32_t>::max(), -1), std::numeric_limits<int32_t>::max())); // MAX & -1 = MAX
43+
};
44+
45+
"Negative values"_test = [] {
46+
And<int16_t> andBlock;
47+
// Test with negative values for int16_t
48+
expect(eq(andBlock.processOne(static_cast<int16_t>(-1), static_cast<int16_t>(-1)), static_cast<int16_t>(-1))); // -1 & -1 = -1
49+
50+
/*
51+
1111 1111 1111 1011 (-5 in two's complement)
52+
& 0000 0000 0000 0011 (3 in binary)
53+
--------------------
54+
0000 0000 0000 0011 (Result = 3)
55+
*/
56+
expect(eq(andBlock.processOne(static_cast<int16_t>(-5), static_cast<int16_t>(3)), static_cast<int16_t>(3))); // -5 & 3 = 3
57+
58+
};
59+
};
60+
61+
int main() { return boost::ut::cfg<boost::ut::override>.run(); }

0 commit comments

Comments
 (0)