Thanks Frank!
It appears that there’s a subtle difference between using log(Phi_approx(y))
and std_normal_lcdf(y)
in C++.
My original code using Phi_approx
(which compiles and works) looks like this:
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> first_term_lcdf = stan::math::log(
stan::math::Phi_approx(
-first_term_cdf_arg
)
);
where first_term_cdf_arg
is of type Eigen::MatrixXd
However, when I change to using std_normal_lcdf(y)
like so
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> first_term_lcdf =
stan::math::std_normal_lcdf(
-first_term_cdf_arg
);
I get the following compilation error:
softmax_approx.cpp:40:57: error: no viable conversion from 'return_type_t<CwiseUnaryOp<scalar_opposite_op<double>, const Matrix<double, -1, -1, 0, -1, -1>>>' (aka 'double') to 'Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>'
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> first_term_lcdf = stan::math::std_normal_lcdf(
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppEigen/include/Eigen/src/Core/Matrix.h:273:5: note: candidate constructor not viable: no known conversion from 'return_type_t<CwiseUnaryOp<scalar_opposite_op<double>, const Matrix<double, -1, -1, 0, -1, -1>>>' (aka 'double') to 'Matrix<double, -1, -1> &&' for 1st argument
Matrix(Matrix&& other) EIGEN_NOEXCEPT_IF(std::is_nothrow_move_constructible<Scalar>::value)
^
/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppEigen/include/Eigen/src/Core/Matrix.h:414:25: note: candidate constructor not viable: no known conversion from 'return_type_t<CwiseUnaryOp<scalar_opposite_op<double>, const Matrix<double, -1, -1, 0, -1, -1>>>' (aka 'double') to 'const Matrix<double, -1, -1> &' for 1st argument
EIGEN_STRONG_INLINE Matrix(const Matrix& other) : Base(other)
^
/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppEigen/include/Eigen/src/Core/Matrix.h:422:25: note: candidate template ignored: could not match 'EigenBase<OtherDerived>' against 'return_type_t<CwiseUnaryOp<scalar_opposite_op<double>, const Matrix<double, -1, -1, 0, -1, -1>>>' (aka 'double')
EIGEN_STRONG_INLINE Matrix(const EigenBase<OtherDerived> &other)
^
/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppEigen/include/Eigen/src/Core/Matrix.h:267:14: note: explicit constructor is not a candidate
explicit Matrix(internal::constructor_without_unaligned_array_assert)
^
/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppEigen/include/Eigen/src/Core/Matrix.h:321:34: note: explicit constructor is not a candidate
explicit EIGEN_STRONG_INLINE Matrix(const std::initializer_list<std::initializer_list<Scalar>>& list) : Base(list) {}
^
/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppEigen/include/Eigen/src/Core/Matrix.h:329:14: note: explicit constructor is not a candidate
explicit Matrix(const T& x)
^
/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppEigen/include/Eigen/src/Core/Matrix.h:435:14: note: explicit constructor is not a candidate
explicit Matrix(const RotationBase<OtherDerived,ColsAtCompileTime>& r);
^
In file included from softmax_approx.cpp:5:
In file included from /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/StanHeaders/include/stan/math/mix.hpp:24:
In file included from /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/StanHeaders/include/stan/math/prim.hpp:16:
In file included from /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/StanHeaders/include/stan/math/prim/prob.hpp:256:
In file included from /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/StanHeaders/include/stan/math/prim/prob/ordered_probit_log.hpp:5:
In file included from /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/StanHeaders/include/stan/math/prim/prob/ordered_probit_lpmf.hpp:13:
/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/StanHeaders/include/stan/math/prim/prob/std_normal_lcdf.hpp:45:28: error: implicit instantiation of undefined template 'stan::scalar_seq_view<Eigen::Matrix<double, -1, -1>>'
scalar_seq_view<T_y_ref> y_vec(y_ref);
^
softmax_approx.cpp:40:87: note: in instantiation of function template specialization 'stan::math::std_normal_lcdf<Eigen::CwiseUnaryOp<Eigen::internal::scalar_opposite_op<double>, const Eigen::Matrix<double, -1, -1>>, nullptr>' requested here
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> first_term_lcdf = stan::math::std_normal_lcdf(
^
/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/StanHeaders/include/stan/math/prim/fun/scalar_seq_view.hpp:18:7: note: template is declared here
class scalar_seq_view;
^
Any ideas on how to use this function correctly? Perhaps it needs a revision to have the same functionality as Phi_approx?
Maybe a good question for @Bob_Carpenter ?
Thanks!
Eric.