roots.cpp 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #include "roots.h"
  2. #include <cyPolynomial.h>
  3. namespace
  4. {
  5. template <int MAX_DEG, typename Derivedcoef, typename DerivedR>
  6. int roots_helper(
  7. const int deg,
  8. const Eigen::MatrixBase<Derivedcoef>& coef,
  9. const typename Derivedcoef::Scalar xmin,
  10. const typename Derivedcoef::Scalar xmax,
  11. Eigen::PlainObjectBase<DerivedR>& R)
  12. {
  13. using cy::PolynomialRoots;
  14. if constexpr (MAX_DEG == 0)
  15. {
  16. // Should be impossible to reach here from roots()
  17. return 0;
  18. }
  19. else
  20. {
  21. if (deg == MAX_DEG)
  22. {
  23. using Scalar = typename Derivedcoef::Scalar;
  24. Scalar r[MAX_DEG];
  25. int nr = PolynomialRoots<MAX_DEG>(r, coef.derived().data(), xmin, xmax);
  26. // will resize if needed. Safe on compile-time sized matrices
  27. R.setConstant(MAX_DEG, std::numeric_limits<Scalar>::quiet_NaN());
  28. for (int i = 0; i < nr; ++i)
  29. {
  30. R[i] = r[i];
  31. }
  32. return nr;
  33. }
  34. return roots_helper<MAX_DEG - 1>(deg, coef, xmin, xmax, R);
  35. }
  36. }
  37. }
  38. template <
  39. typename Derivedcoef,
  40. typename DerivedR>
  41. IGL_INLINE int igl::cycodebase::roots(
  42. const Eigen::MatrixBase<Derivedcoef>& coef,
  43. const typename Derivedcoef::Scalar xmin,
  44. const typename Derivedcoef::Scalar xmax,
  45. Eigen::PlainObjectBase<DerivedR>& R)
  46. {
  47. using Scalar = typename Derivedcoef::Scalar;
  48. // Static assert that DerivedR::Scalar is same as Derivedcoef::Scalar
  49. static_assert(
  50. std::is_same<typename DerivedR::Scalar, Scalar>::value,
  51. "DerivedR::Scalar must be the same as Derivedcoef::Scalar");
  52. // Check that Derivedcoef and DerivedR are vectors
  53. static_assert(
  54. (Derivedcoef::ColsAtCompileTime == 1 ||
  55. Derivedcoef::RowsAtCompileTime == 1) &&
  56. (DerivedR::ColsAtCompileTime == 1 ||
  57. DerivedR::RowsAtCompileTime == 1),
  58. "Derivedcoef and DerivedR must be vectors");
  59. constexpr int MAX_DEG = 16;
  60. const int deg = coef.size() - 1;
  61. if (deg < 1 || deg > MAX_DEG)
  62. {
  63. throw std::runtime_error("Polynomial degree out of range");
  64. }
  65. return ::roots_helper<MAX_DEG>( deg, coef, xmin, xmax, R);
  66. }
  67. #ifdef IGL_STATIC_LIBRARY
  68. // Explicit template specialization
  69. template IGL_INLINE int igl::cycodebase::roots<Eigen::RowVectorXd, Eigen::RowVectorXd>(
  70. const Eigen::MatrixBase<Eigen::RowVectorXd>& coef,
  71. const double xmin,
  72. const double xmax,
  73. Eigen::PlainObjectBase<Eigen::RowVectorXd>& R);
  74. template int igl::cycodebase::roots<Eigen::Matrix<double, 4, 1, 0, 4, 1>, Eigen::Matrix<double, 3, 1, 0, 3, 1>>(Eigen::MatrixBase<Eigen::Matrix<double, 4, 1, 0, 4, 1>> const&, Eigen::Matrix<double, 4, 1, 0, 4, 1>::Scalar, Eigen::Matrix<double, 4, 1, 0, 4, 1>::Scalar, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1>>&);
  75. template int igl::cycodebase::roots<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1>> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1>::Scalar, Eigen::Matrix<double, -1, 1, 0, -1, 1>::Scalar, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1>>&);
  76. #endif