LCOV - code coverage report
Current view: top level - elsa/functionals - PseudoHuber.cpp (source / functions) Hit Total Coverage
Test: coverage-all.lcov Lines: 38 44 86.4 %
Date: 2024-05-16 04:22:26 Functions: 12 14 85.7 %

          Line data    Source code
       1             : #include "PseudoHuber.h"
       2             : #include "DataContainer.h"
       3             : #include "Scaling.h"
       4             : #include "TypeCasts.hpp"
       5             : 
       6             : #include <cmath>
       7             : #include <stdexcept>
       8             : 
       9             : namespace elsa
      10             : {
      11             :     template <typename data_t>
      12             :     PseudoHuber<data_t>::PseudoHuber(const DataDescriptor& domainDescriptor, real_t delta)
      13             :         : Functional<data_t>(domainDescriptor), delta_{delta}
      14           8 :     {
      15             :         // sanity check delta
      16           8 :         if (delta <= static_cast<real_t>(0.0))
      17           0 :             throw InvalidArgumentError("PseudoHuber: delta has to be positive.");
      18           8 :     }
      19             : 
      20             :     template <typename data_t>
      21             :     bool PseudoHuber<data_t>::isDifferentiable() const
      22           0 :     {
      23           0 :         return true;
      24           0 :     }
      25             : 
      26             :     template <typename data_t>
      27             :     data_t PseudoHuber<data_t>::evaluateImpl(const DataContainer<data_t>& Rx) const
      28           2 :     {
      29             :         // note: this is currently not a reduction in DataContainer, but implemented here "manually"
      30             : 
      31           2 :         auto result = static_cast<data_t>(0.0);
      32             : 
      33         886 :         for (index_t i = 0; i < Rx.getSize(); ++i) {
      34         884 :             data_t temp = Rx[i] / delta_;
      35         884 :             result += delta_ * delta_
      36         884 :                       * (sqrt(static_cast<data_t>(1.0) + temp * temp) - static_cast<data_t>(1.0));
      37         884 :         }
      38             : 
      39           2 :         return result;
      40           2 :     }
      41             : 
      42             :     template <typename data_t>
      43             :     void PseudoHuber<data_t>::getGradientImpl(const DataContainer<data_t>& Rx,
      44             :                                               DataContainer<data_t>& out) const
      45           2 :     {
      46         886 :         for (index_t i = 0; i < Rx.getSize(); ++i) {
      47         884 :             data_t temp = Rx[i] / delta_;
      48         884 :             out[i] = Rx[i] / sqrt(static_cast<data_t>(1.0) + temp * temp);
      49         884 :         }
      50           2 :     }
      51             : 
      52             :     template <typename data_t>
      53             :     LinearOperator<data_t>
      54             :         PseudoHuber<data_t>::getHessianImpl(const DataContainer<data_t>& Rx) const
      55           2 :     {
      56           2 :         DataContainer<data_t> scaleFactors(Rx.getDataDescriptor());
      57         886 :         for (index_t i = 0; i < Rx.getSize(); ++i) {
      58         884 :             data_t temp = Rx[i] / delta_;
      59         884 :             data_t tempSq = temp * temp;
      60         884 :             data_t sqrtOnePTempSq = sqrt(static_cast<data_t>(1.0) + tempSq);
      61         884 :             scaleFactors[i] =
      62         884 :                 (sqrtOnePTempSq - tempSq / sqrtOnePTempSq) / (static_cast<data_t>(1.0) + tempSq);
      63         884 :         }
      64             : 
      65           2 :         return leaf(Scaling<data_t>(scaleFactors));
      66           2 :     }
      67             : 
      68             :     template <typename data_t>
      69             :     PseudoHuber<data_t>* PseudoHuber<data_t>::cloneImpl() const
      70           2 :     {
      71           2 :         return new PseudoHuber(this->getDomainDescriptor(), delta_);
      72           2 :     }
      73             : 
      74             :     template <typename data_t>
      75             :     bool PseudoHuber<data_t>::isEqual(const Functional<data_t>& other) const
      76           2 :     {
      77           2 :         if (!Functional<data_t>::isEqual(other))
      78           0 :             return false;
      79             : 
      80           2 :         auto otherPHuber = downcast_safe<PseudoHuber>(&other);
      81           2 :         if (!otherPHuber)
      82           0 :             return false;
      83             : 
      84           2 :         return delta_ == otherPHuber->delta_;
      85           2 :     }
      86             : 
      87             :     // ------------------------------------------
      88             :     // explicit template instantiation
      89             :     template class PseudoHuber<float>;
      90             :     template class PseudoHuber<double>;
      91             :     // no complex-number instantiations for PseudoHuber! (they would not really be useful)
      92             : 
      93             : } // namespace elsa

Generated by: LCOV version 1.14