Skip to content

Commit

Permalink
fix move semantics
Browse files Browse the repository at this point in the history
  • Loading branch information
iskakoff committed May 6, 2021
1 parent 8d22886 commit a5eac1d
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 13 deletions.
14 changes: 12 additions & 2 deletions accumulators/test/binop_with_scalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@
using namespace alps::accumulators::testing;


template<typename ScalarType>
struct tolerance {
static const ScalarType value = 1e-8;
};

template<>
struct tolerance<float> {
static const float value = 1.1e-4;
};

/// Google Test Fixture: argument is acc_vs_pair_gen<A,T> to test (A<vector<T>> op A<T>)
template <typename TGEN>
class AccumulatorVSBinaryOpTest : public ::testing::Test {
Expand Down Expand Up @@ -57,7 +67,7 @@ class AccumulatorVSBinaryOpTest : public ::testing::Test {
\
ASSERT_EQ(vv_mean.size(),vs_mean.size()) << "Vector means sizes differ!"; \
for (size_t i=0; i<vv_mean.size(); ++i) { \
EXPECT_NEAR(vv_mean[i], vs_mean[i], 1E-8) << "Vector means differ at element " << i; \
EXPECT_NEAR(vv_mean[i], vs_mean[i], tolerance<scalar_data_type>::value) << "Vector means differ at element " << i; \
} \
\
/* do not test error if it is not implemented for the accumulator */ \
Expand All @@ -68,7 +78,7 @@ class AccumulatorVSBinaryOpTest : public ::testing::Test {
\
ASSERT_EQ(vv_err.size(),vs_err.size()) << "Vector errors sizes differ!"; \
for (size_t i=0; i<vv_err.size(); ++i) { \
EXPECT_NEAR(vv_err[i], vs_err[i], 1E-8) << "Vector errors differ at element " << i; \
EXPECT_NEAR(vv_err[i], vs_err[i], tolerance<scalar_data_type>::value) << "Vector errors differ at element " << i; \
} \
}

Expand Down
1 change: 1 addition & 0 deletions hdf5/src/archive_read.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

#include <iostream>
#include <memory>
#include <vector>

#include <hdf5.h>
Expand Down
1 change: 0 additions & 1 deletion utilities/include/alps/numeric/tensors/data_storage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ namespace alps {
data_ = std::move(rhs.data_);
return *this;
};

/**
* General tensor assignment
*
Expand Down
73 changes: 63 additions & 10 deletions utilities/include/alps/numeric/tensors/tensor_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,17 +207,70 @@ namespace alps {
template<typename T2, typename St, typename = std::enable_if<std::is_same<Container, storageType>::value, void >>
tensor_base(tensor_base<T2, Dim, St> &&rhs) noexcept: storage_(rhs.storage()), shape_(rhs.shape()), acc_sizes_(rhs.acc_sizes()) {}

/// Different type assignment
template<typename T2, typename St>
tensor_base < T, Dim, Container > &operator=(const tensor_base < T2, Dim, St> &rhs){
assert(size()==rhs.size());
// Different type assignments

// assign when lhs and rhs containers are same
/// Copy assignment
tensor_base < T, Dim, Container > & operator=(const tensor_base < T, Dim, Container > &rhs) {
shape_ = rhs.shape();
acc_sizes_ = rhs.acc_sizes();
storage_ = rhs.storage();
return *this;
};
}
/// Move assignment
tensor_base < T, Dim, Container > & operator=(tensor_base < T, Dim, Container > &&rhs) {
shape_ = std::move(rhs.shape());
acc_sizes_ = std::move(rhs.acc_sizes());
storage_ = std::move(rhs.storage());
return *this;
}

// assign when lhs and rhs containers are different
/// Copy assignment
template<typename Container2>
typename std::enable_if<!std::is_same<Container2, Container>::value, tensor_base < T, Dim, Container > >::type &
operator=(const tensor_base < T, Dim, Container2 > &rhs) {
shape_ = rhs.shape();
acc_sizes_ = rhs.acc_sizes();
reshape(shape_);
std::copy(rhs.storage().data(), rhs.storage().data() + rhs.storage().size(), storage_.data());
return *this;
}
/// Move assignment
template<typename Container2>
typename std::enable_if<!std::is_same<Container2, Container>::value, tensor_base < T, Dim, Container > >::type &
operator=(tensor_base < T, Dim, Container2 > &&rhs) {
shape_ = rhs.shape();
acc_sizes_ = rhs.acc_sizes();
reshape(shape_);
std::copy(rhs.storage().data(), rhs.storage().data() + rhs.storage().size(), storage_.data());
return *this;
}

// assignment for different rhs value type
/// Copy assignment
tensor_base < T, Dim, Container > &operator=(const tensor_base < T, Dim, Container > &rhs) = default;
template<typename T2, typename Ct2>
typename std::enable_if<!std::is_same<T2, T>::value &&
!std::is_same<Container, Ct2>::value &&
std::is_convertible<T2, T>::value, tensor_base < T, Dim, Container > >::type &
operator=(const tensor_base < T2, Dim, Ct2 > &rhs) {
shape_ = rhs.shape();
acc_sizes_ = rhs.acc_sizes();
reshape(shape_);
std::copy(rhs.storage().data(), rhs.storage().data() + rhs.storage().size(), storage_.data());
}
/// Move assignment
tensor_base < T, Dim, Container > &operator=(tensor_base < T, Dim, Container > &&rhs) = default;
template<typename T2, typename Ct2>
typename std::enable_if<!std::is_same<T2, T>::value &&
!std::is_same<Container, Ct2>::value &&
std::is_convertible<T2, T>::value, tensor_base < T, Dim, Container > >::type &
operator=(tensor_base < T2, Dim, Ct2 > &&rhs) {
shape_ = rhs.shape();
acc_sizes_ = rhs.acc_sizes();
reshape(shape_);
std::copy(rhs.storage().data(), rhs.storage().data() + rhs.storage().size(), storage_.data());
}

/// compare tensors
template<typename T2, typename St>
bool operator==(const tensor_base<T2, Dim, St>& rhs) const {
Expand Down Expand Up @@ -283,10 +336,10 @@ namespace alps {
* @return New tensor equal to the current tensor multiplied by scalar
*/
template<typename S>
typename std::enable_if < !std::is_same < S, tensorType >::value, tensor_base< decltype(S{} + T{}), Dim,
typename std::enable_if < !std::is_same < S, tensorType >::value, tensor_base< decltype(S{} * T{}), Dim,
data_storage< decltype(S{} * T{}) > > >::type operator*(S scalar) const {
tensor_base< decltype(S{} + T{}), Dim, data_storage< decltype(S{} * T{}) > > x(*this);
return (x *= static_cast<decltype(S{} + T{})>(scalar));
tensor_base< decltype(S{} * T{}), Dim, data_storage< decltype(S{} * T{}) > > x(*this);
return (x *= static_cast<decltype(S{} * T{})>(scalar));
};

/**
Expand Down
20 changes: 20 additions & 0 deletions utilities/test/tensor_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,17 +112,37 @@ TEST(TensorTest, TestMoveAssignments) {
size_t N = 10;
Eigen::MatrixXd M1 = Eigen::MatrixXd::Random(N, N);
Eigen::MatrixXd M2 = Eigen::MatrixXd::Random(N, N);
Eigen::MatrixXd M3 = Eigen::MatrixXd::Random(N, N);
Eigen::MatrixXf M4 = Eigen::MatrixXf::Random(N, N);
tensor<double, 2> T1(N, N);
tensor<double, 2> T2(N, N);
tensor<double, 2> T3(N, N);
tensor<float, 2> T4(N, N);
tensor<double, 1> T5(N);
for(size_t i = 0; i< N; ++i) {
for (size_t j = 0; j < N; ++j) {
T1(i,j) = M1(i,j);
T2(i,j) = M2(i,j);
T3(i,j) = M3(i,j);
T4(i,j) = M4(i,j);
}
T5(i) = M3(i,i);
}
// direct move asign
T2 = std::move(T1);
// move asign view to view
T3(1) = std::move(T2(1));
// move assign view to storage
T5 = std::move(T2(3));
ASSERT_EQ(T1.size(), 0ul);
ASSERT_EQ(T2.matrix(), M1);
ASSERT_EQ(T2(1,1), T3(1,1));
ASSERT_TRUE(std::equal(T2(3).storage().data(),
T2(3).storage().data() + T2(3).storage().size(),
T5.storage().data(), [&] (const double & l, const double & r) {return std::abs(l-r)<1e-10; } ));
// move assign convertible types
T2 = std::move(T4);
ASSERT_EQ(T2.matrix(), M4.cast<double>());
}

TEST(TensorTest, TestSlices) {
Expand Down

0 comments on commit a5eac1d

Please sign in to comment.