Skip to content

Commit ff5e277

Browse files
committed
Merge branch 'develop' into sum-to-zero-matrix
2 parents b494757 + 59c0014 commit ff5e277

21 files changed

Lines changed: 166 additions & 98 deletions

lib/tbb_2020.3/STAN_CHANGES

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ This file documents changes done for the stan-math project
1010
- Support for Windows ARM64 with RTools:
1111
- build/Makefile.tbb
1212
- L94 Wrapped the use of `--version-script` export in conditional on non-WINARM64
13-
- build/windows.gcc.ino
13+
- build/windows.gcc.inc
1414
- L84 Wrapped the use of `-flifetime-dse` flag in conditional on non-WINARM64
15+
- L101 Wrapped the use of `-msse` in conditional on non-WINARM64
1516

lib/tbb_2020.3/build/windows.gcc.inc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,11 @@ CPLUS_FLAGS += -DUSE_WINTHREAD
9898
CPLUS_FLAGS += -D_WIN32_WINNT=$(_WIN32_WINNT)
9999

100100
# MinGW specific
101-
CPLUS_FLAGS += -DMINGW_HAS_SECURE_API=1 -D__MSVCRT_VERSION__=0x0700 -msse -mthreads
101+
CPLUS_FLAGS += -DMINGW_HAS_SECURE_API=1 -D__MSVCRT_VERSION__=0x0700 -mthreads
102+
# Unused under ARM64 and error with LLVM19+
103+
ifeq (, $(WINARM64))
104+
CPLUS_FLAGS += -msse
105+
endif
102106

103107
CONLY = gcc
104108
debugger = gdb

