00001 /** 00002 * @file utilities.h 00003 * Various templated functions that carry out common vector 00004 * operations (see \ref globalUtilFuncs). 00005 */ 00006 00007 // Copyright 2001 California Institute of Technology 00008 /* 00009 * $Id: utilities.h 387 2010-01-17 18:17:55Z hkmoffa $ 00010 00011 */ 00012 /** 00013 * @defgroup utils Templated Utility Functions 00014 * 00015 * These are templates to perform various simple operations on arrays. 00016 * Note that the compiler will inline these, so using them carries no 00017 * performnce penalty. 00018 */ 00019 00020 #ifndef CT_UTILITIES_H 00021 #define CT_UTILITIES_H 00022 00023 #include "ct_defs.h" 00024 00025 #ifdef WIN32 00026 #pragma warning(disable:4996) 00027 #endif 00028 00029 //! Unary operator to multiply the argument by a constant. 00030 /*! 00031 * The form of this operator is designed for use by std::transform. 00032 * @see @ref scale(). 00033 */ 00034 template<class T> struct timesConstant : public std::unary_function<T, double> 00035 { 00036 //! Constructor 00037 /*! 00038 * @param c Constant of templated type T 00039 * that will be storred internally within the object 00040 * and used in the multiplication operation 00041 */ 00042 timesConstant(T c) : m_c(c) {} 00043 00044 //! Parenthesis operator returning a double 00045 /*! 00046 * @param x Variable of templated type T that will be 00047 * used in the mulitplication operator 00048 * 00049 * @return Returns a value of type double from the internal 00050 * multiplication 00051 */ 00052 double operator()(T x) {return m_c * x;} 00053 00054 //! Storred constant value of time T 00055 T m_c; 00056 }; 00057 00058 00059 namespace Cantera { 00060 00061 /*! 00062 * @defgroup globalUtilFuncs Global Utility Functions 00063 * 00064 */ 00065 //@{ 00066 00067 //! Maximum of two templated quantities, i and j. 00068 /*! 00069 * If \a i and \a j have different types, \a j 00070 * is converted to the type of \a i before the comparison. 00071 * 00072 * @param i first argument, instance of templated class T 00073 * @param j Second argument, instance of templated class S 00074 * @return 00075 * This function returns the maximum of the two values 00076 * as an instance of templated type T. 00077 */ 00078 template<class T, class S> 00079 inline T max(T i, S j) { 00080 return (i > T(j) ? i : T(j)); 00081 } 00082 00083 //! Minimum of two templated quantities, i and j. 00084 /*! 00085 * If \a i and \a j have different types, \a j 00086 * is converted to the type of \a i before the comparison. 00087 * 00088 * @param i first argument, instance of templated class T 00089 * @param j Second argument, instance of templated class S 00090 * @return 00091 * This function returns the minimum of the two values 00092 * as an instance of templated type T. 00093 */ 00094 template<class T, class S> 00095 inline T min(T i, S j) { 00096 return (i < T(j) ? i : T(j)); 00097 } 00098 00099 00100 //! Templated Inner product of two vectors of length 4. 00101 /*! 00102 * If either \a x 00103 * or \a y has length greater than 4, only the first 4 elements 00104 * will be used. 00105 * 00106 * @param x first reference to the templated class V 00107 * @param y second reference to the templated class V 00108 * @return 00109 * This class returns a hard-coded type, doublereal. 00110 */ 00111 template<class V> 00112 inline doublereal dot4(const V& x, const V& y) { 00113 return x[0]*y[0] + x[1]*y[1] + x[2]*y[2] + x[3]*y[3]; 00114 } 00115 00116 00117 //! Tempalted Inner product of two vectors of length 5 00118 /*! 00119 * If either \a x 00120 * or \a y has length greater than 4, only the first 4 elements 00121 * will be used. 00122 * 00123 * @param x first reference to the templated class V 00124 * @param y second reference to the templated class V 00125 * @return 00126 * This class returns a hard-coded type, doublereal. 00127 */ 00128 template<class V> 00129 inline doublereal dot5(const V& x, const V& y) { 00130 return x[0]*y[0] + x[1]*y[1] + x[2]*y[2] + x[3]*y[3] + 00131 x[4]*y[4]; 00132 } 00133 00134 //! Tempalted Inner product of two vectors of length 6 00135 /*! 00136 * If either \a x 00137 * or \a y has length greater than 4, only the first 4 elements 00138 * will be used. 00139 * 00140 * @param x first reference to the templated class V 00141 * @param y second reference to the templated class V 00142 * @return 00143 * This class returns a hard-coded type, doublereal. 00144 */ 00145 template<class V> 00146 inline doublereal dot6(const V& x, const V& y) { 00147 return x[0]*y[0] + x[1]*y[1] + x[2]*y[2] + x[3]*y[3] + 00148 x[4]*y[4] + x[5]*y[5]; 00149 } 00150 00151 //! Function that calculates a templated inner product. 00152 /*! 00153 * This inner product is templated twice. The output variable is hard coded 00154 * to return a doublereal. 00155 * 00156 * template<class InputIter, class InputIter2> 00157 * 00158 * @code 00159 * double x[8], y[8]; 00160 * doublereal dsum = dot<double *,double *>(x, &x+7, y); 00161 * @endcode 00162 * 00163 * @param x_begin Iterator pointing to the beginning, belonging to the 00164 * iterator class InputIter. 00165 * @param x_end Iterator pointing to the end, belonging to the 00166 * iterator class InputIter. 00167 * @param y_begin Iterator pointing to the beginning of y, belonging to the 00168 * iterator class InputIter2. 00169 * @return 00170 * The return is hard-coded to return a double. 00171 */ 00172 template<class InputIter, class InputIter2> 00173 inline doublereal dot(InputIter x_begin, InputIter x_end, 00174 InputIter2 y_begin) { 00175 return inner_product(x_begin, x_end, y_begin, 0.0); 00176 } 00177 00178 //! Multiply elements of an array by a scale factor. 00179 /*! 00180 * \code 00181 * vector_fp in(8, 1.0), out(8); 00182 * scale(in.begin(), in.end(), out.begin(), factor); 00183 * \endcode 00184 * 00185 * @param begin Iterator pointing to the beginning, belonging to the 00186 * iterator class InputIter. 00187 * @param end Iterator pointing to the end, belonging to the 00188 * iterator class InputIter. 00189 * @param out Iterator pointing to the beginning of out, belonging to the 00190 * iterator class OutputIter. This is the output variable 00191 * for this routine. 00192 * @param scale_factor input scale factor belonging to the class S. 00193 */ 00194 template<class InputIter, class OutputIter, class S> 00195 inline void scale(InputIter begin, InputIter end, 00196 OutputIter out, S scale_factor) { 00197 std::transform(begin, end, out, timesConstant<S>(scale_factor)); 00198 } 00199 00200 /*! 00201 * Multiply elements of an array, y, by a scale factor, f and add the 00202 * result to an existing array, x. This is essentially a templated daxpy_ 00203 * operation. 00204 * 00205 * The template arguments are: template<class InputIter, 00206 * class OutputIter, class S> 00207 * 00208 * Simple Code Example of the functionality; 00209 * @code 00210 * double x[10], y[10], f; 00211 * for (i = 0; i < n; i++) { 00212 * y[i] += f * x[i] 00213 * } 00214 * @endcode 00215 * Example of the function call to implement the simple code example 00216 * @code 00217 * double x[10], y[10], f; 00218 * increment_scale(x, x+10, y, f); 00219 * @endcode 00220 * 00221 * It is templated with three parameters. The first template 00222 * is the iterator, InputIter, which controls access to y[]. 00223 * The second template is the iterator OutputIter, which controls 00224 * access to y[]. The third iterator is S, which is f. 00225 * 00226 * @param begin InputIter Iterator for beginning of y[] 00227 * @param end inputIter Iterator for end of y[] 00228 * @param out OutputIter Iterator for beginning of x[] 00229 * @param scale_factor Scale Factor to multiply y[i] by 00230 */ 00231 template<class InputIter, class OutputIter, class S> 00232 inline void increment_scale(InputIter begin, InputIter end, 00233 OutputIter out, S scale_factor) { 00234 for (; begin != end; ++begin, ++out) 00235 *out += scale_factor * *begin; 00236 } 00237 00238 00239 //! Multiply each entry in x by the corresponding entry in y. 00240 /*! 00241 * The template arguments are: template<class InputIter, class OutputIter> 00242 * 00243 * Simple code Equivalent: 00244 * \code 00245 * double x[10], y[10] 00246 * for (n = 0; n < 10; n++) { 00247 * x[n] *= y[n]; 00248 * } 00249 * \endcode 00250 * Example of function call usage to implement the simple code example: 00251 * \code 00252 * double x[10], y[10] 00253 * multiply_each(x, x+10, y); 00254 * \endcode 00255 * 00256 * @param x_begin Iterator pointing to the beginning of the vector x, belonging to the 00257 * iterator class InputIter. 00258 * @param x_end Iterator pointing to the end of the vector x, belonging to the 00259 * iterator class InputIter. The difference between end and begin 00260 * determines the loop length 00261 * @param y_begin Iterator pointing to the beginning of the vector y, belonging to the 00262 * iterator class outputIter. 00263 */ 00264 template<class InputIter, class OutputIter> 00265 inline void multiply_each(OutputIter x_begin, OutputIter x_end, 00266 InputIter y_begin) { 00267 for(; x_begin != x_end; ++x_begin, ++y_begin) *x_begin *= *y_begin; 00268 } 00269 00270 //! Invoke method 'resize' with argument \a m for a sequence of objects (templated version) 00271 /*! 00272 * The template arguments are: template<class InputIter> 00273 * 00274 * Simple code Equivalent: 00275 * \code 00276 * vector<vector<double> *> VV; 00277 * for (n = 0; n < 20; n++) { 00278 * vector<double> *vp = VV[n]; 00279 * vp->resize(m); 00280 * } 00281 * \endcode 00282 * Example of function call usage to implement the simple code example: 00283 * \code 00284 * vector<vector<double> *> VV; 00285 * resize_each(m, &VV[0], &VV[20]); 00286 * \endcode 00287 * 00288 * @param m Integer specifying the size that each object should be resized to. 00289 * @param begin Iterator pointing to the beginning of the sequence of object, belonging to the 00290 * iterator class InputIter. 00291 * @param end Iterator pointing to the end of the sequence of objects, belonging to the 00292 * iterator class InputIter. The difference between end and begin 00293 * determines the loop length 00294 * 00295 * @note This is currently unused. 00296 */ 00297 template<class InputIter> 00298 inline void resize_each(int m, InputIter begin, InputIter end) { 00299 for(; begin != end; ++begin) begin->resize(m); 00300 } 00301 00302 //! The maximum absolute value (templated version) 00303 /*! 00304 * The template arguments are: template<class InputIter> 00305 * 00306 * Simple code Equivalent: 00307 * \code 00308 * double x[10] amax = 0.0; 00309 * for (int n = 0; n < 10; n++) { 00310 * if (fabs(x[n]) > amax) amax = fabs(x[10]); 00311 * } 00312 * return amax; 00313 * \endcode 00314 * Example of function call usage to implement the simple code example: 00315 * \code 00316 * double x[10] 00317 * double amax = absmax(x, x+10); 00318 * \endcode 00319 * 00320 * @param begin Iterator pointing to the beginning of the x vector, belonging to the 00321 * iterator class InputIter. 00322 * @param end Iterator pointing to the end of the x vector, belonging to the 00323 * iterator class InputIter. The difference between end and begin 00324 * determines the loop length 00325 */ 00326 template<class InputIter> 00327 inline doublereal absmax(InputIter begin, InputIter end) { 00328 doublereal amax = 0.0; 00329 for(; begin != end; ++begin) 00330 if (fabs(*begin) > amax) amax = fabs(*begin); 00331 return amax; 00332 } 00333 00334 //! Normalize the values in a sequence, such that they sum to 1.0 (templated version) 00335 /*! 00336 * The template arguments are: template<class InputIter, class OutputIter> 00337 * 00338 * Simple Equivalent: 00339 * \code 00340 * double x[10], y[10], sum = 0.0; 00341 * for (int n = 0; n < 10; n++) { 00342 * sum += x[10]; 00343 * } 00344 * for (int n = 0; n < 10; n++) { 00345 * y[n] = x[n]/sum; 00346 * } 00347 * \endcode 00348 * Example of function call usage: 00349 * \code 00350 * double x[10], y[10]; 00351 * normalize(x, x+10, y); 00352 * \endcode 00353 * 00354 * @param begin Iterator pointing to the beginning of the x vector, belonging to the 00355 * iterator class InputIter. 00356 * @param end Iterator pointing to the end of the x vector, belonging to the 00357 * iterator class InputIter. The difference between end and begin 00358 * determines the loop length 00359 * @param out Iterator pointing to the beginning of the output vector, belonging to the 00360 * iterator class OutputIter. 00361 */ 00362 template<class InputIter, class OutputIter> 00363 inline void normalize(InputIter begin, InputIter end, 00364 OutputIter out) { 00365 doublereal sum = accumulate(begin, end, 0.0); 00366 for (; begin != end; ++begin, ++out) *out = *begin/sum; 00367 } 00368 00369 //! Templated divide of each element of \a x by the corresponding element of \a y. 00370 /*! 00371 * The template arguments are: template<class InputIter, class OutputIter> 00372 * 00373 * Simple Equivalent: 00374 * \code 00375 * double x[10], y[10]; 00376 * for (n = 0; n < 10; n++) { 00377 * x[n] /= y[n]; 00378 * } 00379 * \endcode 00380 * Example of code usage: 00381 * \code 00382 * double x[10], y[10]; 00383 * divide_each(x, x+10, y); 00384 * \endcode 00385 * 00386 * @param x_begin Iterator pointing to the beginning of the x vector, belonging to the 00387 * iterator class OutputIter. 00388 * @param x_end Iterator pointing to the end of the x vector, belonging to the 00389 * iterator class OutputIter. The difference between end and begin 00390 * determines the number of inner iterations. 00391 * @param y_begin Iterator pointing to the beginning of the yvector, belonging to the 00392 * iterator class InputIter. 00393 */ 00394 template<class InputIter, class OutputIter> 00395 inline void divide_each(OutputIter x_begin, OutputIter x_end, 00396 InputIter y_begin) { 00397 for(; x_begin != x_end; ++x_begin, ++y_begin) *x_begin /= *y_begin; 00398 } 00399 00400 //! Increment each entry in \a x by the corresponding entry in \a y. 00401 /*! 00402 * The template arguments are: template<class InputIter, class OutputIter> 00403 * 00404 * @param x_begin Iterator pointing to the beginning of the x vector, belonging to the 00405 * iterator class OutputIter. 00406 * @param x_end Iterator pointing to the end of the x vector, belonging to the 00407 * iterator class OutputIter. The difference between end and begin 00408 * determines the number of inner iterations. 00409 * @param y_begin Iterator pointing to the beginning of the yvector, belonging to the 00410 * iterator class InputIter. 00411 */ 00412 template<class InputIter, class OutputIter> 00413 inline void sum_each(OutputIter x_begin, OutputIter x_end, 00414 InputIter y_begin) { 00415 for(; x_begin != x_end; ++x_begin, ++y_begin) *x_begin += *y_begin; 00416 } 00417 00418 //! Copies a contiguous range in a sequence to indexed 00419 //! positions in another sequence. 00420 /*! 00421 * The template arguments are: template<class InputIter, class OutputIter, class IndexIter> 00422 * 00423 * Example: 00424 * 00425 * \code 00426 * vector<double> x(3), y(20), ; 00427 * vector<int> index(3); 00428 * index[0] = 9; 00429 * index[1] = 2; 00430 * index[3] = 16; 00431 * scatter_copy(x.begin(), x.end(), y.begin(), index.begin()); 00432 * \endcode 00433 * 00434 * This routine is templated 3 times. 00435 * InputIter is an iterator for the source vector 00436 * OutputIter is an iterator for the destination vector 00437 * IndexIter is an iterator for the index into the destination vector. 00438 * 00439 * @param begin Iterator pointing to the beginning of the source vector, belonging to the 00440 * iterator class InputIter. 00441 * @param end Iterator pointing to the end of the source vector, belonging to the 00442 * iterator class InputIter. The difference between end and begin 00443 * determines the number of inner iterations. 00444 * @param result Iterator pointing to the beginning of the output vector, belonging to the 00445 * iterator class outputIter. 00446 * @param index Iterator pointing to the beginning of the index vector, belonging to the 00447 * iterator class IndexIter. 00448 */ 00449 template<class InputIter, class OutputIter, class IndexIter> 00450 inline void scatter_copy(InputIter begin, InputIter end, 00451 OutputIter result, IndexIter index) { 00452 for (; begin != end; ++begin, ++index) { 00453 *(result + *index) = *begin; 00454 } 00455 } 00456 00457 00458 //! Multiply selected elements in an array by a contiguous 00459 //! sequence of multipliers. 00460 /*! 00461 * The template arguments are: template<class InputIter, class RandAccessIter, class IndexIter> 00462 * 00463 * Example: 00464 * \code 00465 * double multipliers[] = {8.9, -2.0, 5.6}; 00466 * int index[] = {7, 4, 13}; 00467 * vector_fp data(20); 00468 * ... 00469 * // Multiply elements 7, 4, and 13 in data by multipliers[0], multipliers[1],and multipliers[2], 00470 * // respectively 00471 * scatter_mult(multipliers, multipliers + 3, data.begin(), index); 00472 * \endcode 00473 * 00474 * @param mult_begin Iterator pointing to the beginning of the multiplier vector, belonging to the 00475 * iterator class InputIter. 00476 * @param mult_end Iterator pointing to the end of the multiplier vector, belonging to the 00477 * iterator class InputIter. The difference between end and begin 00478 * determines the number of inner iterations. 00479 * @param data Iterator pointing to the beginning of the output vector, belonging to the 00480 * iterator class RandAccessIter, that will be selectively multipied. 00481 * @param index Iterator pointing to the beginning of the index vector, belonging to the 00482 * iterator class IndexIter. 00483 */ 00484 template<class InputIter, class RandAccessIter, class IndexIter> 00485 inline void scatter_mult(InputIter mult_begin, InputIter mult_end, 00486 RandAccessIter data, IndexIter index) { 00487 for (; mult_begin != mult_end; ++mult_begin, ++index) { 00488 *(data + *index) *= *mult_begin; 00489 } 00490 } 00491 00492 00493 //! Divide selected elements in an array by a contiguous sequence of divisors. 00494 /*! 00495 * The template arguments are: template<class InputIter, class OutputIter, class IndexIter> 00496 * 00497 * Example: 00498 * \code 00499 * double divisors[] = {8.9, -2.0, 5.6}; 00500 * int index[] = {7, 4, 13}; 00501 * vector_fp data(20); 00502 * ... 00503 * // divide elements 7, 4, and 13 in data by divisors[7] divisors[4], and divisors[13] 00504 * // respectively 00505 * scatter_divide(divisors, divisors + 3, data.begin(), index); 00506 * \endcode 00507 * 00508 * @param begin Iterator pointing to the beginning of the source vector, belonging to the 00509 * iterator class InputIter. 00510 * @param end Iterator pointing to the end of the source vector, belonging to the 00511 * iterator class InputIter. The difference between end and begin 00512 * determines the number of inner iterations. 00513 * @param result Iterator pointing to the beginning of the output vector, belonging to the 00514 * iterator class outputIter. 00515 * @param index Iterator pointing to the beginning of the index vector, belonging to the 00516 * iterator class IndexIter. 00517 */ 00518 template<class InputIter, class OutputIter, class IndexIter> 00519 inline void scatter_divide(InputIter begin, InputIter end, 00520 OutputIter result, IndexIter index) { 00521 for (; begin != end; ++begin, ++index) { 00522 *(result + *index) /= *begin; 00523 } 00524 } 00525 00526 //! Compute \f[ \sum_k x_k \log x_k. \f]. 00527 /*! 00528 * The template arguments are: template<class InputIter> 00529 * 00530 * A small number (1.0E-20) is added before taking the log. This templated 00531 * class does the indicated sun. The template must be an iterator. 00532 * 00533 * @param begin Iterator pointing to the beginning, belonging to the 00534 * iterator class InputIter. 00535 * @param end Iterator pointing to the end, belonging to the 00536 * iterator class InputIter. 00537 * @return 00538 * The return from this class is a double. 00539 */ 00540 template<class InputIter> 00541 inline doublereal sum_xlogx(InputIter begin, InputIter end) { 00542 doublereal sum = 0.0; 00543 for (; begin != end; ++begin) { 00544 sum += (*begin) * std::log(*begin + Tiny); 00545 } 00546 return sum; 00547 } 00548 00549 //! Compute \f[ \sum_k x_k \log Q_k. \f]. 00550 /*! 00551 * The template arguments are: template<class InputIter1, class InputIter2> 00552 * 00553 * This class is templated twice. The first template, InputIter1 00554 * is the iterator that points to $x_k$. The second iterator 00555 * InputIter2, point to $Q_k$. 00556 * A small number (1.0E-20) is added before taking the log. 00557 * 00558 * @param begin Iterator pointing to the beginning, belonging to the 00559 * iterator class InputIter1. 00560 * @param end Iterator pointing to the end, belonging to the 00561 * iterator class InputIter1. 00562 * @param Q_begin Iterator pointing to the beginning of Q_k, belonging to the 00563 * iterator class InputIter2. 00564 * @return 00565 * The return from this class is hard coded to a doublereal. 00566 */ 00567 template<class InputIter1, class InputIter2> 00568 inline doublereal sum_xlogQ(InputIter1 begin, InputIter1 end, 00569 InputIter2 Q_begin) { 00570 doublereal sum = 0.0; 00571 for (; begin != end; ++begin, ++Q_begin) { 00572 sum += (*begin) * std::log(*Q_begin + Tiny); 00573 } 00574 return sum; 00575 } 00576 00577 //! Scale a templated vector by a constant factor. 00578 /*! 00579 * The template arguments are: template<class OutputIter> 00580 * 00581 * This function is essentially a wrapper around the stl 00582 * function %scale(). The function is has one template 00583 * parameter, OutputIter. OutputIter is a templated iterator 00584 * that points to the vector to be scaled. 00585 * 00586 * @param N Length of the vector 00587 * @param alpha scale factor - double 00588 * @param x Templated Iterator to the start of the vector 00589 * to be scaled. 00590 */ 00591 template<class OutputIter> 00592 inline void scale(int N, double alpha, OutputIter x) { 00593 scale(x, x+N, x, alpha); 00594 } 00595 00596 00597 //! Templated evaluation of a polynomial of order 6 00598 /*! 00599 * @param x Value of the independent variable - First template parameter 00600 * @param c Pointer to the polynomial - Second template parameter 00601 */ 00602 template<class D, class R> 00603 R poly6(D x, R* c) { 00604 return ((((((c[6]*x + c[5])*x + c[4])*x + c[3])*x + 00605 c[2])*x + c[1])*x + c[0]); 00606 } 00607 00608 //! Templated evaluation of a polynomial of order 8 00609 /*! 00610 * @param x Value of the independent variable - First template parameter 00611 * @param c Pointer to the polynomial - Second template parameter 00612 */ 00613 template<class D, class R> 00614 R poly8(D x, R* c) { 00615 return ((((((((c[8]*x + c[7])*x + c[6])*x + c[5])*x + c[4])*x + c[3])*x + 00616 c[2])*x + c[1])*x + c[0]); 00617 } 00618 00619 //! Templated evaluation of a polynomial of order 10 00620 /*! 00621 * @param x Value of the independent variable - First template parameter 00622 * @param c Pointer to the polynomial - Second template parameter 00623 */ 00624 template<class D, class R> 00625 R poly10(D x, R* c) { 00626 return ((((((((((c[10]*x + c[9])*x + c[8])*x + c[7])*x 00627 + c[6])*x + c[5])*x + c[4])*x + c[3])*x 00628 + c[2])*x + c[1])*x + c[0]); 00629 } 00630 00631 //! Templated evaluation of a polynomial of order 5 00632 /*! 00633 * @param x Value of the independent variable - First template parameter 00634 * @param c Pointer to the polynomial - Second template parameter 00635 */ 00636 template<class D, class R> 00637 R poly5(D x, R* c) { 00638 return (((((c[5]*x + c[4])*x + c[3])*x + 00639 c[2])*x + c[1])*x + c[0]); 00640 } 00641 00642 //! Evaluates a polynomial of order 4. 00643 /*! 00644 * @param x Value of the independent variable. 00645 * @param c Pointer to the polynomial coefficient array. 00646 */ 00647 template<class D, class R> 00648 R poly4(D x, R* c) { 00649 return ((((c[4]*x + c[3])*x + 00650 c[2])*x + c[1])*x + c[0]); 00651 } 00652 00653 //! Templated evaluation of a polynomial of order 3 00654 /*! 00655 * @param x Value of the independent variable - First template parameter 00656 * @param c Pointer to the polynomial - Second template parameter 00657 */ 00658 template<class D, class R> 00659 R poly3(D x, R* c) { 00660 return (((c[3]*x + c[2])*x + c[1])*x + c[0]); 00661 } 00662 00663 //@} 00664 } 00665 00666 00667 #endif 00668 00669 00670 00671 00672 00673 00674 00675 00676 00677 00678 00679 00680 00681 00682 00683 00684