TRIQS/nda 1.3.0
Multi-dimensional array library for C++
Loading...
Searching...
No Matches
gtest_tools.hpp
Go to the documentation of this file.
1// Copyright (c) 2019-2021 Simons Foundation
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0.txt
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// Authors: Olivier Parcollet, Nils Wentzell
16
17/**
18 * @file
19 * @brief Provides convenient tools for checking nda::basic_array and nda::basic_array_view objects with googletest.
20 */
21
22#pragma once
23
24#ifndef NDA_DEBUG
25#define NDA_DEBUG
26#endif
27
28#include "./nda.hpp"
29
30#include <gtest/gtest.h>
31
32#include <cstdlib>
33#include <iostream>
34#include <sstream>
35
36/**
37 * @addtogroup testing
38 * @{
39 */
40
41/**
42 * @brief Check the absolute difference of two (complex) numbers.
43 *
44 * @tparam X Type of the first number.
45 * @tparam Y Type of the second number.
46 * @param x First number.
47 * @param y Second number.
48 * @param precision Required precision for the comparison to be considered successful.
49 * @return `::testing::AssertionSuccess()` if the absolute difference is less than the given precision,
50 * `::testing::AssertionFailure()` otherwise.
51 */
52template <typename X, typename Y>
53::testing::AssertionResult complex_are_close(X const &x, Y const &y, double precision = 1.e-10) {
54 using std::abs;
55 if (abs(x - y) < precision)
56 return ::testing::AssertionSuccess();
57 else
58 return ::testing::AssertionFailure() << "abs(x - y) = " << abs(x - y) << "\n x = " << x << "\n y = " << y;
59}
60
61/// Macro that expects ::complex_are_close to return true.
62#define EXPECT_COMPLEX_NEAR(X, ...) EXPECT_TRUE(complex_are_close(X, __VA_ARGS__))
63
64/**
65 * @brief Check that two arrays/views are equal, i.e. that they have the same shape and the same elements.
66 *
67 * @tparam X Type of the first array/view.
68 * @tparam Y Type of the second array/view.
69 * @param x First array/view.
70 * @param y Second array/view.
71 * @return `::testing::AssertionSuccess()` if the arrays/view have the same shape and the same elements,
72 * `::testing::AssertionFailure()` otherwise.
73 */
74template <typename X, typename Y>
75::testing::AssertionResult array_are_equal(X const &x, Y const &y) {
76 if (x.shape() != y.shape())
77 return ::testing::AssertionFailure() << "Comparing two arrays of different size "
78 << "\n X = " << x << "\n Y = " << y;
79 if (x == y)
80 return ::testing::AssertionSuccess();
81 else
82 return ::testing::AssertionFailure() << "Arrays have different elements\n X = " << x << "\n Y = " << y;
83}
84
85/// Macro that expects ::array_are_equal to return true.
86#define EXPECT_EQ_ARRAY(X, Y) EXPECT_TRUE(array_are_equal(X, Y));
87
88/// Macro that expects ::array_are_equal to return true.
89#define EXPECT_ARRAY_EQ(X, Y) EXPECT_TRUE(array_are_equal(X, Y));
90
91/**
92 * @brief Check that two arrays/views are close, i.e. that they have the same shape and that the largest element of
93 * their absolute difference is less than a given precision.
94 *
95 * @tparam X Type of the first array/view.
96 * @tparam Y Type of the second array/view.
97 * @param x First array/view.
98 * @param y Second array/view.
99 * @param precision Required precision for the comparison to be considered successful.
100 * @return `::testing::AssertionSuccess()` if the arrays/view have the same shape and largest element of their absolute
101 * difference is less than a given precision. `::testing::AssertionFailure()` otherwise.
102 */
103template <typename X, typename Y>
104::testing::AssertionResult array_are_close(X const &x, Y const &y, double precision = 1.e-10) {
105 nda::array<nda::get_value_t<X>, nda::get_rank<X>> x_reg = x;
106 nda::array<nda::get_value_t<X>, nda::get_rank<X>> y_reg = y;
107
108 // check their shapes
109 if (x_reg.shape() != y_reg.shape())
110 return ::testing::AssertionFailure() << "Comparing two arrays of different size "
111 << "\n X = " << x_reg << "\n Y = " << y_reg;
112
113 // empty arrays are considered equal
114 if (x_reg.size() == 0) return ::testing::AssertionSuccess();
115
116 // check their difference
117 const auto maxdiff = max_element(abs(make_regular(x_reg - y_reg)));
118 if (maxdiff < precision)
119 return ::testing::AssertionSuccess();
120 else
121 return ::testing::AssertionFailure() << "max_element(abs(X - Y)) = " << maxdiff << "\n X = " << x_reg << "\n Y = " << y_reg;
122}
123
124/// Macro that expects ::array_are_close to return true.
125#define EXPECT_ARRAY_NEAR(X, ...) EXPECT_TRUE(array_are_close(X, __VA_ARGS__))
126
127/**
128 * @brief Check that an array/view is close to zero, i.e. that its largest absolute element is less than 1e-10.
129 *
130 * @tparam X Type of the array/view.
131 * @param x Array/View.
132 * @return `::testing::AssertionSuccess()` if the absolute value of every element is less than 1e-10.
133 * `::testing::AssertionFailure()` otherwise.
134 */
135template <typename X>
136::testing::AssertionResult array_almost_zero(X const &x) {
137 nda::array<nda::get_value_t<X>, nda::get_rank<X>> x_reg = x;
138
139 constexpr double eps = 1.e-10;
140 const auto max = max_element(abs(x_reg));
141 if (x_reg.size() == 0 || max < eps)
142 return ::testing::AssertionSuccess();
143 else
144 return ::testing::AssertionFailure() << "max_element(abs(X)) = " << max << "\n X = " << x_reg;
145}
146
147/// Macro that expects ::array_almost_zero to return true.
148#define EXPECT_ARRAY_ZERO(X) EXPECT_TRUE(array_almost_zero(X))
149
150/**
151 * @brief Check that that two generic objects are close, i.e. that their absolute difference is less than 1e-12.
152 *
153 * @tparam X Type of the first object.
154 * @tparam Y Type of the second object.
155 * @param x First object.
156 * @param y Second object.
157 * @return `::testing::AssertionSuccess()` if the absolute value of their difference is less than 1e-12.
158 * `::testing::AssertionFailure()` otherwise.
159 */
160template <typename X, typename Y>
161::testing::AssertionResult generic_are_near(X const &x, Y const &y) {
162 double precision = 1.e-12;
163 using std::abs;
164 if (abs(x - y) > precision)
165 return ::testing::AssertionFailure() << "X = " << x << " and Y = " << y << " are different. \n Difference is: " << abs(x - y);
166 return ::testing::AssertionSuccess();
167}
168
169/// Macro that expects ::generic_are_near to return true.
170#define EXPECT_CLOSE(X, Y) EXPECT_TRUE(generic_are_near(X, Y));
171
172/** @} */
::testing::AssertionResult array_almost_zero(X const &x)
Check that an array/view is close to zero, i.e. that its largest absolute element is less than 1e-10.
::testing::AssertionResult generic_are_near(X const &x, Y const &y)
Check that that two generic objects are close, i.e. that their absolute difference is less than 1e-12...
::testing::AssertionResult array_are_close(X const &x, Y const &y, double precision=1.e-10)
Check that two arrays/views are close, i.e. that they have the same shape and that the largest elemen...
::testing::AssertionResult array_are_equal(X const &x, Y const &y)
Check that two arrays/views are equal, i.e. that they have the same shape and the same elements.
::testing::AssertionResult complex_are_close(X const &x, Y const &y, double precision=1.e-10)
Check the absolute difference of two (complex) numbers.