From e0d7cfedaff337c9372f2779aeb92a40b089447e Mon Sep 17 00:00:00 2001
From: labourasse <labourassee@gmail.com>
Date: Tue, 5 Jul 2022 09:40:38 +0200
Subject: [PATCH] add features for 3D polynomials except offstream

---
 src/analysis/PolynomialP.hpp | 340 +++++++++++++++--------------------
 1 file changed, 147 insertions(+), 193 deletions(-)

diff --git a/src/analysis/PolynomialP.hpp b/src/analysis/PolynomialP.hpp
index 253e6369b..e2830df47 100644
--- a/src/analysis/PolynomialP.hpp
+++ b/src/analysis/PolynomialP.hpp
@@ -161,11 +161,12 @@ class PolynomialP
       size_t total_degree = relative_pos[0] + relative_pos[1];
       absolute_position   = total_degree * (total_degree + 1) / 2 + relative_pos[1];
     } else {
-      throw NotImplementedError("Not yet Available in 3D");
-      // static_assert(Dimension == 3);
-      // size_t total_degree = relative_pos[0] + relative_pos[1] + relative_pos[2];
-      // return (total_degree + 1) * (total_degree + 2) * (total_degree + 3) / 6 + relative_pos[1];
-      // return (N + 1) * (N + 2) * (N + 3) / 6;
+      // throw NotImplementedError("Not yet Available in 3D");
+      static_assert(Dimension == 3);
+      size_t total_degree     = relative_pos[0] + relative_pos[1] + relative_pos[2];
+      size_t total_sub_degree = relative_pos[1] + relative_pos[2];
+      return total_degree * (total_degree + 1) * (total_degree + 2) / 6 +
+             total_sub_degree * (total_sub_degree + 1) / 2 + relative_pos[2];
     }
 
     return absolute_coefs[absolute_position];
@@ -191,11 +192,12 @@ class PolynomialP
       size_t total_degree = relative_pos[0] + relative_pos[1];
       absolute_position   = total_degree * (total_degree + 1) / 2 + relative_pos[1];
     } else {
-      throw NotImplementedError("Not yet Available in 3D");
-      // static_assert(Dimension == 3);
-      // size_t total_degree = relative_pos[0] + relative_pos[1] + relative_pos[2];
-      // return (total_degree + 1) * (total_degree + 2) * (total_degree + 3) / 6 + relative_pos[1];
-      // return (N + 1) * (N + 2) * (N + 3) / 6;
+      // throw NotImplementedError("Not yet Available in 3D");
+      static_assert(Dimension == 3);
+      size_t total_degree     = relative_pos[0] + relative_pos[1] + relative_pos[2];
+      size_t total_sub_degree = relative_pos[1] + relative_pos[2];
+      absolute_position       = total_degree * (total_degree + 1) * (total_degree + 2) / 6 +
+                          total_sub_degree * (total_sub_degree + 1) / 2 + relative_pos[2];
     }
 
     return absolute_coefs[absolute_position];
@@ -219,11 +221,12 @@ class PolynomialP
     } else if constexpr (Dimension == 2) {
       abs_pos = total_degree * (total_degree + 1) / 2 + relative_pos[1];
     } else {
-      throw NotImplementedError("Not yet Available in 3D");
-      // static_assert(Dimension == 3);
-      // size_t total_degree = relative_pos[0] + relative_pos[1] + relative_pos[2];
-      // return (total_degree + 1) * (total_degree + 2) * (total_degree + 3) / 6 + relative_pos[1];
-      // return (N + 1) * (N + 2) * (N + 3) / 6;
+      static_assert(Dimension == 3);
+      size_t total_degree     = relative_pos[0] + relative_pos[1] + relative_pos[2];
+      size_t total_sub_degree = relative_pos[1] + relative_pos[2];
+      abs_pos                 = total_degree * (total_degree + 1) * (total_degree + 2) / 6 +
+                total_sub_degree * (total_sub_degree + 1) / 2 + relative_pos[2];
+      // throw NotImplementedError("Not yet Available in 3D");
     }
 
     return abs_pos;
@@ -275,22 +278,19 @@ class PolynomialP
     }
   }
 
-  PUGS_INLINE constexpr auto
+  PUGS_INLINE constexpr PolynomialP<N, Dimension>
   derivative(const size_t var) const
   {
     const auto P = *this;
     TinyVector<size_coef> coefs(zero);
     PolynomialP<N, Dimension> Q(coefs);
-    if constexpr (N == 0) {
-      return Q;
-    } else {
+    if constexpr (N != 0) {
       Assert(var < Dimension,
              "You can not derive a polynomial with respect to a variable of rank greater than the dimension");
       if constexpr (Dimension == 1) {
-        for (size_t i = 0; i < size_coef; ++i) {
+        for (size_t i = 0; i < size_coef - 1; ++i) {
           coefs[i] = double(i + 1) * P.coefficients()[i + 1];
         }
-        return Q;
       } else if constexpr (Dimension == 2) {
         if (var == 0) {
           for (size_t i = 0; i < N; ++i) {
@@ -313,11 +313,49 @@ class PolynomialP
             }
           }
         }
-        return Q;
       } else {
-        throw NotImplementedError("Not yet Available in 3D");
+        static_assert(Dimension == 3);
+        if (var == 0) {
+          for (size_t i = 0; i < N; ++i) {
+            for (size_t j = 0; j < N - i; ++j) {
+              for (size_t k = 0; k < N - i - j; ++k) {
+                TinyVector<Dimension, size_t> relative_pos(i, j, k);
+                TinyVector<Dimension, size_t> relative_posp(i + 1, j, k);
+                size_t absolute_position            = Q.absolute_position(relative_pos);
+                size_t absolute_positionp           = P.absolute_position(relative_posp);
+                Q.coefficients()[absolute_position] = double(i + 1) * m_coefficients[absolute_positionp];
+              }
+            }
+          }
+        } else if (var == 1) {
+          for (size_t i = 0; i < N; ++i) {
+            for (size_t j = 0; j < N - i; ++j) {
+              for (size_t k = 0; k < N - i - j; ++k) {
+                TinyVector<Dimension, size_t> relative_pos(i, j, k);
+                TinyVector<Dimension, size_t> relative_posp(i, j + 1, k);
+                size_t absolute_position            = Q.absolute_position(relative_pos);
+                size_t absolute_positionp           = P.absolute_position(relative_posp);
+                Q.coefficients()[absolute_position] = double(j + 1) * m_coefficients[absolute_positionp];
+              }
+            }
+          }
+        } else {
+          for (size_t i = 0; i < N; ++i) {
+            for (size_t j = 0; j < N - i; ++j) {
+              for (size_t k = 0; k < N - i - j; ++k) {
+                TinyVector<Dimension, size_t> relative_pos(i, j, k);
+                TinyVector<Dimension, size_t> relative_posp(i, j, k + 1);
+                size_t absolute_position            = Q.absolute_position(relative_pos);
+                size_t absolute_positionp           = P.absolute_position(relative_posp);
+                Q.coefficients()[absolute_position] = double(k + 1) * m_coefficients[absolute_positionp];
+              }
+            }
+          }
+        }
+        // throw NotImplementedError("Not yet Available in 3D");
       }
     }
+    return Q;
   }
 
   PUGS_INLINE
@@ -445,7 +483,92 @@ class PolynomialP
 
       return os;
     } else {
-      throw NotImplementedError("Not yet Available in 3D");
+      // size_t i = 0;
+      // size_t j = 0;
+      // size_t k = N;
+      // TinyVector<Dimension, size_t> rel_pos(i, j, k);
+      // double coef = P[rel_pos];
+      // if (coef != 0.) {
+      //   if (coef < 0.) {
+      //     os << " - ";
+      //   }
+      //   if (coef != 1 && coef != -1) {
+      //     os << std::abs(coef);
+      //   }
+      //   os << "z^" << N;
+      // }
+      // size_t degree = N;
+      // for (size_t l = size_coef - 1; l > 0; --l) {
+      //   if (k > 0) {
+      //     k--;
+      //     if (j < k) {
+      //       j++;
+      //     } else {
+      //       j--;
+      //       i++;
+      //     }
+      //   } else {
+      //     degree--;
+      //     k = degree;
+      //     i = 0;
+      //     j = 0;
+      //   }
+
+      //   rel_pos     = TinyVector<Dimension, size_t>(i, j, k);
+      //   double coef = P[rel_pos];
+      //   if (coef != 0.) {
+      //     if (coef > 0.) {
+      //       os << " + ";
+      //     } else if (coef < 0.) {
+      //       os << " - ";
+      //     }
+      //     if ((coef != 1 && coef != -1) || (i == 0 && j == 0 && k == 0)) {
+      //       os << std::abs(coef);
+      //     }
+      //     if (i == 0 && j == 0 && k == 0)
+      //       continue;
+      //     if (i == 0 && j == 0) {
+      //       if (k != 1) {
+      //         os << "z^" << j;
+      //       } else {
+      //         os << "z";
+      //       }
+      //     } else if (i == 0 && k == 0) {
+      //       if (j == 1) {
+      //         os << "y";
+      //       } else {
+      //         os << "y^" << i;
+      //       }
+      //     } else if (j == 0 && k == 0) {
+      //       if (i == 1) {
+      //         os << "x";
+      //       } else {
+      //         os << "x^" << i;
+      //       }
+      //     } else {
+      //       if (i == 1 && j == 1 && k == 1) {
+      //         os << "xyz";
+      //       } else if (i == 1) {
+      //         os << "x"
+      //            << "y^" << j << "z^" << k;
+      //       } else if (j == 1) {
+      //         os << "x^" << i << "y"
+      //            << "z^" << k;
+      //       } else if (k == 1) {
+      //         os << "x^" << i << "y^" << j << "z";
+      //       } else {
+      //         os << "x^" << i << "y^" << j << "z^" << k;
+      //       }
+      //     }
+      //     all_coef_zero = false;
+      //   }
+      //
+      for (size_t l = 0; l < size_coef; ++l) {
+        double coef = P.coefficients()[l];
+        os << coef << " ";
+      }
+      return os;
+      //      throw NotImplementedError("Not yet Available in 3D");
     }
   }
 
@@ -453,173 +576,4 @@ class PolynomialP
   ~PolynomialP()                               = default;
 };
 
-//   template <size_t M>
-//   PUGS_INLINE constexpr friend void
-//   divide(const PolynomialP<N>& P1, const PolynomialP<M>& P2, PolynomialP<N>& Q, PolynomialP<N>& R)
-//   {
-//     const size_t Nr  = P1.realDegree();
-//     const size_t Mr  = P2.realDegree();
-//     R.coefficients() = P1.coefficients();
-//     Q.coefficients() = zero;
-//     for (ssize_t k = Nr - Mr; k >= 0; --k) {
-//       Q.coefficients()[k] = R.coefficients()[Mr + k] / P2.coefficients()[Mr];
-//       for (ssize_t j = Mr + k; j >= k; --j) {
-//         R.coefficients()[j] -= Q.coefficients()[k] * P2.coefficients()[j - k];
-//       }
-//     }
-//     for (size_t j = Mr; j <= Nr; ++j) {
-//       R.coefficients()[j] = 0;
-//     }
-//   }
-
-//   PUGS_INLINE
-//   constexpr friend PolynomialP<N + 1>
-//   primitive(const PolynomialP<N>& P)
-//   {
-//     TinyVector<N + 2> coefs;
-//     for (size_t i = 0; i < N + 1; ++i) {
-//       coefs[i + 1] = P.coefficients()[i] / double(i + 1);
-//     }
-//     coefs[0] = 0;
-//     return PolynomialP<N + 1>{coefs};
-//   }
-
-//   PUGS_INLINE
-//   constexpr friend std::ostream&
-//   operator<<(std::ostream& os, const PolynomialP<N>& P)
-//   {
-//     //    os << "P(x) = ";
-//     bool all_coef_zero = true;
-//     if (N == 0) {
-//       os << P.coefficients()[0];
-//       return os;
-//     }
-//     if (N != 1) {
-//       if (P.coefficients()[N] != 0.) {
-//         if (P.coefficients()[N] < 0.) {
-//           os << "- ";
-//         }
-//         if (P.coefficients()[N] != 1 && P.coefficients()[N] != -1) {
-//           os << std::abs(P.coefficients()[N]);
-//         }
-//         os << "x^" << N;
-//         all_coef_zero = false;
-//       }
-//     }
-//     for (size_t i = N - 1; i > 1; --i) {
-//       if (P.coefficients()[i] != 0.) {
-//         if (P.coefficients()[i] > 0.) {
-//           os << " + ";
-//         } else if (P.coefficients()[i] < 0.) {
-//           os << " - ";
-//         }
-//         if (P.coefficients()[i] != 1 && P.coefficients()[i] != -1) {
-//           os << std::abs(P.coefficients()[i]);
-//         }
-//         os << "x^" << i;
-//         all_coef_zero = false;
-//       }
-//     }
-//     if (P.coefficients()[1] != 0.) {
-//       if (P.coefficients()[1] > 0. && N != 1) {
-//         os << " + ";
-//       } else if (P.coefficients()[1] < 0.) {
-//         os << " - ";
-//       }
-//       if (P.coefficients()[1] != 1 && P.coefficients()[1] != -1) {
-//         os << std::abs(P.coefficients()[1]);
-//       }
-//       os << "x";
-//       all_coef_zero = false;
-//     }
-//     if (P.coefficients()[0] != 0. || all_coef_zero) {
-//       if (P.coefficients()[0] > 0.) {
-//         os << " + ";
-//       } else if (P.coefficients()[0] < 0.) {
-//         os << " - ";
-//       }
-//       os << std::abs(P.coefficients()[0]);
-//     }
-//     return os;
-//   }
-
-//   PUGS_INLINE
-//   constexpr friend void
-//   lagrangeBasis(const TinyVector<N + 1> zeros, TinyVector<N + 1, PolynomialP<N>>& basis)
-//   {
-//     PolynomialP<N> lj;
-//     for (size_t j = 0; j < N + 1; ++j) {
-//       basis[j] = lagrangePolynomialP(zeros, j);
-//     }
-//   }
-
-//   PUGS_INLINE
-//   constexpr friend PolynomialP<N>
-//   lagrangeToCanonical(const TinyVector<N + 1> lagrange_coefs, const TinyVector<N + 1, PolynomialP<N>>& basis)
-//   {
-//     PolynomialP<N> P(zero);
-//     //    lagrangeBasis({0, 0, 0}, basis);
-//     for (size_t j = 0; j < N + 1; ++j) {
-//       P += basis[j] * lagrange_coefs[j];
-//     }
-//     return P;
-//   }
-
-// template <size_t N>
-// PUGS_INLINE constexpr PolynomialP<N> lagrangePolynomialP(const TinyVector<N + 1> zeros, const size_t k);
-
-// template <size_t N>
-// PUGS_INLINE constexpr TinyVector<N, PolynomialP<N - 1>>
-// lagrangeBasis(const TinyVector<N>& zeros)
-// {
-//   static_assert(N >= 1, "invalid degree");
-//   TinyVector<N, PolynomialP<N - 1>> basis;
-//   PolynomialP<N - 1> lj;
-//   for (size_t j = 0; j < N; ++j) {
-//     basis[j] = lagrangePolynomialP<N - 1>(zeros, j);
-//   }
-//   return basis;
-// }
-
-// template <size_t N>
-// PUGS_INLINE constexpr double
-// integrate(const PolynomialP<N>& P, const double& xinf, const double& xsup)
-// {
-//   PolynomialP<N + 1> Q = primitive(P);
-//   return (Q(xsup) - Q(xinf));
-// }
-
-// template <size_t N>
-// PUGS_INLINE constexpr double
-// symmetricIntegrate(const PolynomialP<N>& P, const double& delta)
-// {
-//   Assert(delta > 0, "A positive delta is needed for symmetricIntegrate");
-//   double integral = 0.;
-//   for (size_t i = 0; i <= N; ++i) {
-//     if (i % 2 == 0)
-//       integral += 2. * P.coefficients()[i] * std::pow(delta, i + 1) / (i + 1);
-//   }
-//   return integral;
-// }
-
-// template <size_t N>
-// PUGS_INLINE constexpr PolynomialP<N>
-// lagrangePolynomialP(const TinyVector<N + 1> zeros, const size_t k)
-// {
-//   for (size_t i = 0; i < N; ++i) {
-//     Assert(zeros[i] < zeros[i + 1], "Interpolation values must be strictly increasing in Lagrange polynomialPs");
-//   }
-//   PolynomialP<N> lk;
-//   lk.coefficients()    = zero;
-//   lk.coefficients()[0] = 1;
-//   for (size_t i = 0; i < N + 1; ++i) {
-//     if (k == i)
-//       continue;
-//     double factor = 1. / (zeros[k] - zeros[i]);
-//     PolynomialP<1> P({-zeros[i] * factor, factor});
-//     lk *= P;
-//   }
-//   return lk;
-// }
-
 #endif   // POLYNOMIALP_HPP
-- 
GitLab