#include "cubic_is_flat.h"

template <typename DerivedC>
IGL_INLINE bool igl::cubic_is_flat(
  const Eigen::MatrixBase<DerivedC>& C,
  const typename DerivedC::Scalar squared_distance_bound)
{
  using Scalar = typename DerivedC::Scalar;
  const auto u = (Scalar(3) * C.row(1) - Scalar(2) * C.row(0) - C.row(3)).array().square().eval();
  const auto v = (Scalar(3) * C.row(2) - Scalar(2) * C.row(3) - C.row(0)).array().square().eval();
  const auto max_uv = u.cwiseMax(v).eval();
  const Scalar tao = max_uv.sum();
  const Scalar tolerance = Scalar(16) * squared_distance_bound;
  return tao <= tolerance;
}

#ifdef IGL_STATIC_LIBRARY
// Explicit template instantiation
// generated by autoexplicit.sh
template bool igl::cubic_is_flat<Eigen::Matrix<double, 4, 2, 1, 4, 2>>(Eigen::MatrixBase<Eigen::Matrix<double, 4, 2, 1, 4, 2>> const&, Eigen::Matrix<double, 4, 2, 1, 4, 2>::Scalar);
// generated by autoexplicit.sh
template bool igl::cubic_is_flat<Eigen::Matrix<double, 4, 2, 0, 4, 2>>(Eigen::MatrixBase<Eigen::Matrix<double, 4, 2, 0, 4, 2>> const&, Eigen::Matrix<double, 4, 2, 0, 4, 2>::Scalar);
#endif
