You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

98 lines
4.2KB

  1. /*
  2. Implementation of the Horner method of polynomial evaluation
  3. Copyright (C) 2011 Darko Veberic, darko.veberic@ijs.si
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #pragma once
  16. namespace dsp {
  17. template<typename Float, class Tag, unsigned int order>
  18. struct Polynomial {
  19. static inline Float Coeff();
  20. static inline Float Coeff(const Float x);
  21. };
  22. template<typename Float, class Tag, unsigned int order>
  23. struct Horner {
  24. static Float Recurse(const Float term, const Float x) {
  25. return Horner<Float, Tag, order - 1>::Recurse(term * x + Polynomial<Float, Tag, order>::Coeff(), x);
  26. }
  27. static Float RecurseAlt(const Float term, const Float x) {
  28. return Horner<Float, Tag, order - 1>::RecurseAlt(Polynomial<Float, Tag, order>::Coeff() + x * term, x);
  29. }
  30. static Float Eval(const Float x) { return Horner<Float, Tag, order - 1>::Recurse(Polynomial<Float, Tag, order>::Coeff(), x); }
  31. static Float EvalAlt(const Float x) { return Horner<Float, Tag, order - 1>::RecurseAlt(Polynomial<Float, Tag, order>::Coeff(), x); }
  32. //
  33. static Float Recurse(const Float term, const Float x, const Float y) {
  34. return Horner<Float, Tag, order - 1>::Recurse(term * x + Polynomial<Float, Tag, order>::Coeff(y), x, y);
  35. }
  36. static Float Eval(const Float x, const Float y) {
  37. return Horner<Float, Tag, order - 1>::Recurse(Polynomial<Float, Tag, order>::Coeff(y), x, y);
  38. }
  39. };
  40. template<typename Float, class Tag>
  41. struct Horner<Float, Tag, 0> {
  42. static Float Recurse(const Float term, const Float x) { return term * x + Polynomial<Float, Tag, 0>::Coeff(); }
  43. static Float Eval(const Float x) { return Polynomial<Float, Tag, 0>::Coeff(); }
  44. //
  45. static Float Recurse(const Float term, const Float x, const Float y) { return term * x + Polynomial<Float, Tag, 0>::Coeff(y); }
  46. static Float Eval(const Float x, const Float y) { return Polynomial<Float, Tag, 0>::Coeff(y); }
  47. };
  48. #define HORNER_COEFF(_Tag_, _i_, _c_) \
  49. template<typename Float> struct Polynomial<Float, _Tag_, _i_> { static Float Coeff() { return Float(_c_); } }
  50. #define HORNER_COEFF2(_Tag_, _i_, _c_y_) \
  51. template<typename Float> struct Polynomial<Float, _Tag_, _i_> { static Float Coeff(const Float y) { return Float(_c_y_); } }
  52. #define HORNER0(F, x, c0) (F)(c0)
  53. #define HORNER1(F, x, c1, c0) HORNER0(F, x, (F)(c1)*(x) + (F)(c0) )
  54. #define HORNER2(F, x, c2, c1, c0) HORNER1(F, x, (F)(c2)*(x) + (F)(c1), c0)
  55. #define HORNER3(F, x, c3, c2, c1, c0) HORNER2(F, x, (F)(c3)*(x) + (F)(c2), c1, c0)
  56. #define HORNER4(F, x, c4, c3, c2, c1, c0) HORNER3(F, x, (F)(c4)*(x) + (F)(c3), c2, c1, c0)
  57. #define HORNER5(F, x, c5, c4, c3, c2, c1, c0) HORNER4(F, x, (F)(c5)*(x) + (F)(c4), c3, c2, c1, c0)
  58. #define HORNER6(F, x, c6, c5, c4, c3, c2, c1, c0) HORNER5(F, x, (F)(c6)*(x) + (F)(c5), c4, c3, c2, c1, c0)
  59. #define HORNER7(F, x, c7, c6, c5, c4, c3, c2, c1, c0) HORNER6(F, x, (F)(c7)*(x) + (F)(c6), c5, c4, c3, c2, c1, c0)
  60. #define HORNER8(F, x, c8, c7, c6, c5, c4, c3, c2, c1, c0) HORNER7(F, x, (F)(c8)*(x) + (F)(c7), c6, c5, c4, c3, c2, c1, c0)
  61. #define HORNER9(F, x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0) HORNER8(F, x, (F)(c9)*(x) + (F)(c8), c7, c6, c5, c4, c3, c2, c1, c0)
  62. }