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 ...@@ -170,6 +170,18 @@ namespace elsa
return _dataHandler->sum(); 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> template <typename data_t>
DataContainer<data_t>& DataContainer<data_t>::operator+=(const DataContainer<data_t>& dc) DataContainer<data_t>& DataContainer<data_t>::operator+=(const DataContainer<data_t>& dc)
{ {
......
...@@ -240,6 +240,12 @@ namespace elsa ...@@ -240,6 +240,12 @@ namespace elsa
/// return the sum of all elements of this signal /// return the sum of all elements of this signal
data_t sum() const; 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 /// compute in-place element-wise addition of another container
DataContainer<data_t>& operator+=(const DataContainer<data_t>& dc); DataContainer<data_t>& operator+=(const DataContainer<data_t>& dc);
......
...@@ -75,6 +75,12 @@ namespace elsa ...@@ -75,6 +75,12 @@ namespace elsa
/// return the sum of all elements of the data vector /// return the sum of all elements of the data vector
virtual data_t sum() const = 0; 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 /// compute in-place element-wise addition of another vector v
virtual DataHandler<data_t>& operator+=(const DataHandler<data_t>& v) = 0; virtual DataHandler<data_t>& operator+=(const DataHandler<data_t>& v) = 0;
......
...@@ -110,6 +110,26 @@ namespace elsa ...@@ -110,6 +110,26 @@ namespace elsa
return _data->sum(); 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> template <typename data_t>
DataHandler<data_t>& DataHandlerCPU<data_t>::operator+=(const DataHandler<data_t>& v) DataHandler<data_t>& DataHandlerCPU<data_t>::operator+=(const DataHandler<data_t>& v)
{ {
...@@ -446,5 +466,4 @@ namespace elsa ...@@ -446,5 +466,4 @@ namespace elsa
template class DataHandlerCPU<double>; template class DataHandlerCPU<double>;
template class DataHandlerCPU<std::complex<double>>; template class DataHandlerCPU<std::complex<double>>;
template class DataHandlerCPU<index_t>; template class DataHandlerCPU<index_t>;
} // namespace elsa } // namespace elsa
...@@ -123,6 +123,12 @@ namespace elsa ...@@ -123,6 +123,12 @@ namespace elsa
/// return the sum of all elements of the data vector /// return the sum of all elements of the data vector
data_t sum() const override; 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() /// copy assign another DataHandlerCPU to this, other types handled in assign()
DataHandlerCPU<data_t>& operator=(const DataHandlerCPU<data_t>& v); DataHandlerCPU<data_t>& operator=(const DataHandlerCPU<data_t>& v);
...@@ -208,5 +214,4 @@ namespace elsa ...@@ -208,5 +214,4 @@ namespace elsa
/// change the vector being handled (rvalue version) /// change the vector being handled (rvalue version)
void attach(std::shared_ptr<DataVector_t>&& data); void attach(std::shared_ptr<DataVector_t>&& data);
}; };
} // namespace elsa } // namespace elsa
...@@ -116,6 +116,18 @@ namespace elsa ...@@ -116,6 +116,18 @@ namespace elsa
return _data->sum(); 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> template <typename data_t>
DataHandler<data_t>& DataHandlerGPU<data_t>::operator+=(const DataHandler<data_t>& v) DataHandler<data_t>& DataHandlerGPU<data_t>::operator+=(const DataHandler<data_t>& v)
{ {
......
...@@ -128,6 +128,12 @@ namespace elsa ...@@ -128,6 +128,12 @@ namespace elsa
/// return the sum of all elements of the data vector /// return the sum of all elements of the data vector
data_t sum() const override; 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 /// copy assign another DataHandlerGPU
DataHandlerGPU<data_t>& operator=(const DataHandlerGPU<data_t>& v); DataHandlerGPU<data_t>& operator=(const DataHandlerGPU<data_t>& v);
......
...@@ -112,6 +112,26 @@ namespace elsa ...@@ -112,6 +112,26 @@ namespace elsa
return _map.sum(); 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> template <typename data_t>
DataHandler<data_t>& DataHandlerMapCPU<data_t>::operator+=(const DataHandler<data_t>& v) DataHandler<data_t>& DataHandlerMapCPU<data_t>::operator+=(const DataHandler<data_t>& v)
{ {
......
...@@ -99,6 +99,12 @@ namespace elsa ...@@ -99,6 +99,12 @@ namespace elsa
/// return the sum of all elements of the data vector /// return the sum of all elements of the data vector
data_t sum() const override; 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 /// compute in-place element-wise addition of another vector v
DataHandler<data_t>& operator+=(const DataHandler<data_t>& v) override; DataHandler<data_t>& operator+=(const DataHandler<data_t>& v) override;
......
...@@ -129,6 +129,18 @@ namespace elsa ...@@ -129,6 +129,18 @@ namespace elsa
return _map.sum(); 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> template <typename data_t>
DataHandler<data_t>& DataHandlerMapGPU<data_t>::operator+=(const DataHandler<data_t>& v) DataHandler<data_t>& DataHandlerMapGPU<data_t>::operator+=(const DataHandler<data_t>& v)
{ {
......
...@@ -118,6 +118,12 @@ namespace elsa ...@@ -118,6 +118,12 @@ namespace elsa
/// return the sum of all elements of the data vector /// return the sum of all elements of the data vector
data_t sum() const override; 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 /// compute in-place element-wise addition of another vector v
DataHandler<data_t>& operator+=(const DataHandler<data_t>& v) override; DataHandler<data_t>& operator+=(const DataHandler<data_t>& v) override;
......
...@@ -217,6 +217,14 @@ TEST_CASE_TEMPLATE_DEFINE("DataContainer: Testing the reduction operations", Tes ...@@ -217,6 +217,14 @@ TEST_CASE_TEMPLATE_DEFINE("DataContainer: Testing the reduction operations", Tes
auto [dc2, randVec2] = generateRandomContainer<data_t>(desc, TestType::handler_t); auto [dc2, randVec2] = generateRandomContainer<data_t>(desc, TestType::handler_t);
REQUIRE_UNARY(checkApproxEq(dc.dot(dc2), randVec.dot(randVec2))); 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 ...@@ -293,8 +301,8 @@ TEST_CASE_TEMPLATE_DEFINE("DataContainer: Testing element-wise access", TestType
for (index_t i = 0; i < dc.getSize(); ++i) for (index_t i = 0; i < dc.getSize(); ++i)
REQUIRE_UNARY(checkApproxEq(dcSqrt[i], randVec.array().square().sqrt()[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 // do exponent check only for floating point types as for integer will likely
// to overflow due to random init over full value range // lead to overflow due to random init over full value range
if constexpr (!std::is_integral_v<data_t>) { if constexpr (!std::is_integral_v<data_t>) {
DataContainer dcExp = exp(dc); DataContainer dcExp = exp(dc);
for (index_t i = 0; i < dc.getSize(); ++i) for (index_t i = 0; i < dc.getSize(); ++i)
...@@ -399,7 +407,8 @@ TEST_CASE_TEMPLATE_DEFINE("DataContainer: Testing element-wise access", TestType ...@@ -399,7 +407,8 @@ TEST_CASE_TEMPLATE_DEFINE("DataContainer: Testing element-wise access", TestType
auto [dcComps1, compsVec1] = auto [dcComps1, compsVec1] =
generateRandomContainer<std::complex<real_t>>(desc, TestType::handler_t); 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] = auto [dcReals2, realsVec2] =
generateRandomContainer<real_t>(desc, TestType::handler_t); 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