Check_is_not_nan not defined for matrices?

I’m running some tests in C++ and I’m a little confused about check_is_not_nan, which is defined under prim/scal/err yet is used inside rev/mat/fun/multiply.hpp on a matrix. Specifically:

  check_not_nan("multiply", "A", A);
  check_not_nan("multiply", "B", B);

where both A and B are matrices. However when I compile code that uses multiply, the returned error states

error: cannot convert 'const Eigen::Matrix<double, -1, 1, 0, -1, 1>' to 'double' without
      a conversion operator

My guess is I’m not including the right files, though, (i) the right files should be included inside multiply.hpp and (ii) I can’t find where in the math library check_is_not_nan is overloaded. Any guidance on how to properly do this matrix multiplication? Thank you

There is code in a PR which could be modified along the line of

template <typename T_y>
inline bool is_not_nan(const T_y& y) {
  for (size_t n = 0; n < stan::length(y); ++n) {
    if (is_nan(value_of_rec(stan::get(y, n))))
      return false;
  }
  return true;
}

Oddly enough, not including rev/mat/fun/multiply.hpp at the top of the file solves the problem. But I doubt this is the wanted behavior.

In which file are you removing the include? I’m missing the reference here: https://github.com/stan-dev/math/blob/develop/stan/math/prim/scal/err/check_not_nan.hpp

I wrote a new C++ file to perform a certain task and in this file I apply multiply() to a matrix and a vector. If I have #include math/prim/.../multiply.hpp at the top, I get the above described error, which is related to check_is_not_nan. If I remove #include .../multiply.hpp, the code compiles and produces the correct result.

You can reproduce the error using the unit test for multiply(). There, the function is tested on two matrices. Note however the unit test does not include .../multiply.hpp. If you do include it, you get the error. I’m not quite sure what this implies. Are there multiple definitions of multiply()? Under the math directory, I only found one hpp file named after the function.

I’m not exactly sure, but I find:

./stan/math/prim/mat/fun/multiply.hpp
./stan/math/rev/mat/fun/multiply.hpp
./stan/math/opencl/multiply.hpp
./lib/boost_1.69.0/boost/multiprecision/cpp_int/multiply.hpp

Clearly it could depend on your other includes, and how the function is being called. Would you post all of the includes?

1 Like

Sorry, I misspoke.

If you include math/rev/.../multiply.hpp you get in trouble. What I should’ve said is there’s only one file defining check_not_nan, and it’s located under the prim directory. But some other version of check_not_nan must also exist.

EDIT: I’ve downloaded the dev version of Stan and everything seems to work fine. I include rev/.../multiply.hpp and get no error when compiling the unit test. So I may have mess something up on the branch I was working on.

1 Like

If I pinpoint where the error came from, I’ll post the details here.

2 Likes

I’ve also seen this error for check_not_nan on the branch gpu gp_exp_quad branch. It has something to do with the order includes for prim/arr/scal

1 Like

If you’re using Eigen in a header, you should always include our specialized header first before anything else involving matrices:

#include <stan/math/prim/mat/functor/Eigen.hpp>

No idea why that got dropped under functor. I would’ve thought it’d make more sense to be right at the top of prim/mat.

1 Like

I assume you mean #include <stan/math/prim/mat/fun/Eigen.hpp>

Yes, that’s the one.

There’s a bit of confusion here and it comes from the Math library’s use of template metaprogramming. We actually use patterns that are well described in “Modern C++ Design” and used extensively by Boost and Eigen, but coming into C++ from different languages (or even from non-heavily-templated C++), this might seem a little tricky.

We’ve written generic templated functions. In particular, you’ve run into check_not_nan. If you look at the source, you’ll see:

template <typename T_y>
struct not_nan<T_y, true> {
  static void check(const char* function, const char* name, const T_y& y) {
    for (size_t n = 0; n < stan::length(y); n++) {
      if (is_nan(value_of_rec(stan::get(y, n))))
        domain_error_vec(function, name, y, n, "is ", ", but must not be nan!");
    }
  }
};

This is super-awesome. We’ve defined a templated function that doesn’t rely on Eigen or even std::vector. Then we partially specialized it for bool is_vec = true without knowing what those things are.

If we never include Eigen or vector, this code is there, but never used. We’re in the clear. Now… if we happen to define a get(...) function that works for Eigen::Matrix, then we can use the check_is_nan function for Eigen::Matrix. If we only include stan/math/prim/scal/err/check_not_nan.hpp, then we’ll only be brining in stan/math/prim/scal/meta/get.hpp. That doesn’t tell us how to operate with Eigen::Matrix. So… we need to include the template specialization before we include check_not_nan. This is where it gets complicated… we need to include it first, then make sure we instantiate the template too.

We take care of all of that by using the big headers:
stan/math/prim/mat.hpp or stan/math/rev/mat.hpp. If you look at those includes, it has things in a particular order.

I don’t know where you’re using it, but you really need to be including the correct template metaprograms before you include check_not_nan (like get and value_of_rec). Or… just use the big header as we suggest here: https://github.com/stan-dev/math/wiki/Include-order-of-headers

4 Likes