Commit 726d9fbba902bc10d4cbe086dc7c91b9c6450329

Authored by Jürgen Knödlseder
1 parent 399c038c

Implement vectorised polynomial interpolation in GIntegrals class (#3203)

include/GIntegrals.hpp
... ... @@ -88,15 +88,14 @@ public:
88 88  
89 89 protected:
90 90 // Protected methods
91   - void init_members(void);
92   - void copy_members(const GIntegrals& integral);
93   - void free_members(void);
94   - double polint(const double* xa,
95   - const GVector* ya,
96   - const int& n,
97   - const int& index,
98   - const double& x,
99   - double* dy);
  91 + void init_members(void);
  92 + void copy_members(const GIntegrals& integral);
  93 + void free_members(void);
  94 + GVector polint(const double* xa,
  95 + const GVector* ya,
  96 + const int& order,
  97 + const double& x,
  98 + GVector* dy);
100 99  
101 100 // Protected data area
102 101 GFunctions* m_kernels; //!< Pointer to function kernels
... ...
src/numerics/GIntegrals.cpp
... ... @@ -333,12 +333,7 @@ GVector GIntegrals::romberg(const double&amp; a, const double&amp; b, const int&amp; order)
333 333 if (m_iter >= order) {
334 334  
335 335 // Compute result using polynom interpolation
336   - for (int i = 0; i < result.size(); ++i) {
337   - double dy = 0;
338   - result[i] = polint(&h[m_iter-order], &s[m_iter-order],
339   - order, i, 0.0, &dy);
340   - dss[i] = dy;
341   - }
  336 + result = polint(&h[m_iter-order], &s[m_iter-order], order, 0.0, &dss);
342 337  
343 338 // If a fixed number of iterations has been requested and if
344 339 // the final iteration was reached then set the converged
... ... @@ -711,80 +706,94 @@ void GIntegrals::free_members(void)
711 706 *
712 707 * @param[in] xa Pointer to array of X values.
713 708 * @param[in] ya Pointer to GVector of Y values.
714   - * @param[in] n Number of elements in arrays.
715   - * @param[in] index GVector index for with interpolations should be performed.
  709 + * @param[in] order Number of elements in arrays.
716 710 * @param[in] x X value for which interpolations should be performed.
717   - * @param[out] dy Pointer to array of error estimates for interpolated values.
718   - * @return Interpolated value.
  711 + * @param[out] dy Pointer to vector of error estimates for interpolated values.
  712 + * @return Vector of interpolated values.
719 713 *
720 714 * Given arrays @p xa[1,..,n] and @p ya[1,..,n], and given a value @p x, this
721 715 * method returns a value y, and an error estimate @p dy. If P(x) is the
722 716 * polynomial of degree n-1, then the returned value y=P(x).
723 717 ***************************************************************************/
724   -double GIntegrals::polint(const double* xa,
725   - const GVector* ya,
726   - const int& n,
727   - const int& index,
728   - const double& x,
729   - double* dy)
  718 +GVector GIntegrals::polint(const double* xa,
  719 + const GVector* ya,
  720 + const int& order,
  721 + const double& x,
  722 + GVector* dy)
730 723 {
  724 + // Get vector dimension
  725 + int nsize = ya->size();
  726 +
731 727 // Initialise result
732   - double y = 0.0;
  728 + GVector y(nsize);
733 729  
734 730 // Allocate temporary memory
735   - double* c = new double[n];
736   - double* d = new double[n];
737   -
738   - // Compute initial distance to first node
739   - double dif = std::abs(x-xa[1]);
  731 + double* c = new double[order];
  732 + double* d = new double[order];
740 733  
741   - // Find index ns of the closest table entry
742   - int ns = 0;
743   - for (int i = 0; i < n; ++i) {
  734 + // Find index nclosest of the closest table entry
  735 + int nclosest = 0;
  736 + double dif = std::abs(x-xa[1]);
  737 + for (int i = 1; i < order; ++i) {
744 738 double dift = std::abs(x-xa[i+1]);
745 739 if (dift < dif) {
746   - ns = i;
747   - dif = dift;
  740 + nclosest = i;
  741 + dif = dift;
748 742 }
749   - double value = ya[i+1][index];
750   - c[i] = value;
751   - d[i] = value;
752 743 }
753 744  
754   - // Get initial approximation to y
755   - y = ya[ns+1][index];
756   - ns--;
  745 + // Loop over vector dimension
  746 + for (int index = 0; index < nsize; ++index) {
757 747  
758   - // Loop over each column of the tableau
759   - for (int m = 1; m < n; ++m) {
  748 + // Set closest table entry
  749 + int ns = nclosest;
760 750  
761   - // Update current c's and d's
762   - for (int i = 0; i < n-m; ++i) {
763   - double ho = xa[i+1] - x;
764   - double hp = xa[i+m+1] - x;
765   - double w = c[i+1] - d[i];
766   - double den = ho - hp;
767   - if (den == 0.0) {
768   - m_isvalid = false;
769   - m_message = "Invalid step size "+gammalib::str(den)+
770   - " encountered. Two values in xa array are"
771   - " identical.";
772   - if (!m_silent) {
773   - gammalib::warning(G_POLINT, m_message);
  751 + // Initialise table values
  752 + for (int i = 0; i < order; ++i) {
  753 + double value = ya[i+1][index];
  754 + c[i] = value;
  755 + d[i] = value;
  756 + }
  757 +
  758 + // Get initial approximation to y
  759 + y[index] = ya[ns+1][index];
  760 + ns--;
  761 +
  762 + // Loop over each column of the tableau
  763 + for (int m = 1; m < order; ++m) {
  764 +
  765 + // Update current c's and d's
  766 + for (int i = 0; i < order-m; ++i) {
  767 + double ho = xa[i+1] - x;
  768 + double hp = xa[i+m+1] - x;
  769 + double w = c[i+1] - d[i];
  770 + double den = ho - hp;
  771 + if (den == 0.0) {
  772 + m_isvalid = false;
  773 + m_message = "Invalid step size "+gammalib::str(den)+
  774 + " encountered. Two values in xa array are"
  775 + " identical.";
  776 + if (!m_silent) {
  777 + gammalib::warning(G_POLINT, m_message);
  778 + }
774 779 }
  780 + den = w/den;
  781 + d[i] = hp*den;
  782 + c[i] = ho*den;
775 783 }
776   - den = w/den;
777   - d[i] = hp*den;
778   - c[i] = ho*den;
779   - }
780 784  
781   - // Compute y correction
782   - *dy = (2*(ns+1) < (n-m)) ? c[ns+1] : d[ns--];
  785 + // Compute y correction
  786 + double delta_y = (2*(ns+1) < (order-m)) ? c[ns+1] : d[ns--];
  787 +
  788 + // Update y
  789 + y[index] += delta_y;
  790 +
  791 + // Store result
  792 + (*dy)[index] = delta_y;
783 793  
784   - // Update y
785   - y += *dy;
  794 + } // endfor: looped over columns of tableau
786 795  
787   - } // endfor: looped over columns of tableau
  796 + } // endfor: looped over vector dimension
788 797  
789 798 // Free temporary memory
790 799 delete [] c;
... ...