Skip to content

Instantly share code, notes, and snippets.

@RobertKrajewski
Created July 9, 2015 16:27
Show Gist options
  • Save RobertKrajewski/042ab741809cb41b0346 to your computer and use it in GitHub Desktop.
Save RobertKrajewski/042ab741809cb41b0346 to your computer and use it in GitHub Desktop.
Lazy interpolation template
#ifndef LAZYINTERPOLATION_H
#define LAZYINTERPOLATION_H
#include <functional>
/**
* @brief This class manages data interpolation and saves results.
* During construction a vector containing data is passed. Interpolated
* data is saved in this class and another interpolation is avoided.
*/
template< template< typename > class Vector, class T >
class LazyInterpolation
{
public:
LazyInterpolation( Vector< T > *f_data_p,
std::function< int( T* , T* ) > f_compare_f,
std::function< void( T*, T*, T&) > f_interpolate_f )
: m_inputData_p( f_data_p ),
m_interpolatedData_o( ),
m_allData_o( ),
m_compare_f( f_compare_f ),
m_interpolate_f( f_interpolate_f )
{
// import input data
for( auto &data_o : *m_inputData_p )
{
m_allData_o.push_back( &data_o );
}
}
~LazyInterpolation( )
{
// delete all intepolated data
for( auto *data_p : m_interpolatedData_o )
{
delete data_p;
}
}
/**
* @brief interpolate interpolates given value
* Searches for value in all interpolated data and returns it if
* available. Otherwise value will be interpolated by its nearest
* neighbours
* @param f_value_o value to be interpolated at
*/
void interpolate( T &f_value_o )
{
int pos = findCrossOver( 0, m_allData_o.size()-1, &f_value_o );
// desired value is smaller than every available value
if( pos == 0 &&
m_compare_f( &f_value_o, m_allData_o.front() ) < 0)
{
f_value_o = *m_allData_o.front();
return;
}
// desired value is bigger than every available value
if( pos == m_allData_o.size()-1 &&
m_compare_f( &f_value_o, m_allData_o.back() ) > 0)
{
f_value_o = *m_allData_o.back();
return;
}
// desired value is found
if( m_compare_f( &f_value_o, m_allData_o[pos] ) == 0)
{
f_value_o = *m_allData_o[pos];
return;
}
// interpolation needed
m_interpolate_f( m_allData_o[ pos ], m_allData_o[ pos + 1 ], f_value_o );
m_interpolatedData_o.push_back( new T( f_value_o ) );
m_allData_o.insert( pos + 1, m_interpolatedData_o.back( ) );
}
/**
* @brief findCrossOver
* @param low
* @param high
* @param x
* @return position of nearest item (smaller/equal) in alldata to x
*/
int findCrossOver( int low, int high, T *x )
{
// x is greater than all
if ( m_compare_f( m_allData_o[ high ], x ) >= 0 )
{
return high;
}
// x is smaller than all
if ( m_compare_f( m_allData_o[ low ], x ) <= 0 )
{
return low;
}
// Find the middle point
int mid = ( low + high ) / 2;
/* If x is same as middle element, then return mid */
if ( m_compare_f( m_allData_o[ mid ], x ) >= 0 &&
m_compare_f( m_allData_o[ mid + 1 ], x ) < 0 )
{
return mid;
}
if( m_compare_f( m_allData_o[ mid ], x ) > 0 )
{
return findCrossOver( mid+1, high, x );
}
else
{
return findCrossOver( low, mid - 1, x );
}
}
private:
/// vector containing the given input data (needs to be sorted!)
Vector< T > *m_inputData_p = nullptr;
/// vector containing every interpolated data (unsorted)
Vector< T* > m_interpolatedData_o;
/// vector containing every data for searching (sorted)
Vector< T* > m_allData_o ;
/// function for comparison between to data T
/// Has to return -1 if left > right
/// 0 if left == right
/// 1 if left < right
std::function< int( T*, T* ) > m_compare_f;
/// function for interpolation between first two parameters
/// saves result in third parameter
std::function< void( T*, T*, T& ) > m_interpolate_f;
};
#endif // LAZYINTERPOLATION_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment