libmoost
/home/mhx/git/github/libmoost/include/moost/algorithm/spline_interpolation.hpp
Go to the documentation of this file.
00001 /* vim:set ts=3 sw=3 sts=3 et: */
00036 #ifndef MOOST_ALGORITHM_SPLINE_INTERPOLATION_HPP
00037 #define MOOST_ALGORITHM_SPLINE_INTERPOLATION_HPP
00038 
00039 #include <cassert>
00040 #include <vector>
00041 #include <algorithm>
00042 
00043 #include <gsl/gsl_spline.h> // gnu scientific library
00044 
00045 #include <boost/noncopyable.hpp>
00046 
00047 #include "../utils/scope_exit.hpp"
00048 
00049 
00050 namespace moost { namespace algorithm {
00051 
00060    class spline_interpolation : private boost::noncopyable
00061    {
00062       private:
00063          typedef moost::utils::scope_exit::type<
00064             gsl_interp *>::call_free_function_with_val interp_t;
00065 
00066          typedef moost::utils::scope_exit::type<
00067             gsl_interp_accel *>::call_free_function_with_val accel_t;
00068 
00069       public:
00070 
00071 
00085          spline_interpolation(
00086                std::vector<double> const & x,
00087                std::vector<double> const & y)
00088             : interp_(gsl_interp_alloc(gsl_interp_cspline, x.size()), &gsl_interp_free)
00089               , accel_(gsl_interp_accel_alloc(), &gsl_interp_accel_free)
00090               , x_(x)
00091               , y_(y)
00092 
00093          {
00094             validate_construction(); // throws on fail
00095             gsl_interp_init(interp_->get(), &x_[0], &y_[0], x_.size());
00096          }
00097 
00098 
00113          bool operator () (double const x, double & y, double const z = 0) const
00114          {
00115             bool ok =  0 == gsl_interp_eval_e(
00116                   interp_->get(),
00117                   &x_[0], &y_[0], x,
00118                   accel_->get(), &y
00119                   );
00120 
00121             if(!ok) { y = z;}
00122 
00123             return ok;
00124          }
00125 
00137          double operator () (double const x) const
00138          {
00139             double y = 0.0;
00140 
00141             if(!(*this)(x, y))
00142             {
00143                throw std::range_error("out of range");
00144             }
00145 
00146             return y;
00147          }
00148 
00149       private:
00150 
00151          void validate_construction() const
00152          {
00153             // x and y must be the same size
00154             assert(x_.size() == y_.size());
00155             if(x_.size() != y_.size())
00156             {
00157                throw std::runtime_error("the size of x and y must be the same");
00158             }
00159 
00160             // x must be sorted by-asc (not my rule, gsl demands it)
00161             bool const sorted = (std::adjacent_find(x_.begin(), x_.end(), std::greater_equal<double>()) == x_.end());
00162             assert(sorted);
00163             if(!sorted)
00164             {
00165                throw std::runtime_error("x must be sorted in assending order");
00166             }
00167          }
00168 
00169       private:
00170          interp_t interp_;
00171          accel_t  accel_;
00172          std::vector<double> const & x_;
00173          std::vector<double> const & y_;
00174    };
00175 
00176 
00177 }}
00178 
00179 #endif // MOOST_ALGORITHM_SPLINE_INTERPOLATION_HPP