stan/math/fwd/fun/hypergeometric_1F0.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ namespace math {
3131
template <typename Ta, typename Tz, typename FvarT = return_type_t<Ta, Tz>,
3232
require_all_stan_scalar_t<Ta, Tz>* = nullptr,
3333
require_any_fvar_t<Ta, Tz>* = nullptr>
34-
FvarT hypergeometric_1f0(const Ta& a, const Tz& z) {
34+
FvarT hypergeometric_1F0(const Ta& a, const Tz& z) {
3535
partials_type_t<Ta> a_val = value_of(a);
3636
partials_type_t<Tz> z_val = value_of(z);
37-
FvarT rtn = FvarT(hypergeometric_1f0(a_val, z_val), 0.0);
37+
FvarT rtn = FvarT(hypergeometric_1F0(a_val, z_val), 0.0);
3838
if (!is_constant_all<Ta>::value) {
3939
rtn.d_ += forward_as<FvarT>(a).d() * -rtn.val() * log1m(z_val);
4040
}

stan/math/fwd/fun/hypergeometric_2F1.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ namespace math {
3030
template <typename Ta1, typename Ta2, typename Tb, typename Tz,
3131
require_all_stan_scalar_t<Ta1, Ta2, Tb, Tz>* = nullptr,
3232
require_any_fvar_t<Ta1, Ta2, Tb, Tz>* = nullptr>
33-
inline return_type_t<Ta1, Ta1, Tb, Tz> hypergeometric_2F1(const Ta1& a1,
33+
inline return_type_t<Ta1, Ta2, Tb, Tz> hypergeometric_2F1(const Ta1& a1,
3434
const Ta2& a2,
3535
const Tb& b,
3636
const Tz& z) {
37-
using fvar_t = return_type_t<Ta1, Ta1, Tb, Tz>;
37+
using fvar_t = return_type_t<Ta1, Ta2, Tb, Tz>;
3838

3939
auto a1_val = value_of(a1);
4040
auto a2_val = value_of(a2);

stan/math/fwd/fun/hypergeometric_pFq.hpp

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include <stan/math/prim/fun/dot_product.hpp>
88
#include <stan/math/prim/fun/grad_pFq.hpp>
99
#include <stan/math/prim/fun/hypergeometric_pFq.hpp>
10+
#include <stan/math/prim/fun/as_column_vector_or_scalar.hpp>
11+
#include <stan/math/prim/fun/to_ref.hpp>
1012

1113
namespace stan {
1214
namespace math {
@@ -30,33 +32,27 @@ template <typename Ta, typename Tb, typename Tz,
3032
bool grad_z = !is_constant<Tz>::value,
3133
require_all_vector_t<Ta, Tb>* = nullptr,
3234
require_fvar_t<FvarT>* = nullptr>
33-
inline FvarT hypergeometric_pFq(const Ta& a, const Tb& b, const Tz& z) {
34-
using PartialsT = partials_type_t<FvarT>;
35-
using ARefT = ref_type_t<Ta>;
36-
using BRefT = ref_type_t<Tb>;
37-
38-
ARefT a_ref = a;
39-
BRefT b_ref = b;
35+
inline FvarT hypergeometric_pFq(Ta&& a, Tb&& b, Tz&& z) {
36+
auto&& a_ref = to_ref(as_column_vector_or_scalar(a));
37+
auto&& b_ref = to_ref(as_column_vector_or_scalar(b));
4038
auto&& a_val = value_of(a_ref);
4139
auto&& b_val = value_of(b_ref);
4240
auto&& z_val = value_of(z);
43-
PartialsT pfq_val = hypergeometric_pFq(a_val, b_val, z_val);
41+
42+
partials_type_t<FvarT> pfq_val = hypergeometric_pFq(a_val, b_val, z_val);
4443
auto grad_tuple
4544
= grad_pFq<grad_a, grad_b, grad_z>(pfq_val, a_val, b_val, z_val);
4645

4746
FvarT rtn = FvarT(pfq_val, 0.0);
4847

49-
if (grad_a) {
50-
rtn.d_ += dot_product(forward_as<promote_scalar_t<FvarT, ARefT>>(a_ref).d(),
51-
std::get<0>(grad_tuple));
48+
if constexpr (grad_a) {
49+
rtn.d_ += dot_product(a_ref.d(), std::get<0>(grad_tuple));
5250
}
53-
if (grad_b) {
54-
rtn.d_ += dot_product(forward_as<promote_scalar_t<FvarT, BRefT>>(b_ref).d(),
55-
std::get<1>(grad_tuple));
51+
if constexpr (grad_b) {
52+
rtn.d_ += dot_product(b_ref.d(), std::get<1>(grad_tuple));
5653
}
57-
if (grad_z) {
58-
rtn.d_ += forward_as<promote_scalar_t<FvarT, Tz>>(z).d_
59-
* std::get<2>(grad_tuple);
54+
if constexpr (grad_z) {
55+
rtn.d_ += z.d_ * std::get<2>(grad_tuple);
6056
}
6157

6258
return rtn;

stan/math/prim/fun/hypergeometric_1F0.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@ namespace math {
2828
* @return Hypergeometric 1F0 function
2929
*/
3030
template <typename Ta, typename Tz, require_all_arithmetic_t<Ta, Tz>* = nullptr>
31-
return_type_t<Ta, Tz> hypergeometric_1f0(const Ta& a, const Tz& z) {
32-
constexpr const char* function = "hypergeometric_1f0";
33-
check_less("hypergeometric_1f0", "abs(z)", std::fabs(z), 1.0);
31+
return_type_t<Ta, Tz> hypergeometric_1F0(const Ta& a, const Tz& z) {
32+
check_less("hypergeometric_1F0", "abs(z)", std::fabs(z), 1.0);
3433

3534
return boost::math::hypergeometric_1F0(a, z, boost_policy_t<>());
3635
}

stan/math/prim/fun/hypergeometric_2F1.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ namespace internal {
4343
* @return Gauss hypergeometric function
4444
*/
4545
template <typename Ta1, typename Ta2, typename Tb, typename Tz,
46-
typename RtnT = boost::optional<return_type_t<Ta1, Ta1, Tb, Tz>>,
46+
typename RtnT = boost::optional<return_type_t<Ta1, Ta2, Tb, Tz>>,
4747
require_all_arithmetic_t<Ta1, Ta2, Tb, Tz>* = nullptr>
4848
inline RtnT hyper_2F1_special_cases(const Ta1& a1, const Ta2& a2, const Tb& b,
4949
const Tz& z) {
@@ -148,10 +148,10 @@ inline RtnT hyper_2F1_special_cases(const Ta1& a1, const Ta2& a2, const Tb& b,
148148
* @return Gauss hypergeometric function
149149
*/
150150
template <typename Ta1, typename Ta2, typename Tb, typename Tz,
151-
typename ScalarT = return_type_t<Ta1, Ta1, Tb, Tz>,
151+
typename ScalarT = return_type_t<Ta1, Ta2, Tb, Tz>,
152152
typename OptT = boost::optional<ScalarT>,
153153
require_all_arithmetic_t<Ta1, Ta2, Tb, Tz>* = nullptr>
154-
inline return_type_t<Ta1, Ta1, Tb, Tz> hypergeometric_2F1(const Ta1& a1,
154+
inline return_type_t<Ta1, Ta2, Tb, Tz> hypergeometric_2F1(const Ta1& a1,
155155
const Ta2& a2,
156156
const Tb& b,
157157
const Tz& z) {

stan/math/prim/fun/hypergeometric_3F2.hpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,20 @@ template <typename Ta, typename Tb, typename Tz,
114114
require_all_vector_t<Ta, Tb>* = nullptr,
115115
require_stan_scalar_t<Tz>* = nullptr>
116116
inline auto hypergeometric_3F2(const Ta& a, const Tb& b, const Tz& z) {
117-
check_3F2_converges("hypergeometric_3F2", a[0], a[1], a[2], b[0], b[1], z);
117+
check_size_match("hypergeometric_3F2", "a", a.size(), "3", 3);
118+
check_size_match("hypergeometric_3F2", "b", b.size(), "2", 2);
119+
120+
auto a_ref = to_vector(a);
121+
auto b_ref = to_vector(b);
122+
123+
check_3F2_converges("hypergeometric_3F2", a_ref[0], a_ref[1], a_ref[2],
124+
b_ref[0], b_ref[1], z);
118125
// Boost's pFq throws convergence errors in some cases, fallback to naive
119126
// infinite-sum approach (tests pass for these)
120-
if (z == 1.0 && (sum(b) - sum(a)) < 0.0) {
121-
return internal::hypergeometric_3F2_infsum(a, b, z);
127+
if (z == 1.0 && (sum(b_ref) - sum(a_ref)) < 0.0) {
128+
return internal::hypergeometric_3F2_infsum(a_ref, b_ref, z);
122129
}
123-
return hypergeometric_pFq(to_vector(a), to_vector(b), z);
130+
return hypergeometric_pFq(a_ref, b_ref, z);
124131
}
125132

126133
/**

stan/math/prim/fun/hypergeometric_pFq.hpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <stan/math/prim/meta.hpp>
55
#include <stan/math/prim/err/check_not_nan.hpp>
66
#include <stan/math/prim/err/check_finite.hpp>
7+
#include <stan/math/prim/fun/to_row_vector.hpp>
78
#include <boost/math/special_functions/hypergeometric_pFq.hpp>
89

910
namespace stan {
@@ -14,10 +15,6 @@ namespace math {
1415
* input arguments:
1516
* \f$_pF_q(a_1,...,a_p;b_1,...,b_q;z)\f$
1617
*
17-
* This function is not intended to be exposed to end users, only
18-
* used for p & q values that are stable with the grad_pFq
19-
* implementation.
20-
*
2118
* See 'grad_pFq.hpp' for the derivatives wrt each parameter
2219
*
2320
* @param[in] a Vector of 'a' arguments to function
@@ -26,7 +23,7 @@ namespace math {
2623
* @return Generalized hypergeometric function
2724
*/
2825
template <typename Ta, typename Tb, typename Tz,
29-
require_all_eigen_st<std::is_arithmetic, Ta, Tb>* = nullptr,
26+
require_all_vector_st<std::is_arithmetic, Ta, Tb>* = nullptr,
3027
require_arithmetic_t<Tz>* = nullptr>
3128
return_type_t<Ta, Tb, Tz> hypergeometric_pFq(const Ta& a, const Tb& b,
3229
const Tz& z) {
@@ -47,8 +44,9 @@ return_type_t<Ta, Tb, Tz> hypergeometric_pFq(const Ta& a, const Tb& b,
4744
std::stringstream msg;
4845
msg << "hypergeometric function pFq does not meet convergence "
4946
<< "conditions with given arguments. "
50-
<< "a: " << a_ref << ", b: " << b_ref << ", "
51-
<< ", z: " << z;
47+
<< "a: " << to_row_vector(a_ref) << ", "
48+
<< "b: " << to_row_vector(b_ref) << ", "
49+
<< "z: " << z;
5250
throw std::domain_error(msg.str());
5351
}
5452

stan/math/prim/fun/inv_logit.hpp

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,14 @@ namespace math {
4949
* @return Inverse logit of argument.
5050
*/
5151
inline double inv_logit(double a) {
52-
using std::exp;
5352
if (a < 0) {
54-
double exp_a = exp(a);
53+
double exp_a = std::exp(a);
5554
if (a < LOG_EPSILON) {
5655
return exp_a;
5756
}
58-
return exp_a / (1 + exp_a);
57+
return exp_a / (1.0 + exp_a);
5958
}
60-
return inv(1 + exp(-a));
59+
return inv(1 + std::exp(-a));
6160
}
6261

6362
/**
@@ -69,28 +68,46 @@ inline double inv_logit(double a) {
6968
*/
7069
struct inv_logit_fun {
7170
template <typename T>
72-
static inline auto fun(const T& x) {
73-
return inv_logit(x);
71+
static inline auto fun(T&& x) {
72+
return inv_logit(std::forward<T>(x));
7473
}
7574
};
7675

7776
/**
78-
* Vectorized version of inv_logit().
77+
* Vectorized version of inv_logit() for containers containing ad types.
7978
*
80-
* @tparam T type of container
81-
* @param x container
79+
* @tparam T type of std::vector
80+
* @param x std::vector
8281
* @return Inverse logit applied to each value in x.
8382
*/
84-
template <
85-
typename T, require_not_var_matrix_t<T>* = nullptr,
86-
require_all_not_nonscalar_prim_or_rev_kernel_expression_t<T>* = nullptr>
87-
inline auto inv_logit(const T& x) {
88-
return apply_scalar_unary<inv_logit_fun, T>::apply(x);
83+
template <typename Container, require_ad_container_t<Container>* = nullptr,
84+
require_all_not_nonscalar_prim_or_rev_kernel_expression_t<
85+
Container>* = nullptr,
86+
require_not_rev_matrix_t<Container>* = nullptr>
87+
inline auto inv_logit(Container&& x) {
88+
return apply_scalar_unary<inv_logit_fun, Container>::apply(
89+
std::forward<Container>(x));
8990
}
9091

91-
// TODO(Tadej): Eigen is introducing their implementation logistic() of this
92-
// in 3.4. Use that once we switch to Eigen 3.4
93-
92+
/**
93+
* Vectorized version of inv_logit() for containers with arithmetic scalar
94+
* types.
95+
*
96+
* @tparam T A type of either `std::vector` or a type that directly inherits
97+
* from `Eigen::DenseBase`. The inner scalar type must not have an auto diff
98+
* scalar type.
99+
* @param x Eigen expression
100+
* @return Inverse logit applied to each value in x.
101+
*/
102+
template <typename Container,
103+
require_container_bt<std::is_arithmetic, Container>* = nullptr,
104+
require_all_not_nonscalar_prim_or_rev_kernel_expression_t<
105+
Container>* = nullptr>
106+
inline auto inv_logit(Container&& x) {
107+
return apply_vector_unary<Container>::apply(
108+
std::forward<Container>(x),
109+
[](const auto& v) { return v.array().logistic(); });
110+
}
94111
} // namespace math
95112
} // namespace stan
96113

0 commit comments

Comments
 (0)