Skip to content

Commit

Permalink
Merge pull request #265 from gsb76/gab_add_addition_operator
Browse files Browse the repository at this point in the history
Allow for adding of std::array of differing types...
  • Loading branch information
nilsdeppe committed Oct 21, 2017
2 parents b4a5663 + 534e0d7 commit be6656a
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 59 deletions.
73 changes: 73 additions & 0 deletions src/DataStructures/DataVector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,79 @@ bool operator==(const DataVector& lhs, const DataVector& rhs);
/// Inequivalence operator for DataVector
bool operator!=(const DataVector& lhs, const DataVector& rhs);

template <typename T, size_t Dim>
std::array<DataVector, Dim> operator+(
const std::array<T, Dim>& lhs,
const std::array<DataVector, Dim>& rhs) noexcept {
std::array<DataVector, Dim> result;
for (size_t i = 0; i < Dim; i++) {
gsl::at(result, i) = gsl::at(lhs, i) + gsl::at(rhs, i);
}
return result;
}
template <typename U, size_t Dim>
std::array<DataVector, Dim> operator+(const std::array<DataVector, Dim>& lhs,
const std::array<U, Dim>& rhs) noexcept {
return rhs + lhs;
}
template <size_t Dim>
std::array<DataVector, Dim> operator+(
const std::array<DataVector, Dim>& lhs,
const std::array<DataVector, Dim>& rhs) noexcept {
std::array<DataVector, Dim> result;
for (size_t i = 0; i < Dim; i++) {
gsl::at(result, i) = gsl::at(lhs, i) + gsl::at(rhs, i);
}
return result;
}
template <size_t Dim>
std::array<DataVector, Dim>& operator+=(
std::array<DataVector, Dim>& lhs,
const std::array<DataVector, Dim>& rhs) noexcept {
for (size_t i = 0; i < Dim; i++) {
gsl::at(lhs, i) += gsl::at(rhs, i);
}
return lhs;
}
template <typename T, size_t Dim>
std::array<DataVector, Dim> operator-(
const std::array<T, Dim>& lhs,
const std::array<DataVector, Dim>& rhs) noexcept {
std::array<DataVector, Dim> result;
for (size_t i = 0; i < Dim; i++) {
gsl::at(result, i) = gsl::at(lhs, i) - gsl::at(rhs, i);
}
return result;
}
template <typename U, size_t Dim>
std::array<DataVector, Dim> operator-(const std::array<DataVector, Dim>& lhs,
const std::array<U, Dim>& rhs) noexcept {
std::array<DataVector, Dim> result;
for (size_t i = 0; i < Dim; i++) {
gsl::at(result, i) = gsl::at(lhs, i) - gsl::at(rhs, i);
}
return result;
}
template <size_t Dim>
std::array<DataVector, Dim> operator-(
const std::array<DataVector, Dim>& lhs,
const std::array<DataVector, Dim>& rhs) noexcept {
std::array<DataVector, Dim> result;
for (size_t i = 0; i < Dim; i++) {
gsl::at(result, i) = gsl::at(lhs, i) - gsl::at(rhs, i);
}
return result;
}
template <size_t Dim>
std::array<DataVector, Dim>& operator-=(
std::array<DataVector, Dim>& lhs,
const std::array<DataVector, Dim>& rhs) noexcept {
for (size_t i = 0; i < Dim; i++) {
gsl::at(lhs, i) -= gsl::at(rhs, i);
}
return lhs;
}

