More uniform binding of Numpy arrays (#381)
Build on RHEL9 / build (push) Successful in 2m54s
Build on RHEL8 / build (push) Successful in 3m31s
Run tests using data on local RHEL8 / build (push) Failing after 4m28s
Build on local RHEL8 / build (push) Successful in 3m6s

- Introduce a standard way to bind numpy arrays: py::array_t<T> and
.noconvert() on the argument
- Take py::array_t by value since it's just a small wrapper
- Update bindings
This commit is contained in:
Erik Fröjdh authored and GitHub committed 2026-09-25 14:40:33 +02:00
1 parent 8579a140f7
commit 941325ea15
26 files changed
+597 -280

No files matched your search

+82
View File
@@ -5,6 +5,8 @@
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_floating_point.hpp>
using Catch::Matchers::WithinAbs;
#include <cstring>
#include <stdexcept>
#include <vector>
using aare::BitOffset;
@@ -49,6 +51,86 @@ TEST_CASE("test_adc_sar_05_decode64to16") {
CHECK(output == 3072UL);
}
TEST_CASE("Decode 64 bit ADC SAR samples from a byte buffer") {
// Two rows of two words each, viewed as raw bytes
aare::NDArray<uint64_t, 2> words({2, 2});
words(0, 0) = 1UL << 29;
words(0, 1) = (1UL << 25) | (1UL << 22);
words(1, 0) = 0;
words(1, 1) = (1UL << 29) | (1UL << 19) | (1UL << 28);
aare::NDView<const uint8_t, 2> bytes(
reinterpret_cast<const uint8_t *>(words.data()), {2, 16});
aare::NDArray<uint16_t, 2> out({2, 2});
aare::adc_sar_05_decode64to16(bytes, out.view());
CHECK(out(0, 0) == 1);
CHECK(out(0, 1) == 3072);
CHECK(out(1, 0) == 0);
CHECK(out(1, 1) == 7);
// Matches the overload that takes the words directly
aare::NDArray<uint16_t, 2> reference({2, 2});
aare::adc_sar_05_decode64to16(words.view(), reference.view());
for (ssize_t i = 0; i < 2; ++i) {
for (ssize_t j = 0; j < 2; ++j) {
CHECK(out(i, j) == reference(i, j));
}
}
}
TEST_CASE("Each byte buffer decoder maps to its own bit order") {
// First two bits of each decoder's bit list
struct Case {
void (*decode)(aare::NDView<const uint8_t, 2>,
aare::NDView<uint16_t, 2>);
int bit0;
int bit1;
};
const Case cases[] = {
{aare::adc_sar_05_06_07_08decode64to16, 29, 17},
{aare::adc_sar_05_decode64to16, 29, 19},
{aare::adc_sar_04_decode64to16, 15, 17},
};
for (const auto &c : cases) {
uint64_t word = (1UL << c.bit0) | (1UL << c.bit1);
std::vector<uint8_t> buffer(8);
std::memcpy(buffer.data(), &word, sizeof(word));
aare::NDView<const uint8_t, 2> bytes(buffer.data(), {1, 8});
aare::NDArray<uint16_t, 2> out({1, 1});
c.decode(bytes, out.view());
CHECK(out(0, 0) == 3);
}
}
TEST_CASE("Byte buffer decoding does not require an aligned buffer") {
// Place the word three bytes into the buffer
std::vector<uint8_t> buffer(3 + 8, 0);
uint64_t word = (1UL << 29) | (1UL << 19);
std::memcpy(buffer.data() + 3, &word, sizeof(word));
aare::NDView<const uint8_t, 2> bytes(buffer.data() + 3, {1, 8});
aare::NDArray<uint16_t, 2> out({1, 1});
aare::adc_sar_05_decode64to16(bytes, out.view());
CHECK(out(0, 0) == 3);
}
TEST_CASE("Byte buffer decoding rejects invalid shapes") {
std::vector<uint8_t> buffer(24, 0);
aare::NDArray<uint16_t, 2> out({1, 1});
// Row length that is not a multiple of 8
aare::NDView<const uint8_t, 2> odd_row(buffer.data(), {2, 12});
REQUIRE_THROWS_AS(aare::adc_sar_05_decode64to16(odd_row, out.view()),
std::invalid_argument);
// Output shape that does not match rows x (bytes / 8)
aare::NDView<const uint8_t, 2> two_words(buffer.data(), {1, 16});
REQUIRE_THROWS_AS(aare::adc_sar_05_decode64to16(two_words, out.view()),
std::invalid_argument);
}
TEST_CASE("test_apply_custom_weights") {
uint16_t input = 1;