diff --git a/include/aare/NDArray.hpp b/include/aare/NDArray.hpp index c3edbfb..3495276 100644 --- a/include/aare/NDArray.hpp +++ b/include/aare/NDArray.hpp @@ -25,7 +25,7 @@ template class NDArray : public ArrayExpr, Ndim> { std::array shape_; std::array strides_; - size_t size_{}; + size_t size_{}; //TODO! do we need to store size when we have shape? T *data_; public: @@ -43,8 +43,7 @@ class NDArray : public ArrayExpr, Ndim> { */ explicit NDArray(std::array shape) : shape_(shape), strides_(c_strides(shape_)), - size_(std::accumulate(shape_.begin(), shape_.end(), 1, - std::multiplies<>())), + size_(num_elements(shape_)), data_(new T[size_]) {} /** @@ -79,6 +78,24 @@ class NDArray : public ArrayExpr, Ndim> { other.reset(); // TODO! is this necessary? } + + //Move constructor from an an array with Ndim + 1 + template > + NDArray(NDArray &&other) + : shape_(drop_first_dim(other.shape())), + strides_(c_strides(shape_)), size_(num_elements(shape_)), + data_(other.data()) { + + // For now only allow move if the size matches, to avoid unreachable data + // if the use case arises we can remove this check + if(size() != other.size()) { + data_ = nullptr; // avoid double free, other will clean up the memory in it's destructor + throw std::runtime_error(LOCATION + + "Size mismatch in move constructor of NDArray"); + } + other.reset(); + } + // Copy constructor NDArray(const NDArray &other) : shape_(other.shape_), strides_(c_strides(shape_)), @@ -212,24 +229,6 @@ class NDArray : public ArrayExpr, Ndim> { void Print_all(); void Print_some(); - template 2)>> - NDArray drop_dimension() && { - - std::array new_shape; - - std::copy(shape_.begin() + 1, shape_.begin() + Ndim, new_shape.begin()); - - NDArray new_array(new_shape); - - delete new_array.data(); - - new_array.data_ref() = data_; - - this->reset(); - - return new_array; - } - void reset() { data_ = nullptr; size_ = 0; diff --git a/include/aare/NDView.hpp b/include/aare/NDView.hpp index 56bca2f..c946c26 100644 --- a/include/aare/NDView.hpp +++ b/include/aare/NDView.hpp @@ -26,6 +26,32 @@ Shape make_shape(const std::vector &shape) { return arr; } + +/** + * @brief Helper function to drop the first dimension of a shape. + * This is useful when you want to create a 2D view from a 3D array. + * @param shape The shape to drop the first dimension from. + * @return A new shape with the first dimension dropped. + */ +template +Shape drop_first_dim(const Shape &shape) { + Shape new_shape; + std::copy(shape.begin() + 1, shape.end(), new_shape.begin()); + return new_shape; +} + +/** + * @brief Helper function when constructing NDArray/NDView. Calculates the number + * of elements in the resulting array from a shape. + * @param shape The shape to calculate the number of elements for. + * @return The number of elements in and NDArray/NDView of that shape. + */ +template +size_t num_elements(const Shape &shape) { + return std::accumulate(shape.begin(), shape.end(), 1, + std::multiplies()); +} + template ssize_t element_offset(const Strides & /*unused*/) { return 0; diff --git a/include/aare/calibration.hpp b/include/aare/calibration.hpp index a94705f..3b18da6 100644 --- a/include/aare/calibration.hpp +++ b/include/aare/calibration.hpp @@ -163,24 +163,22 @@ calculate_pedestal(NDView raw_data, ssize_t n_threads) { NDView)>(&sum_and_count_per_gain), view)); } + Shape<3> shape{num_gains, raw_data.shape(1), raw_data.shape(2)}; + NDArray accumulator(shape, 0); + NDArray count(shape, 0); - NDArray accumulator( - std::array{num_gains, raw_data.shape(1), raw_data.shape(2)}, - 0); - NDArray count( - std::array{num_gains, raw_data.shape(1), raw_data.shape(2)}, - 0); + // Combine the results from the futures for (auto &f : futures) { auto [acc, cnt] = f.get(); accumulator += acc; count += cnt; } - if constexpr (only_gain0) { - return safe_divide(accumulator, count).drop_dimension(); - } else { - return safe_divide(accumulator, count); - } + + // Will move to a NDArray(only_gain0)> + // if only_gain0 is true + return safe_divide(accumulator, count); + } /** diff --git a/src/NDArray.test.cpp b/src/NDArray.test.cpp index 9af8379..a4d687a 100644 --- a/src/NDArray.test.cpp +++ b/src/NDArray.test.cpp @@ -427,4 +427,28 @@ TEST_CASE("Construct an NDArray from an std::array") { for (uint32_t i = 0; i < a.size(); ++i) { REQUIRE(a(i) == b[i]); } +} + + +TEST_CASE("Move construct from an array with Ndim + 1") { + NDArray a({{1,2,2}}, 0); + a(0, 0, 0) = 1; + a(0, 0, 1) = 2; + a(0, 1, 0) = 3; + a(0, 1, 1) = 4; + + + NDArray b(std::move(a)); + REQUIRE(b.shape() == Shape<2>{2,2}); + REQUIRE(b.size() == 4); + REQUIRE(b(0, 0) == 1); + REQUIRE(b(0, 1) == 2); + REQUIRE(b(1, 0) == 3); + REQUIRE(b(1, 1) == 4); + +} + +TEST_CASE("Move construct from an array with Ndim + 1 throws on size mismatch") { + NDArray a({{2,2,2}}, 0); + REQUIRE_THROWS(NDArray(std::move(a))); } \ No newline at end of file