00001 #ifndef TAB_FN_H_IS_INCLUDED 00002 #define TAB_FN_H_IS_INCLUDED 00003 00004 /*! 00005 * \file tab_fn.H 00006 * \brief Contains the definition of the TabulatedFunction class. 00007 * \ingroup group_MLIB 00008 * 00009 */ 00010 00011 #include "std/error.H" 00012 00013 namespace mlib { 00014 00015 //! \brief Function pointer type for the type of functions that can be tabulated 00016 //! by the TabulatedFunction class. 00017 //! \relates TabulatedFunction 00018 typedef double (*real_fn_t)(double); 00019 00020 /*! 00021 * \brief Tabulates values of a given function over an interval [a,b] 00022 * using a specified resolution. 00023 * \ingroup group_MLIB 00024 * 00025 * Approximations of the function at values in [a,b) are returned as 00026 * interpolations of the tabulated values. at values outside that range the 00027 * function itself is used to compute the value. 00028 * 00029 */ 00030 class TabulatedFunction 00031 { 00032 00033 protected: 00034 00035 //! a (the start of the interval over which the function is tabulated) 00036 double _a; 00037 //! b (the end of the interval over which the function is tabulated) 00038 double _b; 00039 //! b - a (the length of the interval over which the function is tabulated) 00040 double _len; 00041 int _res; //!< resolution (# of subintervals) 00042 double _rlen; //!< _res / _len (used in computation) 00043 double* _tab; //!< table of values 00044 real_fn_t _f; //!< the given function 00045 00046 public: 00047 00048 //! \name Constructors 00049 //@{ 00050 00051 //! \brief Constructor that tabulates the function \p f over the range 00052 //! [a,b) by taking \p res samples. 00053 TabulatedFunction(double a, double b, real_fn_t f, int res) : 00054 _tab(0) { 00055 init(a,b,f,res); 00056 } 00057 00058 //! \brief Constructor that creates a tabulated function over the range 00059 //! [a,b) from the values in \p vals. 00060 //! 00061 //! \p vals should have at least \p res elements. 00062 TabulatedFunction(double a, double b, double vals[], int res) : 00063 _tab(0) { 00064 init(a,b,vals,res); 00065 } 00066 00067 //@} 00068 00069 //! \name Initialization Functions 00070 //@{ 00071 00072 //! \brief Creates a tabulated function over the range 00073 //! [a,b) from the values in \p vals. 00074 //! 00075 //! \note \p vals should have at least \p res elements. 00076 //! 00077 //! \param[in] a The start of the range of the tabulated function. 00078 //! \param[in] b The end of the range of the tabulated function. 00079 //! \param[in] vals The values to use as samples of the tabulated function. 00080 //! \param[in] res The number of samples in \p vals. 00081 //! 00082 //! \bug This function checks the for allocation errors from the new 00083 //! operator incorrectly (new doesn't return a null pointer on failure, 00084 //! it throws a bad_alloc exception). 00085 void init(double a, double b, double vals[], int res) { 00086 _a = a; 00087 _b = b; 00088 _len = (b-a); 00089 _f = 0; 00090 _res = res; 00091 00092 delete _tab; 00093 _tab = 0; 00094 00095 if (_len <= 0 ) { 00096 err_msg("TabulatedFunction::init: interval (%f,%f) is bad", a, b); 00097 } else if (_res < 1) { 00098 err_msg("TabulatedFunction::init: resolution (%d) is too small", _res); 00099 } else if ((_tab = new double [ _res + 1 ]) == 0) { 00100 err_ret("TabulatedFunction::init: can't allocate table"); 00101 } else { 00102 _rlen = _res / _len; 00103 for (int n=0; n<=_res; n++) { 00104 _tab[n] = vals[n]; 00105 } 00106 } 00107 } 00108 00109 //! \brief Tabulates the function \p f over the range 00110 //! [a,b) by taking \p res samples. 00111 //! 00112 //! \param[in] a The start of the range over which to tabulate \p f. 00113 //! \param[in] b The end of the range over which to tabulate \p f. 00114 //! \param[in] f The function to tabulate. 00115 //! \param[in] res The number of samples to take while tabulating \p f. 00116 //! 00117 //! \bug This function checks the for allocation errors from the new 00118 //! operator incorrectly (new doesn't return a null pointer on failure, 00119 //! it throws a bad_alloc exception). 00120 void init(double a, double b, real_fn_t f, int res) { 00121 _a = a; 00122 _b = b; 00123 _len = (b - a); 00124 _f = f; 00125 _res = res; 00126 00127 delete _tab; 00128 _tab = 0; 00129 00130 if (_len <= 0 ) { 00131 err_msg("TabulatedFunction::init: interval (%f,%f) is bad", a, b); 00132 } else if (_res < 1) { 00133 err_msg("TabulatedFunction::init: resolution (%d) is too small", _res); 00134 } else if ((_tab = new double [ _res + 1 ]) == 0) { 00135 err_ret("TabulatedFunction::init: can't allocate table"); 00136 } else { 00137 _rlen = _res / _len; 00138 for (int n=0; n<=_res; n++) { 00139 _tab[n] = (*_f)(n/_rlen + _a); 00140 } 00141 } 00142 } 00143 00144 //@} 00145 00146 //! \name Tabulated Function Evaulation 00147 //@{ 00148 00149 //! \brief Evaluates the tabulated function at \p x. 00150 //! 00151 //! Computes the interpolated values of the tabulated function at \p x. 00152 //! 00153 //! If \p x is out of bounds, evaluate the function directly if we have it. 00154 //! If we don't have it, extend the tabulated function to be constant 00155 //! outside of its defined range. 00156 double map(double x) const { 00157 if (x<_a || x>=_b || !_tab) 00158 return _f ? (*_f)(x) : _tab ? _tab[x<_a? 0 : _res] : 0; 00159 else { 00160 double t = _rlen*(x - _a); 00161 int n = (int) floor(t); 00162 double d = t - n; 00163 return _tab[n] + (_tab[n+1] - _tab[n])*d; 00164 } 00165 } 00166 00167 //@} 00168 00169 }; 00170 00171 } // namespace mlib 00172 00173 #endif // TAB_FN_H_IS_INCLUDED 00174 00175 /* end of file tab_fn.H */