24#include "marley/Error.hh"
25#include "marley/marley_utils.hh"
36 template <
typename FirstNumericType,
typename SecondNumericType
41 using OrderedPair = std::pair<FirstNumericType, SecondNumericType>;
42 using Grid = std::vector<OrderedPair>;
43 using GridConstIterator
44 =
typename std::vector<OrderedPair>::const_iterator;
65 LinearLinear = 2, LinearLog = 3, LogLinear = 4,
103 = ExtrapolationMethod::Zero ) : interpolation_method_( interp_method ),
104 extrapolation_method_( extrap_method )
112 : interpolation_method_( interp_method ),
113 extrapolation_method_( extrap_method ), ordered_pairs_( grid )
120 const std::vector<SecondNumericType>& ys,
123 : interpolation_method_( interp_method ),
124 extrapolation_method_( extrap_method )
127 std::string(
"Vectors of x and y values passed to the constructor")
128 +
" of marley::InterpolationGrid have unequal sizes." );
130 double old_x = marley_utils::minus_infinity;
131 for (
size_t j = 0; j < xs.size(); ++j ) {
132 double new_x = xs.at( j );
133 if ( new_x <= old_x )
throw marley::Error(
"The grid point x-values"
134 " defined for a marley::InterpolationGrid object are not strictly"
136 ordered_pairs_.push_back( OrderedPair( xs.at(j), ys.at(j) ) );
141 SecondNumericType
interpolate( FirstNumericType x )
const;
144 void insert( FirstNumericType x, SecondNumericType y );
147 inline size_t size()
const {
return ordered_pairs_.size(); }
150 inline void clear() { ordered_pairs_.clear(); }
153 inline OrderedPair&
at(
size_t j ) {
return ordered_pairs_.at( j ); }
157 inline std::function< SecondNumericType(FirstNumericType) >
get_function()
159 return [ this ]( FirstNumericType x )
160 -> SecondNumericType {
return this->
interpolate( x ); };
165 inline GridConstIterator
lower_bound(
const GridConstIterator& begin,
166 const GridConstIterator& end, FirstNumericType x )
const
168 return std::lower_bound( begin, end, x,
169 [](
const OrderedPair& pair,
const FirstNumericType& f )
170 ->
bool {
return pair.first < f; } );
176 GridConstIterator& begin,
const GridConstIterator& end,
177 FirstNumericType x )
const
179 return std::upper_bound( begin, end, x,
180 [](
const FirstNumericType& f,
const OrderedPair& pair )
181 ->
bool {
return f < pair.first; } );
185 inline const OrderedPair&
front()
const {
return ordered_pairs_.front(); }
188 inline const OrderedPair&
back()
const {
return ordered_pairs_.back(); }
192 {
return interpolation_method_; }
196 { interpolation_method_ = method; }
200 {
return extrapolation_method_; }
204 { extrapolation_method_ = method; }
222 inline void check_grid()
const {
224 if ( ordered_pairs_.size() < 2 )
throw marley::Error(
"A class method"
225 " was called for an InterpolationGrid object that contains less"
226 " than two grid points." );
232 inline bool find_bin_limits( FirstNumericType x,
233 GridConstIterator& lower_point, GridConstIterator& upper_point )
const
239 bool extrapolate =
false;
240 GridConstIterator begin = ordered_pairs_.begin();
241 GridConstIterator end = ordered_pairs_.end();
242 GridConstIterator not_less_point =
lower_bound( begin, end, x );
245 if ( not_less_point == begin ) {
247 upper_point = begin + 1;
249 if ( begin->first != x ) extrapolate =
true;
251 else if ( not_less_point == end ) {
254 lower_point = end - 2;
255 upper_point = end - 1;
259 lower_point = not_less_point - 1;
260 upper_point = not_less_point;
267 template <
typename FirstNumericType,
typename SecondNumericType>
272 InterpolationGrid::GridConstIterator lower_point, upper_point;
274 bool extrapolate = find_bin_limits( x, lower_point, upper_point );
279 if ( extrapolation_method_ == ExtrapolationMethod::Zero )
280 return static_cast< SecondNumericType
>( 0. );
281 else if ( extrapolation_method_ == ExtrapolationMethod::Endpoint ) {
282 if ( lower_point->first > x )
return lower_point->second;
283 else return upper_point->second;
285 else if ( extrapolation_method_ == ExtrapolationMethod::Throw ) {
287 +
" lies outside of the current interpolation grid object"
288 " (which extends from x_min = "
289 + std::to_string( ordered_pairs_.front().first )
290 +
" and x_max = " + std::to_string( ordered_pairs_.back().first )
291 +
") and extrapolation is disabled." );
304 if ( interpolation_method_ == InterpolationMethod::Constant ) {
305 if ( !extrapolate )
return lower_point->second;
306 else if ( lower_point->first > x )
return lower_point->second;
307 else return upper_point->second;
312 FirstNumericType x1 = lower_point->first;
313 FirstNumericType x2 = upper_point->first;
314 SecondNumericType y1 = lower_point->second;
315 SecondNumericType y2 = upper_point->second;
317 bool log_x =
false, log_y =
false;
318 FirstNumericType x_to_use = x;
319 if ( interpolation_method_ == InterpolationMethod::LinearLog )
321 else if ( interpolation_method_ == InterpolationMethod::LogLinear )
323 else if ( interpolation_method_ == InterpolationMethod::LogLog ) {
330 x_to_use = std::log( x );
337 FirstNumericType y_interp = y1 + ( (y2 - y1)/(x2 - x1) )*( x_to_use - x1 );
338 if ( log_y ) y_interp = std::exp( y_interp );
342 template <
typename FirstNumericType,
typename SecondNumericType >
344 FirstNumericType x, SecondNumericType y )
350 GridConstIterator insert_point =
upper_bound( ordered_pairs_.begin(),
351 ordered_pairs_.end(), x );
354 ordered_pairs_.insert( insert_point, OrderedPair(x, y) );
Base class for all exceptions thrown by MARLEY functions.
ExtrapolationMethod
Method to use for computing y(x) when the x value lies beyond the grid boundaries.
void insert(FirstNumericType x, SecondNumericType y)
Add a new ordered pair (x, y) to the grid.
const OrderedPair & back() const
Returns a reference to the last ordered pair.
GridConstIterator lower_bound(const GridConstIterator &begin, const GridConstIterator &end, FirstNumericType x) const
Returns a const_iterator to the first element of the grid for which the x value is not less than (i....
std::function< SecondNumericType(FirstNumericType) > get_function()
Get a std::function object that represents y(x) for this InterpolationGrid.
void clear()
Delete all ordered pairs from the grid.
size_t size() const
Get the number of ordered pairs on the grid.
OrderedPair & at(size_t j)
Get a reference to the jth ordered pair from the grid.
void set_interpolation_method(InterpolationMethod method)
Set the InterpolationMethod to use.
SecondNumericType interpolate(FirstNumericType x) const
Compute y(x) using the current InterpolationMethod.
ExtrapolationMethod extrapolation_method() const
Get the ExtrapolationMethod used by this InterpolationGrid.
InterpolationGrid(InterpolationMethod interp_method=InterpolationMethod::LinearLinear, ExtrapolationMethod extrap_method=ExtrapolationMethod::Zero)
Create an InterpolationGrid without any grid points.
InterpolationMethod interpolation_method() const
Get the InterpolationMethod used by this InterpolationGrid.
InterpolationMethod
Method to use for interpolating between (x,y) grid points.
GridConstIterator upper_bound(const GridConstIterator &begin, const GridConstIterator &end, FirstNumericType x) const
Returns a const_iterator to the first element of the grid for which the x value is greater than x.
void set_extrapolation_method(ExtrapolationMethod method)
Set the ExtrapolationMethod to use.
const OrderedPair & front() const
Returns a reference to the first ordered pair.