@@ -92,6 +92,7 @@ void finite_gradient(
9292 }
9393}
9494
95+ template <bool IsTensorOrderEven>
9596void finite_jacobian (
9697 const Eigen::Ref<const Eigen::VectorXd>& x,
9798 const std::function<Eigen::MatrixXd(const Eigen::VectorXd&)>& f,
@@ -113,18 +114,31 @@ void finite_jacobian(
113114 const Eigen::MatrixXd tmp = f (x);
114115 f_rows = tmp.rows (), f_cols = tmp.cols ();
115116 }
116- jac.setZero (f_rows, f_cols * x.size ());
117+ if constexpr (IsTensorOrderEven) {
118+ jac.setZero (f_rows, f_cols * x.size ());
119+ } else {
120+ jac.setZero (f_rows * x.size (), f_cols);
121+ }
117122
118123 // f: ℝ^n ↦ ℝ^{p×q} ⟹ ∇f: ℝ^n ↦ ℝ^{p×(qn)}
119124 Eigen::VectorXd x_mutable = x;
120125 for (size_t i = 0 ; i < x.size (); i++) {
121126 for (size_t ci = 0 ; ci < inner_steps; ci++) {
122127 x_mutable[i] += internal_coeffs[ci] * eps;
123- jac.middleCols (f_cols * i, f_cols) +=
124- external_coeffs[ci] * f (x_mutable);
128+ if constexpr (IsTensorOrderEven) {
129+ jac.middleCols (f_cols * i, f_cols) +=
130+ external_coeffs[ci] * f (x_mutable);
131+ } else {
132+ jac.middleRows (f_rows * i, f_rows) +=
133+ external_coeffs[ci] * f (x_mutable);
134+ }
125135 x_mutable[i] = x[i];
126136 }
127- jac.middleCols (f_cols * i, f_cols) /= denom;
137+ if constexpr (IsTensorOrderEven) {
138+ jac.middleCols (f_cols * i, f_cols) /= denom;
139+ } else {
140+ jac.middleRows (f_rows * i, f_rows) /= denom;
141+ }
128142 }
129143}
130144
@@ -172,7 +186,12 @@ bool compare_gradient(
172186 const double test_eps,
173187 const std::string& msg)
174188{
175- assert (x.rows () == y.rows ());
189+ if (x.rows () != y.rows ()) {
190+ spdlog::debug (
191+ " {} gradient size mismatch: x.rows()={} y.rows()={}" , msg, x.rows (),
192+ y.rows ());
193+ return false ;
194+ }
176195
177196 bool same = true ;
178197 for (long i = 0 ; i < x.rows (); i++) {
@@ -199,8 +218,13 @@ bool compare_jacobian(
199218 const double test_eps,
200219 const std::string& msg)
201220{
202- assert (x.rows () == y.rows ());
203- assert (x.cols () == y.cols ());
221+ if (x.rows () != y.rows () || x.cols () != y.cols ()) {
222+ spdlog::debug (
223+ " {} jacobian size mismatch: x.rows()={} x.cols()={} "
224+ " y.rows()={} y.cols()={}" ,
225+ msg, x.rows (), x.cols (), y.rows (), y.cols ());
226+ return false ;
227+ }
204228
205229 bool same = true ;
206230 for (long i = 0 ; i < x.rows (); i++) {
@@ -256,4 +280,9 @@ Eigen::MatrixXd unflatten(const Eigen::Ref<const Eigen::VectorXd>& x, int dim)
256280 return X;
257281}
258282
283+ // clang-format off
284+ template void finite_jacobian<false >(const Eigen::Ref<const Eigen::VectorXd>& x, const std::function<Eigen::MatrixXd(const Eigen::VectorXd&)>& f, Eigen::MatrixXd& jac, const AccuracyOrder accuracy, const double eps);
285+ template void finite_jacobian<true >(const Eigen::Ref<const Eigen::VectorXd>& x, const std::function<Eigen::MatrixXd(const Eigen::VectorXd&)>& f, Eigen::MatrixXd& jac, const AccuracyOrder accuracy, const double eps);
286+ // clang-format on
287+
259288} // namespace fd
0 commit comments