Commit 673b5511 authored by andibraimllari's avatar andibraimllari Committed by David Frank
Browse files

#105 add minElement and maxElement reductions

minElement and maxElement return the min and max element of a
DataContainer, respectivly. For complex vectors, an expection is thrown.
parent 254f70e5
Pipeline #717072 failed with stages
in 11 minutes and 16 seconds
......@@ -170,6 +170,18 @@ namespace elsa
return _dataHandler->sum();
}
template <typename data_t>
data_t DataContainer<data_t>::minElement() const
{
return _dataHandler->minElement();
}
template <typename data_t>
data_t DataContainer<data_t>::maxElement() const
{
return _dataHandler->maxElement();
}
template <typename data_t>
DataContainer<data_t>& DataContainer<data_t>::operator+=(const DataContainer<data_t>& dc)
{
......
......@@ -240,6 +240,12 @@ namespace elsa
/// return the sum of all elements of this signal
data_t sum() const;
/// return the min of all elements of this signal
data_t minElement() const;
/// return the max of all elements of this signal
data_t maxElement() const;
/// compute in-place element-wise addition of another container
DataContainer<data_t>& operator+=(const DataContainer<data_t>& dc);
......
......@@ -75,6 +75,12 @@ namespace elsa
/// return the sum of all elements of the data vector
virtual data_t sum() const = 0;
/// return the min of all elements of the data vector
virtual data_t minElement() const = 0;
/// return the max of all elements of the data vector
virtual data_t maxElement() const = 0;
/// compute in-place element-wise addition of another vector v
virtual DataHandler<data_t>& operator+=(const DataHandler<data_t>& v) = 0;
......
......@@ -110,6 +110,26 @@ namespace elsa
return _data->sum();
}
template <typename data_t>
data_t DataHandlerCPU<data_t>::minElement() const
{
if constexpr (isComplex<data_t>) {
throw LogicError("DataHandlerCPU: minElement of complex type not supported");
} else {
return _data->minCoeff();
}
}
template <typename data_t>
data_t DataHandlerCPU<data_t>::maxElement() const
{
if constexpr (isComplex<data_t>) {
throw LogicError("DataHandlerCPU: maxElement of complex type not supported");
} else {
return _data->maxCoeff();
}
}
template <typename data_t>
DataHandler<data_t>& DataHandlerCPU<data_t>::operator+=(const DataHandler<data_t>& v)
{
......@@ -446,5 +466,4 @@ namespace elsa
template class DataHandlerCPU<double>;
template class DataHandlerCPU<std::complex<double>>;
template class DataHandlerCPU<index_t>;
} // namespace elsa
......@@ -123,6 +123,12 @@ namespace elsa
/// return the sum of all elements of the data vector
data_t sum() const override;
/// return the min of all elements of the data vector
data_t minElement() const override;
/// return the max of all elements of the data vector
data_t maxElement() const override;
/// copy assign another DataHandlerCPU to this, other types handled in assign()
DataHandlerCPU<data_t>& operator=(const DataHandlerCPU<data_t>& v);
......@@ -208,5 +214,4 @@ namespace elsa
/// change the vector being handled (rvalue version)
void attach(std::shared_ptr<DataVector_t>&& data);
};
} // namespace elsa
......@@ -116,6 +116,18 @@ namespace elsa
return _data->sum();
}
template <typename data_t>
data_t DataHandlerGPU<data_t>::minElement() const
{
return _data->minElement();
}
template <typename data_t>
data_t DataHandlerGPU<data_t>::maxElement() const
{
return _data->maxElement();
}
template <typename data_t>
DataHandler<data_t>& DataHandlerGPU<data_t>::operator+=(const DataHandler<data_t>& v)
{
......
......@@ -128,6 +128,12 @@ namespace elsa
/// return the sum of all elements of the data vector
data_t sum() const override;
/// return the min of all elements of the data vector
data_t minElement() const override;
/// return the max of all elements of the data vector
data_t maxElement() const override;
/// copy assign another DataHandlerGPU
DataHandlerGPU<data_t>& operator=(const DataHandlerGPU<data_t>& v);
......
......@@ -112,6 +112,26 @@ namespace elsa
return _map.sum();
}
template <typename data_t>
data_t DataHandlerMapCPU<data_t>::minElement() const
{
if constexpr (isComplex<data_t>) {
throw LogicError("DataHandlerCPU: minElement of complex type not supported");
} else {
return _map.minCoeff();
}
}
template <typename data_t>
data_t DataHandlerMapCPU<data_t>::maxElement() const
{
if constexpr (isComplex<data_t>) {
throw LogicError("DataHandlerCPU: maxElement of complex type not supported");
} else {
return _map.maxCoeff();
}
}
template <typename data_t>
DataHandler<data_t>& DataHandlerMapCPU<data_t>::operator+=(const DataHandler<data_t>& v)
{
......
......@@ -99,6 +99,12 @@ namespace elsa
/// return the sum of all elements of the data vector
data_t sum() const override;
/// return the min of all elements of the data vector
data_t minElement() const override;
/// return the max of all elements of the data vector
data_t maxElement() const override;
/// compute in-place element-wise addition of another vector v
DataHandler<data_t>& operator+=(const DataHandler<data_t>& v) override;
......
......@@ -129,6 +129,18 @@ namespace elsa
return _map.sum();
}
template <typename data_t>
data_t DataHandlerMapGPU<data_t>::minElement() const
{
return _map.minElement();
}
template <typename data_t>
data_t DataHandlerMapGPU<data_t>::maxElement() const
{
return _map.maxElement();
}
template <typename data_t>
DataHandler<data_t>& DataHandlerMapGPU<data_t>::operator+=(const DataHandler<data_t>& v)
{
......
......@@ -118,6 +118,12 @@ namespace elsa
/// return the sum of all elements of the data vector
data_t sum() const override;
/// return the min of all elements of the data vector
data_t minElement() const override;
/// return the max of all elements of the data vector
data_t maxElement() const override;
/// compute in-place element-wise addition of another vector v
DataHandler<data_t>& operator+=(const DataHandler<data_t>& v) override;
......
......@@ -217,6 +217,14 @@ TEST_CASE_TEMPLATE_DEFINE("DataContainer: Testing the reduction operations", Tes
auto [dc2, randVec2] = generateRandomContainer<data_t>(desc, TestType::handler_t);
REQUIRE_UNARY(checkApproxEq(dc.dot(dc2), randVec.dot(randVec2)));
if constexpr (isComplex<data_t>) {
CHECK_THROWS(dc.minElement());
CHECK_THROWS(dc.maxElement());
} else {
REQUIRE_UNARY(checkApproxEq(dc.minElement(), randVec.array().minCoeff()));
REQUIRE_UNARY(checkApproxEq(dc.maxElement(), randVec.array().maxCoeff()));
}
}
}
}
......@@ -293,8 +301,8 @@ TEST_CASE_TEMPLATE_DEFINE("DataContainer: Testing element-wise access", TestType
for (index_t i = 0; i < dc.getSize(); ++i)
REQUIRE_UNARY(checkApproxEq(dcSqrt[i], randVec.array().square().sqrt()[i]));
// do exponent check only for floating point types as for integer will likely lead
// to overflow due to random init over full value range
// do exponent check only for floating point types as for integer will likely
// lead to overflow due to random init over full value range
if constexpr (!std::is_integral_v<data_t>) {
DataContainer dcExp = exp(dc);
for (index_t i = 0; i < dc.getSize(); ++i)
......@@ -399,7 +407,8 @@ TEST_CASE_TEMPLATE_DEFINE("DataContainer: Testing element-wise access", TestType
auto [dcComps1, compsVec1] =
generateRandomContainer<std::complex<real_t>>(desc, TestType::handler_t);
THEN("the element-wise maximum operation works as expected for two real DataContainers")
THEN("the element-wise maximum operation works as expected for two real "
"DataContainers")
{
auto [dcReals2, realsVec2] =
generateRandomContainer<real_t>(desc, TestType::handler_t);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment