From e04d1e28f9c1c877f4582ed5574d3672f332c160 Mon Sep 17 00:00:00 2001 From: Bechir Braham Date: Wed, 20 Mar 2024 16:27:22 +0100 Subject: [PATCH 1/2] add dataspan --- core/CMakeLists.txt | 8 +- core/include/aare/DataSpan.hpp | 125 ++++++++++++++++++ core/include/aare/Frame.hpp | 2 + core/src/Frame.cpp | 15 ++- core/{src => test}/CircularFifo.test.cpp | 0 .../ProducerConsumerQueue.test.cpp | 0 core/{src => test}/defs.test.cpp | 0 core/test/wrappers.test.cpp | 49 +++++++ 8 files changed, 195 insertions(+), 4 deletions(-) create mode 100644 core/include/aare/DataSpan.hpp rename core/{src => test}/CircularFifo.test.cpp (100%) rename core/{src => test}/ProducerConsumerQueue.test.cpp (100%) rename core/{src => test}/defs.test.cpp (100%) create mode 100644 core/test/wrappers.test.cpp diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 1af676f..cbdfad8 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -17,9 +17,11 @@ endif() if(AARE_TESTS) set(TestSources - ${CMAKE_CURRENT_SOURCE_DIR}/src/defs.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/ProducerConsumerQueue.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/CircularFifo.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/defs.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/ProducerConsumerQueue.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/CircularFifo.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/wrappers.test.cpp + ) target_sources(tests PRIVATE ${TestSources} ) target_link_libraries(tests PRIVATE core) diff --git a/core/include/aare/DataSpan.hpp b/core/include/aare/DataSpan.hpp new file mode 100644 index 0000000..7df8edc --- /dev/null +++ b/core/include/aare/DataSpan.hpp @@ -0,0 +1,125 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include + + +template ssize_t element_offset(const Strides &) { return 0; } + +template +ssize_t element_offset(const Strides &strides, ssize_t i, Ix... index) { + return i * strides[Dim] + element_offset(strides, index...); +} + +template std::array c_strides(const std::array &shape) { + std::array strides; + std::fill(strides.begin(), strides.end(), 1); + for (ssize_t i = Ndim - 1; i > 0; --i) { + strides[i - 1] = strides[i] * shape[i]; + } + return strides; +} + +template std::array make_array(const std::vector &vec) { + assert(vec.size() == Ndim); + std::array arr; + std::copy_n(vec.begin(), Ndim, arr.begin()); + return arr; +} + +template class DataSpan { + public: + DataSpan(){}; + + DataSpan(T* buffer, std::array shape) { + buffer_ = buffer; + strides_ = c_strides(shape); + shape_ = shape; + size_ = std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies()); + } + + DataSpan(T *buffer, const std::vector &shape) { + buffer_ = buffer; + strides_ = c_strides(make_array(shape)); + shape_ = make_array(shape); + size_ = std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies()); + + } + + DataSpan(Frame& frame) { + assert(Ndim == 2); + buffer_ = reinterpret_cast(frame._get_data()); + strides_ = c_strides({frame.rows(), frame.cols()}); + shape_ = {frame.rows(), frame.cols()}; + size_ = frame.rows() * frame.cols(); + } + + template typename std::enable_if::type operator()(Ix... index) { + return buffer_[element_offset(strides_, index...)]; + } + + template typename std::enable_if::type operator()(Ix... index) const { + return buffer_[element_offset(strides_, index...)]; + } + + ssize_t size() const { return size_; } + + DataSpan(const DataSpan &) = default; + DataSpan(DataSpan &&) = default; + + T *begin() { return buffer_; } + T *end() { return buffer_ + size_; } + T &operator()(ssize_t i) { return buffer_[i]; } + T &operator[](ssize_t i) { return buffer_[i]; } + + DataSpan &operator+=(const T val) { return elemenwise(val, std::plus()); } + DataSpan &operator-=(const T val) { return elemenwise(val, std::minus()); } + DataSpan &operator*=(const T val) { return elemenwise(val, std::multiplies()); } + DataSpan &operator/=(const T val) { return elemenwise(val, std::divides()); } + + DataSpan &operator/=(const DataSpan &other) { return elemenwise(other, std::divides()); } + + DataSpan &operator=(const T val) { + for (auto it = begin(); it != end(); ++it) + *it = val; + return *this; + } + + DataSpan &operator=(const DataSpan &other) { + shape_ = other.shape_; + strides_ = other.strides_; + size_ = other.size_; + buffer_ = other.buffer_; + return *this; + } + auto &shape() { return shape_; } + auto shape(ssize_t i) const { return shape_[i]; } + + T *data() { return buffer_; } + + private: + T *buffer_{nullptr}; + std::array strides_{}; + std::array shape_{}; + ssize_t size_{}; + + template DataSpan &elemenwise(T val, BinaryOperation op) { + for (ssize_t i = 0; i != size_; ++i) { + buffer_[i] = op(buffer_[i], val); + } + return *this; + } + template DataSpan &elemenwise(const DataSpan &other, BinaryOperation op) { + for (ssize_t i = 0; i != size_; ++i) { + buffer_[i] = op(buffer_[i], other.buffer_[i]); + } + return *this; + } +}; + +template class DataSpan; + diff --git a/core/include/aare/Frame.hpp b/core/include/aare/Frame.hpp index abf9150..bf33b07 100644 --- a/core/include/aare/Frame.hpp +++ b/core/include/aare/Frame.hpp @@ -23,6 +23,8 @@ class Frame { Frame(ssize_t rows, ssize_t cols,ssize_t m_bitdepth); Frame(std::byte *fp, ssize_t rows, ssize_t cols,ssize_t m_bitdepth); std::byte* get(int row, int col); + template + void set(int row, int col,T data); // std::vector> get_array(); ssize_t rows() const{ return m_rows; diff --git a/core/src/Frame.cpp b/core/src/Frame.cpp index 7974b5c..7a9e53a 100644 --- a/core/src/Frame.cpp +++ b/core/src/Frame.cpp @@ -1,6 +1,6 @@ #include "aare/Frame.hpp" #include - +#include Frame::Frame(std::byte* bytes, ssize_t rows, ssize_t cols, ssize_t bitdepth): m_rows(rows), m_cols(cols), m_bitdepth(bitdepth) { m_data = new std::byte[rows*cols*bitdepth/8]; @@ -22,6 +22,19 @@ std::byte* Frame::get(int row, int col) { return m_data+(row*m_cols + col)*(m_bitdepth/8); } +template +void Frame::set(int row, int col, T data) { + assert(sizeof(T) == m_bitdepth/8); + if (row < 0 || row >= m_rows || col < 0 || col >= m_cols) { + std::cerr << "Invalid row or column index" << std::endl; + return; + } + std::memcpy(m_data+(row*m_cols + col)*(m_bitdepth/8), &data, m_bitdepth/8); +} + +template void Frame::set(int row, int col, uint16_t data); + + // std::vector> Frame::get_array() { // std::vector> array; // for (int i = 0; i < m_rows; i++) { diff --git a/core/src/CircularFifo.test.cpp b/core/test/CircularFifo.test.cpp similarity index 100% rename from core/src/CircularFifo.test.cpp rename to core/test/CircularFifo.test.cpp diff --git a/core/src/ProducerConsumerQueue.test.cpp b/core/test/ProducerConsumerQueue.test.cpp similarity index 100% rename from core/src/ProducerConsumerQueue.test.cpp rename to core/test/ProducerConsumerQueue.test.cpp diff --git a/core/src/defs.test.cpp b/core/test/defs.test.cpp similarity index 100% rename from core/src/defs.test.cpp rename to core/test/defs.test.cpp diff --git a/core/test/wrappers.test.cpp b/core/test/wrappers.test.cpp new file mode 100644 index 0000000..fc29af2 --- /dev/null +++ b/core/test/wrappers.test.cpp @@ -0,0 +1,49 @@ +#include +#include +#include +#include + +TEST_CASE("Frame") { + auto data = new uint16_t[100]; + for (int i = 0; i < 100; i++) { + data[i] = i; + } + Frame f(reinterpret_cast(data), 10, 10, 16); + for (int i = 0; i < 100; i++) { + REQUIRE((uint16_t)*f.get(i / 10, i % 10) == data[i]); + } + REQUIRE(f.rows() == 10); + REQUIRE(f.cols() == 10); + REQUIRE(f.bitdepth() == 16); + + uint16_t i = 44; + f.set(0, 0, i); + REQUIRE((uint16_t)*f.get(0, 0) == i); + delete[] data; +} + +TEST_CASE("DataSpan") { + auto data = new uint16_t[100]; + for (int i = 0; i < 100; i++) { + data[i] = i; + } + SECTION("constructors") { + DataSpan ds(data, std::vector({10, 10})); + for (int i = 0; i < 100; i++) { + REQUIRE(ds(i / 10, i % 10) == data[i]); + } + } + SECTION("from Frame") { + Frame f(reinterpret_cast(data), 10, 10, 16); + DataSpan ds(f); + for (int i = 0; i < 100; i++) { + REQUIRE(ds(i / 10, i % 10) == data[i]); + } + + f.set(0, 0, (uint16_t)44); + REQUIRE((uint16_t)*f.get(0, 0) == 44); // check that set worked + REQUIRE(ds(0, 0) == 44);// check that ds is updated + REQUIRE(data[0] == 0); // check that data is not updated + } + delete[] data; +} \ No newline at end of file From cca9c5249dfb60db4a73f8732424c1602104b278 Mon Sep 17 00:00:00 2001 From: Bechir Braham Date: Wed, 20 Mar 2024 17:38:01 +0100 Subject: [PATCH 2/2] fix cmake --- CMakeLists.txt | 57 +++++++++++++++++++++--------------------- file_io/CMakeLists.txt | 7 ++++-- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f112f6a..0b227b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,34 @@ else() -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC ) + + if (NOT AARE_PYTHON_BINDINGS) + target_compile_options( + aare_compiler_flags + INTERFACE + -fdiagnostics-parseable-fixits + -fdiagnostics-generate-patch + -fdiagnostics-show-template-tree + -fsanitize=address,undefined,pointer-compare + -fno-sanitize-recover + # -D_FORTIFY_SOURCE=2 # not needed for debug builds + # -fstack-protector # cause errors wih folly (ProducerConsumerQueue.hpp) + -fno-omit-frame-pointer + ) + + target_link_libraries( + aare_compiler_flags + INTERFACE + -fdiagnostics-parseable-fixits + -fdiagnostics-generate-patch + -fdiagnostics-show-template-tree + -fsanitize=address,undefined,pointer-compare + -fno-sanitize-recover + # -D_FORTIFY_SOURCE=2 + -fno-omit-frame-pointer + ) +endif() + endif() if(AARE_USE_WARNINGS) @@ -64,35 +92,6 @@ if(AARE_USE_WARNINGS) ) endif() -if (NOT AARE_PYTHON_BINDINGS) - target_compile_options( - aare_compiler_flags - INTERFACE - -fsanitize=address - -fdiagnostics-parseable-fixits - -fdiagnostics-generate-patch - -fdiagnostics-show-template-tree - -fsanitize=address,undefined,pointer-compare - -fno-sanitize-recover - -D_FORTIFY_SOURCE=2 - -fstack-protector - -fno-omit-frame-pointer - ) - - target_link_libraries( - aare_compiler_flags - INTERFACE - -fsanitize=address - -fdiagnostics-parseable-fixits - -fdiagnostics-generate-patch - -fdiagnostics-show-template-tree - -fsanitize=address,undefined,pointer-compare - -fno-sanitize-recover - -D_FORTIFY_SOURCE=2 - -fstack-protector - -fno-omit-frame-pointer - ) -endif() if(AARE_TESTS) add_subdirectory(tests) endif() diff --git a/file_io/CMakeLists.txt b/file_io/CMakeLists.txt index 8d65baa..474babd 100644 --- a/file_io/CMakeLists.txt +++ b/file_io/CMakeLists.txt @@ -1,5 +1,8 @@ -find_package(nlohmann_json 3.2.0 REQUIRED) - +FetchContent_Declare(json + GIT_REPOSITORY https://github.com/nlohmann/json + GIT_TAG v3.11.3 +) +FetchContent_MakeAvailable(json) set(SourceFiles ${CMAKE_CURRENT_SOURCE_DIR}/src/File.cpp