Skip to content

Commit 160bc06

Browse files
authored
Merge pull request #3191 from stan-dev/fix/3189-forward-as-int-workaround
Allow forward_as to convert integers to doubles
2 parents 9f23455 + 2997e1a commit 160bc06

File tree

3 files changed

+50
-4
lines changed

3 files changed

+50
-4
lines changed

stan/math/prim/meta/forward_as.hpp

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,38 @@ inline T_actual&& forward_as(T_actual&& a) { // NOLINT
5454
* @return nothing, this always throws
5555
* @throw always throws std::runtime_error
5656
*/
57+
template <
58+
typename T_desired, typename T_actual,
59+
require_any_not_eigen_t<T_desired, T_actual>* = nullptr,
60+
typename = std::enable_if_t<
61+
!std::is_same<std::decay<T_actual>, std::decay<T_desired>>::value
62+
&& !(std::is_floating_point_v<std::decay_t<
63+
T_desired>> && std::is_integral_v<std::decay_t<T_actual>>)>>
64+
inline T_desired forward_as(const T_actual& a) {
65+
throw std::runtime_error("Wrong type assumed! Please file a bug report.");
66+
}
67+
68+
/** \ingroup type_trait
69+
* Assume which type we get. If actual type is not convertible to assumed type
70+
* or in case of eigen types compile time rows and columns are not the same and
71+
* desired sizes are not dynamic this has return type of \c T_desired, but it
72+
* only throws. This version should only be used where it is optimized away so
73+
* the throw should never happen.
74+
*
75+
* This handles the edge case where both types are simple arithmetic types
76+
* and we would like to just convert one to another.
77+
*
78+
* @tparam T_desired type of output we need to avoid compile time errors
79+
* @tparam T_actual actual type of the argument
80+
* @param a input value
81+
* @return a
82+
*/
5783
template <typename T_desired, typename T_actual,
5884
typename = std::enable_if_t<
59-
!std::is_same<std::decay<T_actual>, std::decay<T_desired>>::value
60-
&& (!is_eigen<T_desired>::value || !is_eigen<T_actual>::value)>>
85+
std::is_floating_point_v<std::decay_t<
86+
T_desired>> && std::is_integral_v<std::decay_t<T_actual>>>>
6187
inline T_desired forward_as(const T_actual& a) {
62-
throw std::runtime_error("Wrong type assumed! Please file a bug report.");
88+
return static_cast<T_desired>(a);
6389
}
6490

6591
/** \ingroup type_trait

test/unit/math/prim/meta/forward_as_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ TEST(MathMetaPrim, ForwardAsScalar) {
99

1010
EXPECT_NO_THROW(forward_as<int>(a) = 2);
1111
EXPECT_EQ(a, 2);
12-
EXPECT_THROW(forward_as<double>(a), std::runtime_error);
12+
EXPECT_FLOAT_EQ(forward_as<double>(a), 2.0);
1313
}

test/unit/math/rev/prob/normal_id_glm_lpdf_test.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,3 +745,23 @@ TEST(ProbDistributionsNormalIdGLM, glm_matches_normal_id_error_checking) {
745745
EXPECT_THROW(stan::math::normal_id_glm_lpdf(y, x, alpha, beta, sigmaw3),
746746
std::domain_error);
747747
}
748+
749+
TEST(ProbDistributionsNormalIdGLM, glm_type_issue_3189) {
750+
// regression test for https://github.com/stan-dev/math/issues/3189
751+
using Eigen::Dynamic;
752+
using Eigen::Matrix;
753+
using stan::math::var;
754+
int J = 3;
755+
int K = 2;
756+
757+
Eigen::Matrix<double, -1, -1> x(J, K);
758+
x << 1.0, 2.0, 3.0, 4.0, 5.0, 6.0;
759+
760+
Eigen::Matrix<stan::math::var, -1, 1> y(J);
761+
y << 0.1, 0.2, 0.3;
762+
Eigen::Matrix<stan::math::var, -1, 1> beta(K);
763+
beta << 0.5, 0.6;
764+
765+
EXPECT_FLOAT_EQ(stan::math::normal_id_glm_lpdf<false>(y, x, 0, beta, 1).val(),
766+
-27.701815);
767+
}

0 commit comments

Comments
 (0)