/// \cond HIDDEN_SYMBOLS
template <typename VT, bool VF>
DataVector::DataVector(const blaze::Vector<VT, VF>& expression)
Expand Down
66 changes: 29 additions & 37 deletions src/Utilities/StdHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,53 +310,49 @@ inline std::string current_date_and_time() {

// Arithmetic operators for std::array<T, Dim>

template <size_t Dim, typename T>
inline std::array<T, Dim>& operator+=(
std::array<T, Dim>& lhs,
const std::array<T, Dim>& rhs) noexcept(noexcept(lhs[0] += rhs[0])) {
template <size_t Dim, typename T, typename U>
inline std::array<T, Dim>& operator+=(std::array<T, Dim>& lhs,
const std::array<U, Dim>& rhs) noexcept {
for (size_t i = 0; i < Dim; ++i) {
gsl::at(lhs, i) += gsl::at(rhs, i);
}
return lhs;
}

template <size_t Dim, typename T>
inline std::array<T, Dim> operator+(
const std::array<T, Dim>& lhs,
const std::array<T, Dim>&
rhs) noexcept(noexcept(std::declval<std::array<T, Dim>&>() += rhs) and
noexcept(std::array<T, Dim>{lhs})) {
std::array<T, Dim> result = lhs;
result += rhs;
template <size_t Dim, typename T, typename U>
inline auto operator+(const std::array<T, Dim>& lhs,
const std::array<U, Dim>& rhs) noexcept
-> std::array<decltype(lhs[0] + rhs[0]), Dim> {
std::array<decltype(lhs[0] + rhs[0]), Dim> result{};
for (size_t i = 0; i < Dim; ++i) {
gsl::at(result, i) = gsl::at(lhs, i) + gsl::at(rhs, i);
}
return result;
}

template <size_t Dim, typename T>
inline std::array<T, Dim>& operator-=(
std::array<T, Dim>& lhs,
const std::array<T, Dim>& rhs) noexcept(noexcept(lhs[0] -= rhs[0])) {
template <size_t Dim, typename T, typename U>
inline std::array<T, Dim>& operator-=(std::array<T, Dim>& lhs,
const std::array<U, Dim>& rhs) noexcept {
for (size_t i = 0; i < Dim; ++i) {
gsl::at(lhs, i) -= gsl::at(rhs, i);
}
return lhs;
}

template <size_t Dim, typename T>
inline std::array<T, Dim> operator-(
const std::array<T, Dim>& lhs,
const std::array<T, Dim>&
rhs) noexcept(noexcept(std::declval<std::array<T, Dim>&>() -= rhs) and
noexcept(std::array<T, Dim>{lhs})) {
std::array<T, Dim> result = lhs;
result -= rhs;
template <size_t Dim, typename T, typename U>
inline auto operator-(const std::array<T, Dim>& lhs,
const std::array<U, Dim>& rhs) noexcept
-> std::array<decltype(lhs[0] - rhs[0]), Dim> {
std::array<decltype(lhs[0] - rhs[0]), Dim> result{};
for (size_t i = 0; i < Dim; ++i) {
gsl::at(result, i) = gsl::at(lhs, i) - gsl::at(rhs, i);
}
return result;
}

template <size_t Dim, typename T, typename U>
inline std::array<T, Dim> operator*(
const std::array<T, Dim>& lhs,
const U& scale) noexcept(noexcept(lhs[0] * scale) and
noexcept(std::array<T, Dim>{})) {
inline std::array<T, Dim> operator*(const std::array<T, Dim>& lhs,
const U& scale) noexcept {
std::array<T, Dim> result{};
for (size_t i = 0; i < Dim; ++i) {
gsl::at(result, i) = gsl::at(lhs, i) * scale;
Expand All @@ -365,17 +361,14 @@ inline std::array<T, Dim> operator*(
}

template <size_t Dim, typename T, typename U>
inline std::array<T, Dim> operator*(
const U& scale,
const std::array<T, Dim>& rhs) noexcept(noexcept(rhs* scale)) {
inline std::array<T, Dim> operator*(const U& scale,
const std::array<T, Dim>& rhs) noexcept {
return rhs * scale;
}

template <size_t Dim, typename T, typename U>
inline std::array<T, Dim> operator/(
const std::array<T, Dim>& lhs,
const U& scale) noexcept(noexcept(lhs[0] / scale) and
noexcept(std::array<T, Dim>{})) {
inline std::array<T, Dim> operator/(const std::array<T, Dim>& lhs,
const U& scale) noexcept {
std::array<T, Dim> result{};
for (size_t i = 0; i < Dim; ++i) {
gsl::at(result, i) = gsl::at(lhs, i) / scale;
Expand All @@ -384,8 +377,7 @@ inline std::array<T, Dim> operator/(
}

template <size_t Dim, typename T>
inline std::array<T, Dim> operator-(const std::array<T, Dim>& rhs) noexcept(
noexcept(-rhs[0]) and noexcept(std::array<T, Dim>{})) {
inline std::array<T, Dim> operator-(const std::array<T, Dim>& rhs) noexcept {
std::array<T, Dim> result{};
for (size_t i = 0; i < Dim; ++i) {
gsl::at(result, i) = -gsl::at(rhs, i);
Expand Down
71 changes: 71 additions & 0 deletions tests/Unit/DataStructures/Test_DataVector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,77 @@ SPECTRE_TEST_CASE("Unit.DataStructures.DataVector.Math",
x = DataVector(num_pts, 2.);
check_vectors(DataVector(num_pts, 0.82682181043180603), square(sin(x)));
check_vectors(DataVector(num_pts, -0.072067555747765299), cube(cos(x)));

// Test addition of arrays of DataVectors to arrays of doubles.
const DataVector t1{0.0, 1.0, 2.0, 3.0};
const DataVector t2{-0.1, -0.2, -0.3, -0.4};
const DataVector t3{5.0, 4.0, 3.0, 2.0};
const DataVector e1{10.0, 11.0, 12.0, 13.0};
const DataVector e2{19.9, 19.8, 19.7, 19.6};
const DataVector e3{35.0, 34.0, 33.0, 32.0};
const DataVector e4{-10.0, -9.0, -8.0, -7.0};
const DataVector e5{-20.1, -20.2, -20.3, -20.4};
const DataVector e6{-25.0, -26.0, -27.0, -28.0};
const DataVector e7{10.0, 12.0, 14.0, 16.0};
const DataVector e8{19.8, 19.6, 19.4, 19.2};
const DataVector e9{40.0, 38.0, 36.0, 34.0};
const DataVector e10{-10.0, -10.0, -10.0, -10.0};
const DataVector e11{-20.0, -20.0, -20.0, -20.0};
const DataVector e12{-30.0, -30.0, -30.0, -30.0};

const std::array<double, 3> point{{10.0, 20.0, 30.0}};
std::array<DataVector, 3> points{{t1, t2, t3}};
const std::array<DataVector, 3> expected{{e1, e2, e3}};
const std::array<DataVector, 3> expected2{{e4, e5, e6}};
std::array<DataVector, 3> dvectors1{{t1, t2, t3}};
const std::array<DataVector, 3> dvectors2{{e1, e2, e3}};
const std::array<DataVector, 3> expected3{{e7, e8, e9}};
const std::array<DataVector, 3> expected4{{e10, e11, e12}};
CHECK(points + point == expected);
CHECK(point + points == expected);
CHECK(points - point == expected2);
CHECK(point - points == -expected2);

points += point;
CHECK(points == expected);
points -= point;
points -= point;
CHECK(points == expected2);

for (size_t i = 0; i < 3; i++) {
check_vectors(gsl::at((dvectors1 + dvectors2), i), gsl::at(expected3, i));
check_vectors(gsl::at((dvectors1 - dvectors2), i), gsl::at(expected4, i));
}
dvectors1 += dvectors2;
for (size_t i = 0; i < 3; i++) {
check_vectors(gsl::at(dvectors1, i), gsl::at(expected3, i));
}
dvectors1 -= dvectors2;
dvectors1 -= dvectors2;
for (size_t i = 0; i < 3; i++) {
check_vectors(gsl::at(dvectors1, i), gsl::at(expected4, i));
}

// Test calculation of magnitude of DataVector
const std::array<DataVector, 1> d1{{DataVector{-2.5, 3.4}}};
const DataVector expected_d1{2.5, 3.4};
const auto magnitude_d1 = magnitude(d1);
for (size_t i = 0; i < 2; ++i) {
CHECK(expected_d1[i] == approx(magnitude_d1[i]));
}
const std::array<DataVector, 2> d2{{DataVector(2, 3.), DataVector(2, 4.)}};
const DataVector expected_d2(2, 5.);
const auto magnitude_d2 = magnitude(d2);
for (size_t i = 0; i < 2; ++i) {
CHECK(expected_d2[i] == approx(magnitude_d2[i]));
}
const std::array<DataVector, 3> d3{
{DataVector(2, 3.), DataVector(2, -4.), DataVector(2, 12.)}};
const DataVector expected_d3(2, 13.);
const auto magnitude_d3 = magnitude(d3);
for (size_t i = 0; i < 2; ++i) {
CHECK(expected_d3[i] == approx(magnitude_d3[i]));
}
}

// [[OutputRegex, Must copy into same size]]
Expand Down
44 changes: 22 additions & 22 deletions tests/Unit/Utilities/Test_StdHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@
#include <unordered_set>
#include <vector>

#include "DataStructures/DataVector.hpp"
#include "Utilities/Gsl.hpp"
#include "Utilities/Literals.hpp"
#include "Utilities/MakeArray.hpp"
// We wish to explicitly test implicit type conversion when adding std::arrays
// of different fundamentals, so we supress this warning.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#include "Utilities/StdHelpers.hpp"
#pragma GCC diagnostic pop
#include "tests/Unit/TestHelpers.hpp"

SPECTRE_TEST_CASE("Unit.Utilities.StdHelpers.Output", "[Utilities][Unit]") {
Expand Down Expand Up @@ -147,6 +151,23 @@ SPECTRE_TEST_CASE("Unit.Utilities.StdHelpers.StdArrayArithmetic",
for (size_t i = 0; i < Dim; ++i) {
CHECK(gsl::at(neg_p1, i) == approx(gsl::at(expected_neg_p1, i)));
}

const std::array<double, 2> double_array{{2.2, -1.0}};
const std::array<int, 2> int_array{{1, 3}};
const std::array<size_t, 2> size_array{{2, 10}};
const std::array<double, 2> double_plus_int{{3.2, 2.0}};
const std::array<double, 2> double_plus_size{{4.2, 9.0}};
const std::array<size_t, 2> int_plus_size{{3, 13}};
const std::array<size_t, 2> size_minus_int{{1, 7}};
CHECK(double_array + int_array == double_plus_int);
CHECK(double_array + size_array == double_plus_size);
CHECK(int_array + size_array == int_plus_size);
CHECK(int_array + double_array == double_plus_int);
CHECK(size_array + double_array == double_plus_size);
CHECK(size_array + int_array == int_plus_size);
CHECK(size_array - -int_array == int_plus_size);
CHECK(size_array - -double_array == double_plus_size);
CHECK(size_array - int_array == size_minus_int);
}

SPECTRE_TEST_CASE("Unit.Utilities.StdHelpers.StdArrayMagnitude",
Expand All @@ -157,27 +178,6 @@ SPECTRE_TEST_CASE("Unit.Utilities.StdHelpers.StdArrayMagnitude",
CHECK(magnitude(p2) == approx(5.));
const std::array<double, 3> p3{{-2., 10., 11.}};
CHECK(magnitude(p3) == approx(15.));

// Check DataVector case
const std::array<DataVector, 1> d1{{DataVector{-2.5, 3.4}}};
const DataVector expected_d1{2.5, 3.4};
const auto magnitude_d1 = magnitude(d1);
for (size_t i = 0; i < 2; ++i) {
CHECK(expected_d1[i] == approx(magnitude_d1[i]));
}
const std::array<DataVector, 2> d2{{DataVector(2, 3.), DataVector(2, 4.)}};
const DataVector expected_d2(2, 5.);
const auto magnitude_d2 = magnitude(d2);
for (size_t i = 0; i < 2; ++i) {
CHECK(expected_d2[i] == approx(magnitude_d2[i]));
}
const std::array<DataVector, 3> d3{
{DataVector(2, 3.), DataVector(2, -4.), DataVector(2, 12.)}};
const DataVector expected_d3(2, 13.);
const auto magnitude_d3 = magnitude(d3);
for (size_t i = 0; i < 2; ++i) {
CHECK(expected_d3[i] == approx(magnitude_d3[i]));
}
}

SPECTRE_TEST_CASE("Unit.Utilities.StdHelpers.AllButSpecifiedElementOf",
Expand Down

0 comments on commit be6656a

Please sign in to comment.