diff --git a/c++/nda/basic_functions.hpp b/c++/nda/basic_functions.hpp index ce3151355..d747c08b0 100644 --- a/c++/nda/basic_functions.hpp +++ b/c++/nda/basic_functions.hpp @@ -476,7 +476,7 @@ namespace nda { bool operator==(LHS const &lhs, RHS const &rhs) { // FIXME not implemented in clang #ifndef __clang__ - static_assert(std::equality_comparable_with, get_value_t>, + static_assert(std::equality_comparable_with, get_value_t>, "Error in nda::operator==: Only defined when elements are comparable"); #endif if (lhs.shape() != rhs.shape()) return false; diff --git a/c++/nda/gtest_tools.hpp b/c++/nda/gtest_tools.hpp index e3b92d159..3da28477c 100644 --- a/c++/nda/gtest_tools.hpp +++ b/c++/nda/gtest_tools.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2024 Simons Foundation +// Copyright (c) 2019-2021 Simons Foundation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,126 +14,154 @@ // // Authors: Olivier Parcollet, Nils Wentzell +/** + * @file + * @brief Provides convenient tools for testing nda::basic_array and nda::basic_array_view + * objects with googletest. + */ + #pragma once #ifndef NDA_DEBUG #define NDA_DEBUG #endif -#include "nda/basic_array.hpp" -#include -#include -#include // NOLINT +#include "./nda.hpp" -/*#if H5_VERSION_GE(1, 8, 9)*/ -//#include
-//#endif +#include -//using dcomplex = std::complex; +#include +#include +#include -// Complex are close +/** + * @brief Check the absolute difference of two (complex) numbers. + * + * @tparam X Type of the first number. + * @tparam Y Type of the second number. + * @param x First number. + * @param y Second number. + * @param precision Required precision for the comparison to be considered successful. + * @return ::testing::AssertionSuccess() if the absolute difference is less than the given + * precision, ::testing::AssertionFailure() otherwise. + */ template ::testing::AssertionResult complex_are_close(X const &x, Y const &y, double precision = 1.e-10) { using std::abs; if (abs(x - y) < precision) return ::testing::AssertionSuccess(); else - return ::testing::AssertionFailure() << "abs(x-y) = " << abs(x - y) << "\n X = " << x << "\n Y = " << y; + return ::testing::AssertionFailure() << "abs(x - y) = " << abs(x - y) << "\n x = " << x << "\n y = " << y; } +// Macro that uses complex_are_close. #define EXPECT_COMPLEX_NEAR(X, ...) EXPECT_TRUE(complex_are_close(X, __VA_ARGS__)) -// Arrays are equal +/** + * @brief Check that two arrays/views are equal, i.e. that they have the same shape and the + * same elements. + * + * @tparam X Type of the first array/view. + * @tparam Y Type of the second array/view. + * @param x First array/view. + * @param y Second array/view. + * @return ::testing::AssertionSuccess() if the arrays/view have the same shape and the same + * elements, ::testing::AssertionFailure() otherwise. + */ template ::testing::AssertionResult array_are_equal(X const &x, Y const &y) { - if (x.shape() != y.shape()) return ::testing::AssertionFailure() << "Comparing two arrays of different size " << "\n X = " << x << "\n Y = " << y; + if (x.shape() != y.shape()) + return ::testing::AssertionFailure() << "Comparing two arrays of different size " + << "\n X = " << x << "\n Y = " << y; if (x == y) return ::testing::AssertionSuccess(); else return ::testing::AssertionFailure() << "Arrays have different elements\n X = " << x << "\n Y = " << y; } +// Macros that use array_are_equal. #define EXPECT_EQ_ARRAY(X, Y) EXPECT_TRUE(array_are_equal(X, Y)); #define EXPECT_ARRAY_EQ(X, Y) EXPECT_TRUE(array_are_equal(X, Y)); -// Arrays are close +/** + * @brief Check that two arrays/views are close, i.e. that they have the same shape and that + * the largest element of their absolute difference is less than a given precision. + * + * @tparam X Type of the first array/view. + * @tparam Y Type of the second array/view. + * @param x First array/view. + * @param y Second array/view. + * @param precision Required precision for the comparison to be considered successful. + * @return ::testing::AssertionSuccess() if the arrays/view have the same shape and largest + * element of their absolute difference is less than a given precision. + * ::testing::AssertionFailure() otherwise. + */ template -::testing::AssertionResult array_are_close(X const &x1, Y const &y1, double precision = 1.e-10) { - nda::array, nda::get_rank> x = x1; - nda::array, nda::get_rank> y = y1; +::testing::AssertionResult array_are_close(X const &x, Y const &y, double precision = 1.e-10) { + nda::array, nda::get_rank> x_reg = x; + nda::array, nda::get_rank> y_reg = y; - if (x.shape() != y.shape()) return ::testing::AssertionFailure() << "Comparing two arrays of different size " << "\n X = " << x << "\n Y = " << y; + // check their shapes + if (x_reg.shape() != y_reg.shape()) + return ::testing::AssertionFailure() << "Comparing two arrays of different size " + << "\n X = " << x_reg << "\n Y = " << y_reg; - // both x, y are contiguous, I check with basic tools instead of max_element(abs(x - y)) - if (x.size() == 0) return ::testing::AssertionSuccess(); - auto xx = make_regular(x); - auto yy = make_regular(y); - auto maxdiff = max_element(abs(make_regular(xx - yy))); + // empty arrays are considered equal + if (x_reg.size() == 0) return ::testing::AssertionSuccess(); + + // check their difference + const auto maxdiff = max_element(abs(make_regular(x_reg - y_reg))); if (maxdiff < precision) return ::testing::AssertionSuccess(); else - return ::testing::AssertionFailure() << "max_element(abs(x-y)) = " << maxdiff << "\n X = " << x << "\n Y = " << y; + return ::testing::AssertionFailure() << "max_element(abs(X - Y)) = " << maxdiff << "\n X = " << x_reg << "\n Y = " << y_reg; } +// Macro that uses array_are_close. #define EXPECT_ARRAY_NEAR(X, ...) EXPECT_TRUE(array_are_close(X, __VA_ARGS__)) -// Arrays is almost 0 +/** + * @brief Check that an array/view is close to zero, i.e. that its largest absolute element + * is less than 1e-10. + * + * @tparam X Type of the array/view. + * @param x Array/View. + * @return ::testing::AssertionSuccess() if the absolute value of every element is less than + * 1e-10. ::testing::AssertionFailure() otherwise. + */ template -::testing::AssertionResult array_almost_zero(X const &x1) { - double precision = 1.e-10; - nda::array, nda::get_rank> x = x1; +::testing::AssertionResult array_almost_zero(X const &x) { + nda::array, nda::get_rank> x_reg = x; - if (x.size() == 0 || max_element(abs(x)) < precision) + constexpr double eps = 1.e-10; + const auto maxdiff = max_element(abs(x_reg)); + if (x_reg.size() == 0 || maxdiff < eps) return ::testing::AssertionSuccess(); else - return ::testing::AssertionFailure() << "max_element(abs(x-y)) = " << max_element(abs(x)) << "\n X = " << x; + return ::testing::AssertionFailure() << "max_element(abs(X)) = " << maxdiff << "\n X = " << x_reg; } +// Macro that uses array_almost_zero. #define EXPECT_ARRAY_ZERO(X) EXPECT_TRUE(array_almost_zero(X)) -// + +/** + * @brief Check that that two generic objects are close, i.e. that their absolute difference is + * less than 1e-12. + * + * @tparam X Type of the first object. + * @tparam Y Type of the second object. + * @param x First object. + * @param y Second object. + * @return ::testing::AssertionSuccess() if the absolute value of their difference is less than + * 1e-12. ::testing::AssertionFailure() otherwise. + */ template ::testing::AssertionResult generic_are_near(X const &x, Y const &y) { double precision = 1.e-12; using std::abs; if (abs(x - y) > precision) - return ::testing::AssertionFailure() << "X = " << x << " and Y = " << y << " are different. \n Difference is : " << abs(x - y); + return ::testing::AssertionFailure() << "X = " << x << " and Y = " << y << " are different. \n Difference is: " << abs(x - y); return ::testing::AssertionSuccess(); } -#define EXPECT_CLOSE(X, Y) EXPECT_TRUE(generic_are_near(X, Y)); - -// ------------------ HDF5 -------------------- -// -// We serialize to H5, deserialize, compare - -//template T rw_h5(T const &x, std::string filename = "ess", std::string name = "x") { - -//namespace h5 = h5; -//T y; // must be default constructible - -//{ -//h5::file file(filename + ".h5", 'w'); -//h5_write(file, name, x); -//} - -//{ -//h5::file file(filename + ".h5", 'r'); -//h5_read(file, name, y); -//} -//#if H5_VERSION_GE(1, 8, 9) - -////#define TRIQS_TEST_USE_H5_SERIA -//#ifdef TRIQS_TEST_USE_H5_SERIA - -//std::cerr << "Checking H5 serialization/deserialization of \n " << triqs::utility::demangle(typeid(x).name()) << std::endl; -//auto s = h5::serialize(x); -//T x2 = h5::deserialize(s); -//auto s2 = h5::serialize(x); -//std::cerr << "Length of serialization string " << first_dim(s) << std::endl; -//EXPECT_EQ_ARRAY(s, s2); // << "Test h5 save, load, save, compare has failed !"; -//#endif - -//#endif - -//return y; -//} +#define EXPECT_CLOSE(X, Y) EXPECT_TRUE(generic_are_near(X, Y)); diff --git a/c++/nda/sym_grp.hpp b/c++/nda/sym_grp.hpp index 38f8939e7..038e110ac 100644 --- a/c++/nda/sym_grp.hpp +++ b/c++/nda/sym_grp.hpp @@ -280,7 +280,7 @@ namespace nda { for (long i : range(vec.size())) { for (auto const &[lin_idx, op] : sym_classes[i]) { std::apply(a, a.indexmap().to_idx(lin_idx)) = op(vec[i]); } } - }; + } /// Default constructor for a symmetry group. sym_grp() = default; diff --git a/test/c++/clef/common.hpp b/test/c++/clef/common.hpp index f5d71dd78..6f71e5ca7 100644 --- a/test/c++/clef/common.hpp +++ b/test/c++/clef/common.hpp @@ -18,6 +18,7 @@ #include #include +#include #include #include diff --git a/test/c++/nda_basic.cpp b/test/c++/nda_basic.cpp index bad3dd4ef..f4a8d17b0 100644 --- a/test/c++/nda_basic.cpp +++ b/test/c++/nda_basic.cpp @@ -75,13 +75,13 @@ TEST(Assign, Strided) { //NOLINT // P =0 to force out of the first test of slice_layout_prop. We want to test the real algorithm EXPECT_EQ( - nda::slice_static::slice_layout_prop(0, true, std::array{1, 0, 0}, std::array{0, 1, 2}, nda::layout_prop_e::contiguous, 128, 0), + nda::slice_static::detail::slice_layout_prop(0, true, std::array{1, 0, 0}, std::array{0, 1, 2}, nda::layout_prop_e::contiguous, 128, 0), nda::layout_prop_e::strided_1d); EXPECT_EQ( - nda::slice_static::slice_layout_prop(0, true, std::array{0, 1, 0}, std::array{0, 1, 2}, nda::layout_prop_e::contiguous, 128, 0), + nda::slice_static::detail::slice_layout_prop(0, true, std::array{0, 1, 0}, std::array{0, 1, 2}, nda::layout_prop_e::contiguous, 128, 0), nda::layout_prop_e::strided_1d); EXPECT_EQ( - nda::slice_static::slice_layout_prop(0, true, std::array{0, 0, 1}, std::array{0, 1, 2}, nda::layout_prop_e::contiguous, 128, 0), + nda::slice_static::detail::slice_layout_prop(0, true, std::array{0, 0, 1}, std::array{0, 1, 2}, nda::layout_prop_e::contiguous, 128, 0), nda::layout_prop_e::contiguous); static_assert(nda::get_layout_info.prop == nda::layout_prop_e::contiguous); diff --git a/test/c++/nda_functions.cpp b/test/c++/nda_functions.cpp index 9c3ba9bcf..5b6ba2cfd 100644 --- a/test/c++/nda_functions.cpp +++ b/test/c++/nda_functions.cpp @@ -89,7 +89,7 @@ TEST(reshape, checkView) { //NOLINT //================================================ TEST(GroupIndices, check) { //NOLINT - nda::details::is_partition_of_indices<4>(std::array{0, 1}, std::array{2, 3}); + nda::detail::is_partition_of_indices<4>(std::array{0, 1}, std::array{2, 3}); } TEST(GroupIndices, v1) { //NOLINT diff --git a/test/c++/nda_idx_map.cpp b/test/c++/nda_idx_map.cpp index bde3ef2ae..c310f2eb5 100644 --- a/test/c++/nda_idx_map.cpp +++ b/test/c++/nda_idx_map.cpp @@ -23,7 +23,7 @@ auto _ = nda::range::all; auto ___ = nda::ellipsis{}; -using nda::slice_static::slice_stride_order; +using nda::slice_static::slice_idx_map; using namespace nda; @@ -90,7 +90,7 @@ TEST(idxstat, slicemat) { // NOLINT idx_map<2, 0, C_stride_order<2>, layout_prop_e::none> i1{{10, 10}}; - auto [offset2, i2] = slice_stride_order(i1, range(0, 2), 2); + auto [offset2, i2] = slice_idx_map(i1, range(0, 2), 2); static_assert(decltype(i2)::layout_prop == layout_prop_e::strided_1d, "000"); } @@ -101,7 +101,7 @@ TEST(idxstat, slice) { // NOLINT idx_map<3, 0, C_stride_order<3>, layout_prop_e::none> i1{{1, 2, 3}}; - auto [offset2, i2] = slice_stride_order(i1, 0, _, 2); + auto [offset2, i2] = slice_idx_map(i1, 0, _, 2); idx_map<1, 0, C_stride_order<1>, layout_prop_e::strided_1d> c2{{2}, {3}}; @@ -110,7 +110,7 @@ TEST(idxstat, slice) { // NOLINT EXPECT_TRUE(i2 == c2); //NOLINT EXPECT_EQ(offset2, 2); //NOLINT - auto [offset3, i3] = slice_stride_order(i1, _, _, _); + auto [offset3, i3] = slice_idx_map(i1, _, _, _); EXPECT_TRUE(i3 == i1); //NOLINT EXPECT_EQ(offset3, 0); //NOLINT } @@ -119,10 +119,10 @@ TEST(idxstat, slice) { // NOLINT TEST(idxstat, ellipsis) { // NOLINT - EXPECT_EQ(16, encode(nda::slice_static::sliced_mem_stride_order(std::array{0, 1, 2}, std::array{1, 2}))); + EXPECT_EQ(16, encode(nda::slice_static::detail::slice_stride_order(std::array{0, 1, 2}, std::array{1, 2}))); idx_map<3, 0, C_stride_order<3>, layout_prop_e::none> i1{{1, 2, 3}}; - auto [offset2, i2] = slice_stride_order(i1, 0, ___); + auto [offset2, i2] = slice_idx_map(i1, 0, ___); idx_map<2, 0, C_stride_order<2>, layout_prop_e::none> c2{{2, 3}, {3, 1}}; @@ -131,7 +131,7 @@ TEST(idxstat, ellipsis) { // NOLINT EXPECT_TRUE(i2 == c2); //NOLINT EXPECT_EQ(offset2, 0); //NOLINT - auto [offset3, i3] = slice_stride_order(i1, ___); + auto [offset3, i3] = slice_idx_map(i1, ___); EXPECT_TRUE(i3 == i1); //NOLINT EXPECT_EQ(offset3, 0); //NOLINT } @@ -143,7 +143,7 @@ TEST(idxstat, ellipsis2) { // NOLINT idx_map<5, 0, C_stride_order<5>, layout_prop_e::none> i1{{1, 2, 3, 4, 5}}; std::cerr << i1 << std::endl; - auto [offset2, i2] = slice_stride_order(i1, 0, ___, 3, 2); + auto [offset2, i2] = slice_idx_map(i1, 0, ___, 3, 2); idx_map<2, 0, C_stride_order<2>, layout_prop_e::none> c2{{2, 3}, {60, 20}}; std::cerr << i2 << std::endl; diff --git a/test/c++/nda_layout_for_each.cpp b/test/c++/nda_layout_for_each.cpp index 29d0827c2..0dfcd4980 100644 --- a/test/c++/nda_layout_for_each.cpp +++ b/test/c++/nda_layout_for_each.cpp @@ -24,26 +24,26 @@ TEST(NDA, ForEachIndexFromStrideOrder) { constexpr auto order_arr = std::array{1, 2, 0}; constexpr auto order_code = nda::encode(order_arr); - static_assert(nda::details::index_from_stride_order<3>(order_code, 0) == 1); - static_assert(nda::details::index_from_stride_order<3>(order_code, 1) == 2); - static_assert(nda::details::index_from_stride_order<3>(order_code, 2) == 0); - EXPECT_EQ(nda::details::index_from_stride_order<3>(order_code, 0), 1); - EXPECT_EQ(nda::details::index_from_stride_order<3>(order_code, 1), 2); - EXPECT_EQ(nda::details::index_from_stride_order<3>(order_code, 2), 0); + static_assert(nda::detail::index_from_stride_order<3>(order_code, 0) == 1); + static_assert(nda::detail::index_from_stride_order<3>(order_code, 1) == 2); + static_assert(nda::detail::index_from_stride_order<3>(order_code, 2) == 0); + EXPECT_EQ(nda::detail::index_from_stride_order<3>(order_code, 0), 1); + EXPECT_EQ(nda::detail::index_from_stride_order<3>(order_code, 1), 2); + EXPECT_EQ(nda::detail::index_from_stride_order<3>(order_code, 2), 0); } TEST(NDA, ForEachGetExtent) { constexpr auto shape_arr = std::array{2, 3, 4}; constexpr auto shape_code = nda::encode(shape_arr); constexpr auto zeros = nda::stdutil::make_initialized_array(0l); - static_assert(nda::details::get_extent<0, 3, shape_code>(zeros) == 2); - static_assert(nda::details::get_extent<1, 3, shape_code>(zeros) == 3); - static_assert(nda::details::get_extent<2, 3, shape_code>(zeros) == 4); + static_assert(nda::detail::get_extent<0, 3, shape_code>(zeros) == 2); + static_assert(nda::detail::get_extent<1, 3, shape_code>(zeros) == 3); + static_assert(nda::detail::get_extent<2, 3, shape_code>(zeros) == 4); auto shape_dyn = shape_arr; - auto e1 = nda::details::get_extent<0, 3, 0>(shape_dyn); - auto e2 = nda::details::get_extent<1, 3, 0>(shape_dyn); - auto e3 = nda::details::get_extent<2, 3, 0>(shape_dyn); + auto e1 = nda::detail::get_extent<0, 3, 0>(shape_dyn); + auto e2 = nda::detail::get_extent<1, 3, 0>(shape_dyn); + auto e3 = nda::detail::get_extent<2, 3, 0>(shape_dyn); EXPECT_EQ(e1, 2); EXPECT_EQ(e2, 3); EXPECT_EQ(e3, 4); diff --git a/test/c++/nda_view1.cpp b/test/c++/nda_view1.cpp index e60c46b46..e4153aaa7 100644 --- a/test/c++/nda_view1.cpp +++ b/test/c++/nda_view1.cpp @@ -27,7 +27,7 @@ TEST(View, ChangeData) { //NOLINT auto v = a(_, 1, 2); - EXPECT_EQ((nda::slice_static::slice_layout_prop(1, true, std::array{1, 0, 0}, std::array{0, 1, 2}, nda::layout_prop_e::contiguous, + EXPECT_EQ((nda::slice_static::detail::slice_layout_prop(1, true, std::array{1, 0, 0}, std::array{0, 1, 2}, nda::layout_prop_e::contiguous, 128, 0)), nda::layout_prop_e::strided_1d); @@ -59,7 +59,7 @@ TEST(RawPointers, add) { //NOLINT std::vector v1(10), v2(10), vr(10, -1); for (int i = 0; i < 10; ++i) { v1[i] = i; - v2[i] = 10 * i; + v2[i] = 10l * i; } nda::array_view a({3, 3}, v1.data());