LCOV - code coverage report
Current view: top level - include/math - gslInterpolator.hpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 59.2 % 49 29
Test Date: 2026-08-30 22:23:37 Functions: 55.6 % 9 5

            Line data    Source code
       1              : /** \file gslInterpolator.hpp
       2              :  * \brief Class for managing 1-D interpolation using the GNU Scientific Library
       3              :  *
       4              :  * \author Jared R. Males (jaredmales@gmail.com)
       5              :  *
       6              :  * \ingroup gen_math_files
       7              :  *
       8              :  */
       9              : 
      10              : //***********************************************************************//
      11              : // Copyright 2015-2022 Jared R. Males (jaredmales@gmail.com)
      12              : //
      13              : // This file is part of mxlib.
      14              : //
      15              : // mxlib is free software: you can redistribute it and/or modify
      16              : // it under the terms of the GNU General Public License as published by
      17              : // the Free Software Foundation, either version 3 of the License, or
      18              : // (at your option) any later version.
      19              : //
      20              : // mxlib is distributed in the hope that it will be useful,
      21              : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      22              : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      23              : // GNU General Public License for more details.
      24              : //
      25              : // You should have received a copy of the GNU General Public License
      26              : // along with mxlib.  If not, see <http://www.gnu.org/licenses/>.
      27              : //***********************************************************************//
      28              : 
      29              : #ifndef gslInterpolator_hpp
      30              : #define gslInterpolator_hpp
      31              : 
      32              : #include <vector>
      33              : #include <gsl/gsl_interp.h>
      34              : #include <gsl/gsl_errno.h>
      35              : 
      36              : #include "../mxlib.hpp"
      37              : 
      38              : namespace mx
      39              : {
      40              : namespace math
      41              : {
      42              : 
      43              : /// GSL Linear Interpolation
      44              : /** \ingroup interpolation
      45              :  */
      46              : template <typename _realT>
      47              : struct gsl_interp_linear
      48              : {
      49              :     typedef _realT realT;
      50              : 
      51           10 :     static const gsl_interp_type *interpolator()
      52              :     {
      53           10 :         return ::gsl_interp_linear;
      54              :     }
      55              : };
      56              : 
      57              : #ifndef MX_OLD_GSL
      58              : /// GSL Steffen Interpolation
      59              : /** \ingroup interpolation
      60              :  */
      61              : template <typename _realT>
      62              : struct gsl_interp_steffen
      63              : {
      64              :     typedef _realT realT;
      65              : 
      66            0 :     static const gsl_interp_type *interpolator()
      67              :     {
      68            0 :         return ::gsl_interp_steffen;
      69              :     }
      70              : };
      71              : #endif
      72              : 
      73              : /// Class to manage interpolation using the GSL interpolation library.
      74              : /**
      75              :  *
      76              :  * \tparam interpT is the interpolation type, which also specifies the floating point precision.
      77              :  *
      78              :  * \ingroup interpolation
      79              :  */
      80              : template <typename interpT>
      81              : class gslInterpolator
      82              : {
      83              :   public:
      84              :     typedef typename interpT::realT realT;
      85              : 
      86              :     static_assert( std::is_same<double, typename std::remove_cv<realT>::type>::value,
      87              :                    "GSL Interpolation only works with double" );
      88              : 
      89              :   protected:
      90              :     gsl_interp *m_interp{ nullptr };    ///< the gsl interpolator structure
      91              :     gsl_interp_accel *m_acc{ nullptr }; ///< the gsl interpolation accelerator structure
      92              : 
      93              :     realT *m_xin;                       ///< the input x data
      94              :     realT *m_yin;                       ///< the input y data
      95              : 
      96              :   public:
      97              :     /// Default constructor
      98              :     gslInterpolator();
      99              : 
     100              :     /// Raw pointer constructor
     101              :     gslInterpolator( realT *xin, ///< [in] the input x data, this pointer is stored and must remain valid
     102              :                      realT *yin, ///< [in] the input y data, this pointer is stored and must remain valid
     103              :                      size_t Nin  ///< [in] the size of data vectors
     104              :     );
     105              : 
     106              :     /// Vector constructor
     107              :     gslInterpolator( std::vector<realT> &xin, ///< [in] the input x data, the pointer to xin.data() is stored and xin
     108              :                                               ///< must remain unchanged
     109              :                      std::vector<realT> &yin  ///< [in] the input y data, the pointer to yin.data() is stored and yin
     110              :                                               ///< must remain unchanged
     111              :     );
     112              : 
     113              :     /// Destructor
     114              :     /** Deallocates working memory.
     115              :      */
     116              :     ~gslInterpolator();
     117              : 
     118              :     /// Setup the interpolator for the supplied data pointers
     119              :     /**
     120              :      * \throws mx::err::allocerr if allocation fails
     121              :      * \throws mx::err::liberr if GSL initialization fails
     122              :      */
     123              :     void setup( realT *xin, ///< [in] the input x data, this pointer is stored and must remain valid
     124              :                 realT *yin, ///< [in] the input y data, this pointer is stored and must remain valid
     125              :                 size_t Nin  ///< [in] the size of data vectors
     126              :     );
     127              : 
     128              :     /// Setup the interpolator for the supplied data vectors
     129              :     /**
     130              :      * \throws mx::err::sizeerr if the vectors are not the same size
     131              :      * \throws mx::err::allocerr if allocation fails
     132              :      * \throws mx::err::liberr if GSL initialization fails
     133              :      */
     134              :     void setup( std::vector<realT>
     135              :                     &xin, ///< [in] the input x data, the pointer to xin.data() is stored and xin must remain unchanged
     136              :                 std::vector<realT>
     137              :                     &yin  ///< [in] the input y data, the pointer to yin.data() is stored and yin must remain unchanged
     138              :     );
     139              : 
     140              :     /// Calculate the interpolated function value at a point
     141              :     /**
     142              :      * \returns the interpolated value at \p x
     143              :      */
     144              :     realT operator()( const realT &x /**< [in] the point at which to interpolate */ );
     145              : };
     146              : 
     147              : template <typename interpT>
     148            0 : gslInterpolator<interpT>::gslInterpolator()
     149              : {
     150            0 : }
     151              : 
     152              : template <typename interpT>
     153            0 : gslInterpolator<interpT>::gslInterpolator( realT *xin, realT *yin, size_t Nin )
     154              : {
     155            0 :     setup( xin, yin, Nin );
     156            0 : }
     157              : 
     158              : template <typename interpT>
     159           10 : gslInterpolator<interpT>::gslInterpolator( std::vector<realT> &xin, std::vector<realT> &yin )
     160              : {
     161           10 :     setup( xin.data(), yin.data(), xin.size() );
     162           10 : }
     163              : 
     164              : template <typename interpT>
     165           10 : gslInterpolator<interpT>::~gslInterpolator()
     166              : {
     167           10 :     if( m_interp != nullptr )
     168           10 :         gsl_interp_free( m_interp );
     169           10 :     if( m_acc != nullptr )
     170           10 :         gsl_interp_accel_free( m_acc );
     171           10 : }
     172              : 
     173              : template <typename interpT>
     174           10 : void gslInterpolator<interpT>::setup( realT *xin, realT *yin, size_t Nin )
     175              : {
     176           10 :     if( m_interp != nullptr )
     177            0 :         gsl_interp_free( m_interp );
     178           10 :     if( m_acc != nullptr )
     179            0 :         gsl_interp_accel_free( m_acc );
     180              : 
     181           10 :     m_interp = gsl_interp_alloc( interpT::interpolator(), Nin );
     182           10 :     if( !m_interp )
     183              :     {
     184            0 :         throw(mx::exception(error_t::allocerr, "gsl_interp_alloc failed"));
     185              :     }
     186              : 
     187           10 :     m_acc = gsl_interp_accel_alloc();
     188           10 :     if( !m_acc )
     189              :     {
     190            0 :         throw(mx::exception(error_t::allocerr, "gsl_interp_accel_alloc failed" ));
     191              :     }
     192              : 
     193           10 :     int errv = gsl_interp_init( m_interp, xin, yin, Nin );
     194           10 :     if( errv != 0 )
     195              :     {
     196            0 :         throw( mx::exception( error_t::liberr, std::string( "gsl_interp_init failed: " ) + gsl_strerror( errv ) ) );
     197              :     }
     198              : 
     199           10 :     errv = gsl_interp_accel_reset( m_acc );
     200           10 :     if( errv != 0 )
     201              :     {
     202            0 :         throw(
     203            0 :             mx::exception( error_t::liberr, std::string( "gsl_interp_accel_reset failed: " ) + gsl_strerror( errv ) ) );
     204              :     }
     205           10 :     m_xin = xin;
     206           10 :     m_yin = yin;
     207           10 : }
     208              : 
     209              : template <typename interpT>
     210            0 : void gslInterpolator<interpT>::setup( std::vector<realT> &xin, std::vector<realT> &yin )
     211              : {
     212            0 :     if( xin.size() != yin.size() )
     213              :     {
     214            0 :         throw(mx::exception(error_t::sizeerr,"input vectors must be the same size" ));
     215              :     }
     216            0 :     setup( xin.data(), yin.data(), xin.size() );
     217            0 : }
     218              : 
     219              : template <typename interpT>
     220          543 : typename interpT::realT gslInterpolator<interpT>::operator()( const realT &x )
     221              : {
     222              :     realT y;
     223          543 :     int errv = gsl_interp_eval_e( m_interp, m_xin, m_yin, x, m_acc, &y );
     224          543 :     if( errv != 0 && errv != GSL_EDOM )
     225              :     {
     226            0 :         throw(mx::exception(error_t::liberr,"gsl_interp_eval_e failed" ));
     227              :     }
     228          543 :     return y;
     229              : }
     230              : 
     231              : extern template class gslInterpolator<gsl_interp_linear<double>>;
     232              : extern template class gslInterpolator<gsl_interp_steffen<double>>;
     233              : 
     234              : } // namespace math
     235              : } // namespace mx
     236              : 
     237              : #endif // gslInterpolator_hpp
        

Generated by: LCOV version 2.0-1