Commit 34243643 authored by Jens Petit's avatar Jens Petit
Browse files

Extend draft to Operators

parent 13011618
Pipeline #211226 failed with stages
in 25 seconds
......@@ -37,9 +37,9 @@ endif()
# add the elsa modules
add_subdirectory(core)
#add_subdirectory(logging)
#add_subdirectory(io)
#add_subdirectory(operators)
add_subdirectory(logging)
add_subdirectory(io)
add_subdirectory(operators)
#add_subdirectory(functionals)
#add_subdirectory(problems)
#add_subdirectory(solvers)
......
......@@ -45,7 +45,8 @@ namespace elsa
}
template <>
DataContainer<float, 0>::DataContainer(const DataDescriptor& dataDescriptor, const Eigen::Matrix<float, Eigen::Dynamic, 1>& data)
DataContainer<float, 0>::DataContainer(const DataDescriptor& dataDescriptor,
const Eigen::Matrix<float, Eigen::Dynamic, 1>& data)
: _dataDescriptor{dataDescriptor.clone()},
_dataHandler{_dataDescriptor->getNumberOfCoefficients()}
{
......@@ -57,7 +58,8 @@ namespace elsa
}
template <>
DataContainer<double, 0>::DataContainer(const DataDescriptor& dataDescriptor, const Eigen::Matrix<double, Eigen::Dynamic, 1>& data)
DataContainer<double, 0>::DataContainer(const DataDescriptor& dataDescriptor,
const Eigen::Matrix<double, Eigen::Dynamic, 1>& data)
: _dataDescriptor{dataDescriptor.clone()},
_dataHandler{_dataDescriptor->getNumberOfCoefficients()}
{
......@@ -69,7 +71,9 @@ namespace elsa
}
template <>
DataContainer<std::complex<float>, 0>::DataContainer(const DataDescriptor& dataDescriptor, const Eigen::Matrix<std::complex<float>, Eigen::Dynamic, 1>& data)
DataContainer<std::complex<float>, 0>::DataContainer(
const DataDescriptor& dataDescriptor,
const Eigen::Matrix<std::complex<float>, Eigen::Dynamic, 1>& data)
: _dataDescriptor{dataDescriptor.clone()},
_dataHandler{_dataDescriptor->getNumberOfCoefficients()}
{
......@@ -81,7 +85,9 @@ namespace elsa
}
template <>
DataContainer<std::complex<double>, 0>::DataContainer(const DataDescriptor& dataDescriptor, const Eigen::Matrix<std::complex<double>, Eigen::Dynamic, 1>& data)
DataContainer<std::complex<double>, 0>::DataContainer(
const DataDescriptor& dataDescriptor,
const Eigen::Matrix<std::complex<double>, Eigen::Dynamic, 1>& data)
: _dataDescriptor{dataDescriptor.clone()},
_dataHandler{_dataDescriptor->getNumberOfCoefficients()}
{
......@@ -93,7 +99,8 @@ namespace elsa
}
template <>
DataContainer<index_t, 0>::DataContainer(const DataDescriptor& dataDescriptor, const Eigen::Matrix<index_t, Eigen::Dynamic, 1>& data)
DataContainer<index_t, 0>::DataContainer(const DataDescriptor& dataDescriptor,
const Eigen::Matrix<index_t, Eigen::Dynamic, 1>& data)
: _dataDescriptor{dataDescriptor.clone()},
_dataHandler{_dataDescriptor->getNumberOfCoefficients()}
{
......@@ -106,13 +113,13 @@ namespace elsa
template <typename data_t, int handler_t>
DataContainer<data_t, handler_t>::DataContainer(const DataContainer_t& other)
: _dataDescriptor{other._dataDescriptor->clone()},
_dataHandler{other._dataHandler}
: _dataDescriptor{other._dataDescriptor->clone()}, _dataHandler{other._dataHandler}
{
}
template <typename data_t, int handler_t>
DataContainer<data_t, handler_t>& DataContainer<data_t, handler_t>::operator=(const DataContainer<data_t, handler_t>& other)
DataContainer<data_t, handler_t>& DataContainer<data_t, handler_t>::
operator=(const DataContainer<data_t, handler_t>& other)
{
if (this != &other) {
_dataDescriptor = other._dataDescriptor->clone();
......@@ -132,7 +139,8 @@ namespace elsa
}
template <typename data_t, int handler_t>
DataContainer<data_t, handler_t>& DataContainer<data_t, handler_t>::operator=(DataContainer_t&& other)
DataContainer<data_t, handler_t>& DataContainer<data_t, handler_t>::
operator=(DataContainer_t&& other)
{
_dataDescriptor = std::move(other._dataDescriptor);
_dataHandler = std::move(other._dataHandler);
......@@ -181,8 +189,7 @@ namespace elsa
}
template <typename data_t, int handler_t>
data_t
DataContainer<data_t, handler_t>::dot(const DataContainer_t& other) const
data_t DataContainer<data_t, handler_t>::dot(const DataContainer_t& other) const
{
return _dataHandler.dot(other._dataHandler);
}
......@@ -279,33 +286,42 @@ namespace elsa
}
template <>
DataContainer<float, DataHandlerType::MAP_CPU>::DataContainer(const DataDescriptor& dataDescriptor, DataHandlerMapCPU<float> dataHandler)
: _dataDescriptor{dataDescriptor.clone()},
_dataHandler{std::move(dataHandler)} {}
DataContainer<float, DataHandlerType::MAP_CPU>::DataContainer(
const DataDescriptor& dataDescriptor, DataHandlerMapCPU<float> dataHandler)
: _dataDescriptor{dataDescriptor.clone()}, _dataHandler{std::move(dataHandler)}
{
}
template <>
DataContainer<std::complex<double>, DataHandlerType::MAP_CPU>::DataContainer(const DataDescriptor& dataDescriptor, DataHandlerMapCPU<std::complex<double>> dataHandler)
: _dataDescriptor{dataDescriptor.clone()},
_dataHandler{std::move(dataHandler)} {}
DataContainer<std::complex<double>, DataHandlerType::MAP_CPU>::DataContainer(
const DataDescriptor& dataDescriptor, DataHandlerMapCPU<std::complex<double>> dataHandler)
: _dataDescriptor{dataDescriptor.clone()}, _dataHandler{std::move(dataHandler)}
{
}
template <>
DataContainer<std::complex<float>, DataHandlerType::MAP_CPU>::DataContainer(const DataDescriptor& dataDescriptor, DataHandlerMapCPU<std::complex<float>> dataHandler)
: _dataDescriptor{dataDescriptor.clone()},
_dataHandler{std::move(dataHandler)} {}
DataContainer<std::complex<float>, DataHandlerType::MAP_CPU>::DataContainer(
const DataDescriptor& dataDescriptor, DataHandlerMapCPU<std::complex<float>> dataHandler)
: _dataDescriptor{dataDescriptor.clone()}, _dataHandler{std::move(dataHandler)}
{
}
template <>
DataContainer<index_t, DataHandlerType::MAP_CPU>::DataContainer(const DataDescriptor& dataDescriptor, DataHandlerMapCPU<index_t> dataHandler)
: _dataDescriptor{dataDescriptor.clone()},
_dataHandler{std::move(dataHandler)} {}
DataContainer<index_t, DataHandlerType::MAP_CPU>::DataContainer(
const DataDescriptor& dataDescriptor, DataHandlerMapCPU<index_t> dataHandler)
: _dataDescriptor{dataDescriptor.clone()}, _dataHandler{std::move(dataHandler)}
{
}
template <>
DataContainer<double, DataHandlerType::MAP_CPU>::DataContainer(const DataDescriptor& dataDescriptor, DataHandlerMapCPU<double> dataHandler)
: _dataDescriptor{dataDescriptor.clone()},
_dataHandler{std::move(dataHandler)} {}
DataContainer<double, DataHandlerType::MAP_CPU>::DataContainer(
const DataDescriptor& dataDescriptor, DataHandlerMapCPU<double> dataHandler)
: _dataDescriptor{dataDescriptor.clone()}, _dataHandler{std::move(dataHandler)}
{
}
template <typename data_t, int handler_t>
bool DataContainer<data_t, handler_t>::
operator==(const DataContainer_t& other) const
bool DataContainer<data_t, handler_t>::operator==(const DataContainer_t& other) const
{
if (*_dataDescriptor != *other._dataDescriptor)
return false;
......@@ -317,14 +333,14 @@ namespace elsa
}
template <typename data_t, int handler_t>
bool DataContainer<data_t, handler_t>::
operator!=(const DataContainer_t& other) const
bool DataContainer<data_t, handler_t>::operator!=(const DataContainer_t& other) const
{
return !(*this == other);
}
template <typename data_t, int handler_t>
DataContainer<data_t, DataHandlerType::MAP_CPU> DataContainer<data_t, handler_t>::getBlock(index_t i)
DataContainer<data_t, DataHandlerType::MAP_CPU>
DataContainer<data_t, handler_t>::getBlock(index_t i)
{
const auto blockDesc = dynamic_cast<const BlockDescriptor*>(_dataDescriptor.get());
if (!blockDesc)
......@@ -337,7 +353,8 @@ namespace elsa
const auto& ithDesc = blockDesc->getDescriptorOfBlock(i);
index_t blockSize = ithDesc.getNumberOfCoefficients();
return DataContainer<data_t, DataHandlerType::MAP_CPU>{ithDesc, _dataHandler.getBlock(startIndex, blockSize)};
return DataContainer<data_t, DataHandlerType::MAP_CPU>{
ithDesc, _dataHandler.getBlock(startIndex, blockSize)};
}
template <typename data_t, int handler_t>
......@@ -368,8 +385,8 @@ namespace elsa
if (dataDescriptor.getNumberOfCoefficients() != getSize())
throw std::invalid_argument("DataContainer: view must have same size as container");
return DataContainer<data_t, DataHandlerType::MAP_CPU>{
dataDescriptor, _dataHandler.getBlock(0, getSize())};
return DataContainer<data_t, DataHandlerType::MAP_CPU>{dataDescriptor,
_dataHandler.getBlock(0, getSize())};
}
template <typename data_t, int handler_t>
......@@ -381,7 +398,8 @@ namespace elsa
// getBlock() returns a pointer to non-const DH, but that's fine as it gets wrapped in a
// constant container
return DataContainer<data_t, DataHandlerType::MAP_CPU>{ dataDescriptor, _dataHandler.getBlock(0, getSize())};
return DataContainer<data_t, DataHandlerType::MAP_CPU>{dataDescriptor,
_dataHandler.getBlock(0, getSize())};
}
template <typename data_t, int handler_t>
......@@ -391,13 +409,15 @@ namespace elsa
}
template <typename data_t, int handler_t>
typename DataContainer<data_t, handler_t>::const_iterator DataContainer<data_t, handler_t>::begin() const
typename DataContainer<data_t, handler_t>::const_iterator
DataContainer<data_t, handler_t>::begin() const
{
return cbegin();
}
template <typename data_t, int handler_t>
typename DataContainer<data_t, handler_t>::const_iterator DataContainer<data_t, handler_t>::cbegin() const
typename DataContainer<data_t, handler_t>::const_iterator
DataContainer<data_t, handler_t>::cbegin() const
{
return const_iterator(&(*this)[0]);
}
......@@ -409,54 +429,63 @@ namespace elsa
}
template <typename data_t, int handler_t>
typename DataContainer<data_t, handler_t>::const_iterator DataContainer<data_t, handler_t>::end() const
typename DataContainer<data_t, handler_t>::const_iterator
DataContainer<data_t, handler_t>::end() const
{
return cend();
}
template <typename data_t, int handler_t>
typename DataContainer<data_t, handler_t>::const_iterator DataContainer<data_t, handler_t>::cend() const
typename DataContainer<data_t, handler_t>::const_iterator
DataContainer<data_t, handler_t>::cend() const
{
return const_iterator(&(*this)[0] + getSize());
}
template <typename data_t, int handler_t>
typename DataContainer<data_t, handler_t>::reverse_iterator DataContainer<data_t, handler_t>::rbegin()
typename DataContainer<data_t, handler_t>::reverse_iterator
DataContainer<data_t, handler_t>::rbegin()
{
return reverse_iterator(end());
}
template <typename data_t, int handler_t>
typename DataContainer<data_t, handler_t>::const_reverse_iterator DataContainer<data_t, handler_t>::rbegin() const
typename DataContainer<data_t, handler_t>::const_reverse_iterator
DataContainer<data_t, handler_t>::rbegin() const
{
return crbegin();
}
template <typename data_t, int handler_t>
typename DataContainer<data_t, handler_t>::const_reverse_iterator DataContainer<data_t, handler_t>::crbegin() const
typename DataContainer<data_t, handler_t>::const_reverse_iterator
DataContainer<data_t, handler_t>::crbegin() const
{
return const_reverse_iterator(cend());
}
template <typename data_t, int handler_t>
typename DataContainer<data_t, handler_t>::reverse_iterator DataContainer<data_t, handler_t>::rend()
typename DataContainer<data_t, handler_t>::reverse_iterator
DataContainer<data_t, handler_t>::rend()
{
return reverse_iterator(begin());
}
template <typename data_t, int handler_t>
typename DataContainer<data_t, handler_t>::const_reverse_iterator DataContainer<data_t, handler_t>::rend() const
typename DataContainer<data_t, handler_t>::const_reverse_iterator
DataContainer<data_t, handler_t>::rend() const
{
return crend();
}
template <typename data_t, int handler_t>
typename DataContainer<data_t, handler_t>::const_reverse_iterator DataContainer<data_t, handler_t>::crend() const
typename DataContainer<data_t, handler_t>::const_reverse_iterator
DataContainer<data_t, handler_t>::crend() const
{
return const_reverse_iterator(cbegin());
}
template <typename data_t, int handler_t> DataHandlerType DataContainer<data_t, handler_t>::getDataHandlerType() const
template <typename data_t, int handler_t>
DataHandlerType DataContainer<data_t, handler_t>::getDataHandlerType() const
{
return DataHandlerType(handler_t);
}
......
......@@ -257,10 +257,12 @@ namespace elsa
const DataContainer<data_t, DataHandlerType::MAP_CPU> getBlock(index_t i) const;
/// return a view of this DataContainer with a different descriptor
DataContainer<data_t, DataHandlerType::MAP_CPU> viewAs(const DataDescriptor& dataDescriptor);
DataContainer<data_t, DataHandlerType::MAP_CPU>
viewAs(const DataDescriptor& dataDescriptor);
/// return a const view of this DataContainer with a different descriptor
const DataContainer<data_t, DataHandlerType::MAP_CPU> viewAs(const DataDescriptor& dataDescriptor) const;
const DataContainer<data_t, DataHandlerType::MAP_CPU>
viewAs(const DataDescriptor& dataDescriptor) const;
/// iterator for DataContainer (random access and continuous)
using iterator = DataContainerIterator<DataContainer_t>;
......@@ -336,7 +338,8 @@ namespace elsa
friend constexpr auto evaluateOrReturn(Operand const& operand);
/// private constructor accepting a DataDescriptor and a DataHandler
explicit DataContainer(const DataDescriptor& dataDescriptor, DataHandlerMapCPU<data_t> dataHandler);
explicit DataContainer(const DataDescriptor& dataDescriptor,
DataHandlerMapCPU<data_t> dataHandler);
private:
/// the current DataDescriptor
......@@ -344,7 +347,8 @@ namespace elsa
/// the current DataHandler
std::conditional_t<(handler_t == DataHandlerType::MAP_CPU), DataHandlerMapCPU<data_t>,
DataHandlerCPU<data_t>> _dataHandler;
DataHandlerCPU<data_t>>
_dataHandler;
};
/// User-defined template argument deduction guide for the expression based constructor
......
......@@ -45,12 +45,9 @@ namespace elsa
using DataMap_t = Eigen::Map<DataVector_t>;
public:
virtual bool operator==(DataHandler const& other) const = 0;
bool operator!=(DataHandler const& other) const {
return !this->operator==(other);
}
bool operator!=(DataHandler const& other) const { return !this->operator==(other); }
/// convenience typedef to access data type that is internally stored
using value_type = data_t;
......@@ -128,11 +125,12 @@ namespace elsa
/// return a reference to the sequential block starting at startIndex and containing
/// numberOfElements elements
///virtual DataHandlerMapCPU<data_t> getBlock(index_t startIndex,
/// virtual DataHandlerMapCPU<data_t> getBlock(index_t startIndex,
/// return a const reference to the sequential block starting at startIndex and containing
/// numberOfElements elements
///virtual const DataHandlerMapCPU<data_t> getBlock(index_t startIndex, index_t numberOfElements) const = 0;
/// virtual const DataHandlerMapCPU<data_t> getBlock(index_t startIndex, index_t
/// numberOfElements) const = 0;
protected:
/// slow element-wise dot product fall-back for when DataHandler types do not match
......
......@@ -248,7 +248,7 @@ namespace elsa
template <typename data_t>
DataHandlerMapCPU<data_t> DataHandlerCPU<data_t>::getBlock(index_t startIndex,
index_t numberOfElements)
index_t numberOfElements)
{
if (startIndex >= getSize() || numberOfElements > getSize() - startIndex)
throw std::invalid_argument("DataHandler: requested block out of bounds");
......@@ -257,8 +257,8 @@ namespace elsa
}
template <typename data_t>
const DataHandlerMapCPU<data_t>
DataHandlerCPU<data_t>::getBlock(index_t startIndex, index_t numberOfElements) const
const DataHandlerMapCPU<data_t> DataHandlerCPU<data_t>::getBlock(index_t startIndex,
index_t numberOfElements) const
{
if (startIndex >= getSize() || numberOfElements > getSize() - startIndex)
throw std::invalid_argument("DataHandler: requested block out of bounds");
......
......@@ -58,7 +58,6 @@ namespace elsa
friend DataContainer<data_t, 1>;
friend DataContainer<data_t, 2>;
protected:
/// convenience typedef for the Eigen::Matrix data vector
using DataVector_t = Eigen::Matrix<data_t, Eigen::Dynamic, 1>;
......@@ -163,10 +162,12 @@ namespace elsa
/// return a const reference to the sequential block starting at startIndex and containing
/// numberOfElements elements
const DataHandlerMapCPU<data_t> getBlock(index_t startIndex, index_t numberOfElements) const;
const DataHandlerMapCPU<data_t> getBlock(index_t startIndex,
index_t numberOfElements) const;
/// implement the polymorphic comparison operation
bool operator==(DataHandler<data_t> const& other) const override;
protected:
/// the vector storing the data
std::shared_ptr<DataVector_t> _data;
......
......@@ -242,8 +242,8 @@ namespace elsa
}
template <typename data_t>
DataHandlerMapCPU<data_t>
DataHandlerMapCPU<data_t>::getBlock(index_t startIndex, index_t numberOfElements)
DataHandlerMapCPU<data_t> DataHandlerMapCPU<data_t>::getBlock(index_t startIndex,
index_t numberOfElements)
{
if (startIndex >= getSize() || numberOfElements > getSize() - startIndex)
throw std::invalid_argument("DataHandler: requested block out of bounds");
......@@ -252,7 +252,8 @@ namespace elsa
}
template <typename data_t>
const DataHandlerMapCPU<data_t> DataHandlerMapCPU<data_t>::getBlock(index_t startIndex, index_t numberOfElements) const
const DataHandlerMapCPU<data_t>
DataHandlerMapCPU<data_t>::getBlock(index_t startIndex, index_t numberOfElements) const
{
if (startIndex >= getSize() || numberOfElements > getSize() - startIndex)
throw std::invalid_argument("DataHandler: requested block out of bounds");
......
......@@ -136,7 +136,8 @@ namespace elsa
/// return a const reference to the sequential block starting at startIndex and containing
/// numberOfElements elements
const DataHandlerMapCPU<data_t> getBlock(index_t startIndex, index_t numberOfElements) const;
const DataHandlerMapCPU<data_t> getBlock(index_t startIndex,
index_t numberOfElements) const;
/// implement the polymorphic comparison operation
bool operator==(DataHandler<data_t> const& other) const override;
......
......@@ -67,7 +67,9 @@ namespace elsa
}
template <typename data_t>
DataContainer<data_t> LinearOperator<data_t>::apply(const DataContainer<data_t>& x) const
template <int handler_t>
DataContainer<data_t>
LinearOperator<data_t>::apply(const DataContainer<data_t, handler_t>& x) const
{
DataContainer<data_t> result(*_rangeDescriptor);
apply(x, result);
......@@ -75,8 +77,9 @@ namespace elsa
}
template <typename data_t>
void LinearOperator<data_t>::apply(const DataContainer<data_t>& x,
DataContainer<data_t>& Ax) const
template <int handler_t>
void LinearOperator<data_t>::apply(const DataContainer<data_t, handler_t>& x,
DataContainer<data_t, handler_t>& Ax) const
{
applyImpl(x, Ax);
}
......@@ -140,7 +143,9 @@ namespace elsa
}
template <typename data_t>
DataContainer<data_t> LinearOperator<data_t>::applyAdjoint(const DataContainer<data_t>& y) const
template <int handler_t>
DataContainer<data_t>
LinearOperator<data_t>::applyAdjoint(const DataContainer<data_t, handler_t>& y) const
{
DataContainer<data_t> result(*_domainDescriptor);
applyAdjoint(y, result);
......@@ -148,8 +153,9 @@ namespace elsa
}
template <typename data_t>
void LinearOperator<data_t>::applyAdjoint(const DataContainer<data_t>& y,
DataContainer<data_t>& Aty) const
template <int handler_t>
void LinearOperator<data_t>::applyAdjoint(const DataContainer<data_t, handler_t>& y,
DataContainer<data_t, handler_t>& Aty) const
{
applyAdjointImpl(y, Aty);
}
......
......@@ -71,7 +71,8 @@ namespace elsa
*
* Please note: this method uses apply(x, Ax) to perform the actual operation.
*/
DataContainer<data_t> apply(const DataContainer<data_t>& x) const;
template <int handler_t>
DataContainer<data_t> apply(const DataContainer<data_t, handler_t>& x) const;
/**
* \brief apply the operator A to an element in the operator's domain
......@@ -83,7 +84,9 @@ namespace elsa
* classes. (Why is this method not virtual itself? Because you cannot have a non-virtual
* function overloading a virtual one [apply with one vs. two arguments]).
*/
void apply(const DataContainer<data_t>& x, DataContainer<data_t>& Ax) const;
template <int handler_t>
void apply(const DataContainer<data_t, handler_t>& x,
DataContainer<data_t, handler_t>& Ax) const;
/**
* \brief apply the adjoint of operator A to an element of the operator's range
......@@ -95,7 +98,8 @@ namespace elsa
*
* Please note: this method uses applyAdjoint(y, Aty) to perform the actual operation.
*/
DataContainer<data_t> applyAdjoint(const DataContainer<data_t>& y) const;
template <int handler_t>
DataContainer<data_t> applyAdjoint(const DataContainer<data_t, handler_t>& y) const;
/**
* \brief apply the adjoint of operator A to an element of the operator's range
......@@ -107,7 +111,9 @@ namespace elsa
* derived classes. (Why is this method not virtual itself? Because you cannot have a
* non-virtual function overloading a virtual one [applyAdjoint with one vs. two args]).
*/
void applyAdjoint(const DataContainer<data_t>& y, DataContainer<data_t>& Aty) const;
template <int handler_t>
void applyAdjoint(const DataContainer<data_t, handler_t>& y,
DataContainer<data_t, handler_t>& Aty) const;
/// friend operator+ to support composition of LinearOperators (and its derivatives)
friend LinearOperator<data_t> operator+(const LinearOperator<data_t>& lhs,
......
This diff is collapsed.
......@@ -212,176 +212,177 @@ TEMPLATE_PRODUCT_TEST_CASE("Scenario: Assigning to DataHandlerCPU", "", (DataHan
}
}
// WHEN("copy assigning a DataHandlerCPU through base pointers")
// {
// DataHandler<data_t>* dhPtr = &dh;
// Eigen::VectorX<data_t> randVec{size};
// randVec.setRandom();
// const auto dh2Ptr = std::make_unique<const DataHandlerCPU<data_t>>(randVec);
// const auto dh2Map = dh2Ptr->getBlock(size / 2, size / 3);
//
// THEN("sizes must match")
// {
// std::unique_ptr<DataHandler<data_t>> bigDh =
// std::make_unique<DataHandlerCPU<data_t>>(2 * size);
// REQUIRE_THROWS(*dhPtr = *bigDh);
// }
//
// *dhPtr = *dh2Ptr;
// THEN("a shallow copy is performed and associated Maps are updated")
// {
// REQUIRE(useCount(dh) == 2);
// REQUIRE(dh == *dh2Ptr);
// REQUIRE(*dhMap == *dh2Map);
// dh[0] = 1;
// REQUIRE(&dh[0] != &(*dh2Ptr)[0]);
// REQUIRE(*dhMap == *dh2Map);
// REQUIRE(&(*dhMap)[0] == &dh[size / 2]);
// }
// }
//
// WHEN("copy assigning a partial DataHandlerMapCPU through base pointers")
// {
// DataHandler<data_t>* dhPtr = &dh;
// const auto dhCopy = dh;
// Eigen::VectorX<data_t> randVec{2 * size};
// randVec.setRandom();
// const DataHandlerCPU<data_t> dh2{randVec};
// const auto dh2Map = dh2.getBlock(0, size);
//
// THEN("sizes must match")
// {
// const auto bigDh = dh2.getBlock(0, size + 1);
// REQUIRE_THROWS(*dhPtr = *bigDh);
// }
//
// *dhPtr = *dh2Map;
// THEN("a deep copy is performed")
// {
// REQUIRE(useCount(dh) == 1);
// REQUIRE(useCount(dhCopy) == 1);
// REQUIRE(dh == *dh2Map);
// REQUIRE(&(*dhMap)[0] == &dh[size / 2]);
// REQUIRE(dhMap->getSize() == size / 3);
// }
// }
//
// WHEN("copy assigning a full DataHandlerMapCPU (aka a view) through base pointers")
// {
// DataHandler<data_t>* dhPtr = &dh;
// Eigen::VectorX<data_t> randVec{size};
// randVec.setRandom();
// const DataHandlerCPU<data_t> dh2{randVec};
// const auto dh2View = dh2.getBlock(0, size);
// const auto dh2Map = dh2.getBlock(size / 2, size / 3);
//
// THEN("sizes must match")
// {
// std::unique_ptr<DataHandler<data_t>> bigDh =
// std::make_unique<DataHandlerCPU<data_t>>(2 * size);
// auto bigDhView = bigDh->getBlock(0, 2 * size);
// REQUIRE_THROWS(*dhPtr = *bigDhView);
// }
//
// *dhPtr = *dh2View;
// THEN("a shallow copy is performed and associated maps are updated")
// {
// REQUIRE(useCount(dh) == 2);