Getting the right is_nan

This test (below) is failing on my bugfix branch. The issue is that I’m checking for NaN and including the is_nan from stan/math/prim/scal/fun which obviously doesn’t have a non-double version. All the other code in stan/math/prim/scal seems to use is_nan the way I do—include the header and then just use it. If I include the is_nan from stan/math/rev/scal this passes but the prim functions aren’t supposed to include rev headers so another tests fails. What’s the Stan solution here?

Krzysztof

clang++ -I . -isystem lib/eigen_3.2.9 -isystem lib/boost_1.62.0 -isystemlib/cvodes_2.9.0/include -Wall -DBOOST_RESULT_OF_USE_TR1 -DBOOST_NO_DECLTYPE -DBOOST_DISABLE_ASSERTS -DNO_FPRINTF_OUTPUT -pipe -Wno-unused-function -Wno-uninitialized -Wno-c++11-long-long   -c -O0 -include stan/math/rev/scal/fun/grad_inc_beta.hpp -o /dev/null test/dummy.cpp
In file included from <built-in>:325:
In file included from <command line>:5:
In file included from ./stan/math/rev/scal/fun/grad_inc_beta.hpp:4:
./stan/math/prim/scal/fun/grad_2F1.hpp:53:13: error: no matching function for call to 'is_nan'
        if (is_nan(r) || r == 0)
            ^~~~~~
./stan/math/rev/scal/fun/grad_inc_beta.hpp:42:9: note: in instantiation of function template specialization
      'stan::math::grad_2F1<stan::math::var>' requested here
        grad_2F1(dF1, dF2, a + b, var(1.0), a + 1, z);
        ^
./stan/math/prim/scal/fun/is_nan.hpp:17:17: note: candidate function not viable: no known conversion from
      'const stan::math::var' to 'double' for 1st argument
    inline bool is_nan(double x) {
                ^
1 error generated.

I think you want to include the stan/math/rev/scal.hpp file in your test.

Where is the test file located? And what includes do you have at the top?

I wasn’t clear, it’s the header test in the math library. I’ll write
something clearer when I’m at a computer again.

Daniel’s right—you need to include the definition of is_nan for var. Then it’ll get picked up by argument dependent lookup.

So the file that’s triggering the issue first is stan/math/prim/scal/fun/grad_2F1.hpp, if you look on the branch the headers (actually, I’ll just dump; the whole file here) are:

#ifndef STAN_MATH_PRIM_SCAL_FUN_GRAD_2F1_HPP
#define STAN_MATH_PRIM_SCAL_FUN_GRAD_2F1_HPP

#include <stan/math/prim/scal/err/domain_error.hpp>
#include <stan/math/prim/scal/fun/is_nan.hpp>
#include <cmath>

namespace stan {
  namespace math {

    /**
     * Gradient of the hypergeometric function, 2F1(a1, a2, b1, z)
     * with respect to a1 and b1 only.
     *
     * The generalized hypergeometric function is a power series. This
     * implementation computes gradient by computing the power series
     * directly stopping when the series converges to within
     * <code>precision</code> or takes <code>max_steps</code>.
     *
     * If more than <code>max_steps</code> are taken without
     * converging, the function will throw a domain_error.
     *
     * @tparam T type of arguments and result
     * @param[out] gradA1 output argument for partial w.r.t. a1
     * @param[out] gradB1 output argument for partial w.r.t. b1
     * @param[in] a1 a1, see generalized hypergeometric function definition.
     * @param[in] a2 a2, see generalized hypergeometric function definition.
     * @param[in] b1 b1, see generalized hypergeometric function definition.
     * @param[in] z z, see generalized hypergeometric function definition.
     * @param[in] precision precision of the infinite sum. defaults to 1e-6
     * @param[in] max_steps number of steps to take. defaults to 10000
     * @throw throws std::domain_error if not converged after max_steps
     *
     */
    template<typename T>
    void grad_2F1(T& gradA1, T& gradB1, const T& a1, const T& a2,
      const T& b1, const T& z, T precision = 1e-6, int max_steps = 1e5) {
      using std::fabs;

      gradA1 = 0;
      gradB1 = 0;

      T gradA1old = 0;
      T gradB1old = 0;

      int k = 0;
      T tDak = 1.0 / (a1 - 1);

      do {
        const T r = ( (a1 + k) / (b1 + k) ) * ( (a2 + k) / (k + 1) ) * z;
        tDak = r * tDak * (a1 + (k - 1)) / (a1 + k);

        if (is_nan(r) || r == 0)
          break;

        gradA1old = r * gradA1old + tDak;
        gradB1old = r * gradB1old - tDak * ((a1 + k) / (b1 + k));

        gradA1 += gradA1old;
        gradB1 += gradB1old;

        ++k;
        if (k >= max_steps) {
          domain_error("grad_2F1", "k (internal counter)", max_steps,
            "exceeded ",
            " iterations, hypergeometric function did not converge.");
        }
      } while (fabs(tDak * (a1 + (k - 1)) ) > precision);
    }

  }
}
#endif

This fails the math repo’s make-headers test and I had the same thought as Daniel—need to add the rev definition. So I changed the headers to:

#ifndef STAN_MATH_PRIM_SCAL_FUN_GRAD_2F1_HPP
#define STAN_MATH_PRIM_SCAL_FUN_GRAD_2F1_HPP

#include <stan/math/prim/scal/err/domain_error.hpp>
#include <stan/math/rev/scal/fun/is_nan.hpp>
#include <cmath>

This fails make test-math-dependencies, output from Jenkins:

+ make test-math-dependencies
stan/math/prim/scal/fun/grad_2F1.hpp(5): File includes a stan/math/rev header file. [prim]
[WARNINGS] Parsing warnings in console log with parser math-dependencies
[WARNINGS] Computing warning deltas based on reference build #710
[WARNINGS] Ignore new warnings since this is the first valid build
[WARNINGS] Plug-in Result: Failed - <a href="warningsResult">1 warning</a> exceeds the threshold of 0 by 1
Build step 'Scan for compiler warnings' changed build result to FAILURE
Finished: FAILURE

So I guess the question is more how do I include the definition for var in a file in prim?

You shouldn’t include rev files in anything defined in prim. I believe Dan’s point is that you need to include the rev version in the test file where you actually use the function and all of the templates get instantiated, no?

So my confusion is from the fact that this isn’t a test I wrote. The test is make test-headers in the math repo, and the problem is in https://github.com/stan-dev/math/blob/bugfix/issue-487-hypergeometric-functions/stan/math/rev/scal/fun/grad_inc_beta.hpp which I haven’t touched (although I did modify the grad_2F1 function and that’s where the error is triggered). Seems like grad_2F1 should include enough so that when you include it you don’t need to include something else to make it compile, right? grad_2F1 is a little sloppy about assuming all its types are the same so maybe that’s the source of the problem but I don’t see how.

Not quite. We are distributing the code over two cross-cutting graphs: prim, rev, fwd, and mix for the underlying scalar type and scal, arr and mat for the container type. Often you have to include more than one file to get a class to work because it might be partly implemented in prim/scal but need matrices or vectors to be included or reverse mode autodiff to run relevant examples.

This all gets sorted out for users in the 12 (4 x 3) top level includes for the product of the scalar type and container type distinctions.

1 Like

Ok, good to have that confirmed. I’m understanding that this is a feature
of how we’re organizing. I just kept imagining that there would be a clean
solution. K