]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Slightly improve evaluation of polynomial 10994/head
authorMartin Kronbichler <kronbichler@lnm.mw.tum.de>
Fri, 2 Oct 2020 16:03:57 +0000 (18:03 +0200)
committerMartin Kronbichler <kronbichler@lnm.mw.tum.de>
Fri, 2 Oct 2020 16:09:44 +0000 (18:09 +0200)
source/base/polynomial.cc

index cf1d95330738909dedb57f8becd6f0a5844d380e..cbb7bffbdda2db1cc5b42f2c63d2e4e2b13343bf 100644 (file)
@@ -119,6 +119,7 @@ namespace Polynomials
         // form (x-x_1)*(x-x_2)*...*(x-x_n), expand the derivatives like
         // automatic differentiation does.
         const unsigned int n_supp = lagrange_support_points.size();
+        const number       weight = lagrange_weight;
         switch (n_derivatives)
           {
             default:
@@ -151,7 +152,7 @@ namespace Polynomials
                 number k_faculty = 1;
                 for (unsigned int k = 0; k <= n_derivatives; ++k)
                   {
-                    values[k] *= k_faculty * lagrange_weight;
+                    values[k] *= k_faculty * weight;
                     k_faculty *= static_cast<number>(k + 1);
                   }
               }
@@ -159,45 +160,53 @@ namespace Polynomials
 
             // manually implement case 0 (values only), case 1 (value + first
             // derivative), and case 2 (up to second derivative) since they
-            // might be called often. then, we can unroll the loop.
+            // might be called often. then, we can unroll the inner loop and
+            // keep the temporary results as local variables to help the
+            // compiler with the pointer aliasing analysis.
             case 0:
-              values[0] = 1;
-              for (unsigned int i = 0; i < n_supp; ++i)
-                {
-                  const number v = x - lagrange_support_points[i];
-                  values[0] *= v;
-                }
-              values[0] *= lagrange_weight;
-              break;
+              {
+                number value = 1;
+                for (unsigned int i = 0; i < n_supp; ++i)
+                  {
+                    const number v = x - lagrange_support_points[i];
+                    value *= v;
+                  }
+                values[0] = weight * value;
+                break;
+              }
 
             case 1:
-              values[0] = 1;
-              values[1] = 0;
-              for (unsigned int i = 0; i < n_supp; ++i)
-                {
-                  const number v = x - lagrange_support_points[i];
-                  values[1]      = values[1] * v + values[0];
-                  values[0] *= v;
-                }
-              values[0] *= lagrange_weight;
-              values[1] *= lagrange_weight;
-              break;
+              {
+                number value      = 1;
+                number derivative = 0;
+                for (unsigned int i = 0; i < n_supp; ++i)
+                  {
+                    const number v = x - lagrange_support_points[i];
+                    derivative     = derivative * v + value;
+                    value *= v;
+                  }
+                values[0] = weight * value;
+                values[1] = weight * derivative;
+                break;
+              }
 
             case 2:
-              values[0] = 1;
-              values[1] = 0;
-              values[2] = 0;
-              for (unsigned int i = 0; i < n_supp; ++i)
-                {
-                  const number v = x - lagrange_support_points[i];
-                  values[2]      = values[2] * v + values[1];
-                  values[1]      = values[1] * v + values[0];
-                  values[0] *= v;
-                }
-              values[0] *= lagrange_weight;
-              values[1] *= lagrange_weight;
-              values[2] *= static_cast<number>(2) * lagrange_weight;
-              break;
+              {
+                number value      = 1;
+                number derivative = 0;
+                number second     = 0;
+                for (unsigned int i = 0; i < n_supp; ++i)
+                  {
+                    const number v = x - lagrange_support_points[i];
+                    second         = second * v + derivative;
+                    derivative     = derivative * v + value;
+                    value *= v;
+                  }
+                values[0] = weight * value;
+                values[1] = weight * derivative;
+                values[2] = static_cast<number>(2) * weight * second;
+                break;
+              }
           }
         return;
       }

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.