From 9005132a1b1f8a0f33f596984ddcc6c56f4ae043 Mon Sep 17 00:00:00 2001 From: Thomas Hahn Date: Mon, 24 Jun 2024 11:06:44 -0400 Subject: [PATCH] Remove unused layout/rect_str.hpp --- c++/nda/layout.hpp | 1 - c++/nda/layout/rect_str.hpp | 472 ------------------------------- test/c++/nda_layout_rect_str.cpp | 154 ---------- test/c++/nda_str_indices.cpp | 120 -------- 4 files changed, 747 deletions(-) delete mode 100644 c++/nda/layout/rect_str.hpp delete mode 100644 test/c++/nda_layout_rect_str.cpp delete mode 100644 test/c++/nda_str_indices.cpp diff --git a/c++/nda/layout.hpp b/c++/nda/layout.hpp index 823141f1..f620dafc 100644 --- a/c++/nda/layout.hpp +++ b/c++/nda/layout.hpp @@ -27,5 +27,4 @@ #include "./layout/permutation.hpp" #include "./layout/policies.hpp" #include "./layout/range.hpp" -#include "./layout/rect_str.hpp" #include "./layout/slice_static.hpp" diff --git a/c++/nda/layout/rect_str.hpp b/c++/nda/layout/rect_str.hpp deleted file mode 100644 index ab88501a..00000000 --- a/c++/nda/layout/rect_str.hpp +++ /dev/null @@ -1,472 +0,0 @@ -// Copyright (c) 2020-2023 Simons Foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0.txt -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Authors: Olivier Parcollet, Nils Wentzell - -/** - * @file - * @brief Provides an extension to nda::idx_map to support string indices. - */ - -#pragma once - -#include "./idx_map.hpp" -#include "./policies.hpp" -#include "../basic_array.hpp" -#include "../basic_functions.hpp" -#include "../declarations.hpp" -#include "../exceptions.hpp" -#include "../traits.hpp" - -#include -#include -#include -#include -#include -#include - -namespace nda { - - /** - * @addtogroup layout_idx - * @{ - */ - - /// @cond - // Forward declaration. - template - class rect_str; - /// @endcond - - namespace detail { - - // Get the corresponding nda::rect_str type from a given nda::idx_map type. - template - struct rect_str_from_base; - - // Specialization of rect_str_from_base for nda::idx_map. - template - struct rect_str_from_base> { - // nda::rect_str type. - using type = rect_str; - }; - - } // namespace detail - - /** - * @brief Layout that specifies how to map multi-dimensional indices including possible string indices to a - * linear/flat index. - * - * @details It extends the functionality of nda::idx_map by supporting string indices. - * - * @tparam Rank Number of dimensions. - * @tparam StaticExtent Compile-time known shape (zero if fully dynamic). - * @tparam StrideOrder Order in which the dimensions are stored in memory. - * @tparam LayoutProp Compile-time guarantees about the layout of the data in memory. - */ - template - class rect_str : public idx_map { - // Type for storing the string indices. - using ind_t = nda::array, 1>; - - // Type of the nda::idx_map base class. - using base_t = idx_map; - - // String indices for each dimension. - mutable std::shared_ptr s_indices; - - // Number of dynamic dimensions/extents. - using base_t::n_dynamic_extents; - - // Get the shape of the nda::rect_str from given string indices. - static std::array make_shape_from_string_indices(ind_t const &str_indices) { - if (str_indices.size() != Rank) - NDA_RUNTIME_ERROR << "Error in rect_str::make_shape_from_string_indices: String indices do not have the correct rank"; - std::array sha; - for (int i = 0; i < Rank; ++i) sha[i] = str_indices[i].size(); - return sha; - } - - public: - /** - * @brief Get the string indices. - * - * @details If the string indices are not yet initialized, they are initialized with the default values, i.e. "0", - * "1", "2", ..., and so on. - * - * @return String indices. - */ - auto const &get_string_indices() const { - if (not s_indices) { - // string indices are not initialized - auto ind = ind_t(Rank); - for (int i = 0; i < Rank; ++i) { - auto a = nda::array(this->lengths()[i]); - for (int j = 0; j < a.size(); ++j) a(j) = std::to_string(j); - ind(i) = std::move(a); - } - s_indices = std::make_shared(std::move(ind)); - } - return *s_indices; - } - - /// Alias template to check if type `T` can be used to access a specific element. - template - static constexpr int argument_is_allowed_for_call = base_t::template argument_is_allowed_for_call or std::is_constructible_v; - - /// Alias template to check if type `T` can be used to either access a specific element or a slice of elements. - template - static constexpr int argument_is_allowed_for_call_or_slice = - base_t::template argument_is_allowed_for_call_or_slice or std::is_constructible_v; - - /** - * @brief Default constructor. - * @details The string indices are not initialized and the underlying nda::idx_map is default constructed. - */ - rect_str() = default; - - /** - * @brief Construct an nda::rect_str from a given nda::idx_map. - * @param idxm nda::idx_map object. - */ - rect_str(base_t const &idxm) noexcept : base_t{idxm} {} - - /** - * @brief Construct an nda::rect_str from a given nda::idx_map and string indices. - * - * @warning The shape of the string indices is not checked to be consistent with the shape of the nda::idx_map. - * - * @param idxm nda::idx_map object. - * @param str_indices String indices. - */ - rect_str(base_t const &idxm, ind_t const &str_indices) noexcept : base_t{idxm}, s_indices{std::make_shared(std::move(str_indices))} {} - - /** - * @brief Construct an nda::rect_str from another nda::rect_str with different layout properties. - * - * @tparam LP Layout properties of the other nda::rect_str. - * @param rstr Other nda::rect_str object. - */ - template - rect_str(rect_str const &rstr) noexcept - : base_t{rstr}, s_indices{std::make_shared(rstr.get_string_indices())} {} - - /** - * @brief Construct an nda::rect_str from another nda::rect_str with different layout properties and static extents. - * - * @tparam SE Static extents of the other nda::rect_str. - * @tparam LP Layout properties of the other nda::rect_str. - * @param rstr Other nda::rect_str object. - */ - template - rect_str(rect_str const &rstr) noexcept(false) - : base_t{rstr}, s_indices{std::make_shared(rstr.get_string_indices())} {} - - /** - * @brief Construct an nda::rect_str from a given shape and strides. - * - * @param shape Shape of the map. - * @param strides Strides of the map. - */ - rect_str(std::array const &shape, std::array const &strides) noexcept : base_t{shape, strides} {} - - /** - * @brief Construct an nda::rect_str from a given shape and with contiguous strides. - * @param shape Shape of the map. - */ - rect_str(std::array const &shape) noexcept : base_t{shape} {} - - /** - * @brief Construct an nda::rect_str from given string indices and with contiguous strides. - * @param str_indices String indices. - */ - rect_str(nda::array, 1> str_indices) noexcept(false) - : base_t{make_shape_from_string_indices(str_indices)}, s_indices{std::make_shared(std::move(str_indices))} {} - - /** - * @brief Construct an nda::rect_str from an array with its dynamic extents. - * @details The missing extents are taken from the static extents. - * @param shape sta::array containing the dynamic extents only. - */ - rect_str(std::array const &shape) noexcept - requires((base_t::n_dynamic_extents != Rank) and (base_t::n_dynamic_extents != 0)) - : base_t{shape} {} - - /// Default copy constructor. - rect_str(rect_str const &) = default; - - /// Default move constructor. - rect_str(rect_str &&) = default; - - /// Default copy assignment operator. - rect_str &operator=(rect_str const &) = default; - - /// Default move assignment operator. - rect_str &operator=(rect_str &&) = default; - - private: - // Convert a given string argument into a corresponding index. If the argument isn't a string, it is returned as is. - template - auto peel_string(int pos, T const &arg) const { - if constexpr (not std::is_constructible_v) - // argument is not a string, simply return it - return arg; - else { - // argument is a string, find its position in the string indices of the given dimension - auto const &sind = get_string_indices(); - auto const &idx = sind[pos]; - auto it = std::find(idx.begin(), idx.end(), arg); - if (it == idx.end()) NDA_RUNTIME_ERROR << "Error in nda::rect_str: Key " << arg << " at position " << pos << " does not match an index"; - return it - idx.begin(); - } - } - - // Actual implementation of the function call operator. - template - [[nodiscard]] FORCEINLINE long call_impl(std::index_sequence, Args... args) const { - // calls the underlying nda::idx_map::operator() after converting all string arguments to long indices - return base_t::operator()(peel_string(Is, args)...); - } - - public: - /** - * @brief Function call operator to map a given multi-dimensional index to a linear index. - * - * @details See also nda::idx_map. - * - * @tparam Args Types of the arguments. - * @param args Multi-dimensional index, including possible string indices. - * @return Linear/Flat index. - */ - template - FORCEINLINE long operator()(Args const &...args) const { - return call_impl(std::make_index_sequence{}, args...); - } - - private: - // Helper function to get a new nda::rect_str by taking a slice of the current one. - template - FORCEINLINE decltype(auto) slice_impl(std::index_sequence, Args const &...args) const { - // convert string arguments to long indices and slice the underlying nda::idx_map - auto const [offset, idxm2] = base_t::slice(peel_string(Is, args)...); - - // type of sliced nda::rect_str - using new_rect_str_t = typename detail::rect_str_from_base>::type; - - // if the string indices have not been initialized, simply return a new nda::rect_str with the sliced nda::idx_map - if (not s_indices) return std::make_pair(offset, new_rect_str_t{idxm2}); - - // otherwise slice the string indices as well (not optimized but simple) - auto const ¤t_ind = get_string_indices(); - ind_t ind2((not argument_is_allowed_for_call + ...)); // will not work for ellipsis that cover more than one dimension - auto add_string_indices = [p = 0, ¤t_ind, &ind2](int n, auto const &y) mutable -> void { - using U = std::decay_t; - if constexpr (not argument_is_allowed_for_call) { ind2[p++] = current_ind[n](y); } - }; - (add_string_indices(Is, args), ...); - - return std::make_pair(offset, new_rect_str_t{idxm2, ind2}); - } - - public: - /** - * @brief Get a new nda::rect_str by taking a slice of the current one. - * - * @warning nda::ellipsis that cover more than 1 dimension will not work properly. Use `nda::range::all_t` instead. - * - * @tparam Args Types of the arguments. - * @param args Multi-dimensional index consisting of strings, `long`, `nda::range`, `nda::range::all_t` or - * nda::ellipsis objects. - * @return A std::pair containing the offset in memory, i.e. the flat index of the first element of the slice and - * the new nda::rect_str. - */ - template - auto slice(Args const &...args) const { - return slice_impl(std::make_index_sequence{}, args...); - } - - /** - * @brief Equal-to operator for two nda::rect_str objects. - * - * @param rhs Right hand side nda::rect_str operand. - * @return True if the underlying nda::idx_map and the string indices are equal, false otherwise. - */ - bool operator==(rect_str const &rhs) const { - return base_t::operator==(rhs) and (!s_indices or !rhs.s_indices or (*s_indices == *(rhs.s_indices))); - } - - /** - * @brief Not-equal-to operator for two nda::rect_str objects. - * - * @param rhs Right hand side nda::rect_str operand. - * @return True if they are not equal, false otherwise. - */ - bool operator!=(rect_str const &rhs) { return !(operator==(rhs)); } - - /** - * @brief Create a new nda::rect_str by permuting the indices/dimensions with a given permutation. - * - * @details Let `A` be the current and ``A'`` the new, permuted map. `P` is the given permutation. We define the - * permuted nda::rect_str ``A'`` to be the one with the following properties: - * - ``A'(i_0,...,i_{n-1}) = A(i_{P[0]},...,i_{P[n-1]})`` - * - ``A'.lengths()[k] == A.lengths()[P^{-1}[k]]`` - * - ``A'.strides()[k] == A.strides()[P^{-1}[k]]`` - * - The stride order of ``A'`` is the composition of `P` and the stride order of `A` (note that the stride order - * itself is a permutation). - * - * @tparam Permutation Permutation to apply. - * @return New nda::rect_str with permuted indices. - */ - template - auto transpose() const { - // transpose the underlying nda::idx_map - auto idxm2 = base_t::template transpose(); - - // type of transposed nda::rect_str - using new_rect_str_t = typename detail::rect_str_from_base>::type; - - // if the string indices have not been initialized, simply return the transposed nda::rect_str - if (not s_indices) return new_rect_str_t{idxm2}; - - // otherwise transpose the string indices as well - ind_t ind2(s_indices->size()); - static constexpr std::array permu = decode(Permutation); - for (int u = 0; u < Rank; ++u) { ind2[permu[u]] = (*s_indices)[u]; } - return new_rect_str_t{idxm2, ind2}; - } - }; - - /** @} */ - - /** - * @addtogroup layout_pols - * @{ - */ - - /// @cond - // Forward declarations. - struct C_stride_layout_str; - struct F_stride_layout_str; - /// @endcond - - /** - * @brief Contiguous layout policy with C-order (row-major order) and possible string indices. - * @details The last dimension varies the fastest, the first dimension varies the slowest. - */ - struct C_layout_str { - /// Multi-dimensional to flat index mapping. - template - using mapping = rect_str, layout_prop_e::contiguous>; - - /// The same layout policy, but with no guarantee of contiguity. - using with_lowest_guarantee_t = C_stride_layout_str; - - /// The same layout policy, but with guarantee of contiguity. - using contiguous_t = C_layout_str; - }; - - /** - * @brief Contiguous layout policy with Fortran-order (column-major order) and possible string indices. - * @details The first dimension varies the fastest, the last dimension varies the slowest. - */ - struct F_layout_str { - /// Multi-dimensional to flat index mapping. - template - using mapping = rect_str, layout_prop_e::contiguous>; - - /// The same layout policy, but with no guarantee of contiguity. - using with_lowest_guarantee_t = F_stride_layout_str; - - /// The same layout policy, but with guarantee of contiguity. - using contiguous_t = F_layout_str; - }; - - /** - * @brief Strided (non-contiguous) layout policy with C-order (row-major order) and possible string indices. - * @details The last dimension varies the fastest, the first dimension varies the slowest. - */ - struct C_stride_layout_str { - /// Multi-dimensional to flat index mapping. - template - using mapping = rect_str, layout_prop_e::none>; - - /// The same layout policy, but with no guarantee of contiguity. - using with_lowest_guarantee_t = C_stride_layout_str; - - /// The same layout policy, but with guarantee of contiguity. - using contiguous_t = C_layout_str; - }; - - /** - * @brief Strided (non-contiguous) layout policy with Fortran-order (column-major order) and possible string indices. - * @details The first dimension varies the fastest, the last dimension varies the slowest. - */ - struct F_stride_layout_str { - /// Multi-dimensional to flat index mapping. - template - using mapping = rect_str, layout_prop_e::none>; - - /// The same layout policy, but with no guarantee of contiguity. - using with_lowest_guarantee_t = F_stride_layout_str; - - /// The same layout policy, but with guarantee of contiguity. - using contiguous_t = F_layout_str; - }; - - /** - * @brief Generic layout policy with arbitrary order and possible string indices. - * - * @tparam StaticExtent Compile-time known shape (zero if dynamic). - * @tparam StrideOrder Order in which the dimensions are stored in memory. - * @tparam LayoutProp Compile-time guarantees about the layout of the data in memory. - */ - template - struct basic_layout_str { - // FIXME C++20 : StrideOrder will be a std::array WITH SAME rank - /// Multi-dimensional to flat index mapping. - template - using mapping = rect_str; - - /// The same layout policy, but with no guarantee of contiguity. - using with_lowest_guarantee_t = basic_layout_str; - - /// The same layout policy, but with guarantee of contiguity. - using contiguous_t = basic_layout_str; - }; - - namespace detail { - - // Get the correct layout policy given a general nda::rect_str. - template - struct layout_to_policy> { - using type = basic_layout_str; - }; - - // Get the correct layout policy given a general nda::rect_str. - template - struct layout_to_policy, layout_prop_e::contiguous>> { - using type = C_layout_str; - }; - - // Get the correct layout policy given a strided nda::rect_str with C-order. - template - struct layout_to_policy, layout_prop_e::none>> { - using type = C_stride_layout_str; - }; - - } // namespace detail - - /** @} */ - -} // namespace nda diff --git a/test/c++/nda_layout_rect_str.cpp b/test/c++/nda_layout_rect_str.cpp deleted file mode 100644 index 033e3d7d..00000000 --- a/test/c++/nda_layout_rect_str.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) 2018 Commissariat à l'énergie atomique et aux énergies alternatives (CEA) -// Copyright (c) 2018 Centre national de la recherche scientifique (CNRS) -// Copyright (c) 2018-2023 Simons Foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0.txt -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Authors: Thomas Hahn - -#include "./test_common.hpp" - -#include -#include -#include -#include -#include - -#include -#include - -using namespace nda; - -// Make a std::array with long values. -template -std::array make_array(Is... is) { - return {is...}; -} - -TEST(NDA, RectStrFromExistingIdxMap) { - // create a rect_str from an existing idx_map - idx_map<3, 0, C_stride_order<3>, layout_prop_e::contiguous> idxm{{2, 3, 4}}; - auto sidxm = rect_str(idxm); - - // check the basics - EXPECT_EQ(sidxm.rank(), 3); - EXPECT_EQ(sidxm.size(), 24); - EXPECT_EQ(sidxm.ce_size(), 0); - EXPECT_EQ(sidxm.lengths(), (make_array(2, 3, 4))); - EXPECT_EQ(sidxm.strides(), (make_array(12, 4, 1))); - EXPECT_EQ(sidxm.stride_order, (std::array{0, 1, 2})); - EXPECT_EQ(sidxm.min_stride(), 1); - EXPECT_TRUE(sidxm.is_contiguous()); - EXPECT_TRUE(sidxm.is_strided_1d()); - EXPECT_TRUE(sidxm.is_stride_order_C()); - EXPECT_TRUE(sidxm.is_stride_order_valid()); - - // check the string indices - auto idxs = sidxm.get_string_indices(); - for (int i = 0; i < sidxm.rank(); ++i) { - for (int j = 0; j < sidxm.lengths()[i]; ++j) { EXPECT_EQ(idxs(i)(j), std::to_string(j)); } - } - - // check the function call operator - for (int i = 0; i < 2; ++i) { - for (int j = 0; j < 3; ++j) { - for (int k = 0; k < 4; ++k) { - EXPECT_EQ(idxm(i, j, k), sidxm(std::to_string(i), std::to_string(j), std::to_string(k))); - EXPECT_EQ(idxm(i, j, k), sidxm(i, std::to_string(j), k)); - } - } - } -} - -TEST(NDA, RectStrFromGivenStringIndices) { - // create a rect_str from string indices - nda::array, 1> idxs{{"a", "b"}, {"A", "B", "C"}, {"w", "x", "y", "z"}}; - rect_str<3, 0, Fortran_stride_order<3>, layout_prop_e::contiguous> sidxm(idxs); - - // check the basics - EXPECT_EQ(sidxm.rank(), 3); - EXPECT_EQ(sidxm.size(), 24); - EXPECT_EQ(sidxm.ce_size(), 0); - EXPECT_EQ(sidxm.lengths(), (make_array(2, 3, 4))); - EXPECT_EQ(sidxm.strides(), (make_array(1, 2, 6))); - EXPECT_EQ(sidxm.stride_order, (std::array{2, 1, 0})); - EXPECT_EQ(sidxm.min_stride(), 1); - EXPECT_TRUE(sidxm.is_contiguous()); - EXPECT_TRUE(sidxm.is_strided_1d()); - EXPECT_TRUE(sidxm.is_stride_order_Fortran()); - EXPECT_TRUE(sidxm.is_stride_order_valid()); - - // check the function call operator - for (int k = 0; k < 4; ++k) { - for (int j = 0; j < 3; ++j) { - for (int i = 0; i < 2; ++i) { EXPECT_EQ(sidxm(i, j, k), sidxm(idxs(0)(i), idxs(1)(j), idxs(2)(k))); } - } - } -} - -TEST(NDA, RectStrFromDynamicExtentsOnly) { - // create a rect_str from its dynamic extents only - rect_str<2, encode(std::array{0, 10}), C_stride_order<2>, layout_prop_e::contiguous> sidxm(std::array{10l}); - - // check the basics - EXPECT_EQ(sidxm.rank(), 2); - EXPECT_EQ(sidxm.size(), 100); - EXPECT_EQ(sidxm.ce_size(), 0); - EXPECT_EQ(sidxm.lengths(), (make_array(10, 10))); - EXPECT_EQ(sidxm.strides(), (make_array(10, 1))); - EXPECT_EQ(sidxm.stride_order, (std::array{0, 1})); - EXPECT_EQ(sidxm.min_stride(), 1); - EXPECT_TRUE(sidxm.is_contiguous()); - EXPECT_TRUE(sidxm.is_strided_1d()); - EXPECT_TRUE(sidxm.is_stride_order_C()); - EXPECT_TRUE(sidxm.is_stride_order_valid()); - - // check the function call operator - for (int i = 0; i < 10; ++i) { - for (int j = 0; j < 3; ++j) { EXPECT_EQ(sidxm(i, j), sidxm(std::to_string(i), std::to_string(j))); } - } -} - -TEST(NDA, RectStrSlicesFrom3DMap) { - // create a rect_str from string indices - nda::array, 1> idxs{{"a", "b"}, {"a", "b", "c"}, {"a", "b", "c", "d"}}; - rect_str<3, 0, C_stride_order<3>, layout_prop_e::contiguous> sidxm1(idxs); - - // take a trivial full slice (ellipsis are not working) - // auto [offset2, r2] = r1.slice(ellipsis{}); - auto [offset2, sidxm2] = sidxm1.slice(range::all, range::all, range::all); - EXPECT_EQ(offset2, 0); - EXPECT_EQ(sidxm1, sidxm2); - - // take a strided 3D slice - nda::array, 1> idxs3D{{"a", "b"}, {"a", "c"}, {"b", "d"}}; - auto [offset3, sidxm3] = sidxm1.slice(range::all, range(0, 3, 2), range(1, 4, 2)); - EXPECT_EQ(offset3, 1); - EXPECT_EQ(sidxm3.get_string_indices(), idxs3D); - EXPECT_EQ(sidxm3.rank(), 3); - EXPECT_EQ(sidxm3.lengths(), make_array(2, 2, 2)); - EXPECT_EQ(sidxm3.strides(), make_array(12, 8, 2)); - EXPECT_EQ(sidxm3.min_stride(), 2); - EXPECT_EQ(sidxm3.layout_prop, layout_prop_e::none); - - // take a strided 2D slice - nda::array, 1> idxs2D{{"a", "c"}, {"b", "d"}}; - auto [offset4, sidxm4] = sidxm1.slice("a", range(0, 3, 2), range(1, 4, 2)); - EXPECT_EQ(offset4, 1); - EXPECT_EQ(sidxm4.get_string_indices(), idxs2D); - EXPECT_EQ(sidxm4.rank(), 2); - EXPECT_EQ(sidxm4.lengths(), make_array(2, 2)); - EXPECT_EQ(sidxm4.strides(), make_array(8, 2)); - EXPECT_EQ(sidxm4.min_stride(), 2); - EXPECT_EQ(sidxm4.layout_prop, layout_prop_e::none); -} diff --git a/test/c++/nda_str_indices.cpp b/test/c++/nda_str_indices.cpp deleted file mode 100644 index 1d2a2feb..00000000 --- a/test/c++/nda_str_indices.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2020 Simons Foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0.txt -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Authors: Olivier Parcollet - -#include "./test_common.hpp" - -#include -#include - -#include -#include - -// Test fixture for testing arrays with string indices. -class NDAStringIndices : public ::testing::Test { - protected: - using lay_t = nda::array::layout_t; - nda::array A; - nda::array, 1> str_idxs; - - void SetUp() override { - str_idxs = nda::array, 1>{{"a", "b", "c"}, {"A", "B"}}; - lay_t lay{str_idxs}; - A = nda::array(lay); - for (int i = 0; i < A.shape()[0]; ++i) - for (int j = 0; j < A.shape()[1]; ++j) A(i, j) = i + 10 * j; - } -}; - -TEST_F(NDAStringIndices, ConstructArrayWithoutStringIndices) { - nda::array B(3, 2); - nda::array, 1> idxs = B.indexmap().get_string_indices(); - EXPECT_EQ(idxs.shape(), (std::array{2})); - for (int i = 0; i < B.rank; ++i) - for (int j = 0; j < B.shape()[i]; ++j) EXPECT_EQ(idxs(i)(j), std::to_string(j)); -} - -TEST_F(NDAStringIndices, ConstructArrayWithStringIndices) { - EXPECT_EQ(A.shape(), (std::array{3, 2})); - EXPECT_EQ(str_idxs, A.indexmap().get_string_indices()()); -} - -TEST_F(NDAStringIndices, ConstructArrayWithStringIndexLayout) { - nda::array B(lay_t{str_idxs}); - EXPECT_EQ(B.shape(), (std::array{3, 2})); - EXPECT_EQ(str_idxs, B.indexmap().get_string_indices()()); -} - -TEST_F(NDAStringIndices, CrossConstructArray) { - nda::array B(A); - EXPECT_EQ(A.shape(), B.shape()); - for (int i = 0; i < A.shape()[0]; ++i) - for (int j = 0; j < A.shape()[1]; ++j) EXPECT_EQ(B(i, j), A(i, j)); -} - -TEST_F(NDAStringIndices, CrossConstructView) { - nda::array_view B_v(A); - EXPECT_EQ(A.shape(), B_v.shape()); - for (int i = 0; i < A.shape()[0]; ++i) - for (int j = 0; j < A.shape()[1]; ++j) EXPECT_EQ(B_v(i, j), A(i, j)); -} - -TEST_F(NDAStringIndices, AccessArray) { - EXPECT_EQ(A(std::string{"a"}, std::string{"A"}), A(0, 0)); - - for (int i = 0; i < A.shape()[0]; ++i) - for (int j = 0; j < A.shape()[1]; ++j) EXPECT_EQ(A(str_idxs[0][i], str_idxs[1][j]), A(i, j)); - - EXPECT_EQ(A("a", "A"), A(0, 0)); - - EXPECT_THROW(A("z", "A"), nda::runtime_error); -} - -TEST_F(NDAStringIndices, EqualToOperator) { - EXPECT_TRUE(A == A); - auto B = A; - EXPECT_TRUE(A == B); - B(0, 0) += 3; - EXPECT_FALSE(A == B); -} - -TEST_F(NDAStringIndices, SliceRangeAll) { - auto slice = A(nda::range::all, "A"); - nda::array_view A_v(A); - auto exp_v = A_v(nda::range::all, 0); - nda::array, 1> idxs{{"a", "b", "c"}}; - EXPECT_EQ_ARRAY(slice, exp_v); - EXPECT_EQ(slice.indexmap().get_string_indices(), idxs); -} - -TEST_F(NDAStringIndices, SliceRange) { - auto slice = A(nda::range(0, 2), "A"); - nda::array_view A_v(A); - auto exp_v = A_v(nda::range(0, 2), 0); - nda::array, 1> idxs{{"a", "b"}}; - EXPECT_EQ_ARRAY(slice, exp_v); - EXPECT_EQ(slice.indexmap().get_string_indices(), idxs); -} - -TEST_F(NDAStringIndices, TransposedView) { - auto A_t = nda::transposed_view<1, 0>(A); - - nda::array, 1> idxs_t{{"A", "B"}, {"a", "b", "c"}}; - EXPECT_EQ(A_t.indexmap().get_string_indices(), idxs_t); - - auto A_v1 = nda::transposed_view<1, 0>(nda::array_view{A}); - auto A_v2 = nda::array_view{A_t}; - EXPECT_EQ_ARRAY(A_v1, A_v2); -}