From 2a097be095c832115446a5069d7002f4276d993c Mon Sep 17 00:00:00 2001 From: Franzi Date: Mon, 7 Feb 2022 12:00:38 +0100 Subject: [PATCH 001/179] Adding LPDF for 7-parameter drift-diffusion model --- .../fwd/functor/operands_and_partials.hpp | 44 +- .../math/opencl/rev/operands_and_partials.hpp | 3 +- stan/math/prim/fun.hpp | 2 + stan/math/prim/fun/wiener5_lpdf.hpp | 559 +++++++++++++ stan/math/prim/fun/wiener7_lpdf.hpp | 539 ++++++++++++ stan/math/prim/functor.hpp | 1 + stan/math/prim/functor/hcubature.hpp | 469 +++++++++++ .../prim/functor/operands_and_partials.hpp | 32 +- stan/math/prim/prob.hpp | 1 + stan/math/prim/prob/wiener_full_lpdf.hpp | 769 ++++++++++++++++++ .../rev/functor/operands_and_partials.hpp | 121 ++- .../functor/operands_and_partials_test.cpp | 4 +- .../math/prim/prob/wiener_full_prec_test.cpp | 263 ++++++ test/unit/math/prim/prob/wiener_full_test.cpp | 263 ++++++ .../functor/operands_and_partials_test.cpp | 14 +- 15 files changed, 3026 insertions(+), 58 deletions(-) create mode 100644 stan/math/prim/fun/wiener5_lpdf.hpp create mode 100644 stan/math/prim/fun/wiener7_lpdf.hpp create mode 100644 stan/math/prim/functor/hcubature.hpp create mode 100644 stan/math/prim/prob/wiener_full_lpdf.hpp create mode 100644 test/unit/math/prim/prob/wiener_full_prec_test.cpp create mode 100644 test/unit/math/prim/prob/wiener_full_test.cpp diff --git a/stan/math/fwd/functor/operands_and_partials.hpp b/stan/math/fwd/functor/operands_and_partials.hpp index bf8e087d521..3e4053449e2 100644 --- a/stan/math/fwd/functor/operands_and_partials.hpp +++ b/stan/math/fwd/functor/operands_and_partials.hpp @@ -22,7 +22,8 @@ class ops_partials_edge> { : partial_(0), partials_(partial_), operand_(op) {} private: - template + template friend class stan::math::operands_and_partials; const Op& operand_; @@ -62,19 +63,25 @@ class ops_partials_edge> { * @tparam Op3 type of the third operand * @tparam Op4 type of the fourth operand * @tparam Op5 type of the fifth operand + * @tparam Op6 type of the sixth operand + * @tparam Op7 type of the seventh operand + * @tparam Op8 type of the eighth operand * @tparam T_return_type return type of the expression. This defaults * to a template metaprogram that calculates the scalar promotion of - * Op1 -- Op5 + * Op1 -- Op8 */ template -class operands_and_partials> { + typename Op6, typename Op7, typename Op8, typename Dx> +class operands_and_partials> { public: internal::ops_partials_edge> edge1_; internal::ops_partials_edge> edge2_; internal::ops_partials_edge> edge3_; internal::ops_partials_edge> edge4_; internal::ops_partials_edge> edge5_; + internal::ops_partials_edge> edge6_; + internal::ops_partials_edge> edge7_; + internal::ops_partials_edge> edge8_; using T_return_type = fvar; explicit operands_and_partials(const Op1& o1) : edge1_(o1) {} operands_and_partials(const Op1& o1, const Op2& o2) @@ -87,6 +94,20 @@ class operands_and_partials> { operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3, const Op4& o4, const Op5& o5) : edge1_(o1), edge2_(o2), edge3_(o3), edge4_(o4), edge5_(o5) {} + operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3, + const Op4& o4, const Op5& o5, const Op6& o6) + : edge1_(o1), edge2_(o2), edge3_(o3), edge4_(o4), edge5_(o5), + edge6_(o6) {} + operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3, + const Op4& o4, const Op5& o5, const Op6& o6, + const Op7& o7) + : edge1_(o1), edge2_(o2), edge3_(o3), edge4_(o4), edge5_(o5), + edge6_(o6), edge7_(o7) {} + operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3, + const Op4& o4, const Op5& o5, const Op6& o6, + const Op7& o7, const Op8& o8) + : edge1_(o1), edge2_(o2), edge3_(o3), edge4_(o4), edge5_(o5), + edge6_(o6), edge7_(o7), edge8_(o8) {} /** \ingroup type_trait * Build the node to be stored on the autodiff graph. @@ -103,7 +124,8 @@ class operands_and_partials> { */ T_return_type build(Dx value) { Dx deriv - = edge1_.dx() + edge2_.dx() + edge3_.dx() + edge4_.dx() + edge5_.dx(); + = edge1_.dx() + edge2_.dx() + edge3_.dx() + edge4_.dx() + edge5_.dx() + + edge6_.dx() + edge7_.dx() + edge8_.dx(); return T_return_type(value, deriv); } }; @@ -124,7 +146,8 @@ class ops_partials_edge>> { operands_(ops) {} private: - template + template friend class stan::math::operands_and_partials; const Op& operands_; @@ -150,7 +173,8 @@ class ops_partials_edge, R, C>> { operands_(ops) {} private: - template + template friend class stan::math::operands_and_partials; const Op& operands_; @@ -178,7 +202,8 @@ class ops_partials_edge, R, C>>> { } private: - template + template friend class stan::math::operands_and_partials; const Op& operands_; @@ -207,7 +232,8 @@ class ops_partials_edge>>> { } private: - template + template friend class stan::math::operands_and_partials; const Op& operands_; diff --git a/stan/math/opencl/rev/operands_and_partials.hpp b/stan/math/opencl/rev/operands_and_partials.hpp index d25c2a157a8..6d62a01841d 100644 --- a/stan/math/opencl/rev/operands_and_partials.hpp +++ b/stan/math/opencl/rev/operands_and_partials.hpp @@ -27,7 +27,8 @@ class ops_partials_edge, operands_(ops) {} private: - template + template friend class stan::math::operands_and_partials; var_value operands_; static constexpr int size() noexcept { return 0; } diff --git a/stan/math/prim/fun.hpp b/stan/math/prim/fun.hpp index aac5428c208..0998e5134ff 100644 --- a/stan/math/prim/fun.hpp +++ b/stan/math/prim/fun.hpp @@ -367,6 +367,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/stan/math/prim/fun/wiener5_lpdf.hpp b/stan/math/prim/fun/wiener5_lpdf.hpp new file mode 100644 index 00000000000..6c6661c3200 --- /dev/null +++ b/stan/math/prim/fun/wiener5_lpdf.hpp @@ -0,0 +1,559 @@ +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef STAN_MATH_PRIM_FUN_WIENER5_LPDF_HPP +#define STAN_MATH_PRIM_FUN_WIENER5_LPDF_HPP + +#include +#include + +namespace stan { +namespace math { + +/* + * The log of the first passage time density function for a (Wiener) + * drift diffusion model with 5 parameters. + * -boundary separation (alpha), + * -drift rate (delta), + * -relative starting point (beta), + * -non-decision time (tau), + * -inter-trial variability in drift rate (sv). + * For details see wiener_full_lpdf. + */ + +//----------------------------------------------- +// DENSITY and derivatives +//----------------------------------------------- + +namespace internal { + +// calculate density in log +template +return_type_t dwiener5( + const T_y& q, const T_alpha& a, const T_delta& vn, const T_beta& wn, + const T_sv& sv, const double& err) { + using T_return_type = return_type_t; + using std::ceil; + using std::log; + using std::pow; + using std::sqrt; + + static const double PISQ = square(pi()); // pi*pi + + T_return_type kll, kss, ans, v, w; + + w = 1.0 - wn; + v = -vn; + + T_return_type q_asq = q / pow(a, 2); + ans = 0.0; + + // calculate the number of terms needed for short t + T_return_type lg1; + if (sv != 0) { + T_return_type eta_sqr = pow(sv, 2); + T_return_type temp = 1 + eta_sqr * q; + lg1 = (eta_sqr * pow(a * w, 2) - 2 * a * v * w - pow(v, 2) * q) / 2.0 / temp + - 2 * log(a) - 0.5 * log(temp); + } else { + lg1 = (-2 * a * v * w - pow(v, 2) * q) / 2.0 - 2 * log(a); + } + T_return_type es = (err - lg1); + T_return_type K1 = (sqrt(2.0 * q_asq) + w) / 2.0; + T_return_type u_eps + = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log(q_asq) + 2.0 * (es)); + T_return_type arg = -q_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + T_return_type K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; + kss = ceil(fmax(K1, K2)); + + // calculate the number of terms needed for large t + T_return_type el = es; + K1 = 1.0 / (pi() * sqrt(q_asq)); + K2 = 0.0; + T_return_type temp_ = -2.0 * (log(pi() * q_asq) + el); + if (temp_ >= 0) + K2 = sqrt(temp_ / (pow(pi(), 2) * q_asq)); + kll = ceil(fmax(K1, K2)); + + // if small t is better + if (2 * kss <= kll) { + T_return_type fplus = NEGATIVE_INFTY; + T_return_type fminus = NEGATIVE_INFTY; + T_return_type twot = 2.0 * q_asq; + if (static_cast(kss) > 0) { + for (size_t k = static_cast(kss); k >= 1; k--) { + T_return_type temp1 = w + 2.0 * k; + T_return_type temp2 = w - 2.0 * k; + + fplus = log_sum_exp(log(temp1) - pow(temp1, 2) / twot, fplus); + fminus = log_sum_exp(log(-temp2) - pow(temp2, 2) / twot, fminus); + } + } + fplus = log_sum_exp(log(w) - pow(w, 2) / twot, fplus); + ans = lg1 + + (-0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log(q_asq) + + log_diff_exp(fplus, fminus)); + // if large t is better + } else { + T_return_type fplus = NEGATIVE_INFTY; + T_return_type fminus = NEGATIVE_INFTY; + T_return_type halfq = q_asq / 2.0; + for (size_t k = static_cast(kll); k >= 1; k--) { + T_return_type temp = k * pi(); + T_return_type check = sin(temp * w); + if (check > 0) + fplus = log_sum_exp(log(static_cast(k)) + - pow(temp, 2) * halfq + log(check), + fplus); + else + fminus = log_sum_exp(log(static_cast(k)) + - pow(temp, 2) * halfq + log(-check), + fminus); + } + if (fplus < fminus) { + ans = NEGATIVE_INFTY; + } else { + ans = lg1 + log_diff_exp(fplus, fminus) + LOG_PI; + } + } + return ans; +} +//----------------------------------------------- + +// d/dt DENSITY +// calculate derivative of density with respect to t (in log, ans = +// d/dt(log(f))=d/dt f'/f; ans*exp(ld)=f' on normal scale) +template +return_type_t dtdwiener5( + const T_y& q, const T_alpha& a, const T_delta& vn, const T_beta& wn, + const T_sv& sv, const double& err) { + using T_return_type = return_type_t; + using std::ceil; + using std::exp; + using std::log; + using std::pow; + using std::sqrt; + + static const double PISQ = square(pi()); // pi*pi + + T_return_type kll, kss, ans, v, w; + + w = 1.0 - wn; + v = -vn; + + // prepare some variables + T_return_type q_asq = q / pow(a, 2); + T_return_type la = 2.0 * log(a); + T_return_type ans0, lg1; + if (sv != 0) { + T_return_type eta_sqr = pow(sv, 2); + T_return_type temp = (1 + eta_sqr * q); + ans0 = -0.5 + * (pow(eta_sqr, 2) * (q + pow(a * w, 2)) + + eta_sqr * (1 - 2 * a * v * w) + pow(v, 2)) + / pow(temp, 2); + lg1 = (eta_sqr * pow(a * w, 2) - 2 * a * v * w - pow(v, 2) * q) / 2.0 / temp + - la - 0.5 * log(temp); + } else { + ans0 = -0.5 * pow(v, 2); + lg1 = (-2 * a * v * w - pow(v, 2) * q) / 2.0 - la; + } + T_return_type factor = lg1 - la; + + T_return_type ld = dwiener5(q, a, vn, wn, sv, + err - log(max(fabs(ans0 - 1.5 / q), fabs(ans0)))); + + // calculate the number of terms kss needed for small t + T_return_type es = err - lg1; + es = es + la; + T_return_type K1 = (sqrt(3.0 * q_asq) + w) / 2.0; + T_return_type u_eps = fmin( + -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(q_asq) + 2.0 * es) / 3.0); + T_return_type arg = -3.0 * q_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + T_return_type K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; + kss = ceil(fmax(K1, K2)); + + // calculate number of terms kll needed for large t + T_return_type el = err - lg1; + el = el + la; + K1 = sqrt(3.0 / q_asq) / pi(); + u_eps = fmin(-1.0, el + log(0.6) + LOG_PI + 2.0 * log(q_asq)); + arg = -2.0 / PISQ / q_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + T_return_type kl = (arg > 0) ? sqrt(arg) : K1; + kll = ceil(fmax(kl, K1)); + + T_return_type erg; + T_return_type newsign = 1; + T_return_type fplus = NEGATIVE_INFTY; + T_return_type fminus = NEGATIVE_INFTY; + + // if small t is better + if (2 * kss < kll) { + // calculate terms of the sum for small t + T_return_type twot = 2.0 * q_asq; + if (static_cast(kss) > 0) { + for (size_t k = static_cast(kss); k >= 1; k--) { + T_return_type temp1 = w + 2.0 * k; + T_return_type temp2 = w - 2.0 * k; + fplus = log_sum_exp(3.0 * log(temp1) - temp1 * temp1 / twot, fplus); + fminus = log_sum_exp(3.0 * log(-temp2) - temp2 * temp2 / twot, fminus); + } + } + fplus = log_sum_exp(3.0 * log(w) - w * w / twot, fplus); + if (fplus < fminus) { + newsign = -1; + erg = log_diff_exp(fminus, fplus); + } else { + erg = log_diff_exp(fplus, fminus); + } + + ans = ans0 - 1.5 / q + + newsign + * exp(factor - 1.5 * LOG_TWO - LOG_SQRT_PI - 3.5 * log(q_asq) + + erg - ld); + // if large t is better + } else { + // calculate terms of the sum for large t + T_return_type halfq = q_asq / 2.0; + for (size_t k = static_cast(kll); k >= 1; k--) { + T_return_type temp = pi() * k; + T_return_type zwi = sin(temp * w); + if (zwi > 0) { + fplus = log_sum_exp(3.0 * log(static_cast(k)) + - temp * temp * halfq + log(zwi), + fplus); + } + if (zwi < 0) { + fminus = log_sum_exp(3.0 * log(static_cast(k)) + - temp * temp * halfq + log(-zwi), + fminus); + } + } + if (fplus < fminus) { + erg = log_diff_exp(fminus, fplus); + newsign = -1; + } else { + erg = log_diff_exp(fplus, fminus); + } + + ans = ans0 - newsign * exp(factor + 3.0 * LOG_PI - LOG_TWO + erg - ld); + } + return ans; +} +//----------------------------------------------- + +// d/da DENSITY +// calculate derivative of density with respect to a (in log, ans = +// d/da(log(f))=d/da f'/f; ans*exp(ld)=f' on normal scale) +template +return_type_t dadwiener5( + const T_y& q, const T_alpha& a, const T_delta& vn, const T_beta& wn, + const T_sv& sv, const double& err, const int& normal_or_log) { + using T_return_type = return_type_t; + using std::ceil; + using std::exp; + using std::log; + using std::pow; + using std::sqrt; + + static const double PISQ = square(pi()); // pi*pi + + T_return_type kll, kss, ans, v, w; + + T_return_type la = log(a); + T_return_type lq = log(q); + + w = 1.0 - wn; + v = -vn; + + // prepare some variables + T_return_type q_asq = q / pow(a, 2); + T_return_type ans0, lg1; + if (sv != 0) { + T_return_type eta_sqr = pow(sv, 2); + T_return_type temp = (1 + eta_sqr * q); + ans0 = (-v * w + eta_sqr * pow(w, 2) * a) / temp; + lg1 = (eta_sqr * pow(a * w, 2) - 2 * a * v * w - pow(v, 2) * q) / 2.0 / temp + - 2 * la - 0.5 * log(temp); + } else { + ans0 = -v * w; + lg1 = (-2 * a * v * w - pow(v, 2) * q) / 2.0 - 2 * la; + } + T_return_type factor = lg1 - 3 * la; + + T_return_type ld + = dwiener5(q, a, vn, wn, sv, + err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); + + // calculate the number of terms kss needed for small t + T_return_type es = err - lg1; + es = es + la; + es = es - LOG_TWO + 2.0 * la - lq; + T_return_type K1 = (sqrt(3.0 * q_asq) + w) / 2.0; + T_return_type u_eps = fmin( + -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(q_asq) + 2.0 * es) / 3.0); + T_return_type arg = -3.0 * q_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + T_return_type K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; + kss = ceil(fmax(K1, K2)); + + // calculate number of terms kll needed for large t + T_return_type el = err - lg1; + el = el + la; + el = el - LOG_TWO + 2.0 * la - lq; + K1 = sqrt(3.0 / q_asq) / pi(); + u_eps = fmin(-1.0, el + log(0.6) + LOG_PI + 2.0 * log(q_asq)); + arg = -2.0 / PISQ / q_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + T_return_type kl = (arg > 0) ? sqrt(arg) : K1; + kll = ceil(fmax(kl, K1)); + + T_return_type erg; + T_return_type newsign = 1; + T_return_type fplus = NEGATIVE_INFTY; + T_return_type fminus = NEGATIVE_INFTY; + + // if small t is better + if (2 * kss < kll) { + // calculate terms of the sum for short t + T_return_type twot = 2.0 * q_asq; + if (static_cast(kss) > 0) { + for (size_t k = static_cast(kss); k >= 1; k--) { + T_return_type temp1 = w + 2.0 * k; + T_return_type temp2 = w - 2.0 * k; + fplus = log_sum_exp(3.0 * log(temp1) - temp1 * temp1 / twot, fplus); + fminus = log_sum_exp(3.0 * log(-temp2) - temp2 * temp2 / twot, fminus); + } + } + fplus = log_sum_exp(3.0 * log(w) - w * w / twot, fplus); + if (fplus < fminus) { + newsign = -1; + erg = log_diff_exp(fminus, fplus); + } else { + erg = log_diff_exp(fplus, fminus); + } + + ans = ans0 + 1.0 / a + - newsign + * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * lq + 4.0 * la + lg1 + + erg - ld); + // if large t is better + } else { + // calculate terms of the sum for large t + T_return_type halfq = q_asq / 2.0; + for (size_t k = static_cast(kll); k >= 1; k--) { + T_return_type temp = pi() * k; + T_return_type zwi = sin(temp * w); + if (zwi > 0) { + fplus = log_sum_exp(3.0 * log(static_cast(k)) + - temp * temp * halfq + log(zwi), + fplus); + } + if (zwi < 0) { + fminus = log_sum_exp(3.0 * log(static_cast(k)) + - temp * temp * halfq + log(-zwi), + fminus); + } + } + if (fplus > fminus) { + erg = log_diff_exp(fplus, fminus); + } else { + erg = log_diff_exp(fminus, fplus); + newsign = -1; + } + + ans = ans0 - 2.0 / a + newsign * exp(lq + factor + 3.0 * LOG_PI + erg - ld); + } + if (normal_or_log == 1) + return ans * exp(ld); // derivative of f for hcubature + else + return ans; // derivative of log(f) +} +//----------------------------------------------- + +// d/dv DENSITY +// calculate derivative of density with respect to v (in log, ans = +// d/dv(log(f))=d/dv f'/f; ans*exp(ld)=f' on normal scale) +template +return_type_t dvdwiener5(const T_y& q, + const T_alpha& a, + const T_delta& vn, + const T_beta& wn, + const T_sv& sv) { + using T_return_type = return_type_t; + using std::pow; + + T_return_type temp; + if (sv != 0) { + temp = 1 + pow(sv, 2) * q; + temp = (a * (1 - wn) - vn * q) / temp; + } else { + temp = (a * (1 - wn) - vn * q); + } + return temp; +} +//----------------------------------------------- + +// d/dw DENSITY +// calculate derivative of density with respect to w (in log, ans = +// d/dw(log(f))=d/dw f'/f; ans*exp(ld)=f' on normal scale) +template +return_type_t dwdwiener5( + const T_y& q, const T_alpha& a, const T_delta& vn, const T_beta& wn, + const T_sv& sv, const double& err, const int& normal_or_log) { + using T_return_type = return_type_t; + using std::ceil; + using std::exp; + using std::log; + using std::pow; + using std::sqrt; + + T_return_type kll, kss, ans, v, w; + T_return_type sign = -1; + + w = 1.0 - wn; + v = -vn; + + // prepare some variables + T_return_type q_asq = q / pow(a, 2); + T_return_type ans0, lg1; + if (sv != 0) { + T_return_type eta_sqr = pow(sv, 2); + T_return_type temp = (1 + eta_sqr * q); + ans0 = (-v * a + eta_sqr * pow(a, 2) * w) / temp; + lg1 = (eta_sqr * pow(a * w, 2) - 2 * a * v * w - pow(v, 2) * q) / 2.0 / temp + - 2 * log(a) - 0.5 * log(temp); + } else { + ans0 = -v * a; + lg1 = (-2 * a * v * w - pow(v, 2) * q) / 2.0 - 2 * log(a); + } + T_return_type ld = dwiener5(q, a, vn, wn, sv, err - log(fabs(ans0))); + + T_return_type ls = -lg1 + ld; + T_return_type ll = -lg1 + ld; + + // calculate the number of terms kss needed for small t + T_return_type K1 = (sqrt(3.0 * q_asq) + w) / 2.0; + T_return_type u_eps + = fmin(-1.0, 2.0 * (err - lg1) + LOG_TWO + LOG_PI + 2.0 * log(q_asq)); + T_return_type arg = -q_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + T_return_type K2 = (arg > 0) ? 0.5 * (sqrt(arg) + w) : K1; + kss = ceil(fmax(K1, K2)); + + // calculate number of terms kll needed for large t + K1 = sqrt(2.0 / q_asq) / pi(); + u_eps = fmin(-1.0, log(4.0 / 9.0) + 2.0 * LOG_PI + 3.0 * log(q_asq) + + 2.0 * (err - lg1)); + arg = -(u_eps - sqrt(-2.0 * u_eps - 2.0)); + K2 = (arg > 0) ? 1.0 / pi() * sqrt(arg / q_asq) : K1; + kll = ceil(fmax(K1, K2)); + + T_return_type erg; + T_return_type newsign = 1; + T_return_type fplus = NEGATIVE_INFTY; + T_return_type fminus = NEGATIVE_INFTY; + + // if small t is better + if (2 * kss < kll) { + // calculate terms of the sum for short t + T_return_type twot = 2.0 * q_asq; + for (size_t k = static_cast(kss); k >= 1; k--) { + T_return_type temp1 = pow((w + 2 * k), 2); + T_return_type temp2 = pow((w - 2 * k), 2); + T_return_type temp3 = temp1 - q_asq; + T_return_type temp4 = temp2 - q_asq; + if (temp3 > 0) + fplus = log_sum_exp(log(temp3) - temp1 / twot, fplus); + else if (temp3 < 0) + fminus = log_sum_exp(log(-(temp3)) - temp1 / twot, fminus); + if (temp4 > 0) + fplus = log_sum_exp(log(temp4) - temp2 / twot, fplus); + else if (temp4 < 0) + fminus = log_sum_exp(log(-(temp4)) - temp2 / twot, fminus); + } + T_return_type temp = pow(w, 2); + T_return_type temp1 = temp - q_asq; + if (temp1 > 0) + fplus = log_sum_exp(log(temp1) - temp / twot, fplus); + else if (temp1 < 0) + fminus = log_sum_exp(log(-(temp1)) - temp / twot, fminus); + + if (fplus < fminus) { + newsign = -1; + erg = log_diff_exp(fminus, fplus); + } else { + erg = log_diff_exp(fplus, fminus); + } + + ans = ans0 + - newsign + * exp(erg - ls - 2.5 * log(q_asq) - 0.5 * LOG_TWO + - 0.5 * LOG_PI); + // if large t is better + } else { + // calculate terms of the sum for large t + T_return_type halfq = q_asq / 2.0; + for (size_t k = static_cast(kll); k >= 1; k--) { + T_return_type temp = pi() * k; + T_return_type x = cos(temp * w); + if (x > 0) + fplus = log_sum_exp(2.0 * log(static_cast(k)) + - pow(temp, 2) * halfq + log(x), + fplus); + else if (x < 0) + fminus = log_sum_exp(2.0 * log(static_cast(k)) + - pow(temp, 2) * halfq + log(-x), + fminus); + } + if (fplus < fminus) { + erg = log_diff_exp(fminus, fplus); + newsign = -1; + } else { + erg = log_diff_exp(fplus, fminus); + } + + ans = ans0 + newsign * exp(erg - ll + 2.0 * LOG_PI); + } + if (normal_or_log == 1) + return ans * sign * exp(ld); // derivative of f for hcubature + else + return ans * sign; // derivative of log(f) +} +//----------------------------------------------- + +// d/dsv DENSITY +// calculate derivative of density with respect to sv (in log, ans = +// d/dsv(log(f))=d/dsv f'/f; ans*exp(ld)=f' on normal scale) +template +return_type_t dsvdwiener5( + const T_y& q, const T_alpha& a, const T_delta& vn, const T_beta& wn, + const T_sv& sv) { + using T_return_type = return_type_t; + using std::pow; + + T_return_type v, w; + + v = -vn; + w = 1 - wn; + + T_return_type temp = 1 + pow(sv, 2) * q; + T_return_type t1 = -q / temp; + T_return_type t2 + = (pow(a * w, 2) + 2 * a * v * w * q + pow(v * q, 2)) / pow(temp, 2); + return sv * (t1 + t2); +} +//----------------------------------------------- + +} // namespace internal +} // namespace math +} // namespace stan +#endif diff --git a/stan/math/prim/fun/wiener7_lpdf.hpp b/stan/math/prim/fun/wiener7_lpdf.hpp new file mode 100644 index 00000000000..494dec72e83 --- /dev/null +++ b/stan/math/prim/fun/wiener7_lpdf.hpp @@ -0,0 +1,539 @@ +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef STAN_MATH_PRIM_FUN_WIENER7_LPDF_HPP +#define STAN_MATH_PRIM_FUN_WIENER7_LPDF_HPP + +#include +#include + +namespace stan { +namespace math { + +/* + * Helper functions for the log of the first passage time density function for a + * (Wiener) drift diffusion model with 7 parameters. -boundary separation + * (alpha), -drift rate (delta), -relative starting point (beta), -non-decision + * time (tau), -inter-trial variability in drift rate (sv). -inter-trial + * variability in relative starting point (sw). -inter-trial variability in + * non-decition time (st0). For details see wiener_full_lpdf. + */ + +namespace internal { + +// tools +template +struct my_params { + T_y y; + T_alpha a; + T_delta v; + T_beta w; + T_t0 t0; + T_sv sv; + T_sw sw; + T_st0 st0; + T_err lerr; +}; + +template +struct my_params2 { + T_y y; + T_alpha a; + T_delta v; + T_beta w; + T_beta_lower w_lower; + T_beta_upper w_upper; + T_t0 t0; + T_sv sv; + T_sw sw; + T_sw_mean sw_mean; + T_st0 st0; + T_err lerr; +}; + +template +struct my_params3 { + T_y y; + T_alpha a; + T_delta v; + T_beta w; + T_t0 t0; + T_t0_mean t0_mean; + T_sv sv; + T_sw sw; + T_st0 st0; + T_st0_mean st0_mean; + T_err lerr; +}; + +// calculate derivative of density of wiener5 with respect to y (version for +// wiener7) +template +return_type_t dtdwiener5_for_7( + const T_y& q, const T_alpha& a, const T_delta& v, const T_beta& w, + const T_sv& sv, const double& err) { + using T_return_type = return_type_t; + using std::ceil; + using std::exp; + using std::log; + using std::pow; + using std::sqrt; + + static const double PISQ = square(pi()); // pi*pi + + T_return_type kll, kss, ans; + + // prepare some variables + T_return_type q_asq = q / pow(a, 2); + T_return_type la = 2.0 * log(a); + T_return_type ans0, lg1; + if (sv != 0) { + T_return_type eta_sqr = pow(sv, 2); + T_return_type temp = (1 + eta_sqr * q); + ans0 = -0.5 + * (pow(eta_sqr, 2) * (q + pow(a * w, 2)) + + eta_sqr * (1 - 2 * a * v * w) + pow(v, 2)) + / pow(temp, 2); + lg1 = (eta_sqr * pow(a * w, 2) - 2 * a * v * w - pow(v, 2) * q) / 2.0 / temp + - la - 0.5 * log(temp); + } else { + ans0 = -0.5 * pow(v, 2); + lg1 = (-2 * a * v * w - pow(v, 2) * q) / 2.0 - la; + } + T_return_type factor = lg1 - la; + + T_return_type ld = dwiener5(q, a, -v, 1 - w, sv, + err - log(max(fabs(ans0), fabs(ans0 - 1.5 / q)))); + + // calculate the number of terms kss needed for small y + T_return_type es = err - lg1; + es = es + la; + T_return_type K1 = (sqrt(3.0 * q_asq) + w) / 2.0; + T_return_type u_eps = fmin( + -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(q_asq) + 2.0 * es) / 3.0); + T_return_type arg = -3.0 * q_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + T_return_type K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; + kss = ceil(fmax(K1, K2)); + + // calculate number of terms kll needed for large y + T_return_type el = err - lg1; + el = el + la; + K1 = sqrt(3.0 / q_asq) / pi(); + u_eps = fmin(-1.0, el + log(0.6) + LOG_PI + 2.0 * log(q_asq)); + arg = -2.0 / PISQ / q_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + T_return_type kl = (arg > 0) ? sqrt(arg) : K1; + kll = ceil(fmax(kl, K1)); + + T_return_type erg; + T_return_type newsign = 1; + T_return_type fplus = NEGATIVE_INFTY; + T_return_type fminus = NEGATIVE_INFTY; + + // if small y is better + if (2 * kss < kll) { + // calculate terms of the sum for small y + T_return_type twot = 2.0 * q_asq; + if (static_cast(kss) > 0) { + for (size_t k = static_cast(kss); k >= 1; k--) { + T_return_type temp1 = w + 2.0 * k; + T_return_type temp2 = w - 2.0 * k; + fplus = log_sum_exp(3.0 * log(temp1) - temp1 * temp1 / twot, fplus); + fminus = log_sum_exp(3.0 * log(-temp2) - temp2 * temp2 / twot, fminus); + } + } + fplus = log_sum_exp(3.0 * log(w) - w * w / twot, fplus); + if (fplus < fminus) { + newsign = -1; + erg = log_diff_exp(fminus, fplus); + } else { + erg = log_diff_exp(fplus, fminus); + } + + ans = ans0 - 1.5 / q + + newsign + * exp(factor - 1.5 * LOG_TWO - LOG_SQRT_PI - 3.5 * log(q_asq) + + erg - ld); + // if large y is better + } else { + // calculate terms of the sum for large y + T_return_type halfq = q_asq / 2.0; + for (size_t k = static_cast(kll); k >= 1; k--) { + T_return_type temp = pi() * k; + T_return_type zwi = sin(temp * w); + if (zwi > 0) { + fplus = log_sum_exp(3.0 * log(static_cast(k)) + - temp * temp * halfq + log(zwi), + fplus); + } + if (zwi < 0) { + fminus = log_sum_exp(3.0 * log(static_cast(k)) + - temp * temp * halfq + log(-zwi), + fminus); + } + } + if (fplus < fminus) { + erg = log_diff_exp(fminus, fplus); + newsign = -1; + } else { + erg = log_diff_exp(fplus, fminus); + } + + ans = ans0 - newsign * exp(factor + 3.0 * LOG_PI - LOG_TWO + erg - ld); + } + return ans * exp(ld); +} +//----------------------------------------------- + +// integrand density (on normal scale) +template +return_type_t int_ddiff(const T_x& x, const T_p& p) { + using T_return_type = return_type_t; + my_params* params + = static_cast*>(p); + T_return_type y = (params->y); + T_return_type a = (params->a); + T_return_type v = (params->v); + T_return_type t0 = (params->t0); + T_return_type w = (params->w); + T_return_type sw = (params->sw); + T_return_type sv = (params->sv); + T_return_type st0 = (params->st0); + T_return_type lerr = (params->lerr); + + using T_x_ref = ref_type_t; + T_x_ref x_ref = x; + scalar_seq_view x_vec(x_ref); + + T_return_type retval; + + T_return_type omega = sw ? w + sw * (x_vec[0] - 0.5) : w; + T_return_type t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); + if (y - t0_ <= 0) { + retval = 0.0; + } else { + T_return_type ldW = dwiener5(y - t0_, a, v, omega, sv, lerr); + retval = exp(ldW); + } + return retval; +} +//----------------------------------------------- + +// integrand d/dt (on normal scale) +template +return_type_t int_dtddiff(const T_x& x, const T_p& p) { + using T_return_type = return_type_t; + my_params* params + = static_cast*>(p); + T_return_type y = (params->y); + T_return_type a = (params->a); + T_return_type v = (params->v); + T_return_type t0 = (params->t0); + T_return_type w = (params->w); + T_return_type sw = (params->sw); + T_return_type sv = (params->sv); + T_return_type st0 = (params->st0); + T_return_type lerr = (params->lerr); + + using T_x_ref = ref_type_t; + T_x_ref x_ref = x; + scalar_seq_view x_vec(x_ref); + + T_return_type retval; + + T_return_type omega = sw ? w + sw * (x_vec[0] - 0.5) : w; + T_return_type t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); + + if (y - t0_ <= 0) { + retval = 0.0; + } else { + retval = dtdwiener5_for_7(y - t0_, a, -v, 1 - omega, sv, lerr); + } + return retval; +} +//----------------------------------------------- + +// integrand d/da (on normal scale) +template +return_type_t int_daddiff(const T_x& x, const T_p& p) { + using T_return_type = return_type_t; + my_params* params + = static_cast*>(p); + T_return_type y = (params->y); + T_return_type a = (params->a); + T_return_type v = (params->v); + T_return_type t0 = (params->t0); + T_return_type w = (params->w); + T_return_type sw = (params->sw); + T_return_type sv = (params->sv); + T_return_type st0 = (params->st0); + T_return_type lerr = (params->lerr); + + using T_x_ref = ref_type_t; + T_x_ref x_ref = x; + scalar_seq_view x_vec(x_ref); + + T_return_type retval; + + T_return_type omega = sw ? w + sw * (x_vec[0] - 0.5) : w; + T_return_type t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); + + if (y - t0_ <= 0) { + retval = 0.0; + } else { + // prepare some variables for error estimation in density + T_return_type eta_sqr = pow(sv, 2); + T_return_type temp = (1 + eta_sqr * (y - t0_)); + T_return_type ans0 + = (v * (1 - omega) + eta_sqr * pow((1 - omega), 2) * a) / temp; + T_return_type factor + = max(ans0 + 1.0 / a, ans0 - 2.0 / a); // factor from small and large + // representation, for same + // computation as in dadwiener5 + // compute partial derivative + retval = dadwiener5(y - t0_, a, v, omega, sv, lerr, 1); + } + return retval; +} +//----------------------------------------------- + +// integrand d/dv (on normal scale) +template +return_type_t int_dvddiff(const T_x& x, const T_p& p) { + using T_return_type = return_type_t; + my_params* params + = static_cast*>(p); + T_return_type y = (params->y); + T_return_type a = (params->a); + T_return_type v = (params->v); + T_return_type t0 = (params->t0); + T_return_type w = (params->w); + T_return_type sw = (params->sw); + T_return_type sv = (params->sv); + T_return_type st0 = (params->st0); + T_return_type lerr = (params->lerr); + + using T_x_ref = ref_type_t; + T_x_ref x_ref = x; + scalar_seq_view x_vec(x_ref); + + T_return_type retval; + + T_return_type omega = sw ? w + sw * (x_vec[0] - 0.5) : w; + T_return_type t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); + + if (y - t0_ <= 0) { + retval = 0.0; + } else { + retval = dvdwiener5(y - t0_, a, v, omega, sv) + * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); + } + return retval; +} +//----------------------------------------------- + +// integrand d/dw (on normal scale) +template +return_type_t int_dwddiff(const T_x& x, const T_p& p) { + using T_return_type = return_type_t; + my_params* params + = static_cast*>(p); + T_return_type y = (params->y); + T_return_type a = (params->a); + T_return_type v = (params->v); + T_return_type t0 = (params->t0); + T_return_type w = (params->w); + T_return_type sw = (params->sw); + T_return_type sv = (params->sv); + T_return_type st0 = (params->st0); + T_return_type lerr = (params->lerr); + + using T_x_ref = ref_type_t; + T_x_ref x_ref = x; + scalar_seq_view x_vec(x_ref); + + T_return_type retval; + + T_return_type omega = sw ? w + sw * (x_vec[0] - 0.5) : w; + T_return_type t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); + + if (y - t0_ <= 0) { + retval = 0.0; + } else { + // prepare some variables for error estimation in density + T_return_type eta_sqr = pow(sv, 2); + T_return_type temp = (1 + eta_sqr * (y - t0_)); + T_return_type ans0 = (v * a + eta_sqr * pow(a, 2) * (1 - omega)) / temp; + // compute partial derivative + retval = dwdwiener5(y - t0_, a, v, omega, sv, lerr, 1); + } + return retval; +} +//----------------------------------------------- + +// integrand d/dsv (on normal scale) +template +return_type_t int_dsvddiff(const T_x& x, const T_p& p) { + using T_return_type = return_type_t; + my_params* params + = static_cast*>(p); + T_return_type y = (params->y); + T_return_type a = (params->a); + T_return_type v = (params->v); + T_return_type t0 = (params->t0); + T_return_type w = (params->w); + T_return_type sw = (params->sw); + T_return_type sv = (params->sv); + T_return_type st0 = (params->st0); + T_return_type lerr = (params->lerr); + + using T_x_ref = ref_type_t; + T_x_ref x_ref = x; + scalar_seq_view x_vec(x_ref); + + T_return_type retval; + + T_return_type omega = sw ? w + sw * (x_vec[0] - 0.5) : w; + T_return_type t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); + + if (y - t0_ <= 0) { + retval = 0.0; + } else { + retval = dsvdwiener5(y - t0_, a, v, omega, sv) + * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); + } + return retval; +} +//----------------------------------------------- + +// integrand d/dsw (on normal scale) +template +return_type_t int_dswddiff(const T_x& x, const T_p& p) { + using T_return_type = return_type_t; + my_params2* params + = static_cast*>( + p); + T_return_type y = (params->y); + T_return_type a = (params->a); + T_return_type v = (params->v); + T_return_type t0 = (params->t0); + T_return_type w = (params->w); + T_return_type w_lower = (params->w_lower); + T_return_type w_upper = (params->w_upper); + T_return_type sw = (params->sw); + T_return_type sw_mean = (params->sw_mean); + T_return_type sv = (params->sv); + T_return_type st0 = (params->st0); + T_return_type lerr = (params->lerr); + + using T_x_ref = ref_type_t; + T_x_ref x_ref = x; + scalar_seq_view x_vec(x_ref); + + T_return_type t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); + + T_return_type f, fl, fu; + if (y - t0_ <= 0) { + return 0.0; + } else { + fl = exp(internal::dwiener5(y - t0_, a, v, w_lower, sv, lerr)); + fu = exp(internal::dwiener5(y - t0_, a, v, w_upper, sv, lerr)); + } + return 1 / sw_mean * 0.5 * (fl + fu); +} +//----------------------------------------------- + +// integrand d/dst0 (on normal scale) +template +return_type_t int_dst0ddiff(const T_x& x, const T_p& p) { + using T_return_type = return_type_t; + my_params3* params + = static_cast< + my_params3*>(p); + T_return_type y = (params->y); + T_return_type a = (params->a); + T_return_type v = (params->v); + T_return_type t0 = (params->t0); + T_return_type t0_mean = (params->t0_mean); + T_return_type w = (params->w); + T_return_type sw = (params->sw); + T_return_type sv = (params->sv); + T_return_type st0 = (params->st0); + T_return_type st0_mean = (params->st0_mean); + T_return_type lerr = (params->lerr); + + using T_x_ref = ref_type_t; + T_x_ref x_ref = x; + scalar_seq_view x_vec(x_ref); + + T_return_type t0_ = sw ? (st0_mean ? t0_mean + st0_mean * x_vec[1] : t0_mean) + : (st0_mean ? t0_mean + st0_mean * x_vec[0] : t0_mean); + + T_return_type omega = sw ? w + sw * (x_vec[0] - 0.5) : w; + + T_return_type f; + if (y - t0_ <= 0) { + return 0.0; + } else { + f = exp(internal::dwiener5(y - t0_, a, v, omega, sv, lerr)); + } + return 1 / st0 * f; +} +//----------------------------------------------- + +} // namespace internal +} // namespace math +} // namespace stan +#endif diff --git a/stan/math/prim/functor.hpp b/stan/math/prim/functor.hpp index 0ec5c343ff7..5590b5115c5 100644 --- a/stan/math/prim/functor.hpp +++ b/stan/math/prim/functor.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp new file mode 100644 index 00000000000..b047414cd01 --- /dev/null +++ b/stan/math/prim/functor/hcubature.hpp @@ -0,0 +1,469 @@ +// For the code in hcubature.hpp, the package JuliaMath/HCubature.jl +// written in Julia by Steven G. Johnson served as a template. +// It comes with the following MIT "Expat" license: +// +// Copyright (c) 2017: Steven G. Johnson. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files +// (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. + +#ifndef STAN_MATH_PRIM_FUNCTOR_HCUBATURE_HPP +#define STAN_MATH_PRIM_FUNCTOR_HCUBATURE_HPP + +#include +#include +#include +#include +#include +#include + +namespace stan { +namespace math { + +namespace internal { + +// tools +static const double xd7[8] = {-9.9145537112081263920685469752598e-01, + -9.4910791234275852452618968404809e-01, + -8.6486442335976907278971278864098e-01, + -7.415311855993944398638647732811e-01, + -5.8608723546769113029414483825842e-01, + -4.0584515137739716690660641207707e-01, + -2.0778495500789846760068940377309e-01, + 0.0}; + +static const double wd7[8] = {2.2935322010529224963732008059913e-02, + 6.3092092629978553290700663189093e-02, + 1.0479001032225018383987632254189e-01, + 1.4065325971552591874518959051021e-01, + 1.6900472663926790282658342659795e-01, + 1.9035057806478540991325640242055e-01, + 2.0443294007529889241416199923466e-01, + 2.0948214108472782801299917489173e-01}; + +static const double gwd7[4] = {1.2948496616886969327061143267787e-01, + 2.797053914892766679014677714229e-01, + 3.8183005050511894495036977548818e-01, + 4.1795918367346938775510204081658e-01}; + +struct one_d { + double result; + double err; + int kdivide = 0; +}; + +struct GenzMalik { + std::vector p[4]; + double w[5]; + double wd[4]; +}; + +template +void combination(T_c& c, const T_n& n, const T_p& p, const T_x& x) { + size_t i, r, k = 0; + for (i = 0; i < p - 1; i++) { + c[i] = (i != 0) ? c[i - 1] : 0; + do { + c[i]++; + r = choose(n - c[i], p - (i + 1)); + k = k + r; + } while (k < x); + k = k - r; + } + if (p > 1) + c[p - 1] = c[p - 2] + x - k; + else + c[0] = x; +} + +template +void combos(const T_k& k, const T_lambda& lambda, const T_n& n, T_p& p) { + T_k* c = reinterpret_cast(malloc(k * sizeof(T_k))); + for (size_t i = 1; i != choose(n, k) + 1; i++) { + T_lambda* temp = reinterpret_cast(calloc(n, sizeof(T_lambda))); + combination(c, n, k, i); + for (size_t j = 0; j != k; j++) + temp[c[j] - 1] = lambda; + p.push_back(temp); + } + free(c); +} + +template +void increment(T_index& index, const T_k& k, const T_lambda& lambda, + const T_n& n, const T_c& c, T_temp& temp) { + // temp size n, all elements initially zero + if (index.size() == 0) { + index.push_back(false); + for (size_t j = 0; j != k; j++) + temp[c[j] - 1] = lambda; + return; + } + T_k first_zero = 0; + while ((first_zero < index.size()) && index[first_zero]) + first_zero++; + if (first_zero == index.size()) { + index.flip(); + for (size_t j = 0; j != index.size(); j++) + temp[c[j] - 1] *= -1; + index.push_back(true); + temp[c[index.size() - 1] - 1] = -lambda; + } else { + for (size_t i = 0; i != first_zero + 1; i++) { + // index[i] = !index[i]; + if (index[i]) + index[i] = 0; + else + index[i] = 1; + temp[c[i] - 1] *= -1; + } + } +} + +template +void signcombos(const T_k& k, const T_lambda& lambda, const T_n& n, T_p& p) { + T_k* c = reinterpret_cast(malloc(k * sizeof(T_k))); + for (size_t i = 1; i != choose(n, k) + 1; i++) { + T_lambda* temp = reinterpret_cast(calloc(n, sizeof(T_lambda))); + combination(c, n, k, i); + std::vector index; + index.clear(); + for (size_t j = 0; j != pow(2, k); j++) { + increment(index, k, lambda, n, c, temp); + T_lambda* next = + reinterpret_cast(malloc(n * sizeof(T_lambda))); + memcpy(next, temp, n * sizeof(T_lambda)); + p.push_back(next); + } + free(temp); + } + free(c); +} + +template +void gauss_kronrod(const F& integrand, const T_a& a, const T_b& b, T_oned& out, + T_pars& pars) { + using T_return_type = return_type_t; + std::vector c(1, 0); + std::vector cp(1, 0); + std::vector cm(1, 0); + c[0] = 0.5 * (a + b); + T_return_type delta = 0.5 * (b - a); + T_return_type f0 = integrand(c, pars); + T_return_type I = f0 * wd7[7]; + T_return_type Idash = f0 * gwd7[3]; + for (size_t i = 0; i != 7; i++) { + T_return_type deltax = delta * xd7[i]; + cp[0] = c[0] + deltax; + cm[0] = c[0] - deltax; + T_return_type fx = integrand(cp, pars); + T_return_type temp = integrand(cm, pars); + fx += temp; + I += fx * wd7[i]; + if (i % 2 == 1) + Idash += fx * gwd7[i / 2]; + } + T_return_type V = fabs(delta); + I *= V; + Idash *= V; + out.result = I; + out.err = fabs(I - Idash); + std::vector().swap(c); + std::vector().swap(cp); + std::vector().swap(cm); +} + +template +void make_GenzMalik(const T_n& n, T_GenzMalik& g) { + using T_return_type = return_type_t; + T_return_type l4 = sqrt(9 * 1.0 / 10); + T_return_type l2 = sqrt(9 * 1.0 / 70); + T_return_type l3 = l4; + T_return_type l5 = sqrt(9 * 1.0 / 19); + + T_return_type twopn = pow(2, n); + + g.w[0] = twopn * ((12824 - 9120 * n + 400 * n * n) * 1.0 / 19683); + g.w[1] = twopn * (980.0 / 6561); + g.w[2] = twopn * ((1820 - 400 * n) * 1.0 / 19683); + g.w[3] = twopn * (200.0 / 19683); + g.w[4] = 6859.0 / 19683; + g.wd[3] = twopn * (25.0 / 729); + g.wd[2] = twopn * ((265 - 100 * n) * 1.0 / 1458); + g.wd[1] = twopn * (245.0 / 486); + g.wd[0] = twopn * ((729 - 950 * n + 50 * n * n) * 1.0 / 729); + + combos(1, l2, n, g.p[0]); + combos(1, l3, n, g.p[1]); + signcombos(2, l4, n, g.p[2]); + signcombos(n, l5, n, g.p[3]); +} + +template +void clean_GenzMalik(T_GenzMalik& g) { + for (size_t j = 0; j != 4; j++) + for (size_t i = 0; i != g.p[j].size(); i++) + if (g.p[j][i]) + free(g.p[j][i]); +} + +template +void integrate_GenzMalik(const F& integrand, T_GenzMalik& g, const T_n& n, + const T_a& a, const T_b& b, T_oned& out, + T_pars& pars) { + using T_return_type = return_type_t; + std::vector c(n, 0); + double* deltac = reinterpret_cast(malloc(n * sizeof(double))); + + for (size_t i = 0; i != n; i++) + c[i] = (a[i] + b[i]) / 2; + + for (size_t i = 0; i != n; i++) + deltac[i] = fabs(b[i] - a[i]) / 2; + T_return_type v = 1.0; + for (size_t i = 0; i != n; i++) + v *= deltac[i]; + + if (v == 0.0) { + out.err = 0.0; + out.result = 0.0; + out.kdivide = 0; + free(deltac); + return; + } + + T_return_type f1 = integrand(c, pars); + T_return_type f2 = 0.0; + T_return_type f3 = 0.0; + T_return_type twelvef1 = 12 * f1; + + T_return_type maxdivdiff = 0.0; + T_return_type* divdiff = + reinterpret_cast(malloc(n * sizeof(T_return_type))); + T_return_type* p2 = + reinterpret_cast(malloc(n * sizeof(T_return_type))); + T_return_type* p3 = + reinterpret_cast(malloc(n * sizeof(T_return_type))); + std::vector cc(n, 0); + + for (size_t i = 0; i != n; i++) { + for (size_t j = 0; j != n; j++) + p2[j] = deltac[j] * g.p[0][i][j]; + + for (size_t j = 0; j != n; j++) + cc[j] = c[j] + p2[j]; + T_return_type f2i = integrand(cc, pars); + for (size_t j = 0; j != n; j++) + cc[j] = c[j] - p2[j]; + T_return_type temp = integrand(cc, pars); + f2i += temp; + + for (size_t j = 0; j != n; j++) + p3[j] = deltac[j] * g.p[1][i][j]; + for (size_t j = 0; j != n; j++) + cc[j] = c[j] + p3[j]; + T_return_type f3i = integrand(cc, pars); + for (size_t j = 0; j != n; j++) + cc[j] = c[j] - p3[j]; + temp = integrand(cc, pars); + f3i += temp; + f2 += f2i; + f3 += f3i; + divdiff[i] = fabs(f3i + twelvef1 - 7 * f2i); + } + free(p2); + free(p3); + T_return_type* p4 = + reinterpret_cast(malloc(n * sizeof(T_return_type))); + T_return_type f4 = 0.0; + for (size_t i = 0; i != g.p[2].size(); i++) { + for (size_t j = 0; j != n; j++) + p4[j] = deltac[j] * g.p[2][i][j]; + for (size_t j = 0; j != n; j++) + cc[j] = c[j] + p4[j]; + T_return_type temp = integrand(cc, pars); + f4 += temp; + } + free(p4); + T_return_type f5 = 0.0; + T_return_type* p5 = + reinterpret_cast(malloc(n * sizeof(T_return_type))); + for (size_t i = 0; i != g.p[3].size(); i++) { + for (size_t j = 0; j != n; j++) + p5[j] = deltac[j] * g.p[3][i][j]; + + for (size_t j = 0; j != n; j++) + cc[j] = c[j] + p5[j]; + T_return_type temp = integrand(cc, pars); + f5 += temp; + } + free(p5); + std::vector().swap(cc); + T_return_type I + = v + * (g.w[0] * f1 + g.w[1] * f2 + g.w[2] * f3 + g.w[3] * f4 + g.w[4] * f5); + T_return_type Idash + = v * (g.wd[0] * f1 + g.wd[1] * f2 + g.wd[2] * f3 + g.wd[3] * f4); + T_return_type E = fabs(I - Idash); + + int kdivide = 0; + T_return_type deltaf = E / (pow(10, n) * v); + for (size_t i = 0; i != n; i++) { + T_return_type delta = divdiff[i] - maxdivdiff; + if (delta > deltaf) { + kdivide = i; + maxdivdiff = divdiff[i]; + } else if ((fabs(delta) <= deltaf) && (deltac[i] > deltac[kdivide])) { + kdivide = i; + } + } + out.result = I; + out.err = E; + out.kdivide = kdivide; + free(deltac); + free(divdiff); + std::vector().swap(c); +} + +class Box { + public: + Box(std::vector a, std::vector b, double& I, double& err, + int& kdivide) + : a(a), b(b), I(I), E(err), kdiv(kdivide) {} + bool operator<(const Box& box) const { return E > box.E; } + std::vector a; + std::vector b; + double I; + double E; + int kdiv; +}; + +inline class Box make_box(int n, std::vector a, std::vector b, + one_d out) { + std::vector ac(a); + std::vector bc(b); + Box box(ac, bc, out.result, out.err, out.kdivide); + return box; +} + +} // namespace internal + +// hcubature +template +return_type_t hcubature( + const F& integrand, const T_pars& pars, const T_n& n, const T_a& a, + const T_b& b, const T_maxEval& maxEval, const T_reqAbsError& reqAbsError, + const T_reqRelError& reqRelError) { + using T_return_type + = return_type_t; + + using T_a_ref = ref_type_t; + using T_b_ref = ref_type_t; + + T_a_ref a_ref = a; + T_b_ref b_ref = b; + + scalar_seq_view a_vec(a_ref); + scalar_seq_view b_vec(b_ref); + + internal::one_d out; + internal::GenzMalik g; + + if (n == 1) { + internal::gauss_kronrod(integrand, a_vec.val(0), b_vec.val(0), out, pars); + } else { + internal::make_GenzMalik(n, g); + internal::integrate_GenzMalik(integrand, g, n, a, b, out, pars); + } + T_return_type numevals + = (n == 1) ? 15 : 1 + 4 * n + 2 * n * (n - 1) + pow(2, n); + T_return_type evals_per_box = numevals; + T_return_type kdiv = out.kdivide; + T_return_type err = out.err; + T_return_type val = out.result; + // convergence test + if ((err <= fmax(reqRelError * fabs(val), reqAbsError)) + || ((maxEval != 0) && (numevals >= maxEval))) { + internal::clean_GenzMalik(g); + return val; + } + + std::multiset ms; + ms.insert(internal::make_box(n, a, b, out)); + + while (true) { + std::multiset::iterator it; + it = ms.begin(); + internal::Box box = *it; + ms.erase(it); + // split along dimension kdiv + T_return_type w = (box.b[box.kdiv] - box.a[box.kdiv]) / 2; + std::vector ma(box.a); + + ma[box.kdiv] += w; + std::vector mb(box.b); + mb[box.kdiv] -= w; + + if (n == 1) { + internal::gauss_kronrod(integrand, ma[0], box.b[0], out, pars); + } else { + internal::integrate_GenzMalik(integrand, g, n, ma, box.b, out, pars); + } + internal::Box box1 = make_box(n, ma, box.b, out); + ms.insert(box1); + + if (n == 1) { + internal::gauss_kronrod(integrand, box.a[0], mb[0], out, pars); + } else { + internal::integrate_GenzMalik(integrand, g, n, box.a, mb, out, pars); + } + internal::Box box2 = make_box(n, box.a, mb, out); + ms.insert(box2); + val += box1.I + box2.I - box.I; + err += box1.E + box2.E - box.E; + numevals += 2 * evals_per_box; + + std::vector().swap(box.a); + std::vector().swap(box.b); + std::vector().swap(ma); + std::vector().swap(mb); + if (((err <= max(reqRelError * fabs(val), reqAbsError)) + || ((maxEval != 0) && (numevals >= maxEval))) + || !(std::isfinite(val))) { + break; + } + } + val = 0.0; + err = 0.0; + + for (std::multiset::reverse_iterator rit = ms.rbegin(); + rit != ms.rend(); rit++) { + val += (*rit).I; + err += (*rit).E; + } + + for (std::multiset::iterator it = ms.begin(); it != ms.end(); + it++) { + internal::Box box = *it; + std::vector().swap(box.a); + std::vector().swap(box.b); + } + internal::clean_GenzMalik(g); + return val; +} // hcubature + +} // namespace math +} // namespace stan +#endif diff --git a/stan/math/prim/functor/operands_and_partials.hpp b/stan/math/prim/functor/operands_and_partials.hpp index abfff95ff9d..9b3faeff4dc 100644 --- a/stan/math/prim/functor/operands_and_partials.hpp +++ b/stan/math/prim/functor/operands_and_partials.hpp @@ -12,8 +12,10 @@ namespace stan { namespace math { template > + typename Op4 = double, typename Op5 = double, typename Op6 = double, + typename Op7 = double, typename Op8 = double, + typename T_return_type + = return_type_t> class operands_and_partials; // Forward declaration namespace internal { @@ -70,7 +72,8 @@ class ops_partials_edge> { static constexpr int size() noexcept { return 0; } // reverse mode private: - template + template friend class stan::math::operands_and_partials; }; template @@ -100,7 +103,7 @@ constexpr double * * This base template is instantiated when all operands are * primitives and we don't want to calculate derivatives at - * all. So all Op1 - Op5 must be arithmetic primitives + * all. So all Op1 - Op8 must be arithmetic primitives * like int or double. This is controlled with the * T_return_type type parameter. * @@ -109,12 +112,15 @@ constexpr double * @tparam Op3 type of the third operand * @tparam Op4 type of the fourth operand * @tparam Op5 type of the fifth operand + * @tparam Op6 type of the sixth operand + * @tparam Op7 type of the seventh operand + * @tparam Op8 type of the eighth operand * @tparam T_return_type return type of the expression. This defaults * to calling a template metaprogram that calculates the scalar - * promotion of Op1..Op4 + * promotion of Op1..Op8 */ template + typename Op6, typename Op7, typename Op8, typename T_return_type> class operands_and_partials { public: explicit operands_and_partials(const Op1& /* op1 */) noexcept {} @@ -126,6 +132,17 @@ class operands_and_partials { operands_and_partials(const Op1& /* op1 */, const Op2& /* op2 */, const Op3& /* op3 */, const Op4& /* op4 */, const Op5& /* op5 */) noexcept {} + operands_and_partials(const Op1& /* op1 */, const Op2& /* op2 */, + const Op3& /* op3 */, const Op4& /* op4 */, + const Op5& /* op5 */, const Op6& /* op6 */) noexcept {} + operands_and_partials(const Op1& /* op1 */, const Op2& /* op2 */, + const Op3& /* op3 */, const Op4& /* op4 */, + const Op5& /* op5 */, const Op6& /* op6 */, + const Op7& /* op7 */) noexcept {} + operands_and_partials(const Op1& /* op1 */, const Op2& /* op2 */, + const Op3& /* op3 */, const Op4& /* op4 */, + const Op5& /* op5 */, const Op6& /* op6 */, + const Op7& /* op7 */, const Op8& /* op8 */) noexcept {} /** \ingroup type_trait * Build the node to be stored on the autodiff graph. @@ -148,6 +165,9 @@ class operands_and_partials { internal::ops_partials_edge> edge3_; internal::ops_partials_edge> edge4_; internal::ops_partials_edge> edge5_; + internal::ops_partials_edge> edge6_; + internal::ops_partials_edge> edge7_; + internal::ops_partials_edge> edge8_; }; } // namespace math diff --git a/stan/math/prim/prob.hpp b/stan/math/prim/prob.hpp index bfd8cfdc07e..9d5446eab4f 100644 --- a/stan/math/prim/prob.hpp +++ b/stan/math/prim/prob.hpp @@ -366,6 +366,7 @@ #include #include #include +#include #include #include #include diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp new file mode 100644 index 00000000000..f536ce4b6b7 --- /dev/null +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -0,0 +1,769 @@ +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef STAN_MATH_PRIM_PROB_WIENER_FULL_LPDF_HPP +#define STAN_MATH_PRIM_PROB_WIENER_FULL_LPDF_HPP + +#include + +namespace stan { +namespace math { + +namespace internal { + +template +inline return_type_t +wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, + const T_alpha& a, const T_delta& v, const T_beta& w, + const T_t0& t0, const T_sv& sv, const T_sw& sw, + const T_st0& st0, const double& prec) { + using T_partials_return = partials_return_t; + using T_y_ref = ref_type_t; + using T_alpha_ref = ref_type_t; + using T_delta_ref = ref_type_t; + using T_beta_ref = ref_type_t; + using T_t0_ref = ref_type_t; + using T_sv_ref = ref_type_t; + using T_sw_ref = ref_type_t; + using T_st0_ref = ref_type_t; + + check_consistent_sizes(function_name, "Random variable", y, + "Boundary separation", a, "Drift rate", v, + "A-priori bias", w, "Nondecision time", t0, + "Inter-trial variability in drift rate", sv, + "Inter-trial variability in A-priori bias", sw, + "Inter-trial variability in Nondecision time", st0); + + check_consistent_size(function_name, "Random variable", y, 1); + check_consistent_size(function_name, "Boundary separation", a, 1); + check_consistent_size(function_name, "Drift rate", v, 1); + check_consistent_size(function_name, "A-priori bias", w, 1); + check_consistent_size(function_name, "Nondecision time", t0, 1); + check_consistent_size(function_name, "Inter-trial variability in drift rate", + sv, 1); + check_consistent_size(function_name, + "Inter-trial variability in A-priori bias", sw, 1); + check_consistent_size(function_name, + "Inter-trial variability in Nondecision time", st0, 1); + + T_y_ref y_ref = y; + T_alpha_ref alpha_ref = a; + T_delta_ref delta_ref = v; + T_beta_ref beta_ref = w; + T_t0_ref t0_ref = t0; + T_sv_ref sv_ref = sv; + T_sw_ref sw_ref = sw; + T_st0_ref st0_ref = st0; + + check_positive_finite(function_name, "Random variable", value_of(y_ref)); + check_positive_finite(function_name, "Boundary separation", + value_of(alpha_ref)); + check_finite(function_name, "Drift rate", value_of(delta_ref)); + check_less(function_name, "A-priori bias", value_of(beta_ref), 1); + check_greater(function_name, "A-priori bias", value_of(beta_ref), 0); + check_nonnegative(function_name, "Nondecision time", value_of(t0_ref)); + check_finite(function_name, "Nondecision time", value_of(t0_ref)); + check_nonnegative(function_name, "Inter-trial variability in drift rate", + value_of(sv_ref)); + check_finite(function_name, "Inter-trial variability in drift rate", + value_of(sv_ref)); + check_bounded(function_name, "Inter-trial variability in A-priori bias", + value_of(sw_ref), 0, 1); + check_nonnegative(function_name, + "Inter-trial variability in Nondecision time", value_of(st0_ref)); + check_finite(function_name, "Inter-trial variability in Nondecision time", + value_of(st0_ref)); + + if (size_zero(y, a, v, w, t0) || size_zero(sv, sw, st0)) return 0; + + size_t N = max_size(y, a, v, w, t0, sv, sw, st0); + if (!N) return 0; + + scalar_seq_view y_vec(y_ref); + scalar_seq_view alpha_vec(alpha_ref); + scalar_seq_view delta_vec(delta_ref); + scalar_seq_view beta_vec(beta_ref); + scalar_seq_view t0_vec(t0_ref); + scalar_seq_view sv_vec(sv_ref); + scalar_seq_view sw_vec(sw_ref); + scalar_seq_view st0_vec(st0_ref); + size_t N_y_t0 = max_size(y, t0, st0); + + for (size_t i = 0; i < N_y_t0; ++i) { + if (y_vec[i] <= t0_vec[i]) { + std::stringstream msg; + msg << ", but must be greater than nondecision time = " << t0_vec[i]; + std::string msg_str(msg.str()); + throw_domain_error(function_name, "Random variable", y_vec[i], " = ", + msg_str.c_str()); + } + } + size_t N_beta_sw = max_size(w, sw); + for (size_t i = 0; i < N_beta_sw; ++i) { + if (beta_vec[i] - .5 * sw_vec[i] <= 0) { + std::stringstream msg; + msg << ", but must be smaller than 2*(A-priori bias) = " + << 2 * beta_vec[i]; + std::string msg_str(msg.str()); + throw_domain_error(function_name, + "Inter-trial variability in A-priori bias", sw_vec[i], + " = ", msg_str.c_str()); + } + if (beta_vec[i] + .5 * sw_vec[i] >= 1) { + std::stringstream msg; + msg << ", but must be smaller than 2*(1-A-priori bias) = " + << 2 * (1 - beta_vec[i]); + std::string msg_str(msg.str()); + throw_domain_error(function_name, + "Inter-trial variability in A-priori bias", sw_vec[i], + " = ", msg_str.c_str()); + } + } + + if (!include_summand::value) return 0; + + // abstol_wiener5 z.B. 1e-12 on normal scale + // T_partials_return error_bound = 1e-6; + // alpha in Skizze + T_partials_return error_bound_dens = 1e-6; // precision for + // density (fixed here, test with 1e-6 and 1e-2) + T_partials_return lerror_bound_dens = log(error_bound_dens); + T_partials_return error_bound = prec; // precision for + // derivatives (controllable by user) + T_partials_return lerror_bound = log(error_bound); // log(alpha) + T_partials_return abstol = 0.0; + T_partials_return reltol = .9 * error_bound; // eps_rel(Integration) + T_partials_return abstol_wiener5 = 1e-12; // eps_abs(wiener5) + T_partials_return labstol_wiener5 = log(abstol_wiener5); + // log(eps_abs(wiener5) + T_partials_return Meval = 6000; + T_partials_return dens = 0.0; + T_partials_return ld = 0.0; + operands_and_partials + ops_partials(y_ref, alpha_ref, delta_ref, beta_ref, t0_ref, sv_ref, + sw_ref, st0_ref); + + // calculate density and partials + for (size_t i = 0; i < N; i++) { + // Calculate 4-parameter model without inter-trial variabilities (if + // sv_vec[i] == 0) or 5-parameter model with inter-trial variability in + // drift rate (if sv_vec[i] != 0) + if (sw_vec[i] == 0 && st0_vec[i] == 0) { + const T_partials_return y_val = y_vec.val(i); + const T_partials_return alpha_val = alpha_vec.val(i); + const T_partials_return delta_val = delta_vec.val(i); + const T_partials_return beta_val = beta_vec.val(i); + const T_partials_return t0_val = t0_vec.val(i); + const T_partials_return sv_val = sv_vec.val(i); + + dens = internal::dwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, + sv_val, labstol_wiener5); + if (labstol_wiener5 > fabs(dens) + lerror_bound_dens - log(2)) + dens = internal::dwiener5(y_val - t0_val, alpha_val, delta_val, + beta_val, sv_val, fabs(dens) + lerror_bound_dens - log(2)); + ld += dens; + + // computation of derivative for t and precision check in order to give + // the value as deriv_t to edge1 and as -deriv_t to edge5 + T_partials_return deriv_t = internal::dtdwiener5(y_val - t0_val, + alpha_val, delta_val, beta_val, sv_val, labstol_wiener5); + if (labstol_wiener5 > log(fabs(deriv_t)) + dens + lerror_bound - log(2)) + deriv_t = internal::dtdwiener5(y_val - t0_val, alpha_val, delta_val, + beta_val, sv_val, log(fabs(deriv_t)) + dens + lerror_bound - log(4)); + + // computation of derivatives and precision checks + if (!is_constant_all::value) { + ops_partials.edge1_.partials_[i] = deriv_t; + } + if (!is_constant_all::value) { + T_partials_return deriv_a + = internal::dadwiener5(y_val - t0_val, alpha_val, delta_val, + beta_val, sv_val, labstol_wiener5, 0); + if (labstol_wiener5 > log(fabs(deriv_a)) + dens + lerror_bound - log(2)) + deriv_a = internal::dadwiener5( + y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, + log(fabs(deriv_a)) + dens + lerror_bound - log(4), 0); + ops_partials.edge2_.partials_[i] = deriv_a; + } + if (!is_constant_all::value) { + ops_partials.edge3_.partials_[i] = internal::dvdwiener5( + y_val - t0_val, alpha_val, delta_val, beta_val, sv_val); + } + if (!is_constant_all::value) { + T_partials_return deriv_w + = internal::dwdwiener5(y_val - t0_val, alpha_val, delta_val, + beta_val, sv_val, labstol_wiener5, 0); + if (labstol_wiener5 > log(fabs(deriv_w)) + dens + lerror_bound - log(2)) + deriv_w = internal::dwdwiener5( + y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, + log(fabs(deriv_w)) + dens + lerror_bound - log(4), 0); + ops_partials.edge4_.partials_[i] = deriv_w; + } + if (!is_constant_all::value) { + ops_partials.edge5_.partials_[i] = -deriv_t; + } + if (!is_constant_all::value) { + ops_partials.edge6_.partials_[i] = internal::dsvdwiener5( + y_val - t0_val, alpha_val, delta_val, beta_val, sv_val); + } + if (!is_constant_all::value) { + ops_partials.edge7_.partials_[i] = 0; + } + if (!is_constant_all::value) { + ops_partials.edge8_.partials_[i] = 0; + } + // Calculate 6-, or 7-parameter model + } else { + const T_partials_return y_val = y_vec.val(i); + const T_partials_return alpha_val = alpha_vec.val(i); + const T_partials_return delta_val = delta_vec.val(i); + const T_partials_return beta_val = beta_vec.val(i); + const T_partials_return t0_val = t0_vec.val(i); + const T_partials_return sv_val = sv_vec.val(i); + const T_partials_return sw_val = sw_vec.val(i); + const T_partials_return st0_val = st0_vec.val(i); + internal::my_params< + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return> + params = {y_val, alpha_val, delta_val, beta_val, t0_val, sv_val, + sw_val, st0_val, labstol_wiener5 - log(2)}; + int dim = (sw_val != 0) + (st0_val != 0); + check_positive(function_name, + "(Inter-trial variability in A-priori bias) + " + "(Inter-trial variability in nondecision time)", + dim); + + std::vector xmin(dim, 0); + std::vector xmax(dim, 1); + + if (st0_val) xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); + + dens = hcubature(internal::int_ddiff, void*>, ¶ms, + dim, xmin, xmax, Meval, abstol, reltol / 2); + if (labstol_wiener5 + > fabs(log(dens)) + log(.1) + lerror_bound_dens - log(2)) { + internal::my_params< + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return> + params_new_error + = {y_val, + alpha_val, + delta_val, + beta_val, + t0_val, + sv_val, + sw_val, + st0_val, + log(.1) + lerror_bound_dens - log(2) + log(fabs(dens))}; + dens = hcubature(internal::int_ddiff, void*>, + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, reltol); + } + ld += log(dens); + + // computation of derivative for t and precision check in order to give + // the value as deriv_t to edge1 and as -deriv_t to edge5 + T_partials_return deriv_t_7; + deriv_t_7 + = 1/dens*hcubature(internal::int_dtddiff, void*>, + ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); + if (labstol_wiener5 + > log(fabs(deriv_t_7)) + log(.1) + lerror_bound - log(2)) { + internal::my_params< + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return> + params_new_error + = {y_val, + alpha_val, + delta_val, + beta_val, + t0_val, + sv_val, + sw_val, + st0_val, + log(.1) + lerror_bound - log(4) + log(fabs(deriv_t_7))}; + deriv_t_7 + = 1/dens*hcubature(internal::int_dtddiff, void*>, + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, reltol / 2); + } + + // computation of derivatives and precision checks + T_partials_return deriv; + if (!is_constant_all::value) { + ops_partials.edge1_.partials_[i] = deriv_t_7; + } + if (!is_constant_all::value) { + deriv + = 1/dens*hcubature(internal::int_daddiff, void*>, + ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); + if (labstol_wiener5 + > log(fabs(deriv)) + log(.1) + lerror_bound - log(2)) { + internal::my_params< + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return> + params_new_error + = {y_val, + alpha_val, + delta_val, + beta_val, + t0_val, + sv_val, + sw_val, + st0_val, + log(.1) + lerror_bound - log(4) + log(fabs(deriv))}; + deriv = 1 / dens + * hcubature(internal::int_daddiff, void*>, + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, reltol / 2); + } + ops_partials.edge2_.partials_[i] = deriv; + } + if (!is_constant_all::value) { + deriv + = 1 / dens + * hcubature(internal::int_dvddiff, void*>, + ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); + if (labstol_wiener5 + > log(fabs(deriv)) + log(.1) + lerror_bound - log(2)) { + internal::my_params< + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return> + params_new_error + = {y_val, + alpha_val, + delta_val, + beta_val, + t0_val, + sv_val, + sw_val, + st0_val, + log(.1) + lerror_bound - log(2) + log(fabs(deriv))}; + deriv = 1 / dens + * hcubature(internal::int_dvddiff, void*>, + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, reltol / 2); + } + ops_partials.edge3_.partials_[i] = deriv; + } + if (!is_constant_all::value) { + deriv + = 1 / dens + * hcubature(internal::int_dwddiff, void*>, + ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); + if (labstol_wiener5 + > log(fabs(deriv)) + log(.1) + lerror_bound - log(2)) { + internal::my_params< + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return> + params_new_error + = {y_val, + alpha_val, + delta_val, + beta_val, + t0_val, + sv_val, + sw_val, + st0_val, + log(.1) + lerror_bound - log(4) + log(fabs(deriv))}; + deriv = 1 / dens + * hcubature(internal::int_dwddiff, void*>, + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, reltol / 2); + } + ops_partials.edge4_.partials_[i] = deriv; + } + if (!is_constant_all::value) { + ops_partials.edge5_.partials_[i] = -deriv_t_7; + } + if (!is_constant_all::value) { + deriv + = 1 / dens + * hcubature(internal::int_dsvddiff, void*>, + ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); + if (labstol_wiener5 + > log(fabs(deriv)) + log(.1) + lerror_bound - log(2)) { + internal::my_params< + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return> + params_new_error + = {y_val, + alpha_val, + delta_val, + beta_val, + t0_val, + sv_val, + sw_val, + st0_val, + log(.1) + lerror_bound - log(2) + log(fabs(deriv))}; + deriv + = 1 / dens + * hcubature(internal::int_dsvddiff, void*>, + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, reltol / 2); + } + ops_partials.edge6_.partials_[i] = deriv; + } + if (!is_constant_all::value) { + if (sw_val == 0) { + ops_partials.edge7_.partials_[i] = 0; + } else { + T_partials_return lower, upper, width, fl, fu; + + lower = beta_val - sw_val / 2; + lower = (0 > lower) ? 0 : lower; + upper = beta_val + sw_val / 2; + upper = (1 < upper) ? 1 : upper; + width = upper - lower; + + int dim_ = (st0_val != 0); + if (dim_ == 0) { + fl = exp(internal::dwiener5(y_val - t0_val, alpha_val, delta_val, + lower, sv_val, labstol_wiener5)); + fu = exp(internal::dwiener5(y_val - t0_val, alpha_val, delta_val, + upper, sv_val, labstol_wiener5)); + if (labstol_wiener5 > log(fabs(fl + fu) + log(sw_val) - log(2) + + lerror_bound - log(2))) { + fl = exp(internal::dwiener5(y_val - t0_val, alpha_val, delta_val, + lower, sv_val, + lerror_bound - log(2) + log(sw_val) + - log(2) + log(fabs(fl + fu)))); + fu = exp(internal::dwiener5(y_val - t0_val, alpha_val, delta_val, + upper, sv_val, + lerror_bound - log(2) + log(sw_val) + - log(2) + log(fabs(fl + fu)))); + } + deriv = 1 / width * 0.5 * (fl + fu); + } else { + internal::my_params2< + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return> + params_sw + = {y_val, alpha_val, delta_val, beta_val, + lower, upper, t0_val, sv_val, + 0, sw_val, st0_val, labstol_wiener5 - log(2)}; + deriv = hcubature( + internal::int_dswddiff, void*>, ¶ms_sw, + dim_, xmin, xmax, Meval, abstol, reltol / 2); + if (labstol_wiener5 + > log(fabs(deriv) + log(.1) + lerror_bound - log(2))) { + internal::my_params2< + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return> + params_new_error_sw + = {y_val, + alpha_val, + delta_val, + beta_val, + lower, + upper, + t0_val, + sv_val, + 0, + sw_val, + st0_val, + log(fabs(deriv)) + log(.1) + lerror_bound - log(2)}; + deriv = hcubature( + internal::int_dswddiff, void*>, + ¶ms_new_error_sw, dim_, xmin, xmax, Meval, abstol, + reltol / 2); + } + } + ops_partials.edge7_.partials_[i] = deriv / dens - 1 / sw_val; + } + } + if (!is_constant_all::value) { + T_partials_return f; + if (st0_val == 0) { + ops_partials.edge8_.partials_[i] = 0; + } else if (y_val - (t0_val + st0_val) <= 0) { + ops_partials.edge8_.partials_[i] = -1 / st0_val; + } else { + int dim_ = (sw_val != 0); + if (dim_ == 0) { + f = exp(internal::dwiener5(y_val - (t0_val + st0_val), alpha_val, + delta_val, beta_val, sv_val, + labstol_wiener5)); + if (labstol_wiener5 + > log(fabs(f) + log(st0_val) - log(2) + lerror_bound - log(2))) + f = exp(internal::dwiener5(y_val - (t0_val + st0_val), alpha_val, + delta_val, beta_val, sv_val, + lerror_bound - log(2) + log(st0_val) + - log(2) + log(fabs(f)))); + deriv = 1 / st0_val * f; + } else { + internal::my_params3< + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return> + params_st = {y_val, + alpha_val, + delta_val, + beta_val, + t0_val, + t0_val + st0_val, + sv_val, + sw_val, + st0_val, + 0, + labstol_wiener5 - log(2)}; + deriv = hcubature( + internal::int_dst0ddiff, void*>, ¶ms_st, + dim_, xmin, xmax, Meval, abstol, reltol / 2); + if (labstol_wiener5 + > log(fabs(deriv) + log(.1) + lerror_bound - log(2))) { + internal::my_params3< + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return, + T_partials_return, T_partials_return> + params_new_error_st + = {y_val, + alpha_val, + delta_val, + beta_val, + t0_val, + t0_val + st0_val, + sv_val, + sw_val, + st0_val, + 0, + log(fabs(deriv)) + log(.1) + lerror_bound - log(2)}; + deriv = hcubature( + internal::int_dst0ddiff, void*>, + ¶ms_new_error_st, dim_, xmin, xmax, Meval, abstol, + reltol / 2); + } + } + ops_partials.edge8_.partials_[i] = -1 / st0_val + deriv / dens; + } + } + std::vector().swap(xmin); + std::vector().swap(xmax); + } + } + + return ops_partials.build(ld); +} +//----------------------------------------------- + + +} // namespace internal + + + + + + +/** \ingroup prob_dists + * The log of the first passage time density function for a (Wiener) + * drift diffusion model with up to 7 parameters, where + * \f$y\in \mathbb{R}_{+}\f$ is the reacion time, \f$a \in \mathbb{R}_{+}\f$ + * the boundary separation, \f$v \in \mathbb{R}\f$ the drifte rate, + * \f$w \in (0, 1)\f$ the relative starting point (aka a-priori bias), + * \f$t_0 \in \mathbb{R}_{\geq 0}\f$ the non-decision time, \f$s_v \in + * \mathbb{R}_{\geq 0}\f$ the inter-trial variability of the drift rate, + * \f$s_w \in [0, 1)\f$ the inter-trial variability of the relative starting + * point, and \f$s_{t_0} \in \mathbb{R}_{\geq 0}\f$ the inter-trial variability of + * the non-decision time. + * + * + \f{eqnarray*}{ + y &\sim& \text{wiener_full}(a,v,w,t_0,s_v,s_w,s_{t_0}) \\ + \log(p(y|a,v,w,t_0,s_v,s_w,s_{t_0})) &=& \log(\frac{1}{s_{t_0}} + \int_{t_0}^{t_o + s_{t_0}} \frac{1}{s_{w}}\int_{w -0.5s_w}^{w + 0.5s_{w}} + \int_{-\infty}^{\infty} p_3(y-\tau_0|a,\nu,\omega) \\ + &&\times\frac{1}{\sqrt{2\pi s_\nu^2}} + \mathbb{e}^{-\frac{(\nu-v)^2}{2s_\nu^2}} \ d\nu \ d\omega \ d\tau_0) \\ + &=& \log(\frac{1}{s_{t_0}} + \int_{t_0}^{t_o + s_{t_0}} \frac{1}{s_{w}}\int_{w -0.5s_w}^{w + 0.5s_{w}} + M \times p_3(y-\tau_0|a,v,\omega) \ d\omega \ d\tau_0), + \f} + * where \f$M\f$ and \f$p_3()\f$ are defined, by using \f$t:=y-\tau_0\f$, as + \f{eqnarray*}{ + M &:=& \frac{1}{\sqrt{1+s^2_v t}} \mathbb{e}^{av\omega+\frac{v^2t}{2}+\frac{s^2_v a^2 \omega^2-2av\omega-v^2t}{2(1+s^2_vt)}} \text{ and} \\ + p_3(t|a,v,w) &:=& \frac{1}{a^2} \mathbb{e}^{-a v w -\frac{v^2t}{2}} f(\frac{t}{a^2}|0,1,w), + \f} + * where \f$f(t^*=\frac{t}{a^2}|0,1,w)\f$ has two forms + \f{eqnarray*}{ + f_l(t^*|0,1,w) &=& \sum_{k=1}^{\infty} k\pi \mathbb{e}^{-\frac{k^2\pi^2t^*}{2}} + \sin{(k \pi w)}\text{ and} \\ + f_s(t^*|0,1,w) &=& \sum_{k=-\infty}^{\infty} \frac{1}{\sqrt{2\pi (t^*)^3}} (w+2k) + \mathbb{e}^{-\frac{(w+2k)^2}{2t^*}}, + \f} + * which are selected depending on the number of components \f$k\f$, needed to + * guarantee a certain precision. + * + * Note that the parametrization for non-decision time and relative starting point is as follows: + * \c t0 is the lower bound of the variability interval; + * \c w is the mean of the variability interval. + * + * See \b Details below for more details on how to use \c wiener_full_lpdf(). + * + * @tparam T_y type of scalar + * @tparam T_alpha type of boundary + * @tparam T_delta type of drift rate + * @tparam T_beta type of relative starting point + * @tparam T_t0 type of non-decision time + * @tparam T_sv type of inter-trial variability of drift rate + * @tparam T_sw type of inter-trial variability of relative starting point + * @tparam T_st0 type of inter-trial variability of non-decision time + * + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param v The drift rate + * @param w The relative starting point + * @param t0 The non-decision time + * @param sv The inter-trial variability of the drift rate + * @param sw The inter-trial variability of the relative starting point + * @param st0 The inter-trial variability of the non-decision time + * @return The log of the Wiener first passage time density with + * the specified arguments for upper boundary responses + * @throw std::domain_error if non-decision time \c t0 is greater than reaction time \c y. + * @throw std::domain_error if \c 1-sw/2 is smaller than or equal to \c w. + * @throw std::domain_error if \c sw/2 is larger than or equal to \c w. + * + * + * + * **Details** + * + * The function can be called by + @code + target += wiener_full_lpdf(y, a, v, w, t0, sv, sw, st0); + @endcode + * or + @code + y ~ wiener_full(a, v, w, t0, sv, sw, st0); + @endcode + * + * By default \c wiener_full_lpdf() gives the log of the + * Wiener first-passage time probability density function for the \e upper response + * boundary. To use the \e lower response boundary \c v and \c w must be changed to + * \c -v and \c (1-w), respectively. + * + * \c sv, \c sw, \c st0, and \c t0 can be set to zero, indicating no inter-trial + * variability in \f$v\f$, no inter-trial variability in \f$w\f$, no + * inter-trial variability in \f$t_0\f$, and no non-decision time, respectively. + * If \c t0 is zero, \c st0 must be zero as well. For example, when no inter-trial + * variability for the relative starting point is needed one can write something like: + @code + target += wiener_full_lpdf(y, a, v, w, t0, sv, 0, st0) + @endcode + * If no inter-trial variability is needed at all one can write something like: + @code + target += wiener_full_lpdf(y, a, v, w, t0, 0, 0, 0) + @endcode + * If for some reason no non-decision time is assumed one can write something like: + @code + target += wiener_full_lpdf(y, a, v, w, 0, sv, sw, 0) + @endcode + * + * To also control the precision in the estimation of the partial derivatives, + * call the function \c wiener_full_prec_lpdf(), analogously: + @code + target += wiener_full__prec_lpdf(y, a, v, w, t0, sv, sw, st0, precision); + @endcode + * + * + * **References** + * - Blurton, S. P., Kesselmeier, M., & Gondan, M. (2017). The first-passage + * time distribution for the diffusion model with variable drift. + * *Journal of Mathematical Psychology, 76*, 7–12. + * https://doi.org/10.1016/j.jmp.2016.11.003 + * - Foster, K., & Singmann, H. (2021). Another Approximation of the First-Passage + * Time Densities for the Ratcliff Diffusion Decision Model. + * *arXiv preprint arXiv:2104.01902* + * - Gondan, M., Blurton, S. P., & Kesselmeier, M. (2014). Even faster and even + * more accurate first-passage time densities and distributions for the Wiener + * diffusion model. *Journal of Mathematical Psychology, 60*, 20–22. + * https://doi.org/10.1016/j.jmp.2014.05.002 + * - Hartmann, R., & Klauer, K. C. (2021). Partial derivatives for the + * first-passage time distribution in Wiener diffusion models. + * *Journal of Mathematical Psychology, 103*, 102550. + * https://doi.org/10.1016/j.jmp.2021.102550 + * - Navarro, D. J., & Fuss, I. G. (2009). Fast and accurate calculations for + * first-passage times in Wiener diffusion models. + * *Journal of Mathematical Psychology, 53*(4), 222–230. + * https://doi.org/10.1016/j.jmp.2009.02.003 + */ + +template +inline return_type_t +wiener_full_lpdf(const T_y& y, const T_alpha& a, const T_delta& v, + const T_beta& w, const T_t0& t0, const T_sv& sv, + const T_sw& sw, const T_st0& st0) { + double precision = 1e-4; + + return internal::wiener_full_prec_impl_lpdf( + "wiener_full_lpdf", y, a, v, w, t0, sv, sw, st0, precision); +} + +template +inline return_type_t +wiener_full_lpdf(const T_y& y, const T_alpha& a, const T_delta& v, + const T_beta& w, const T_t0& t0, const T_sv& sv, + const T_sw& sw, const T_st0& st0) { + double precision = 1e-4; + + return internal::wiener_full_prec_impl_lpdf("wiener_full_lpdf", + y, a, v, w, t0, sv, sw, st0, precision); +} + + + + /** \ingroup prob_dists + * The log of the first passage time density function for a (Wiener) + * drift diffusion model with up to 7 parameters with the option + * to control for the precision in the estimation of the partial derivatives. + * + * For \b Details see \c wiener_full_lpdf(). The usage and behavior of these + * functions are the same excpet of the control over the precision. + */ + +template +inline return_type_t +wiener_full_prec_lpdf(const T_y& y, const T_alpha& a, const T_delta& v, + const T_beta& w, const T_t0& t0, const T_sv& sv, + const T_sw& sw, const T_st0& st0, const double& prec) { + return internal::wiener_full_prec_impl_lpdf( + "wiener_full_prec_lpdf", y, a, v, w, t0, sv, sw, st0, prec); +} + +template +inline return_type_t +wiener_full_prec_lpdf(const T_y& y, const T_alpha& a, const T_delta& v, + const T_beta& w, const T_t0& t0, const T_sv& sv, + const T_sw& sw, const T_st0& st0, const double& prec) { + return internal::wiener_full_prec_impl_lpdf("wiener_full_prec_lpdf", + y, a, v, w, t0, sv, sw, st0, prec); +} + + + +} // namespace math +} // namespace stan +#endif diff --git a/stan/math/rev/functor/operands_and_partials.hpp b/stan/math/rev/functor/operands_and_partials.hpp index 908d5803174..faa31b02b6b 100644 --- a/stan/math/rev/functor/operands_and_partials.hpp +++ b/stan/math/rev/functor/operands_and_partials.hpp @@ -34,7 +34,8 @@ class ops_partials_edge { : partial_(0), partials_(partial_), operand_(op) {} private: - template + template friend class stan::math::operands_and_partials; var operand_; static constexpr int size() noexcept { return 1; } @@ -109,15 +110,22 @@ inline void update_adjoints(StdVec1& x, const Vec2& y, const vari& z) { * @tparam Op3 type of the third operand * @tparam Op4 type of the fourth operand * @tparam Op5 type of the fifth operand + * @tparam Op6 type of the sixth operand + * @tparam Op7 type of the seventh operand + * @tparam Op8 type of the eighth operand */ -template -class operands_and_partials { +template +class operands_and_partials { public: internal::ops_partials_edge> edge1_; internal::ops_partials_edge> edge2_; internal::ops_partials_edge> edge3_; internal::ops_partials_edge> edge4_; internal::ops_partials_edge> edge5_; + internal::ops_partials_edge> edge6_; + internal::ops_partials_edge> edge7_; + internal::ops_partials_edge> edge8_; explicit operands_and_partials(const Op1& o1) : edge1_(o1) {} operands_and_partials(const Op1& o1, const Op2& o2) @@ -130,6 +138,35 @@ class operands_and_partials { operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3, const Op4& o4, const Op5& o5) : edge1_(o1), edge2_(o2), edge3_(o3), edge4_(o4), edge5_(o5) {} + operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3, + const Op4& o4, const Op5& o5, const Op6& o6) + : edge1_(o1), + edge2_(o2), + edge3_(o3), + edge4_(o4), + edge5_(o5), + edge6_(o6) {} + operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3, + const Op4& o4, const Op5& o5, const Op6& o6, + const Op7& o7) + : edge1_(o1), + edge2_(o2), + edge3_(o3), + edge4_(o4), + edge5_(o5), + edge6_(o6), + edge7_(o7) {} + operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3, + const Op4& o4, const Op5& o5, const Op6& o6, + const Op7& o7, const Op8& o8) + : edge1_(o1), + edge2_(o2), + edge3_(o3), + edge4_(o4), + edge5_(o5), + edge6_(o6), + edge7_(o7), + edge8_(o8) {} /** \ingroup type_trait * Build the node to be stored on the autodiff graph. @@ -145,29 +182,41 @@ class operands_and_partials { * @return the node to be stored in the expression graph for autodiff */ var build(double value) { - return make_callback_var( - value, [operand1 = edge1_.operand(), partial1 = edge1_.partial(), - operand2 = edge2_.operand(), partial2 = edge2_.partial(), - operand3 = edge3_.operand(), partial3 = edge3_.partial(), - operand4 = edge4_.operand(), partial4 = edge4_.partial(), - operand5 = edge5_.operand(), - partial5 = edge5_.partial()](const auto& vi) mutable { - if (!is_constant::value) { - internal::update_adjoints(operand1, partial1, vi); - } - if (!is_constant::value) { - internal::update_adjoints(operand2, partial2, vi); - } - if (!is_constant::value) { - internal::update_adjoints(operand3, partial3, vi); - } - if (!is_constant::value) { - internal::update_adjoints(operand4, partial4, vi); - } - if (!is_constant::value) { - internal::update_adjoints(operand5, partial5, vi); - } - }); + return make_callback_var(value, [ + operand1 = edge1_.operand(), partial1 = edge1_.partial(), + operand2 = edge2_.operand(), partial2 = edge2_.partial(), + operand3 = edge3_.operand(), partial3 = edge3_.partial(), + operand4 = edge4_.operand(), partial4 = edge4_.partial(), + operand5 = edge5_.operand(), partial5 = edge5_.partial(), + operand6 = edge6_.operand(), partial6 = edge6_.partial(), + operand7 = edge7_.operand(), partial7 = edge7_.partial(), + operand8 = edge8_.operand(), partial8 = edge8_.partial() + ](const auto& vi) mutable { + if (!is_constant::value) { + internal::update_adjoints(operand1, partial1, vi); + } + if (!is_constant::value) { + internal::update_adjoints(operand2, partial2, vi); + } + if (!is_constant::value) { + internal::update_adjoints(operand3, partial3, vi); + } + if (!is_constant::value) { + internal::update_adjoints(operand4, partial4, vi); + } + if (!is_constant::value) { + internal::update_adjoints(operand5, partial5, vi); + } + if (!is_constant::value) { + internal::update_adjoints(operand6, partial6, vi); + } + if (!is_constant::value) { + internal::update_adjoints(operand7, partial7, vi); + } + if (!is_constant::value) { + internal::update_adjoints(operand8, partial8, vi); + } + }); } }; @@ -186,7 +235,8 @@ class ops_partials_edge> { operands_(op.begin(), op.end()) {} private: - template + template friend class stan::math::operands_and_partials; Op operands_; @@ -207,7 +257,8 @@ class ops_partials_edge> { operands_(ops) {} private: - template + template friend class stan::math::operands_and_partials; arena_t operands_; inline int size() const noexcept { return this->operands_.size(); } @@ -223,12 +274,13 @@ class ops_partials_edge, require_eigen_t> { broadcast_array partials_vec_; // For multivariate explicit ops_partials_edge(const var_value& ops) : partials_( - plain_type_t::Zero(ops.vi_->rows(), ops.vi_->cols())), + plain_type_t::Zero(ops.vi_->rows(), ops.vi_->cols())), partials_vec_(partials_), operands_(ops) {} private: - template + template friend class stan::math::operands_and_partials; var_value operands_; @@ -256,7 +308,8 @@ class ops_partials_edge>> { } private: - template + template friend class stan::math::operands_and_partials; Op operands_; @@ -286,7 +339,8 @@ class ops_partials_edge>> { } private: - template + template friend class stan::math::operands_and_partials; Op operands_; inline int size() const noexcept { @@ -311,7 +365,8 @@ class ops_partials_edge>, } private: - template + template friend class stan::math::operands_and_partials; std::vector, arena_allocator>> operands_; diff --git a/test/unit/math/prim/functor/operands_and_partials_test.cpp b/test/unit/math/prim/functor/operands_and_partials_test.cpp index 83a7eb031d4..6a1b4e9845a 100644 --- a/test/unit/math/prim/functor/operands_and_partials_test.cpp +++ b/test/unit/math/prim/functor/operands_and_partials_test.cpp @@ -7,8 +7,8 @@ TEST(MathMetaPrim, OperandsAndPartials) { operands_and_partials o1(1.0); operands_and_partials o2(2.0, 3.0, 4.0, 5.0); - // This is size 10 because of the two empty broadcast arrays in each edge - EXPECT_EQ(10, sizeof(o2)); + // This is size 16 because of the two empty broadcast arrays in each edge + EXPECT_EQ(16, sizeof(o2)); EXPECT_FLOAT_EQ(27.1, o1.build(27.1)); } diff --git a/test/unit/math/prim/prob/wiener_full_prec_test.cpp b/test/unit/math/prim/prob/wiener_full_prec_test.cpp new file mode 100644 index 00000000000..5e7f6e942e2 --- /dev/null +++ b/test/unit/math/prim/prob/wiener_full_prec_test.cpp @@ -0,0 +1,263 @@ +#include +#include +#include +#include + +#include +#include + +// signature: wiener_full_prec_lpdf(y, a, v, w, t0, sv, sw, st0, precision); + +// CHECKING FOR (IN)VALID INPUT + +TEST(mathPrimScalProbWienerFullPrecScal, valid) { + using stan::math::wiener_full_prec_lpdf; + using stan::math::INFTY; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, + sw = 0.2, st0 = 0.1; + EXPECT_NO_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, sw, st0, 1e-4)); + rt = 5; a = 1; v = 1; w = 0.5; t0 = 0.0; sv = 0.0; sw = 0.0; st0 = 0.0; + EXPECT_NO_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, sw, st0, 1e-4)); +} + +// rt +TEST(mathPrimScalProbWienerFullPrecScal, invalid_rt) { + using stan::math::wiener_full_prec_lpdf; + using stan::math::INFTY; + double a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_prec_lpdf(0, a, v, w, t0, sv, + sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(-1, a, v, w, t0, sv, + sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(INFTY, a, v, w, t0, sv, + sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(-INFTY, a, v, w, t0, sv, + sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(NAN, a, v, w, t0, sv, + sw, st0, 1e-4), std::domain_error); +} + + +// a +TEST(mathPrimScalProbWienerFullPrecScal, invalid_a) { + using stan::math::wiener_full_prec_lpdf; + using stan::math::INFTY; + double rt = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_prec_lpdf(rt, 0, v, w, t0, sv, + sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, -1, v, w, t0, sv, + sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, INFTY, v, w, t0, sv, + sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, -INFTY, v, w, t0, sv, + sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, NAN, v, w, t0, sv, + sw, st0, 1e-4), std::domain_error); +} + + +// v +TEST(mathPrimScalProbWienerFullPrecScal, invalid_v) { + using stan::math::wiener_full_prec_lpdf; + using stan::math::INFTY; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, + sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, INFTY, w, t0, sv, + sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, -INFTY, w, t0, sv, + sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, NAN, w, t0, sv, + sw, st0, 1e-4), std::domain_error); +} + + +// w +TEST(mathPrimScalProbWienerFullPrecScal, invalid_w) { + using stan::math::wiener_full_prec_lpdf; + using stan::math::INFTY; + double rt = 1, a = 1, v = -1, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, -0.1, t0, sv, + sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 0, t0, sv, + sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 1, t0, sv, + sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 1.1, t0, sv, + sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, INFTY, t0, sv, + sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, -INFTY, t0, sv, + sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, NAN, t0, sv, + sw, st0, 1e-4), std::domain_error); +} + + +// t0 +TEST(mathPrimScalProbWienerFullPrecScal, invalid_t0) { + using stan::math::wiener_full_prec_lpdf; + using stan::math::INFTY; + double rt = 1, a = 1, v = -1, w = 0.5, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, 2, sv, sw, + st0, 1e-4), std::domain_error); // rt must be greater than t0 + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, + -1, sv, sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, + INFTY, sv, sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, + -INFTY, sv, sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, + NAN, sv, sw, st0, 1e-4), std::domain_error); +} + + +// sv +TEST(mathPrimScalProbWienerFullPrecScal, invalid_sv) { + using stan::math::wiener_full_prec_lpdf; + using stan::math::INFTY; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, + -1, sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, + INFTY, sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, + -INFTY, sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, + NAN, sw, st0, 1e-4), std::domain_error); +} + + +// sw +TEST(mathPrimScalProbWienerFullPrecScal, invalid_sw) { + using stan::math::wiener_full_prec_lpdf; + using stan::math::INFTY; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, + -1, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 0.8, t0, sv, 0.5, st0, + 1e-4), std::domain_error); // sw must be smaller than 2*(1-w) + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 0.3, t0, sv, 0.7, st0, + 1e-4), std::domain_error); // sw must be smaller than 2*w + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, + INFTY, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, + -INFTY, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, + NAN, st0, 1e-4), std::domain_error); +} + + +// st0 +TEST(mathPrimScalProbWienerFullPrecScal, invalid_st0) { + using stan::math::wiener_full_prec_lpdf; + using stan::math::INFTY; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2; + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, + sw, -1, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, + sw, INFTY, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, + sw, -INFTY, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, + sw, NAN, 1e-4), std::domain_error); +} + + +// CHECK THAT ALL VALID SCALAR TYPES ARE ACCEPTED +template +void check_scalar_types(F& f, double value, double res, double deriv) { + // - f: Function with a single parameter exposed, all others + // have to be scalars + // - value: value to be used for the parameter + // - res: expected result of calling `f` with `value` + // - deriv: expected result of partial of f with respect to the + // parameter in `value` + using stan::math::var; + double err_tol = 2e-6; + + // type double + EXPECT_NEAR(f(value), res, err_tol); + + // type var with derivative + var value_var = value; + var result_var = f(value_var); + result_var.grad(); + EXPECT_NEAR(value_of(result_var), res, err_tol); + EXPECT_NEAR(value_var.adj(), deriv, err_tol); +} + +TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { + // tests all parameter types individually, with other parameters + // set to double + using stan::math::wiener_full_prec_lpdf; + double err_tol = 2e-6; + + std::vector rt {1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector a {1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector v {1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector w {0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; + std::vector t0 {0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0}; + std::vector sv {0.1, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0}; + std::vector sw {0.1, 0.1, 0, 0.1, 0, 0.1, 0, 0, 0}; + std::vector st0 {0.1, 0, 0.1, 0.1, 0, 0, 0.1, 0, 0}; + + std::vector result {-2.426204, -2.710348, -2.422505, -2.422795, + -2.70665, -2.706812, -2.419095, -2.703112, + -3.790072}; + std::vector drt {-5.437337, -5.436798, -5.437332, -5.434799, + -5.436791, -5.434801, -5.434802, -5.434802, + -5.434802}; + std::vector da { 5.857318, 6.395031, 5.856484, 5.858549, + 6.394195, 6.396512, 5.857722, 6.395684, + 8.369604}; + std::vector dv {-0.2428443, -0.2967977, -0.2436664, -0.2446629, + -0.297619, -0.2991696, -0.2454931, -0.3, -0.5}; + std::vector dw {-0.9891369, -0.9887305, -0.9973428, -0.9915453, + -0.9969335, -0.991674, -0.9997794, -0.9999097, + -0.9999953}; + std::vector dt0 { 5.437337, 5.436798, 5.437332, 5.434799, + 5.436791, 5.434801, 5.434802, 5.434802, + 5.434802}; + std::vector dsv {-0.06793703, -0.07047449, -0.06797882, 0.0, + -0.07050737, 0.0, 0.0, 0.0, 0.0}; + std::vector dsw {-0.07406705, -0.07407386, 0.0, -0.07410901, 0.0, + -0.07410686, 0.0, 0.0, 0.0}; + std::vector dst0 { 2.963915, 0.0, 2.963912, 2.962338, 0.0, + 0.0, 2.96234, 0.0, 0.0}; + + for (int i = 0; i < result.size(); i++) { + // rt + auto f_rt = [=](auto value) {return wiener_full_prec_lpdf(value, a[i], + v[i], w[i], t0[i], sv[i], sw[i], st0[i], 1e-6);}; + check_scalar_types(f_rt, rt[i], result[i], drt[i]); + // a + auto f_a = [=](auto value) {return wiener_full_prec_lpdf(rt[i], value, + v[i], w[i], t0[i], sv[i], sw[i], st0[i], 1e-6);}; + check_scalar_types(f_a, a[i], result[i], da[i]); + // v + auto f_v = [=](auto value) {return wiener_full_prec_lpdf(rt[i], a[i], + value, w[i], t0[i], sv[i], sw[i], st0[i], 1e-6);}; + check_scalar_types(f_v, v[i], result[i], dv[i]); + // w + auto f_w = [=](auto value) {return wiener_full_prec_lpdf(rt[i], a[i], + v[i], value, t0[i], sv[i], sw[i], st0[i], 1e-6);}; + check_scalar_types(f_w, w[i], result[i], dw[i]); + // t0 + auto f_t0 = [=](auto value) {return wiener_full_prec_lpdf(rt[i], a[i], + v[i], w[i], value, sv[i], sw[i], st0[i], 1e-6);}; + check_scalar_types(f_t0, t0[i], result[i], dt0[i]); + // sv + auto f_sv = [=](auto value) {return wiener_full_prec_lpdf(rt[i], a[i], + v[i], w[i], t0[i], value, sw[i], st0[i], 1e-6);}; + check_scalar_types(f_sv, sv[i], result[i], dsv[i]); + // sw + auto f_sw = [=](auto value) {return wiener_full_prec_lpdf(rt[i], a[i], + v[i], w[i], t0[i], sv[i], value, st0[i], 1e-6);}; + check_scalar_types(f_sw, sw[i], result[i], dsw[i]); + // st0 + auto f_st0 = [=](auto value) {return wiener_full_prec_lpdf(rt[i], a[i], + v[i], w[i], t0[i], sv[i], sw[i], value, 1e-6);}; + check_scalar_types(f_st0, st0[i], result[i], dst0[i]); + } +} + diff --git a/test/unit/math/prim/prob/wiener_full_test.cpp b/test/unit/math/prim/prob/wiener_full_test.cpp new file mode 100644 index 00000000000..2ae9a6228c6 --- /dev/null +++ b/test/unit/math/prim/prob/wiener_full_test.cpp @@ -0,0 +1,263 @@ +#include +#include +#include +#include + +#include +#include + +// signature: wiener_full_lpdf(y, a, v, w, t0, sv, sw, st0); + +// CHECKING FOR (IN)VALID INPUT + +TEST(mathPrimScalProbWienerFullScal, valid) { + using stan::math::wiener_full_lpdf; + using stan::math::INFTY; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, + sw = 0.2, st0 = 0.1; + EXPECT_NO_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, sw, st0)); + rt = 5; a = 1; v = 1; w = 0.5; t0 = 0.0; sv = 0.0; sw = 0.0; st0 = 0.0; + EXPECT_NO_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, sw, st0)); +} + +// rt +TEST(mathPrimScalProbWienerFullScal, invalid_rt) { + using stan::math::wiener_full_lpdf; + using stan::math::INFTY; + double a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(0, a, v, w, t0, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(-1, a, v, w, t0, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(INFTY, a, v, w, t0, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(-INFTY, a, v, w, t0, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(NAN, a, v, w, t0, sv, + sw, st0), std::domain_error); +} + + +// a +TEST(mathPrimScalProbWienerFullScal, invalid_a) { + using stan::math::wiener_full_lpdf; + using stan::math::INFTY; + double rt = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, 0, v, w, t0, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, -1, v, w, t0, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, INFTY, v, w, t0, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, -INFTY, v, w, t0, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, NAN, v, w, t0, sv, + sw, st0), std::domain_error); +} + + +// v +TEST(mathPrimScalProbWienerFullScal, invalid_v) { + using stan::math::wiener_full_lpdf; + using stan::math::INFTY; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, + sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, INFTY, w, t0, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, -INFTY, w, t0, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, NAN, w, t0, sv, + sw, st0), std::domain_error); +} + + +// w +TEST(mathPrimScalProbWienerFullScal, invalid_w) { + using stan::math::wiener_full_lpdf; + using stan::math::INFTY; + double rt = 1, a = 1, v = -1, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, v, -0.1, t0, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, 0, t0, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, 1, t0, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, 1.1, t0, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, INFTY, t0, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, -INFTY, t0, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, NAN, t0, sv, + sw, st0), std::domain_error); +} + + +// t0 +TEST(mathPrimScalProbWienerFullScal, invalid_t0) { + using stan::math::wiener_full_lpdf; + using stan::math::INFTY; + double rt = 1, a = 1, v = -1, w = 0.5, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, 2, sv, + sw, st0), std::domain_error); // rt must be greater than t0 + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, -1, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, INFTY, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, -INFTY, sv, + sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, NAN, sv, + sw, st0), std::domain_error); +} + + +// sv +TEST(mathPrimScalProbWienerFullScal, invalid_sv) { + using stan::math::wiener_full_lpdf; + using stan::math::INFTY; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, + t0, -1, sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, + t0, INFTY, sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, + t0, -INFTY, sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, + t0, NAN, sw, st0), std::domain_error); +} + + +// sw +TEST(mathPrimScalProbWienerFullScal, invalid_sw) { + using stan::math::wiener_full_lpdf; + using stan::math::INFTY; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, + -1, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, 0.8, t0, sv, + 0.5, st0), std::domain_error); // sw must be smaller than 2*(1-w) + EXPECT_THROW(wiener_full_lpdf(rt, a, v, 0.3, t0, sv, + 0.7, st0), std::domain_error); // sw must be smaller than 2*w + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, + INFTY, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, + -INFTY, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, + NAN, st0), std::domain_error); +} + + +// st0 +TEST(mathPrimScalProbWienerFullScal, invalid_st0) { + using stan::math::wiener_full_lpdf; + using stan::math::INFTY; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2; + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, + sw, -1), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, + sw, INFTY), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, + sw, -INFTY), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, + sw, NAN), std::domain_error); +} + + +// CHECK THAT ALL VALID SCALAR TYPES ARE ACCEPTED +template +void check_scalar_types(F& f, double value, double res, double deriv) { + // - f: Function with a single parameter exposed, all others + // have to be scalars + // - value: value to be used for the parameter + // - res: expected result of calling `f` with `value` + // - deriv: expected result of partial of f with respect to + // the parameter in `value` + using stan::math::var; + double err_tol = 2e-4; + + // type double + EXPECT_NEAR(f(value), res, err_tol); + + // type var with derivative + var value_var = value; + var result_var = f(value_var); + result_var.grad(); + EXPECT_NEAR(value_of(result_var), res, err_tol); + EXPECT_NEAR(value_var.adj(), deriv, err_tol); +} + +TEST(ProbWienerFull, wiener_full_all_scalar) { + // tests all parameter types individually, with other + // parameters set to double + using stan::math::wiener_full_lpdf; + + std::vector rt {1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector a {1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector v {1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector w {0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; + std::vector t0 {0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0}; + std::vector sv {0.1, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0}; + std::vector sw {0.1, 0.1, 0, 0.1, 0, 0.1, 0, 0, 0}; + std::vector st0 {0.1, 0, 0.1, 0.1, 0, 0, 0.1, 0, 0}; + + std::vector result {-2.426204, -2.710348, -2.422505, -2.422795, + -2.70665, -2.706812, -2.419095, -2.703112, + -3.790072}; + std::vector drt {-5.437337, -5.436798, -5.437332, -5.434799, + -5.436791, -5.434801, -5.434802, -5.434802, + -5.434802}; + std::vector da { 5.857318, 6.395031, 5.856484, 5.858549, + 6.394195, 6.396512, 5.857722, 6.395684, + 8.369604}; + std::vector dv {-0.2428443, -0.2967977, -0.2436664, -0.2446629, + -0.297619, -0.2991696, -0.2454931, -0.3, -0.5}; + std::vector dw {-0.9891369, -0.9887305, -0.9973428, -0.9915453, + -0.9969335, -0.991674, -0.9997794, -0.9999097, + -0.9999953}; + std::vector dt0 { 5.437337, 5.436798, 5.437332, 5.434799, + 5.436791, 5.434801, 5.434802, 5.434802, + 5.434802}; + std::vector dsv {-0.06793703, -0.07047449, -0.06797882, 0.0, + -0.07050737, 0.0, 0.0, 0.0, 0.0}; + std::vector dsw {-0.07406705, -0.07407386, 0.0, -0.07410901, 0.0, + -0.07410686, 0.0, 0.0, 0.0}; + std::vector dst0 { 2.963915, 0.0, 2.963912, 2.962338, 0.0, + 0.0, 2.96234, 0.0, 0.0}; + + + for (int i = 0; i < result.size(); i++) { + // rt + auto f_rt = [=](auto value) {return wiener_full_lpdf(value, a[i], v[i], + w[i], t0[i], sv[i], sw[i], st0[i]);}; + check_scalar_types(f_rt, rt[i], result[i], drt[i]); + // a + auto f_a = [=](auto value) {return wiener_full_lpdf(rt[i], value, v[i], + w[i], t0[i], sv[i], sw[i], st0[i]);}; + check_scalar_types(f_a, a[i], result[i], da[i]); + // v + auto f_v = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], value, + w[i], t0[i], sv[i], sw[i], st0[i]);}; + check_scalar_types(f_v, v[i], result[i], dv[i]); + // w + auto f_w = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], + value, t0[i], sv[i], sw[i], st0[i]);}; + check_scalar_types(f_w, w[i], result[i], dw[i]); + // t0 + auto f_t0 = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], + w[i], value, sv[i], sw[i], st0[i]);}; + check_scalar_types(f_t0, t0[i], result[i], dt0[i]); + // sv + auto f_sv = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], + w[i], t0[i], value, sw[i], st0[i]);}; + check_scalar_types(f_sv, sv[i], result[i], dsv[i]); + // sw + auto f_sw = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], + w[i], t0[i], sv[i], value, st0[i]);}; + check_scalar_types(f_sw, sw[i], result[i], dsw[i]); + // st0 + auto f_st0 = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], + w[i], t0[i], sv[i], sw[i], value);}; + check_scalar_types(f_st0, st0[i], result[i], dst0[i]); + } +} + diff --git a/test/unit/math/rev/functor/operands_and_partials_test.cpp b/test/unit/math/rev/functor/operands_and_partials_test.cpp index 7d22f99a3d9..33627460be8 100644 --- a/test/unit/math/rev/functor/operands_and_partials_test.cpp +++ b/test/unit/math/rev/functor/operands_and_partials_test.cpp @@ -10,7 +10,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsScal) { double d1; operands_and_partials o3(d1); - EXPECT_EQ(10, sizeof(o3)); + EXPECT_EQ(16, sizeof(o3)); var v1 = var(0.0); @@ -35,7 +35,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsVec) { vector_d d_vec(4); operands_and_partials o3(d_vec); - EXPECT_EQ(10, sizeof(o3)); + EXPECT_EQ(16, sizeof(o3)); vector_v v_vec(4); var v1 = var(0.0); @@ -72,7 +72,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsStdVec) { std::vector d_vec(4); operands_and_partials> o3(d_vec); - EXPECT_EQ(10, sizeof(o3)); + EXPECT_EQ(16, sizeof(o3)); std::vector v_vec; var v1 = var(0.0); @@ -110,7 +110,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsMat) { d_mat << 10.0, 20.0, 30.0, 40.0; operands_and_partials o3(d_mat); - EXPECT_EQ(10, sizeof(o3)); + EXPECT_EQ(16, sizeof(o3)); matrix_v v_mat(2, 2); var v1 = var(0.0); @@ -153,7 +153,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsMatMultivar) { d_mat_vec.push_back(d_mat); operands_and_partials> o3(d_mat_vec); - EXPECT_EQ(10, sizeof(o3)); + EXPECT_EQ(16, sizeof(o3)); matrix_v v_mat1(2, 2); var v1 = var(0.0); @@ -218,7 +218,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsMultivar) { d_vec_vec.push_back(d_vec2); operands_and_partials> o3(d_vec_vec); - EXPECT_EQ(10, sizeof(o3)); + EXPECT_EQ(16, sizeof(o3)); vector_v v_vec1(2); var v1 = var(0.0); @@ -293,7 +293,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsMultivarMixed) { // 2 partials stdvecs, 4 pointers to edges, 2 pointers to operands // vecs - EXPECT_EQ(120, sizeof(o4)); + EXPECT_EQ(128, sizeof(o4)); std::vector grad; var v = o4.build(10.0); From 48362d3bb3e4da5cc43fe1795471a1d894f04b44 Mon Sep 17 00:00:00 2001 From: Stan BuildBot Date: Fri, 7 Oct 2022 12:52:32 -0400 Subject: [PATCH 002/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- .../fwd/functor/operands_and_partials.hpp | 32 +- stan/math/prim/fun/wiener5_lpdf.hpp | 8 +- stan/math/prim/fun/wiener7_lpdf.hpp | 2 +- stan/math/prim/functor/hcubature.hpp | 24 +- stan/math/prim/prob/wiener_full_lpdf.hpp | 131 ++++---- .../rev/functor/operands_and_partials.hpp | 72 ++-- .../math/prim/prob/wiener_full_prec_test.cpp | 311 ++++++++--------- test/unit/math/prim/prob/wiener_full_test.cpp | 312 +++++++++--------- 8 files changed, 474 insertions(+), 418 deletions(-) diff --git a/stan/math/fwd/functor/operands_and_partials.hpp b/stan/math/fwd/functor/operands_and_partials.hpp index 3e4053449e2..53e97e50416 100644 --- a/stan/math/fwd/functor/operands_and_partials.hpp +++ b/stan/math/fwd/functor/operands_and_partials.hpp @@ -71,7 +71,7 @@ class ops_partials_edge> { * Op1 -- Op8 */ template + typename Op6, typename Op7, typename Op8, typename Dx> class operands_and_partials> { public: internal::ops_partials_edge> edge1_; @@ -96,18 +96,33 @@ class operands_and_partials> { : edge1_(o1), edge2_(o2), edge3_(o3), edge4_(o4), edge5_(o5) {} operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3, const Op4& o4, const Op5& o5, const Op6& o6) - : edge1_(o1), edge2_(o2), edge3_(o3), edge4_(o4), edge5_(o5), + : edge1_(o1), + edge2_(o2), + edge3_(o3), + edge4_(o4), + edge5_(o5), edge6_(o6) {} operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3, const Op4& o4, const Op5& o5, const Op6& o6, const Op7& o7) - : edge1_(o1), edge2_(o2), edge3_(o3), edge4_(o4), edge5_(o5), - edge6_(o6), edge7_(o7) {} + : edge1_(o1), + edge2_(o2), + edge3_(o3), + edge4_(o4), + edge5_(o5), + edge6_(o6), + edge7_(o7) {} operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3, const Op4& o4, const Op5& o5, const Op6& o6, const Op7& o7, const Op8& o8) - : edge1_(o1), edge2_(o2), edge3_(o3), edge4_(o4), edge5_(o5), - edge6_(o6), edge7_(o7), edge8_(o8) {} + : edge1_(o1), + edge2_(o2), + edge3_(o3), + edge4_(o4), + edge5_(o5), + edge6_(o6), + edge7_(o7), + edge8_(o8) {} /** \ingroup type_trait * Build the node to be stored on the autodiff graph. @@ -123,9 +138,8 @@ class operands_and_partials> { * @return the value with its derivative */ T_return_type build(Dx value) { - Dx deriv - = edge1_.dx() + edge2_.dx() + edge3_.dx() + edge4_.dx() + edge5_.dx() - + edge6_.dx() + edge7_.dx() + edge8_.dx(); + Dx deriv = edge1_.dx() + edge2_.dx() + edge3_.dx() + edge4_.dx() + + edge5_.dx() + edge6_.dx() + edge7_.dx() + edge8_.dx(); return T_return_type(value, deriv); } }; diff --git a/stan/math/prim/fun/wiener5_lpdf.hpp b/stan/math/prim/fun/wiener5_lpdf.hpp index 6c6661c3200..746342da069 100644 --- a/stan/math/prim/fun/wiener5_lpdf.hpp +++ b/stan/math/prim/fun/wiener5_lpdf.hpp @@ -99,7 +99,7 @@ return_type_t dwiener5( ans = lg1 + (-0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log(q_asq) + log_diff_exp(fplus, fminus)); - // if large t is better + // if large t is better } else { T_return_type fplus = NEGATIVE_INFTY; T_return_type fminus = NEGATIVE_INFTY; @@ -218,7 +218,7 @@ return_type_t dtdwiener5( + newsign * exp(factor - 1.5 * LOG_TWO - LOG_SQRT_PI - 3.5 * log(q_asq) + erg - ld); - // if large t is better + // if large t is better } else { // calculate terms of the sum for large t T_return_type halfq = q_asq / 2.0; @@ -343,7 +343,7 @@ return_type_t dadwiener5( - newsign * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * lq + 4.0 * la + lg1 + erg - ld); - // if large t is better + // if large t is better } else { // calculate terms of the sum for large t T_return_type halfq = q_asq / 2.0; @@ -497,7 +497,7 @@ return_type_t dwdwiener5( - newsign * exp(erg - ls - 2.5 * log(q_asq) - 0.5 * LOG_TWO - 0.5 * LOG_PI); - // if large t is better + // if large t is better } else { // calculate terms of the sum for large t T_return_type halfq = q_asq / 2.0; diff --git a/stan/math/prim/fun/wiener7_lpdf.hpp b/stan/math/prim/fun/wiener7_lpdf.hpp index 494dec72e83..8903bf36819 100644 --- a/stan/math/prim/fun/wiener7_lpdf.hpp +++ b/stan/math/prim/fun/wiener7_lpdf.hpp @@ -166,7 +166,7 @@ return_type_t dtdwiener5_for_7( + newsign * exp(factor - 1.5 * LOG_TWO - LOG_SQRT_PI - 3.5 * log(q_asq) + erg - ld); - // if large y is better + // if large y is better } else { // calculate terms of the sum for large y T_return_type halfq = q_asq / 2.0; diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index b047414cd01..b2d5a6a36aa 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -139,8 +139,8 @@ void signcombos(const T_k& k, const T_lambda& lambda, const T_n& n, T_p& p) { index.clear(); for (size_t j = 0; j != pow(2, k); j++) { increment(index, k, lambda, n, c, temp); - T_lambda* next = - reinterpret_cast(malloc(n * sizeof(T_lambda))); + T_lambda* next + = reinterpret_cast(malloc(n * sizeof(T_lambda))); memcpy(next, temp, n * sizeof(T_lambda)); p.push_back(next); } @@ -249,12 +249,12 @@ void integrate_GenzMalik(const F& integrand, T_GenzMalik& g, const T_n& n, T_return_type twelvef1 = 12 * f1; T_return_type maxdivdiff = 0.0; - T_return_type* divdiff = - reinterpret_cast(malloc(n * sizeof(T_return_type))); - T_return_type* p2 = - reinterpret_cast(malloc(n * sizeof(T_return_type))); - T_return_type* p3 = - reinterpret_cast(malloc(n * sizeof(T_return_type))); + T_return_type* divdiff + = reinterpret_cast(malloc(n * sizeof(T_return_type))); + T_return_type* p2 + = reinterpret_cast(malloc(n * sizeof(T_return_type))); + T_return_type* p3 + = reinterpret_cast(malloc(n * sizeof(T_return_type))); std::vector cc(n, 0); for (size_t i = 0; i != n; i++) { @@ -284,8 +284,8 @@ void integrate_GenzMalik(const F& integrand, T_GenzMalik& g, const T_n& n, } free(p2); free(p3); - T_return_type* p4 = - reinterpret_cast(malloc(n * sizeof(T_return_type))); + T_return_type* p4 + = reinterpret_cast(malloc(n * sizeof(T_return_type))); T_return_type f4 = 0.0; for (size_t i = 0; i != g.p[2].size(); i++) { for (size_t j = 0; j != n; j++) @@ -297,8 +297,8 @@ void integrate_GenzMalik(const F& integrand, T_GenzMalik& g, const T_n& n, } free(p4); T_return_type f5 = 0.0; - T_return_type* p5 = - reinterpret_cast(malloc(n * sizeof(T_return_type))); + T_return_type* p5 + = reinterpret_cast(malloc(n * sizeof(T_return_type))); for (size_t i = 0; i != g.p[3].size(); i++) { for (size_t j = 0; j != n; j++) p5[j] = deltac[j] * g.p[3][i][j]; diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index f536ce4b6b7..8143e07508b 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -78,14 +78,17 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, check_bounded(function_name, "Inter-trial variability in A-priori bias", value_of(sw_ref), 0, 1); check_nonnegative(function_name, - "Inter-trial variability in Nondecision time", value_of(st0_ref)); + "Inter-trial variability in Nondecision time", + value_of(st0_ref)); check_finite(function_name, "Inter-trial variability in Nondecision time", value_of(st0_ref)); - if (size_zero(y, a, v, w, t0) || size_zero(sv, sw, st0)) return 0; + if (size_zero(y, a, v, w, t0) || size_zero(sv, sw, st0)) + return 0; size_t N = max_size(y, a, v, w, t0, sv, sw, st0); - if (!N) return 0; + if (!N) + return 0; scalar_seq_view y_vec(y_ref); scalar_seq_view alpha_vec(alpha_ref); @@ -129,7 +132,8 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, } if (!include_summand::value) return 0; + T_st0>::value) + return 0; // abstol_wiener5 z.B. 1e-12 on normal scale // T_partials_return error_bound = 1e-6; @@ -170,16 +174,19 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, sv_val, labstol_wiener5); if (labstol_wiener5 > fabs(dens) + lerror_bound_dens - log(2)) dens = internal::dwiener5(y_val - t0_val, alpha_val, delta_val, - beta_val, sv_val, fabs(dens) + lerror_bound_dens - log(2)); + beta_val, sv_val, + fabs(dens) + lerror_bound_dens - log(2)); ld += dens; // computation of derivative for t and precision check in order to give // the value as deriv_t to edge1 and as -deriv_t to edge5 - T_partials_return deriv_t = internal::dtdwiener5(y_val - t0_val, - alpha_val, delta_val, beta_val, sv_val, labstol_wiener5); + T_partials_return deriv_t + = internal::dtdwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, + sv_val, labstol_wiener5); if (labstol_wiener5 > log(fabs(deriv_t)) + dens + lerror_bound - log(2)) - deriv_t = internal::dtdwiener5(y_val - t0_val, alpha_val, delta_val, - beta_val, sv_val, log(fabs(deriv_t)) + dens + lerror_bound - log(4)); + deriv_t = internal::dtdwiener5( + y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, + log(fabs(deriv_t)) + dens + lerror_bound - log(4)); // computation of derivatives and precision checks if (!is_constant_all::value) { @@ -222,7 +229,7 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, if (!is_constant_all::value) { ops_partials.edge8_.partials_[i] = 0; } - // Calculate 6-, or 7-parameter model + // Calculate 6-, or 7-parameter model } else { const T_partials_return y_val = y_vec.val(i); const T_partials_return alpha_val = alpha_vec.val(i); @@ -236,7 +243,8 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return> - params = {y_val, alpha_val, delta_val, beta_val, t0_val, sv_val, + params = {y_val, alpha_val, delta_val, + beta_val, t0_val, sv_val, sw_val, st0_val, labstol_wiener5 - log(2)}; int dim = (sw_val != 0) + (st0_val != 0); check_positive(function_name, @@ -247,7 +255,8 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, std::vector xmin(dim, 0); std::vector xmax(dim, 1); - if (st0_val) xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); + if (st0_val) + xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); dens = hcubature(internal::int_ddiff, void*>, ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); @@ -268,7 +277,8 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, st0_val, log(.1) + lerror_bound_dens - log(2) + log(fabs(dens))}; dens = hcubature(internal::int_ddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, reltol); + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, + reltol); } ld += log(dens); @@ -276,7 +286,8 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, // the value as deriv_t to edge1 and as -deriv_t to edge5 T_partials_return deriv_t_7; deriv_t_7 - = 1/dens*hcubature(internal::int_dtddiff, void*>, + = 1 / dens + * hcubature(internal::int_dtddiff, void*>, ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 > log(fabs(deriv_t_7)) + log(.1) + lerror_bound - log(2)) { @@ -295,8 +306,10 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, st0_val, log(.1) + lerror_bound - log(4) + log(fabs(deriv_t_7))}; deriv_t_7 - = 1/dens*hcubature(internal::int_dtddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, reltol / 2); + = 1 / dens + * hcubature(internal::int_dtddiff, void*>, + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, + reltol / 2); } // computation of derivatives and precision checks @@ -306,7 +319,8 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, } if (!is_constant_all::value) { deriv - = 1/dens*hcubature(internal::int_daddiff, void*>, + = 1 / dens + * hcubature(internal::int_daddiff, void*>, ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 > log(fabs(deriv)) + log(.1) + lerror_bound - log(2)) { @@ -325,8 +339,9 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, st0_val, log(.1) + lerror_bound - log(4) + log(fabs(deriv))}; deriv = 1 / dens - * hcubature(internal::int_daddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, reltol / 2); + * hcubature(internal::int_daddiff, void*>, + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, + reltol / 2); } ops_partials.edge2_.partials_[i] = deriv; } @@ -352,8 +367,9 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, st0_val, log(.1) + lerror_bound - log(2) + log(fabs(deriv))}; deriv = 1 / dens - * hcubature(internal::int_dvddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, reltol / 2); + * hcubature(internal::int_dvddiff, void*>, + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, + reltol / 2); } ops_partials.edge3_.partials_[i] = deriv; } @@ -379,8 +395,9 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, st0_val, log(.1) + lerror_bound - log(4) + log(fabs(deriv))}; deriv = 1 / dens - * hcubature(internal::int_dwddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, reltol / 2); + * hcubature(internal::int_dwddiff, void*>, + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, + reltol / 2); } ops_partials.edge4_.partials_[i] = deriv; } @@ -411,7 +428,8 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, deriv = 1 / dens * hcubature(internal::int_dsvddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, reltol / 2); + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, + reltol / 2); } ops_partials.edge6_.partials_[i] = deriv; } @@ -563,14 +581,8 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, } //----------------------------------------------- - } // namespace internal - - - - - /** \ingroup prob_dists * The log of the first passage time density function for a (Wiener) * drift diffusion model with up to 7 parameters, where @@ -580,7 +592,8 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * \f$t_0 \in \mathbb{R}_{\geq 0}\f$ the non-decision time, \f$s_v \in * \mathbb{R}_{\geq 0}\f$ the inter-trial variability of the drift rate, * \f$s_w \in [0, 1)\f$ the inter-trial variability of the relative starting - * point, and \f$s_{t_0} \in \mathbb{R}_{\geq 0}\f$ the inter-trial variability of + * point, and \f$s_{t_0} \in \mathbb{R}_{\geq 0}\f$ the inter-trial variability + of * the non-decision time. * * @@ -597,20 +610,21 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, \f} * where \f$M\f$ and \f$p_3()\f$ are defined, by using \f$t:=y-\tau_0\f$, as \f{eqnarray*}{ - M &:=& \frac{1}{\sqrt{1+s^2_v t}} \mathbb{e}^{av\omega+\frac{v^2t}{2}+\frac{s^2_v a^2 \omega^2-2av\omega-v^2t}{2(1+s^2_vt)}} \text{ and} \\ - p_3(t|a,v,w) &:=& \frac{1}{a^2} \mathbb{e}^{-a v w -\frac{v^2t}{2}} f(\frac{t}{a^2}|0,1,w), - \f} + M &:=& \frac{1}{\sqrt{1+s^2_v t}} + \mathbb{e}^{av\omega+\frac{v^2t}{2}+\frac{s^2_v a^2 + \omega^2-2av\omega-v^2t}{2(1+s^2_vt)}} \text{ and} \\ p_3(t|a,v,w) &:=& + \frac{1}{a^2} \mathbb{e}^{-a v w -\frac{v^2t}{2}} f(\frac{t}{a^2}|0,1,w), \f} * where \f$f(t^*=\frac{t}{a^2}|0,1,w)\f$ has two forms \f{eqnarray*}{ f_l(t^*|0,1,w) &=& \sum_{k=1}^{\infty} k\pi \mathbb{e}^{-\frac{k^2\pi^2t^*}{2}} \sin{(k \pi w)}\text{ and} \\ - f_s(t^*|0,1,w) &=& \sum_{k=-\infty}^{\infty} \frac{1}{\sqrt{2\pi (t^*)^3}} (w+2k) - \mathbb{e}^{-\frac{(w+2k)^2}{2t^*}}, - \f} + f_s(t^*|0,1,w) &=& \sum_{k=-\infty}^{\infty} \frac{1}{\sqrt{2\pi (t^*)^3}} + (w+2k) \mathbb{e}^{-\frac{(w+2k)^2}{2t^*}}, \f} * which are selected depending on the number of components \f$k\f$, needed to * guarantee a certain precision. * - * Note that the parametrization for non-decision time and relative starting point is as follows: + * Note that the parametrization for non-decision time and relative starting + point is as follows: * \c t0 is the lower bound of the variability interval; * \c w is the mean of the variability interval. * @@ -635,7 +649,8 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * @param st0 The inter-trial variability of the non-decision time * @return The log of the Wiener first passage time density with * the specified arguments for upper boundary responses - * @throw std::domain_error if non-decision time \c t0 is greater than reaction time \c y. + * @throw std::domain_error if non-decision time \c t0 is greater than reaction + time \c y. * @throw std::domain_error if \c 1-sw/2 is smaller than or equal to \c w. * @throw std::domain_error if \c sw/2 is larger than or equal to \c w. * @@ -653,15 +668,19 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, @endcode * * By default \c wiener_full_lpdf() gives the log of the - * Wiener first-passage time probability density function for the \e upper response - * boundary. To use the \e lower response boundary \c v and \c w must be changed to + * Wiener first-passage time probability density function for the \e upper + response + * boundary. To use the \e lower response boundary \c v and \c w must be changed + to * \c -v and \c (1-w), respectively. * * \c sv, \c sw, \c st0, and \c t0 can be set to zero, indicating no inter-trial * variability in \f$v\f$, no inter-trial variability in \f$w\f$, no * inter-trial variability in \f$t_0\f$, and no non-decision time, respectively. - * If \c t0 is zero, \c st0 must be zero as well. For example, when no inter-trial - * variability for the relative starting point is needed one can write something like: + * If \c t0 is zero, \c st0 must be zero as well. For example, when no + inter-trial + * variability for the relative starting point is needed one can write something + like: @code target += wiener_full_lpdf(y, a, v, w, t0, sv, 0, st0) @endcode @@ -669,12 +688,13 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, @code target += wiener_full_lpdf(y, a, v, w, t0, 0, 0, 0) @endcode - * If for some reason no non-decision time is assumed one can write something like: + * If for some reason no non-decision time is assumed one can write something + like: @code target += wiener_full_lpdf(y, a, v, w, 0, sv, sw, 0) @endcode * - * To also control the precision in the estimation of the partial derivatives, + * To also control the precision in the estimation of the partial derivatives, * call the function \c wiener_full_prec_lpdf(), analogously: @code target += wiener_full__prec_lpdf(y, a, v, w, t0, sv, sw, st0, precision); @@ -686,7 +706,8 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * time distribution for the diffusion model with variable drift. * *Journal of Mathematical Psychology, 76*, 7–12. * https://doi.org/10.1016/j.jmp.2016.11.003 - * - Foster, K., & Singmann, H. (2021). Another Approximation of the First-Passage + * - Foster, K., & Singmann, H. (2021). Another Approximation of the + First-Passage * Time Densities for the Ratcliff Diffusion Decision Model. * *arXiv preprint arXiv:2104.01902* * - Gondan, M., Blurton, S. P., & Kesselmeier, M. (2014). Even faster and even @@ -713,7 +734,7 @@ wiener_full_lpdf(const T_y& y, const T_alpha& a, const T_delta& v, double precision = 1e-4; return internal::wiener_full_prec_impl_lpdf( + T_beta, T_t0, T_sv, T_sw, T_st0>( "wiener_full_lpdf", y, a, v, w, t0, sv, sw, st0, precision); } @@ -725,13 +746,11 @@ wiener_full_lpdf(const T_y& y, const T_alpha& a, const T_delta& v, const T_sw& sw, const T_st0& st0) { double precision = 1e-4; - return internal::wiener_full_prec_impl_lpdf("wiener_full_lpdf", - y, a, v, w, t0, sv, sw, st0, precision); + return internal::wiener_full_prec_impl_lpdf( + "wiener_full_lpdf", y, a, v, w, t0, sv, sw, st0, precision); } - - - /** \ingroup prob_dists +/** \ingroup prob_dists * The log of the first passage time density function for a (Wiener) * drift diffusion model with up to 7 parameters with the option * to control for the precision in the estimation of the partial derivatives. @@ -748,7 +767,7 @@ wiener_full_prec_lpdf(const T_y& y, const T_alpha& a, const T_delta& v, const T_beta& w, const T_t0& t0, const T_sv& sv, const T_sw& sw, const T_st0& st0, const double& prec) { return internal::wiener_full_prec_impl_lpdf( + T_beta, T_t0, T_sv, T_sw, T_st0>( "wiener_full_prec_lpdf", y, a, v, w, t0, sv, sw, st0, prec); } @@ -758,12 +777,10 @@ inline return_type_t wiener_full_prec_lpdf(const T_y& y, const T_alpha& a, const T_delta& v, const T_beta& w, const T_t0& t0, const T_sv& sv, const T_sw& sw, const T_st0& st0, const double& prec) { - return internal::wiener_full_prec_impl_lpdf("wiener_full_prec_lpdf", - y, a, v, w, t0, sv, sw, st0, prec); + return internal::wiener_full_prec_impl_lpdf( + "wiener_full_prec_lpdf", y, a, v, w, t0, sv, sw, st0, prec); } - - } // namespace math } // namespace stan #endif diff --git a/stan/math/rev/functor/operands_and_partials.hpp b/stan/math/rev/functor/operands_and_partials.hpp index faa31b02b6b..b63e9d91b12 100644 --- a/stan/math/rev/functor/operands_and_partials.hpp +++ b/stan/math/rev/functor/operands_and_partials.hpp @@ -182,41 +182,41 @@ class operands_and_partials { * @return the node to be stored in the expression graph for autodiff */ var build(double value) { - return make_callback_var(value, [ - operand1 = edge1_.operand(), partial1 = edge1_.partial(), - operand2 = edge2_.operand(), partial2 = edge2_.partial(), - operand3 = edge3_.operand(), partial3 = edge3_.partial(), - operand4 = edge4_.operand(), partial4 = edge4_.partial(), - operand5 = edge5_.operand(), partial5 = edge5_.partial(), - operand6 = edge6_.operand(), partial6 = edge6_.partial(), - operand7 = edge7_.operand(), partial7 = edge7_.partial(), - operand8 = edge8_.operand(), partial8 = edge8_.partial() - ](const auto& vi) mutable { - if (!is_constant::value) { - internal::update_adjoints(operand1, partial1, vi); - } - if (!is_constant::value) { - internal::update_adjoints(operand2, partial2, vi); - } - if (!is_constant::value) { - internal::update_adjoints(operand3, partial3, vi); - } - if (!is_constant::value) { - internal::update_adjoints(operand4, partial4, vi); - } - if (!is_constant::value) { - internal::update_adjoints(operand5, partial5, vi); - } - if (!is_constant::value) { - internal::update_adjoints(operand6, partial6, vi); - } - if (!is_constant::value) { - internal::update_adjoints(operand7, partial7, vi); - } - if (!is_constant::value) { - internal::update_adjoints(operand8, partial8, vi); - } - }); + return make_callback_var( + value, [operand1 = edge1_.operand(), partial1 = edge1_.partial(), + operand2 = edge2_.operand(), partial2 = edge2_.partial(), + operand3 = edge3_.operand(), partial3 = edge3_.partial(), + operand4 = edge4_.operand(), partial4 = edge4_.partial(), + operand5 = edge5_.operand(), partial5 = edge5_.partial(), + operand6 = edge6_.operand(), partial6 = edge6_.partial(), + operand7 = edge7_.operand(), partial7 = edge7_.partial(), + operand8 = edge8_.operand(), + partial8 = edge8_.partial()](const auto& vi) mutable { + if (!is_constant::value) { + internal::update_adjoints(operand1, partial1, vi); + } + if (!is_constant::value) { + internal::update_adjoints(operand2, partial2, vi); + } + if (!is_constant::value) { + internal::update_adjoints(operand3, partial3, vi); + } + if (!is_constant::value) { + internal::update_adjoints(operand4, partial4, vi); + } + if (!is_constant::value) { + internal::update_adjoints(operand5, partial5, vi); + } + if (!is_constant::value) { + internal::update_adjoints(operand6, partial6, vi); + } + if (!is_constant::value) { + internal::update_adjoints(operand7, partial7, vi); + } + if (!is_constant::value) { + internal::update_adjoints(operand8, partial8, vi); + } + }); } }; @@ -274,7 +274,7 @@ class ops_partials_edge, require_eigen_t> { broadcast_array partials_vec_; // For multivariate explicit ops_partials_edge(const var_value& ops) : partials_( - plain_type_t::Zero(ops.vi_->rows(), ops.vi_->cols())), + plain_type_t::Zero(ops.vi_->rows(), ops.vi_->cols())), partials_vec_(partials_), operands_(ops) {} diff --git a/test/unit/math/prim/prob/wiener_full_prec_test.cpp b/test/unit/math/prim/prob/wiener_full_prec_test.cpp index 5e7f6e942e2..3dd99a93ae9 100644 --- a/test/unit/math/prim/prob/wiener_full_prec_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_prec_test.cpp @@ -11,160 +11,159 @@ // CHECKING FOR (IN)VALID INPUT TEST(mathPrimScalProbWienerFullPrecScal, valid) { - using stan::math::wiener_full_prec_lpdf; using stan::math::INFTY; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, - sw = 0.2, st0 = 0.1; + using stan::math::wiener_full_prec_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, + st0 = 0.1; EXPECT_NO_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, sw, st0, 1e-4)); - rt = 5; a = 1; v = 1; w = 0.5; t0 = 0.0; sv = 0.0; sw = 0.0; st0 = 0.0; + rt = 5; + a = 1; + v = 1; + w = 0.5; + t0 = 0.0; + sv = 0.0; + sw = 0.0; + st0 = 0.0; EXPECT_NO_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, sw, st0, 1e-4)); } // rt TEST(mathPrimScalProbWienerFullPrecScal, invalid_rt) { - using stan::math::wiener_full_prec_lpdf; using stan::math::INFTY; + using stan::math::wiener_full_prec_lpdf; double a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(0, a, v, w, t0, sv, - sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(-1, a, v, w, t0, sv, - sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(INFTY, a, v, w, t0, sv, - sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(-INFTY, a, v, w, t0, sv, - sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(NAN, a, v, w, t0, sv, - sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(0, a, v, w, t0, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(-1, a, v, w, t0, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(INFTY, a, v, w, t0, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(-INFTY, a, v, w, t0, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(NAN, a, v, w, t0, sv, sw, st0, 1e-4), + std::domain_error); } - // a TEST(mathPrimScalProbWienerFullPrecScal, invalid_a) { - using stan::math::wiener_full_prec_lpdf; using stan::math::INFTY; + using stan::math::wiener_full_prec_lpdf; double rt = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, 0, v, w, t0, sv, - sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, -1, v, w, t0, sv, - sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, INFTY, v, w, t0, sv, - sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, -INFTY, v, w, t0, sv, - sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, NAN, v, w, t0, sv, - sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, 0, v, w, t0, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, -1, v, w, t0, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, INFTY, v, w, t0, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, -INFTY, v, w, t0, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, NAN, v, w, t0, sv, sw, st0, 1e-4), + std::domain_error); } - // v TEST(mathPrimScalProbWienerFullPrecScal, invalid_v) { - using stan::math::wiener_full_prec_lpdf; using stan::math::INFTY; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, - sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, INFTY, w, t0, sv, - sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, -INFTY, w, t0, sv, - sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, NAN, w, t0, sv, - sw, st0, 1e-4), std::domain_error); + using stan::math::wiener_full_prec_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, + st0 = 0.1; + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, INFTY, w, t0, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, -INFTY, w, t0, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, NAN, w, t0, sv, sw, st0, 1e-4), + std::domain_error); } - // w TEST(mathPrimScalProbWienerFullPrecScal, invalid_w) { - using stan::math::wiener_full_prec_lpdf; using stan::math::INFTY; + using stan::math::wiener_full_prec_lpdf; double rt = 1, a = 1, v = -1, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, -0.1, t0, sv, - sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 0, t0, sv, - sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 1, t0, sv, - sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 1.1, t0, sv, - sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, INFTY, t0, sv, - sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, -INFTY, t0, sv, - sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, NAN, t0, sv, - sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, -0.1, t0, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 0, t0, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 1, t0, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 1.1, t0, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, INFTY, t0, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, -INFTY, t0, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, NAN, t0, sv, sw, st0, 1e-4), + std::domain_error); } - // t0 TEST(mathPrimScalProbWienerFullPrecScal, invalid_t0) { - using stan::math::wiener_full_prec_lpdf; using stan::math::INFTY; + using stan::math::wiener_full_prec_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, 2, sv, sw, - st0, 1e-4), std::domain_error); // rt must be greater than t0 - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, - -1, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, - INFTY, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, - -INFTY, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, - NAN, sv, sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, 2, sv, sw, st0, 1e-4), + std::domain_error); // rt must be greater than t0 + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, -1, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, INFTY, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, -INFTY, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, NAN, sv, sw, st0, 1e-4), + std::domain_error); } - // sv TEST(mathPrimScalProbWienerFullPrecScal, invalid_sv) { - using stan::math::wiener_full_prec_lpdf; using stan::math::INFTY; + using stan::math::wiener_full_prec_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, - -1, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, - INFTY, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, - -INFTY, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, - NAN, sw, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, -1, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, INFTY, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, -INFTY, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, NAN, sw, st0, 1e-4), + std::domain_error); } - // sw TEST(mathPrimScalProbWienerFullPrecScal, invalid_sw) { - using stan::math::wiener_full_prec_lpdf; using stan::math::INFTY; + using stan::math::wiener_full_prec_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, - -1, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 0.8, t0, sv, 0.5, st0, - 1e-4), std::domain_error); // sw must be smaller than 2*(1-w) - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 0.3, t0, sv, 0.7, st0, - 1e-4), std::domain_error); // sw must be smaller than 2*w - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, - INFTY, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, - -INFTY, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, - NAN, st0, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, -1, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 0.8, t0, sv, 0.5, st0, 1e-4), + std::domain_error); // sw must be smaller than 2*(1-w) + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 0.3, t0, sv, 0.7, st0, 1e-4), + std::domain_error); // sw must be smaller than 2*w + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, INFTY, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, -INFTY, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, NAN, st0, 1e-4), + std::domain_error); } - // st0 TEST(mathPrimScalProbWienerFullPrecScal, invalid_st0) { - using stan::math::wiener_full_prec_lpdf; using stan::math::INFTY; + using stan::math::wiener_full_prec_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, - sw, -1, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, - sw, INFTY, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, - sw, -INFTY, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, - sw, NAN, 1e-4), std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, sw, -1, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, sw, INFTY, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, sw, -INFTY, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, sw, NAN, 1e-4), + std::domain_error); } - // CHECK THAT ALL VALID SCALAR TYPES ARE ACCEPTED -template +template void check_scalar_types(F& f, double value, double res, double deriv) { // - f: Function with a single parameter exposed, all others // have to be scalars @@ -192,72 +191,86 @@ TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { using stan::math::wiener_full_prec_lpdf; double err_tol = 2e-6; - std::vector rt {1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector a {1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector v {1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector w {0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; - std::vector t0 {0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0}; - std::vector sv {0.1, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0}; - std::vector sw {0.1, 0.1, 0, 0.1, 0, 0.1, 0, 0, 0}; - std::vector st0 {0.1, 0, 0.1, 0.1, 0, 0, 0.1, 0, 0}; + std::vector rt{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector a{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector v{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector w{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; + std::vector t0{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0}; + std::vector sv{0.1, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0}; + std::vector sw{0.1, 0.1, 0, 0.1, 0, 0.1, 0, 0, 0}; + std::vector st0{0.1, 0, 0.1, 0.1, 0, 0, 0.1, 0, 0}; - std::vector result {-2.426204, -2.710348, -2.422505, -2.422795, - -2.70665, -2.706812, -2.419095, -2.703112, - -3.790072}; - std::vector drt {-5.437337, -5.436798, -5.437332, -5.434799, - -5.436791, -5.434801, -5.434802, -5.434802, - -5.434802}; - std::vector da { 5.857318, 6.395031, 5.856484, 5.858549, - 6.394195, 6.396512, 5.857722, 6.395684, - 8.369604}; - std::vector dv {-0.2428443, -0.2967977, -0.2436664, -0.2446629, - -0.297619, -0.2991696, -0.2454931, -0.3, -0.5}; - std::vector dw {-0.9891369, -0.9887305, -0.9973428, -0.9915453, - -0.9969335, -0.991674, -0.9997794, -0.9999097, - -0.9999953}; - std::vector dt0 { 5.437337, 5.436798, 5.437332, 5.434799, - 5.436791, 5.434801, 5.434802, 5.434802, - 5.434802}; - std::vector dsv {-0.06793703, -0.07047449, -0.06797882, 0.0, - -0.07050737, 0.0, 0.0, 0.0, 0.0}; - std::vector dsw {-0.07406705, -0.07407386, 0.0, -0.07410901, 0.0, - -0.07410686, 0.0, 0.0, 0.0}; - std::vector dst0 { 2.963915, 0.0, 2.963912, 2.962338, 0.0, - 0.0, 2.96234, 0.0, 0.0}; + std::vector result{-2.426204, -2.710348, -2.422505, + -2.422795, -2.70665, -2.706812, + -2.419095, -2.703112, -3.790072}; + std::vector drt{-5.437337, -5.436798, -5.437332, -5.434799, -5.436791, + -5.434801, -5.434802, -5.434802, -5.434802}; + std::vector da{5.857318, 6.395031, 5.856484, 5.858549, 6.394195, + 6.396512, 5.857722, 6.395684, 8.369604}; + std::vector dv{-0.2428443, -0.2967977, -0.2436664, + -0.2446629, -0.297619, -0.2991696, + -0.2454931, -0.3, -0.5}; + std::vector dw{-0.9891369, -0.9887305, -0.9973428, + -0.9915453, -0.9969335, -0.991674, + -0.9997794, -0.9999097, -0.9999953}; + std::vector dt0{5.437337, 5.436798, 5.437332, 5.434799, 5.436791, + 5.434801, 5.434802, 5.434802, 5.434802}; + std::vector dsv{-0.06793703, -0.07047449, -0.06797882, + 0.0, -0.07050737, 0.0, + 0.0, 0.0, 0.0}; + std::vector dsw{-0.07406705, -0.07407386, 0.0, -0.07410901, 0.0, + -0.07410686, 0.0, 0.0, 0.0}; + std::vector dst0{2.963915, 0.0, 2.963912, 2.962338, 0.0, + 0.0, 2.96234, 0.0, 0.0}; for (int i = 0; i < result.size(); i++) { // rt - auto f_rt = [=](auto value) {return wiener_full_prec_lpdf(value, a[i], - v[i], w[i], t0[i], sv[i], sw[i], st0[i], 1e-6);}; + auto f_rt = [=](auto value) { + return wiener_full_prec_lpdf(value, a[i], v[i], w[i], t0[i], sv[i], sw[i], + st0[i], 1e-6); + }; check_scalar_types(f_rt, rt[i], result[i], drt[i]); // a - auto f_a = [=](auto value) {return wiener_full_prec_lpdf(rt[i], value, - v[i], w[i], t0[i], sv[i], sw[i], st0[i], 1e-6);}; + auto f_a = [=](auto value) { + return wiener_full_prec_lpdf(rt[i], value, v[i], w[i], t0[i], sv[i], + sw[i], st0[i], 1e-6); + }; check_scalar_types(f_a, a[i], result[i], da[i]); // v - auto f_v = [=](auto value) {return wiener_full_prec_lpdf(rt[i], a[i], - value, w[i], t0[i], sv[i], sw[i], st0[i], 1e-6);}; + auto f_v = [=](auto value) { + return wiener_full_prec_lpdf(rt[i], a[i], value, w[i], t0[i], sv[i], + sw[i], st0[i], 1e-6); + }; check_scalar_types(f_v, v[i], result[i], dv[i]); // w - auto f_w = [=](auto value) {return wiener_full_prec_lpdf(rt[i], a[i], - v[i], value, t0[i], sv[i], sw[i], st0[i], 1e-6);}; + auto f_w = [=](auto value) { + return wiener_full_prec_lpdf(rt[i], a[i], v[i], value, t0[i], sv[i], + sw[i], st0[i], 1e-6); + }; check_scalar_types(f_w, w[i], result[i], dw[i]); // t0 - auto f_t0 = [=](auto value) {return wiener_full_prec_lpdf(rt[i], a[i], - v[i], w[i], value, sv[i], sw[i], st0[i], 1e-6);}; + auto f_t0 = [=](auto value) { + return wiener_full_prec_lpdf(rt[i], a[i], v[i], w[i], value, sv[i], sw[i], + st0[i], 1e-6); + }; check_scalar_types(f_t0, t0[i], result[i], dt0[i]); // sv - auto f_sv = [=](auto value) {return wiener_full_prec_lpdf(rt[i], a[i], - v[i], w[i], t0[i], value, sw[i], st0[i], 1e-6);}; + auto f_sv = [=](auto value) { + return wiener_full_prec_lpdf(rt[i], a[i], v[i], w[i], t0[i], value, sw[i], + st0[i], 1e-6); + }; check_scalar_types(f_sv, sv[i], result[i], dsv[i]); // sw - auto f_sw = [=](auto value) {return wiener_full_prec_lpdf(rt[i], a[i], - v[i], w[i], t0[i], sv[i], value, st0[i], 1e-6);}; + auto f_sw = [=](auto value) { + return wiener_full_prec_lpdf(rt[i], a[i], v[i], w[i], t0[i], sv[i], value, + st0[i], 1e-6); + }; check_scalar_types(f_sw, sw[i], result[i], dsw[i]); // st0 - auto f_st0 = [=](auto value) {return wiener_full_prec_lpdf(rt[i], a[i], - v[i], w[i], t0[i], sv[i], sw[i], value, 1e-6);}; + auto f_st0 = [=](auto value) { + return wiener_full_prec_lpdf(rt[i], a[i], v[i], w[i], t0[i], sv[i], sw[i], + value, 1e-6); + }; check_scalar_types(f_st0, st0[i], result[i], dst0[i]); } } - diff --git a/test/unit/math/prim/prob/wiener_full_test.cpp b/test/unit/math/prim/prob/wiener_full_test.cpp index 2ae9a6228c6..4158b7537f7 100644 --- a/test/unit/math/prim/prob/wiener_full_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_test.cpp @@ -11,160 +11,159 @@ // CHECKING FOR (IN)VALID INPUT TEST(mathPrimScalProbWienerFullScal, valid) { - using stan::math::wiener_full_lpdf; using stan::math::INFTY; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, - sw = 0.2, st0 = 0.1; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, + st0 = 0.1; EXPECT_NO_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, sw, st0)); - rt = 5; a = 1; v = 1; w = 0.5; t0 = 0.0; sv = 0.0; sw = 0.0; st0 = 0.0; + rt = 5; + a = 1; + v = 1; + w = 0.5; + t0 = 0.0; + sv = 0.0; + sw = 0.0; + st0 = 0.0; EXPECT_NO_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, sw, st0)); } // rt TEST(mathPrimScalProbWienerFullScal, invalid_rt) { - using stan::math::wiener_full_lpdf; using stan::math::INFTY; + using stan::math::wiener_full_lpdf; double a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(0, a, v, w, t0, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(-1, a, v, w, t0, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(INFTY, a, v, w, t0, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(-INFTY, a, v, w, t0, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(NAN, a, v, w, t0, sv, - sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(0, a, v, w, t0, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(-1, a, v, w, t0, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(INFTY, a, v, w, t0, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(-INFTY, a, v, w, t0, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(NAN, a, v, w, t0, sv, sw, st0), + std::domain_error); } - // a TEST(mathPrimScalProbWienerFullScal, invalid_a) { - using stan::math::wiener_full_lpdf; using stan::math::INFTY; + using stan::math::wiener_full_lpdf; double rt = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, 0, v, w, t0, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, -1, v, w, t0, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, INFTY, v, w, t0, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, -INFTY, v, w, t0, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, NAN, v, w, t0, sv, - sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, 0, v, w, t0, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, -1, v, w, t0, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, INFTY, v, w, t0, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, -INFTY, v, w, t0, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, NAN, v, w, t0, sv, sw, st0), + std::domain_error); } - // v TEST(mathPrimScalProbWienerFullScal, invalid_v) { - using stan::math::wiener_full_lpdf; using stan::math::INFTY; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, - sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, INFTY, w, t0, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, -INFTY, w, t0, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, NAN, w, t0, sv, - sw, st0), std::domain_error); + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, + st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, INFTY, w, t0, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, -INFTY, w, t0, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, NAN, w, t0, sv, sw, st0), + std::domain_error); } - // w TEST(mathPrimScalProbWienerFullScal, invalid_w) { - using stan::math::wiener_full_lpdf; using stan::math::INFTY; + using stan::math::wiener_full_lpdf; double rt = 1, a = 1, v = -1, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, v, -0.1, t0, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, 0, t0, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, 1, t0, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, 1.1, t0, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, INFTY, t0, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, -INFTY, t0, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, NAN, t0, sv, - sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, -0.1, t0, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, 0, t0, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, 1, t0, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, 1.1, t0, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, INFTY, t0, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, -INFTY, t0, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, NAN, t0, sv, sw, st0), + std::domain_error); } - // t0 TEST(mathPrimScalProbWienerFullScal, invalid_t0) { - using stan::math::wiener_full_lpdf; using stan::math::INFTY; + using stan::math::wiener_full_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, 2, sv, - sw, st0), std::domain_error); // rt must be greater than t0 - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, -1, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, INFTY, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, -INFTY, sv, - sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, NAN, sv, - sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, 2, sv, sw, st0), + std::domain_error); // rt must be greater than t0 + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, -1, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, INFTY, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, -INFTY, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, NAN, sv, sw, st0), + std::domain_error); } - // sv TEST(mathPrimScalProbWienerFullScal, invalid_sv) { - using stan::math::wiener_full_lpdf; using stan::math::INFTY; + using stan::math::wiener_full_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, - t0, -1, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, - t0, INFTY, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, - t0, -INFTY, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, - t0, NAN, sw, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, -1, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, INFTY, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, -INFTY, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, NAN, sw, st0), + std::domain_error); } - // sw TEST(mathPrimScalProbWienerFullScal, invalid_sw) { - using stan::math::wiener_full_lpdf; using stan::math::INFTY; + using stan::math::wiener_full_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, - -1, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, 0.8, t0, sv, - 0.5, st0), std::domain_error); // sw must be smaller than 2*(1-w) - EXPECT_THROW(wiener_full_lpdf(rt, a, v, 0.3, t0, sv, - 0.7, st0), std::domain_error); // sw must be smaller than 2*w - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, - INFTY, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, - -INFTY, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, - NAN, st0), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, -1, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, 0.8, t0, sv, 0.5, st0), + std::domain_error); // sw must be smaller than 2*(1-w) + EXPECT_THROW(wiener_full_lpdf(rt, a, v, 0.3, t0, sv, 0.7, st0), + std::domain_error); // sw must be smaller than 2*w + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, INFTY, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, -INFTY, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, NAN, st0), + std::domain_error); } - // st0 TEST(mathPrimScalProbWienerFullScal, invalid_st0) { - using stan::math::wiener_full_lpdf; using stan::math::INFTY; + using stan::math::wiener_full_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2; - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, - sw, -1), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, - sw, INFTY), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, - sw, -INFTY), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, - sw, NAN), std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, sw, -1), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, sw, INFTY), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, sw, -INFTY), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, sw, NAN), + std::domain_error); } - // CHECK THAT ALL VALID SCALAR TYPES ARE ACCEPTED -template +template void check_scalar_types(F& f, double value, double res, double deriv) { // - f: Function with a single parameter exposed, all others // have to be scalars @@ -191,73 +190,86 @@ TEST(ProbWienerFull, wiener_full_all_scalar) { // parameters set to double using stan::math::wiener_full_lpdf; - std::vector rt {1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector a {1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector v {1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector w {0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; - std::vector t0 {0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0}; - std::vector sv {0.1, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0}; - std::vector sw {0.1, 0.1, 0, 0.1, 0, 0.1, 0, 0, 0}; - std::vector st0 {0.1, 0, 0.1, 0.1, 0, 0, 0.1, 0, 0}; - - std::vector result {-2.426204, -2.710348, -2.422505, -2.422795, - -2.70665, -2.706812, -2.419095, -2.703112, - -3.790072}; - std::vector drt {-5.437337, -5.436798, -5.437332, -5.434799, - -5.436791, -5.434801, -5.434802, -5.434802, - -5.434802}; - std::vector da { 5.857318, 6.395031, 5.856484, 5.858549, - 6.394195, 6.396512, 5.857722, 6.395684, - 8.369604}; - std::vector dv {-0.2428443, -0.2967977, -0.2436664, -0.2446629, - -0.297619, -0.2991696, -0.2454931, -0.3, -0.5}; - std::vector dw {-0.9891369, -0.9887305, -0.9973428, -0.9915453, - -0.9969335, -0.991674, -0.9997794, -0.9999097, - -0.9999953}; - std::vector dt0 { 5.437337, 5.436798, 5.437332, 5.434799, - 5.436791, 5.434801, 5.434802, 5.434802, - 5.434802}; - std::vector dsv {-0.06793703, -0.07047449, -0.06797882, 0.0, - -0.07050737, 0.0, 0.0, 0.0, 0.0}; - std::vector dsw {-0.07406705, -0.07407386, 0.0, -0.07410901, 0.0, - -0.07410686, 0.0, 0.0, 0.0}; - std::vector dst0 { 2.963915, 0.0, 2.963912, 2.962338, 0.0, - 0.0, 2.96234, 0.0, 0.0}; + std::vector rt{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector a{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector v{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector w{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; + std::vector t0{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0}; + std::vector sv{0.1, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0}; + std::vector sw{0.1, 0.1, 0, 0.1, 0, 0.1, 0, 0, 0}; + std::vector st0{0.1, 0, 0.1, 0.1, 0, 0, 0.1, 0, 0}; + std::vector result{-2.426204, -2.710348, -2.422505, + -2.422795, -2.70665, -2.706812, + -2.419095, -2.703112, -3.790072}; + std::vector drt{-5.437337, -5.436798, -5.437332, -5.434799, -5.436791, + -5.434801, -5.434802, -5.434802, -5.434802}; + std::vector da{5.857318, 6.395031, 5.856484, 5.858549, 6.394195, + 6.396512, 5.857722, 6.395684, 8.369604}; + std::vector dv{-0.2428443, -0.2967977, -0.2436664, + -0.2446629, -0.297619, -0.2991696, + -0.2454931, -0.3, -0.5}; + std::vector dw{-0.9891369, -0.9887305, -0.9973428, + -0.9915453, -0.9969335, -0.991674, + -0.9997794, -0.9999097, -0.9999953}; + std::vector dt0{5.437337, 5.436798, 5.437332, 5.434799, 5.436791, + 5.434801, 5.434802, 5.434802, 5.434802}; + std::vector dsv{-0.06793703, -0.07047449, -0.06797882, + 0.0, -0.07050737, 0.0, + 0.0, 0.0, 0.0}; + std::vector dsw{-0.07406705, -0.07407386, 0.0, -0.07410901, 0.0, + -0.07410686, 0.0, 0.0, 0.0}; + std::vector dst0{2.963915, 0.0, 2.963912, 2.962338, 0.0, + 0.0, 2.96234, 0.0, 0.0}; for (int i = 0; i < result.size(); i++) { // rt - auto f_rt = [=](auto value) {return wiener_full_lpdf(value, a[i], v[i], - w[i], t0[i], sv[i], sw[i], st0[i]);}; + auto f_rt = [=](auto value) { + return wiener_full_lpdf(value, a[i], v[i], w[i], t0[i], sv[i], sw[i], + st0[i]); + }; check_scalar_types(f_rt, rt[i], result[i], drt[i]); // a - auto f_a = [=](auto value) {return wiener_full_lpdf(rt[i], value, v[i], - w[i], t0[i], sv[i], sw[i], st0[i]);}; + auto f_a = [=](auto value) { + return wiener_full_lpdf(rt[i], value, v[i], w[i], t0[i], sv[i], sw[i], + st0[i]); + }; check_scalar_types(f_a, a[i], result[i], da[i]); // v - auto f_v = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], value, - w[i], t0[i], sv[i], sw[i], st0[i]);}; + auto f_v = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], value, w[i], t0[i], sv[i], sw[i], + st0[i]); + }; check_scalar_types(f_v, v[i], result[i], dv[i]); // w - auto f_w = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], - value, t0[i], sv[i], sw[i], st0[i]);}; + auto f_w = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], v[i], value, t0[i], sv[i], sw[i], + st0[i]); + }; check_scalar_types(f_w, w[i], result[i], dw[i]); // t0 - auto f_t0 = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], - w[i], value, sv[i], sw[i], st0[i]);}; + auto f_t0 = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], v[i], w[i], value, sv[i], sw[i], + st0[i]); + }; check_scalar_types(f_t0, t0[i], result[i], dt0[i]); // sv - auto f_sv = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], - w[i], t0[i], value, sw[i], st0[i]);}; + auto f_sv = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], v[i], w[i], t0[i], value, sw[i], + st0[i]); + }; check_scalar_types(f_sv, sv[i], result[i], dsv[i]); // sw - auto f_sw = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], - w[i], t0[i], sv[i], value, st0[i]);}; + auto f_sw = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], v[i], w[i], t0[i], sv[i], value, + st0[i]); + }; check_scalar_types(f_sw, sw[i], result[i], dsw[i]); // st0 - auto f_st0 = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], - w[i], t0[i], sv[i], sw[i], value);}; + auto f_st0 = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], v[i], w[i], t0[i], sv[i], sw[i], + value); + }; check_scalar_types(f_st0, st0[i], result[i], dst0[i]); } } - From a773f2959a383d0426f79db76a58273dd155f2a1 Mon Sep 17 00:00:00 2001 From: Valentin Pratz Date: Fri, 7 Oct 2022 19:57:52 +0200 Subject: [PATCH 003/179] hcubature: Changed sqrt to std::sqrt and pow to std::pow --- stan/math/prim/functor/hcubature.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index b2d5a6a36aa..ba86e4e49fc 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -137,7 +137,7 @@ void signcombos(const T_k& k, const T_lambda& lambda, const T_n& n, T_p& p) { combination(c, n, k, i); std::vector index; index.clear(); - for (size_t j = 0; j != pow(2, k); j++) { + for (size_t j = 0; j != std::pow(2, k); j++) { increment(index, k, lambda, n, c, temp); T_lambda* next = reinterpret_cast(malloc(n * sizeof(T_lambda))); @@ -186,12 +186,12 @@ void gauss_kronrod(const F& integrand, const T_a& a, const T_b& b, T_oned& out, template void make_GenzMalik(const T_n& n, T_GenzMalik& g) { using T_return_type = return_type_t; - T_return_type l4 = sqrt(9 * 1.0 / 10); - T_return_type l2 = sqrt(9 * 1.0 / 70); + T_return_type l4 = std::sqrt(9 * 1.0 / 10); + T_return_type l2 = std::sqrt(9 * 1.0 / 70); T_return_type l3 = l4; - T_return_type l5 = sqrt(9 * 1.0 / 19); + T_return_type l5 = std::sqrt(9 * 1.0 / 19); - T_return_type twopn = pow(2, n); + T_return_type twopn = std::pow(2, n); g.w[0] = twopn * ((12824 - 9120 * n + 400 * n * n) * 1.0 / 19683); g.w[1] = twopn * (980.0 / 6561); @@ -318,7 +318,7 @@ void integrate_GenzMalik(const F& integrand, T_GenzMalik& g, const T_n& n, T_return_type E = fabs(I - Idash); int kdivide = 0; - T_return_type deltaf = E / (pow(10, n) * v); + T_return_type deltaf = E / (std::pow(10, n) * v); for (size_t i = 0; i != n; i++) { T_return_type delta = divdiff[i] - maxdivdiff; if (delta > deltaf) { @@ -388,7 +388,7 @@ return_type_t hcubature( internal::integrate_GenzMalik(integrand, g, n, a, b, out, pars); } T_return_type numevals - = (n == 1) ? 15 : 1 + 4 * n + 2 * n * (n - 1) + pow(2, n); + = (n == 1) ? 15 : 1 + 4 * n + 2 * n * (n - 1) + std::pow(2, n); T_return_type evals_per_box = numevals; T_return_type kdiv = out.kdivide; T_return_type err = out.err; From 651391bd0e328847069b90f81357b89e3a448d76 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Mon, 10 Oct 2022 13:49:53 +0200 Subject: [PATCH 004/179] update for cpplint-error --- stan/math/prim/prob/wiener_full_lpdf.hpp | 133 +++++++---------------- 1 file changed, 41 insertions(+), 92 deletions(-) diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 8143e07508b..bb9c35cb530 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -262,20 +262,14 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 > fabs(log(dens)) + log(.1) + lerror_bound_dens - log(2)) { + T_partials_return new_error + = log(.1) + lerror_bound_dens - log(2) + log(fabs(dens)); internal::my_params< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return> - params_new_error - = {y_val, - alpha_val, - delta_val, - beta_val, - t0_val, - sv_val, - sw_val, - st0_val, - log(.1) + lerror_bound_dens - log(2) + log(fabs(dens))}; + params_new_error = {y_val, alpha_val, delta_val, beta_val, t0_val, + sv_val, sw_val, st0_val, new_error}; dens = hcubature(internal::int_ddiff, void*>, ¶ms_new_error, dim, xmin, xmax, Meval, abstol, reltol); @@ -291,20 +285,14 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 > log(fabs(deriv_t_7)) + log(.1) + lerror_bound - log(2)) { + T_partials_return new_error + = log(.1) + lerror_bound - log(4) + log(fabs(deriv_t_7)); internal::my_params< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return> - params_new_error - = {y_val, - alpha_val, - delta_val, - beta_val, - t0_val, - sv_val, - sw_val, - st0_val, - log(.1) + lerror_bound - log(4) + log(fabs(deriv_t_7))}; + params_new_error = {y_val, alpha_val, delta_val, beta_val, t0_val, + sv_val, sw_val, st0_val, new_error}; deriv_t_7 = 1 / dens * hcubature(internal::int_dtddiff, void*>, @@ -324,20 +312,15 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 > log(fabs(deriv)) + log(.1) + lerror_bound - log(2)) { + T_partials_return new_error + = log(.1) + lerror_bound - log(4) + log(fabs(deriv)); internal::my_params< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return> params_new_error - = {y_val, - alpha_val, - delta_val, - beta_val, - t0_val, - sv_val, - sw_val, - st0_val, - log(.1) + lerror_bound - log(4) + log(fabs(deriv))}; + = {y_val, alpha_val, delta_val, beta_val, t0_val, + sv_val, sw_val, st0_val, new_error}; deriv = 1 / dens * hcubature(internal::int_daddiff, void*>, ¶ms_new_error, dim, xmin, xmax, Meval, abstol, @@ -352,20 +335,15 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 > log(fabs(deriv)) + log(.1) + lerror_bound - log(2)) { + T_partials_return new_error + = log(.1) + lerror_bound - log(2) + log(fabs(deriv)); internal::my_params< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return> params_new_error - = {y_val, - alpha_val, - delta_val, - beta_val, - t0_val, - sv_val, - sw_val, - st0_val, - log(.1) + lerror_bound - log(2) + log(fabs(deriv))}; + = {y_val, alpha_val, delta_val, beta_val, t0_val, + sv_val, sw_val, st0_val, new_error}; deriv = 1 / dens * hcubature(internal::int_dvddiff, void*>, ¶ms_new_error, dim, xmin, xmax, Meval, abstol, @@ -380,20 +358,15 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 > log(fabs(deriv)) + log(.1) + lerror_bound - log(2)) { + T_partials_return new_error + = log(.1) + lerror_bound - log(4) + log(fabs(deriv)); internal::my_params< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return> params_new_error - = {y_val, - alpha_val, - delta_val, - beta_val, - t0_val, - sv_val, - sw_val, - st0_val, - log(.1) + lerror_bound - log(4) + log(fabs(deriv))}; + = {y_val, alpha_val, delta_val, beta_val, t0_val, + sv_val, sw_val, st0_val, new_error}; deriv = 1 / dens * hcubature(internal::int_dwddiff, void*>, ¶ms_new_error, dim, xmin, xmax, Meval, abstol, @@ -411,20 +384,15 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 > log(fabs(deriv)) + log(.1) + lerror_bound - log(2)) { + T_partials_return new_error + = log(.1) + lerror_bound - log(2) + log(fabs(deriv)); internal::my_params< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return> params_new_error - = {y_val, - alpha_val, - delta_val, - beta_val, - t0_val, - sv_val, - sw_val, - st0_val, - log(.1) + lerror_bound - log(2) + log(fabs(deriv))}; + = {y_val, alpha_val, delta_val, beta_val, t0_val, + sv_val, sw_val, st0_val, new_error}; deriv = 1 / dens * hcubature(internal::int_dsvddiff, void*>, @@ -478,24 +446,17 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, dim_, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 > log(fabs(deriv) + log(.1) + lerror_bound - log(2))) { + T_partials_return new_error + = log(fabs(deriv)) + log(.1) + lerror_bound - log(2); internal::my_params2< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return> params_new_error_sw - = {y_val, - alpha_val, - delta_val, - beta_val, - lower, - upper, - t0_val, - sv_val, - 0, - sw_val, - st0_val, - log(fabs(deriv)) + log(.1) + lerror_bound - log(2)}; + = {y_val, alpha_val, delta_val, beta_val, + lower, upper, t0_val, sv_val, + 0, sw_val, st0_val, new_error}; deriv = hcubature( internal::int_dswddiff, void*>, ¶ms_new_error_sw, dim_, xmin, xmax, Meval, abstol, @@ -525,44 +486,32 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, - log(2) + log(fabs(f)))); deriv = 1 / st0_val * f; } else { + T_partials_return new_error = labstol_wiener5 - log(2); internal::my_params3< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return> - params_st = {y_val, - alpha_val, - delta_val, - beta_val, - t0_val, - t0_val + st0_val, - sv_val, - sw_val, - st0_val, - 0, - labstol_wiener5 - log(2)}; + params_st = {y_val, alpha_val, delta_val, + beta_val, t0_val, t0_val + st0_val, + sv_val, sw_val, st0_val, + 0, new_error}; deriv = hcubature( internal::int_dst0ddiff, void*>, ¶ms_st, dim_, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 > log(fabs(deriv) + log(.1) + lerror_bound - log(2))) { + T_partials_return new_error + = log(fabs(deriv)) + log(.1) + lerror_bound - log(2); internal::my_params3< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return> - params_new_error_st - = {y_val, - alpha_val, - delta_val, - beta_val, - t0_val, - t0_val + st0_val, - sv_val, - sw_val, - st0_val, - 0, - log(fabs(deriv)) + log(.1) + lerror_bound - log(2)}; + params_new_error_st = {y_val, alpha_val, delta_val, + beta_val, t0_val, t0_val + st0_val, + sv_val, sw_val, st0_val, + 0, new_error}; deriv = hcubature( internal::int_dst0ddiff, void*>, ¶ms_new_error_st, dim_, xmin, xmax, Meval, abstol, @@ -593,7 +542,7 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * \mathbb{R}_{\geq 0}\f$ the inter-trial variability of the drift rate, * \f$s_w \in [0, 1)\f$ the inter-trial variability of the relative starting * point, and \f$s_{t_0} \in \mathbb{R}_{\geq 0}\f$ the inter-trial variability - of + * of * the non-decision time. * * From b8d5bd5ec523cf31afe54be208d076b82b487289 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Mon, 10 Oct 2022 14:11:46 +0200 Subject: [PATCH 005/179] corrected for error in operands_and_partials --- stan/math/rev/functor/operands_and_partials.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/functor/operands_and_partials.hpp b/stan/math/rev/functor/operands_and_partials.hpp index b63e9d91b12..6c384368348 100644 --- a/stan/math/rev/functor/operands_and_partials.hpp +++ b/stan/math/rev/functor/operands_and_partials.hpp @@ -35,7 +35,7 @@ class ops_partials_edge { private: template + typename, typename, typename> friend class stan::math::operands_and_partials; var operand_; static constexpr int size() noexcept { return 1; } From 51392ddcaa97d0a17856da78eedbce8a9cb3162e Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Thu, 20 Oct 2022 09:51:58 +0200 Subject: [PATCH 006/179] adapted constants --- stan/math/prim/fun/wiener5_lpdf.hpp | 8 ++- stan/math/prim/prob/wiener_full_lpdf.hpp | 75 ++++++++++++------------ 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/stan/math/prim/fun/wiener5_lpdf.hpp b/stan/math/prim/fun/wiener5_lpdf.hpp index 746342da069..9ab28d2fea2 100644 --- a/stan/math/prim/fun/wiener5_lpdf.hpp +++ b/stan/math/prim/fun/wiener5_lpdf.hpp @@ -78,7 +78,7 @@ return_type_t dwiener5( K2 = 0.0; T_return_type temp_ = -2.0 * (log(pi() * q_asq) + el); if (temp_ >= 0) - K2 = sqrt(temp_ / (pow(pi(), 2) * q_asq)); + K2 = sqrt(temp_ / (PISQ * q_asq)); kll = ceil(fmax(K1, K2)); // if small t is better @@ -415,6 +415,8 @@ return_type_t dwdwiener5( using std::log; using std::pow; using std::sqrt; + + static const double TWO_LOG_PI = 2.0 * LOG_PI; T_return_type kll, kss, ans, v, w; T_return_type sign = -1; @@ -450,7 +452,7 @@ return_type_t dwdwiener5( // calculate number of terms kll needed for large t K1 = sqrt(2.0 / q_asq) / pi(); - u_eps = fmin(-1.0, log(4.0 / 9.0) + 2.0 * LOG_PI + 3.0 * log(q_asq) + u_eps = fmin(-1.0, log(4.0 / 9.0) + TWO_LOG_PI + 3.0 * log(q_asq) + 2.0 * (err - lg1)); arg = -(u_eps - sqrt(-2.0 * u_eps - 2.0)); K2 = (arg > 0) ? 1.0 / pi() * sqrt(arg / q_asq) : K1; @@ -520,7 +522,7 @@ return_type_t dwdwiener5( erg = log_diff_exp(fplus, fminus); } - ans = ans0 + newsign * exp(erg - ll + 2.0 * LOG_PI); + ans = ans0 + newsign * exp(erg - ll + TWO_LOG_PI); } if (normal_or_log == 1) return ans * sign * exp(ld); // derivative of f for hcubature diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index bb9c35cb530..1cbb16eb697 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -34,6 +34,9 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, using T_sv_ref = ref_type_t; using T_sw_ref = ref_type_t; using T_st0_ref = ref_type_t; + + static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; + static constexpr double LOG_POINT1 = -1; check_consistent_sizes(function_name, "Random variable", y, "Boundary separation", a, "Drift rate", v, @@ -172,10 +175,10 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, dens = internal::dwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, labstol_wiener5); - if (labstol_wiener5 > fabs(dens) + lerror_bound_dens - log(2)) + if (labstol_wiener5 > fabs(dens) + lerror_bound_dens - LOG_TWO) dens = internal::dwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, - fabs(dens) + lerror_bound_dens - log(2)); + fabs(dens) + lerror_bound_dens - LOG_TWO); ld += dens; // computation of derivative for t and precision check in order to give @@ -183,10 +186,10 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, T_partials_return deriv_t = internal::dtdwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, labstol_wiener5); - if (labstol_wiener5 > log(fabs(deriv_t)) + dens + lerror_bound - log(2)) + if (labstol_wiener5 > log(fabs(deriv_t)) + dens + lerror_bound - LOG_TWO) deriv_t = internal::dtdwiener5( y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, - log(fabs(deriv_t)) + dens + lerror_bound - log(4)); + log(fabs(deriv_t)) + dens + lerror_bound - LOG_FOUR); // computation of derivatives and precision checks if (!is_constant_all::value) { @@ -196,10 +199,10 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, T_partials_return deriv_a = internal::dadwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, labstol_wiener5, 0); - if (labstol_wiener5 > log(fabs(deriv_a)) + dens + lerror_bound - log(2)) + if (labstol_wiener5 > log(fabs(deriv_a)) + dens + lerror_bound - LOG_TWO) deriv_a = internal::dadwiener5( y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, - log(fabs(deriv_a)) + dens + lerror_bound - log(4), 0); + log(fabs(deriv_a)) + dens + lerror_bound - LOG_FOUR, 0); ops_partials.edge2_.partials_[i] = deriv_a; } if (!is_constant_all::value) { @@ -210,10 +213,10 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, T_partials_return deriv_w = internal::dwdwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, labstol_wiener5, 0); - if (labstol_wiener5 > log(fabs(deriv_w)) + dens + lerror_bound - log(2)) + if (labstol_wiener5 > log(fabs(deriv_w)) + dens + lerror_bound - LOG_TWO) deriv_w = internal::dwdwiener5( y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, - log(fabs(deriv_w)) + dens + lerror_bound - log(4), 0); + log(fabs(deriv_w)) + dens + lerror_bound - LOG_FOUR, 0); ops_partials.edge4_.partials_[i] = deriv_w; } if (!is_constant_all::value) { @@ -245,7 +248,7 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, T_partials_return, T_partials_return, T_partials_return> params = {y_val, alpha_val, delta_val, beta_val, t0_val, sv_val, - sw_val, st0_val, labstol_wiener5 - log(2)}; + sw_val, st0_val, labstol_wiener5 - LOG_TWO}; int dim = (sw_val != 0) + (st0_val != 0); check_positive(function_name, "(Inter-trial variability in A-priori bias) + " @@ -261,9 +264,9 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, dens = hcubature(internal::int_ddiff, void*>, ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 - > fabs(log(dens)) + log(.1) + lerror_bound_dens - log(2)) { + > fabs(log(dens)) + LOG_POINT1 + lerror_bound_dens - LOG_TWO) { T_partials_return new_error - = log(.1) + lerror_bound_dens - log(2) + log(fabs(dens)); + = LOG_POINT1 + lerror_bound_dens - LOG_TWO + log(fabs(dens)); internal::my_params< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, @@ -284,9 +287,9 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * hcubature(internal::int_dtddiff, void*>, ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 - > log(fabs(deriv_t_7)) + log(.1) + lerror_bound - log(2)) { + > log(fabs(deriv_t_7)) + LOG_POINT1 + lerror_bound - LOG_TWO) { T_partials_return new_error - = log(.1) + lerror_bound - log(4) + log(fabs(deriv_t_7)); + = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv_t_7)); internal::my_params< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, @@ -311,9 +314,9 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * hcubature(internal::int_daddiff, void*>, ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 - > log(fabs(deriv)) + log(.1) + lerror_bound - log(2)) { + > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { T_partials_return new_error - = log(.1) + lerror_bound - log(4) + log(fabs(deriv)); + = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv)); internal::my_params< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, @@ -334,9 +337,9 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * hcubature(internal::int_dvddiff, void*>, ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 - > log(fabs(deriv)) + log(.1) + lerror_bound - log(2)) { + > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { T_partials_return new_error - = log(.1) + lerror_bound - log(2) + log(fabs(deriv)); + = LOG_POINT1 + lerror_bound - LOG_TWO + log(fabs(deriv)); internal::my_params< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, @@ -357,9 +360,9 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * hcubature(internal::int_dwddiff, void*>, ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 - > log(fabs(deriv)) + log(.1) + lerror_bound - log(2)) { + > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { T_partials_return new_error - = log(.1) + lerror_bound - log(4) + log(fabs(deriv)); + = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv)); internal::my_params< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, @@ -383,9 +386,9 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * hcubature(internal::int_dsvddiff, void*>, ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 - > log(fabs(deriv)) + log(.1) + lerror_bound - log(2)) { + > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { T_partials_return new_error - = log(.1) + lerror_bound - log(2) + log(fabs(deriv)); + = LOG_POINT1 + lerror_bound - LOG_TWO + log(fabs(deriv)); internal::my_params< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, @@ -419,16 +422,16 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, lower, sv_val, labstol_wiener5)); fu = exp(internal::dwiener5(y_val - t0_val, alpha_val, delta_val, upper, sv_val, labstol_wiener5)); - if (labstol_wiener5 > log(fabs(fl + fu) + log(sw_val) - log(2) - + lerror_bound - log(2))) { + if (labstol_wiener5 > log(fabs(fl + fu) + log(sw_val) - LOG_TWO + + lerror_bound - LOG_TWO)) { fl = exp(internal::dwiener5(y_val - t0_val, alpha_val, delta_val, lower, sv_val, - lerror_bound - log(2) + log(sw_val) - - log(2) + log(fabs(fl + fu)))); + lerror_bound - LOG_TWO + log(sw_val) + - LOG_TWO + log(fabs(fl + fu)))); fu = exp(internal::dwiener5(y_val - t0_val, alpha_val, delta_val, upper, sv_val, - lerror_bound - log(2) + log(sw_val) - - log(2) + log(fabs(fl + fu)))); + lerror_bound - LOG_TWO + log(sw_val) + - LOG_TWO + log(fabs(fl + fu)))); } deriv = 1 / width * 0.5 * (fl + fu); } else { @@ -440,14 +443,14 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, params_sw = {y_val, alpha_val, delta_val, beta_val, lower, upper, t0_val, sv_val, - 0, sw_val, st0_val, labstol_wiener5 - log(2)}; + 0, sw_val, st0_val, labstol_wiener5 - LOG_TWO}; deriv = hcubature( internal::int_dswddiff, void*>, ¶ms_sw, dim_, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 - > log(fabs(deriv) + log(.1) + lerror_bound - log(2))) { + > log(fabs(deriv) + LOG_POINT1 + lerror_bound - LOG_TWO)) { T_partials_return new_error - = log(fabs(deriv)) + log(.1) + lerror_bound - log(2); + = log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO; internal::my_params2< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, @@ -479,14 +482,14 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, delta_val, beta_val, sv_val, labstol_wiener5)); if (labstol_wiener5 - > log(fabs(f) + log(st0_val) - log(2) + lerror_bound - log(2))) + > log(fabs(f) + log(st0_val) - LOG_TWO + lerror_bound - LOG_TWO)) f = exp(internal::dwiener5(y_val - (t0_val + st0_val), alpha_val, delta_val, beta_val, sv_val, - lerror_bound - log(2) + log(st0_val) - - log(2) + log(fabs(f)))); + lerror_bound - LOG_TWO + log(st0_val) + - LOG_TWO + log(fabs(f)))); deriv = 1 / st0_val * f; } else { - T_partials_return new_error = labstol_wiener5 - log(2); + T_partials_return new_error = labstol_wiener5 - LOG_TWO; internal::my_params3< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, @@ -500,9 +503,9 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, internal::int_dst0ddiff, void*>, ¶ms_st, dim_, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 - > log(fabs(deriv) + log(.1) + lerror_bound - log(2))) { + > log(fabs(deriv) + LOG_POINT1 + lerror_bound - LOG_TWO)) { T_partials_return new_error - = log(fabs(deriv)) + log(.1) + lerror_bound - log(2); + = log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO; internal::my_params3< T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, T_partials_return, From 60ec161b170a7a47cd008b00c18fb79f2e8ede65 Mon Sep 17 00:00:00 2001 From: Stan BuildBot Date: Thu, 20 Oct 2022 03:53:31 -0400 Subject: [PATCH 007/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/fun/wiener5_lpdf.hpp | 8 ++++---- stan/math/prim/prob/wiener_full_lpdf.hpp | 16 +++++++++------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/stan/math/prim/fun/wiener5_lpdf.hpp b/stan/math/prim/fun/wiener5_lpdf.hpp index 9ab28d2fea2..22385b296ec 100644 --- a/stan/math/prim/fun/wiener5_lpdf.hpp +++ b/stan/math/prim/fun/wiener5_lpdf.hpp @@ -415,8 +415,8 @@ return_type_t dwdwiener5( using std::log; using std::pow; using std::sqrt; - - static const double TWO_LOG_PI = 2.0 * LOG_PI; + + static const double TWO_LOG_PI = 2.0 * LOG_PI; T_return_type kll, kss, ans, v, w; T_return_type sign = -1; @@ -452,8 +452,8 @@ return_type_t dwdwiener5( // calculate number of terms kll needed for large t K1 = sqrt(2.0 / q_asq) / pi(); - u_eps = fmin(-1.0, log(4.0 / 9.0) + TWO_LOG_PI + 3.0 * log(q_asq) - + 2.0 * (err - lg1)); + u_eps = fmin( + -1.0, log(4.0 / 9.0) + TWO_LOG_PI + 3.0 * log(q_asq) + 2.0 * (err - lg1)); arg = -(u_eps - sqrt(-2.0 * u_eps - 2.0)); K2 = (arg > 0) ? 1.0 / pi() * sqrt(arg / q_asq) : K1; kll = ceil(fmax(K1, K2)); diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 1cbb16eb697..3a3b8594f8d 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -34,9 +34,9 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, using T_sv_ref = ref_type_t; using T_sw_ref = ref_type_t; using T_st0_ref = ref_type_t; - - static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; - static constexpr double LOG_POINT1 = -1; + + static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; + static constexpr double LOG_POINT1 = -1; check_consistent_sizes(function_name, "Random variable", y, "Boundary separation", a, "Drift rate", v, @@ -199,7 +199,8 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, T_partials_return deriv_a = internal::dadwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, labstol_wiener5, 0); - if (labstol_wiener5 > log(fabs(deriv_a)) + dens + lerror_bound - LOG_TWO) + if (labstol_wiener5 + > log(fabs(deriv_a)) + dens + lerror_bound - LOG_TWO) deriv_a = internal::dadwiener5( y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, log(fabs(deriv_a)) + dens + lerror_bound - LOG_FOUR, 0); @@ -213,7 +214,8 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, T_partials_return deriv_w = internal::dwdwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, labstol_wiener5, 0); - if (labstol_wiener5 > log(fabs(deriv_w)) + dens + lerror_bound - LOG_TWO) + if (labstol_wiener5 + > log(fabs(deriv_w)) + dens + lerror_bound - LOG_TWO) deriv_w = internal::dwdwiener5( y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, log(fabs(deriv_w)) + dens + lerror_bound - LOG_FOUR, 0); @@ -481,8 +483,8 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, f = exp(internal::dwiener5(y_val - (t0_val + st0_val), alpha_val, delta_val, beta_val, sv_val, labstol_wiener5)); - if (labstol_wiener5 - > log(fabs(f) + log(st0_val) - LOG_TWO + lerror_bound - LOG_TWO)) + if (labstol_wiener5 > log(fabs(f) + log(st0_val) - LOG_TWO + + lerror_bound - LOG_TWO)) f = exp(internal::dwiener5(y_val - (t0_val + st0_val), alpha_val, delta_val, beta_val, sv_val, lerror_bound - LOG_TWO + log(st0_val) From d54199ac059d9ccbe9513ed8f4a95b8787f9e566 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Sun, 29 Jan 2023 19:12:45 +0100 Subject: [PATCH 008/179] Removed old version of hcubature --- stan/math/prim/functor/hcubature.hpp | 469 --------------------------- 1 file changed, 469 deletions(-) delete mode 100644 stan/math/prim/functor/hcubature.hpp diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp deleted file mode 100644 index ba86e4e49fc..00000000000 --- a/stan/math/prim/functor/hcubature.hpp +++ /dev/null @@ -1,469 +0,0 @@ -// For the code in hcubature.hpp, the package JuliaMath/HCubature.jl -// written in Julia by Steven G. Johnson served as a template. -// It comes with the following MIT "Expat" license: -// -// Copyright (c) 2017: Steven G. Johnson. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files -// (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. - -#ifndef STAN_MATH_PRIM_FUNCTOR_HCUBATURE_HPP -#define STAN_MATH_PRIM_FUNCTOR_HCUBATURE_HPP - -#include -#include -#include -#include -#include -#include - -namespace stan { -namespace math { - -namespace internal { - -// tools -static const double xd7[8] = {-9.9145537112081263920685469752598e-01, - -9.4910791234275852452618968404809e-01, - -8.6486442335976907278971278864098e-01, - -7.415311855993944398638647732811e-01, - -5.8608723546769113029414483825842e-01, - -4.0584515137739716690660641207707e-01, - -2.0778495500789846760068940377309e-01, - 0.0}; - -static const double wd7[8] = {2.2935322010529224963732008059913e-02, - 6.3092092629978553290700663189093e-02, - 1.0479001032225018383987632254189e-01, - 1.4065325971552591874518959051021e-01, - 1.6900472663926790282658342659795e-01, - 1.9035057806478540991325640242055e-01, - 2.0443294007529889241416199923466e-01, - 2.0948214108472782801299917489173e-01}; - -static const double gwd7[4] = {1.2948496616886969327061143267787e-01, - 2.797053914892766679014677714229e-01, - 3.8183005050511894495036977548818e-01, - 4.1795918367346938775510204081658e-01}; - -struct one_d { - double result; - double err; - int kdivide = 0; -}; - -struct GenzMalik { - std::vector p[4]; - double w[5]; - double wd[4]; -}; - -template -void combination(T_c& c, const T_n& n, const T_p& p, const T_x& x) { - size_t i, r, k = 0; - for (i = 0; i < p - 1; i++) { - c[i] = (i != 0) ? c[i - 1] : 0; - do { - c[i]++; - r = choose(n - c[i], p - (i + 1)); - k = k + r; - } while (k < x); - k = k - r; - } - if (p > 1) - c[p - 1] = c[p - 2] + x - k; - else - c[0] = x; -} - -template -void combos(const T_k& k, const T_lambda& lambda, const T_n& n, T_p& p) { - T_k* c = reinterpret_cast(malloc(k * sizeof(T_k))); - for (size_t i = 1; i != choose(n, k) + 1; i++) { - T_lambda* temp = reinterpret_cast(calloc(n, sizeof(T_lambda))); - combination(c, n, k, i); - for (size_t j = 0; j != k; j++) - temp[c[j] - 1] = lambda; - p.push_back(temp); - } - free(c); -} - -template -void increment(T_index& index, const T_k& k, const T_lambda& lambda, - const T_n& n, const T_c& c, T_temp& temp) { - // temp size n, all elements initially zero - if (index.size() == 0) { - index.push_back(false); - for (size_t j = 0; j != k; j++) - temp[c[j] - 1] = lambda; - return; - } - T_k first_zero = 0; - while ((first_zero < index.size()) && index[first_zero]) - first_zero++; - if (first_zero == index.size()) { - index.flip(); - for (size_t j = 0; j != index.size(); j++) - temp[c[j] - 1] *= -1; - index.push_back(true); - temp[c[index.size() - 1] - 1] = -lambda; - } else { - for (size_t i = 0; i != first_zero + 1; i++) { - // index[i] = !index[i]; - if (index[i]) - index[i] = 0; - else - index[i] = 1; - temp[c[i] - 1] *= -1; - } - } -} - -template -void signcombos(const T_k& k, const T_lambda& lambda, const T_n& n, T_p& p) { - T_k* c = reinterpret_cast(malloc(k * sizeof(T_k))); - for (size_t i = 1; i != choose(n, k) + 1; i++) { - T_lambda* temp = reinterpret_cast(calloc(n, sizeof(T_lambda))); - combination(c, n, k, i); - std::vector index; - index.clear(); - for (size_t j = 0; j != std::pow(2, k); j++) { - increment(index, k, lambda, n, c, temp); - T_lambda* next - = reinterpret_cast(malloc(n * sizeof(T_lambda))); - memcpy(next, temp, n * sizeof(T_lambda)); - p.push_back(next); - } - free(temp); - } - free(c); -} - -template -void gauss_kronrod(const F& integrand, const T_a& a, const T_b& b, T_oned& out, - T_pars& pars) { - using T_return_type = return_type_t; - std::vector c(1, 0); - std::vector cp(1, 0); - std::vector cm(1, 0); - c[0] = 0.5 * (a + b); - T_return_type delta = 0.5 * (b - a); - T_return_type f0 = integrand(c, pars); - T_return_type I = f0 * wd7[7]; - T_return_type Idash = f0 * gwd7[3]; - for (size_t i = 0; i != 7; i++) { - T_return_type deltax = delta * xd7[i]; - cp[0] = c[0] + deltax; - cm[0] = c[0] - deltax; - T_return_type fx = integrand(cp, pars); - T_return_type temp = integrand(cm, pars); - fx += temp; - I += fx * wd7[i]; - if (i % 2 == 1) - Idash += fx * gwd7[i / 2]; - } - T_return_type V = fabs(delta); - I *= V; - Idash *= V; - out.result = I; - out.err = fabs(I - Idash); - std::vector().swap(c); - std::vector().swap(cp); - std::vector().swap(cm); -} - -template -void make_GenzMalik(const T_n& n, T_GenzMalik& g) { - using T_return_type = return_type_t; - T_return_type l4 = std::sqrt(9 * 1.0 / 10); - T_return_type l2 = std::sqrt(9 * 1.0 / 70); - T_return_type l3 = l4; - T_return_type l5 = std::sqrt(9 * 1.0 / 19); - - T_return_type twopn = std::pow(2, n); - - g.w[0] = twopn * ((12824 - 9120 * n + 400 * n * n) * 1.0 / 19683); - g.w[1] = twopn * (980.0 / 6561); - g.w[2] = twopn * ((1820 - 400 * n) * 1.0 / 19683); - g.w[3] = twopn * (200.0 / 19683); - g.w[4] = 6859.0 / 19683; - g.wd[3] = twopn * (25.0 / 729); - g.wd[2] = twopn * ((265 - 100 * n) * 1.0 / 1458); - g.wd[1] = twopn * (245.0 / 486); - g.wd[0] = twopn * ((729 - 950 * n + 50 * n * n) * 1.0 / 729); - - combos(1, l2, n, g.p[0]); - combos(1, l3, n, g.p[1]); - signcombos(2, l4, n, g.p[2]); - signcombos(n, l5, n, g.p[3]); -} - -template -void clean_GenzMalik(T_GenzMalik& g) { - for (size_t j = 0; j != 4; j++) - for (size_t i = 0; i != g.p[j].size(); i++) - if (g.p[j][i]) - free(g.p[j][i]); -} - -template -void integrate_GenzMalik(const F& integrand, T_GenzMalik& g, const T_n& n, - const T_a& a, const T_b& b, T_oned& out, - T_pars& pars) { - using T_return_type = return_type_t; - std::vector c(n, 0); - double* deltac = reinterpret_cast(malloc(n * sizeof(double))); - - for (size_t i = 0; i != n; i++) - c[i] = (a[i] + b[i]) / 2; - - for (size_t i = 0; i != n; i++) - deltac[i] = fabs(b[i] - a[i]) / 2; - T_return_type v = 1.0; - for (size_t i = 0; i != n; i++) - v *= deltac[i]; - - if (v == 0.0) { - out.err = 0.0; - out.result = 0.0; - out.kdivide = 0; - free(deltac); - return; - } - - T_return_type f1 = integrand(c, pars); - T_return_type f2 = 0.0; - T_return_type f3 = 0.0; - T_return_type twelvef1 = 12 * f1; - - T_return_type maxdivdiff = 0.0; - T_return_type* divdiff - = reinterpret_cast(malloc(n * sizeof(T_return_type))); - T_return_type* p2 - = reinterpret_cast(malloc(n * sizeof(T_return_type))); - T_return_type* p3 - = reinterpret_cast(malloc(n * sizeof(T_return_type))); - std::vector cc(n, 0); - - for (size_t i = 0; i != n; i++) { - for (size_t j = 0; j != n; j++) - p2[j] = deltac[j] * g.p[0][i][j]; - - for (size_t j = 0; j != n; j++) - cc[j] = c[j] + p2[j]; - T_return_type f2i = integrand(cc, pars); - for (size_t j = 0; j != n; j++) - cc[j] = c[j] - p2[j]; - T_return_type temp = integrand(cc, pars); - f2i += temp; - - for (size_t j = 0; j != n; j++) - p3[j] = deltac[j] * g.p[1][i][j]; - for (size_t j = 0; j != n; j++) - cc[j] = c[j] + p3[j]; - T_return_type f3i = integrand(cc, pars); - for (size_t j = 0; j != n; j++) - cc[j] = c[j] - p3[j]; - temp = integrand(cc, pars); - f3i += temp; - f2 += f2i; - f3 += f3i; - divdiff[i] = fabs(f3i + twelvef1 - 7 * f2i); - } - free(p2); - free(p3); - T_return_type* p4 - = reinterpret_cast(malloc(n * sizeof(T_return_type))); - T_return_type f4 = 0.0; - for (size_t i = 0; i != g.p[2].size(); i++) { - for (size_t j = 0; j != n; j++) - p4[j] = deltac[j] * g.p[2][i][j]; - for (size_t j = 0; j != n; j++) - cc[j] = c[j] + p4[j]; - T_return_type temp = integrand(cc, pars); - f4 += temp; - } - free(p4); - T_return_type f5 = 0.0; - T_return_type* p5 - = reinterpret_cast(malloc(n * sizeof(T_return_type))); - for (size_t i = 0; i != g.p[3].size(); i++) { - for (size_t j = 0; j != n; j++) - p5[j] = deltac[j] * g.p[3][i][j]; - - for (size_t j = 0; j != n; j++) - cc[j] = c[j] + p5[j]; - T_return_type temp = integrand(cc, pars); - f5 += temp; - } - free(p5); - std::vector().swap(cc); - T_return_type I - = v - * (g.w[0] * f1 + g.w[1] * f2 + g.w[2] * f3 + g.w[3] * f4 + g.w[4] * f5); - T_return_type Idash - = v * (g.wd[0] * f1 + g.wd[1] * f2 + g.wd[2] * f3 + g.wd[3] * f4); - T_return_type E = fabs(I - Idash); - - int kdivide = 0; - T_return_type deltaf = E / (std::pow(10, n) * v); - for (size_t i = 0; i != n; i++) { - T_return_type delta = divdiff[i] - maxdivdiff; - if (delta > deltaf) { - kdivide = i; - maxdivdiff = divdiff[i]; - } else if ((fabs(delta) <= deltaf) && (deltac[i] > deltac[kdivide])) { - kdivide = i; - } - } - out.result = I; - out.err = E; - out.kdivide = kdivide; - free(deltac); - free(divdiff); - std::vector().swap(c); -} - -class Box { - public: - Box(std::vector a, std::vector b, double& I, double& err, - int& kdivide) - : a(a), b(b), I(I), E(err), kdiv(kdivide) {} - bool operator<(const Box& box) const { return E > box.E; } - std::vector a; - std::vector b; - double I; - double E; - int kdiv; -}; - -inline class Box make_box(int n, std::vector a, std::vector b, - one_d out) { - std::vector ac(a); - std::vector bc(b); - Box box(ac, bc, out.result, out.err, out.kdivide); - return box; -} - -} // namespace internal - -// hcubature -template -return_type_t hcubature( - const F& integrand, const T_pars& pars, const T_n& n, const T_a& a, - const T_b& b, const T_maxEval& maxEval, const T_reqAbsError& reqAbsError, - const T_reqRelError& reqRelError) { - using T_return_type - = return_type_t; - - using T_a_ref = ref_type_t; - using T_b_ref = ref_type_t; - - T_a_ref a_ref = a; - T_b_ref b_ref = b; - - scalar_seq_view a_vec(a_ref); - scalar_seq_view b_vec(b_ref); - - internal::one_d out; - internal::GenzMalik g; - - if (n == 1) { - internal::gauss_kronrod(integrand, a_vec.val(0), b_vec.val(0), out, pars); - } else { - internal::make_GenzMalik(n, g); - internal::integrate_GenzMalik(integrand, g, n, a, b, out, pars); - } - T_return_type numevals - = (n == 1) ? 15 : 1 + 4 * n + 2 * n * (n - 1) + std::pow(2, n); - T_return_type evals_per_box = numevals; - T_return_type kdiv = out.kdivide; - T_return_type err = out.err; - T_return_type val = out.result; - // convergence test - if ((err <= fmax(reqRelError * fabs(val), reqAbsError)) - || ((maxEval != 0) && (numevals >= maxEval))) { - internal::clean_GenzMalik(g); - return val; - } - - std::multiset ms; - ms.insert(internal::make_box(n, a, b, out)); - - while (true) { - std::multiset::iterator it; - it = ms.begin(); - internal::Box box = *it; - ms.erase(it); - // split along dimension kdiv - T_return_type w = (box.b[box.kdiv] - box.a[box.kdiv]) / 2; - std::vector ma(box.a); - - ma[box.kdiv] += w; - std::vector mb(box.b); - mb[box.kdiv] -= w; - - if (n == 1) { - internal::gauss_kronrod(integrand, ma[0], box.b[0], out, pars); - } else { - internal::integrate_GenzMalik(integrand, g, n, ma, box.b, out, pars); - } - internal::Box box1 = make_box(n, ma, box.b, out); - ms.insert(box1); - - if (n == 1) { - internal::gauss_kronrod(integrand, box.a[0], mb[0], out, pars); - } else { - internal::integrate_GenzMalik(integrand, g, n, box.a, mb, out, pars); - } - internal::Box box2 = make_box(n, box.a, mb, out); - ms.insert(box2); - val += box1.I + box2.I - box.I; - err += box1.E + box2.E - box.E; - numevals += 2 * evals_per_box; - - std::vector().swap(box.a); - std::vector().swap(box.b); - std::vector().swap(ma); - std::vector().swap(mb); - if (((err <= max(reqRelError * fabs(val), reqAbsError)) - || ((maxEval != 0) && (numevals >= maxEval))) - || !(std::isfinite(val))) { - break; - } - } - val = 0.0; - err = 0.0; - - for (std::multiset::reverse_iterator rit = ms.rbegin(); - rit != ms.rend(); rit++) { - val += (*rit).I; - err += (*rit).E; - } - - for (std::multiset::iterator it = ms.begin(); it != ms.end(); - it++) { - internal::Box box = *it; - std::vector().swap(box.a); - std::vector().swap(box.b); - } - internal::clean_GenzMalik(g); - return val; -} // hcubature - -} // namespace math -} // namespace stan -#endif From 0ba5d42296ce021854a3aad8ce61b93777c29e6f Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Sun, 29 Jan 2023 21:55:34 +0100 Subject: [PATCH 009/179] int Meval --- stan/math/prim/prob/wiener_full_lpdf.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 3a3b8594f8d..93527ec065a 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -152,7 +152,7 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, T_partials_return abstol_wiener5 = 1e-12; // eps_abs(wiener5) T_partials_return labstol_wiener5 = log(abstol_wiener5); // log(eps_abs(wiener5) - T_partials_return Meval = 6000; + int Meval = 6000; T_partials_return dens = 0.0; T_partials_return ld = 0.0; operands_and_partials Date: Mon, 30 Jan 2023 12:11:50 +0100 Subject: [PATCH 010/179] changed name check_scalar_types_2 --- .../math/prim/prob/wiener_full_prec_test.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/unit/math/prim/prob/wiener_full_prec_test.cpp b/test/unit/math/prim/prob/wiener_full_prec_test.cpp index 3dd99a93ae9..c788f7be599 100644 --- a/test/unit/math/prim/prob/wiener_full_prec_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_prec_test.cpp @@ -164,7 +164,7 @@ TEST(mathPrimScalProbWienerFullPrecScal, invalid_st0) { // CHECK THAT ALL VALID SCALAR TYPES ARE ACCEPTED template -void check_scalar_types(F& f, double value, double res, double deriv) { +void check_scalar_types_2(F& f, double value, double res, double deriv) { // - f: Function with a single parameter exposed, all others // have to be scalars // - value: value to be used for the parameter @@ -229,48 +229,48 @@ TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { return wiener_full_prec_lpdf(value, a[i], v[i], w[i], t0[i], sv[i], sw[i], st0[i], 1e-6); }; - check_scalar_types(f_rt, rt[i], result[i], drt[i]); + check_scalar_types_2(f_rt, rt[i], result[i], drt[i]); // a auto f_a = [=](auto value) { return wiener_full_prec_lpdf(rt[i], value, v[i], w[i], t0[i], sv[i], sw[i], st0[i], 1e-6); }; - check_scalar_types(f_a, a[i], result[i], da[i]); + check_scalar_types_2(f_a, a[i], result[i], da[i]); // v auto f_v = [=](auto value) { return wiener_full_prec_lpdf(rt[i], a[i], value, w[i], t0[i], sv[i], sw[i], st0[i], 1e-6); }; - check_scalar_types(f_v, v[i], result[i], dv[i]); + check_scalar_types_2(f_v, v[i], result[i], dv[i]); // w auto f_w = [=](auto value) { return wiener_full_prec_lpdf(rt[i], a[i], v[i], value, t0[i], sv[i], sw[i], st0[i], 1e-6); }; - check_scalar_types(f_w, w[i], result[i], dw[i]); + check_scalar_types_2(f_w, w[i], result[i], dw[i]); // t0 auto f_t0 = [=](auto value) { return wiener_full_prec_lpdf(rt[i], a[i], v[i], w[i], value, sv[i], sw[i], st0[i], 1e-6); }; - check_scalar_types(f_t0, t0[i], result[i], dt0[i]); + check_scalar_types_2(f_t0, t0[i], result[i], dt0[i]); // sv auto f_sv = [=](auto value) { return wiener_full_prec_lpdf(rt[i], a[i], v[i], w[i], t0[i], value, sw[i], st0[i], 1e-6); }; - check_scalar_types(f_sv, sv[i], result[i], dsv[i]); + check_scalar_types_2(f_sv, sv[i], result[i], dsv[i]); // sw auto f_sw = [=](auto value) { return wiener_full_prec_lpdf(rt[i], a[i], v[i], w[i], t0[i], sv[i], value, st0[i], 1e-6); }; - check_scalar_types(f_sw, sw[i], result[i], dsw[i]); + check_scalar_types_2(f_sw, sw[i], result[i], dsw[i]); // st0 auto f_st0 = [=](auto value) { return wiener_full_prec_lpdf(rt[i], a[i], v[i], w[i], t0[i], sv[i], sw[i], value, 1e-6); }; - check_scalar_types(f_st0, st0[i], result[i], dst0[i]); + check_scalar_types_2(f_st0, st0[i], result[i], dst0[i]); } } From f5f32869498936bfba17331a0d8d88f51d525ff1 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Thu, 23 Mar 2023 15:57:33 +0100 Subject: [PATCH 011/179] removed warranty + toplevel comments, changed names, using, constants, pow, if --- stan/math/prim/fun/wiener5_lpdf.hpp | 431 ++++++++---------- stan/math/prim/fun/wiener7_lpdf.hpp | 142 +++--- stan/math/prim/prob/wiener_full_lpdf.hpp | 138 +++--- .../math/prim/prob/wiener_full_prec_test.cpp | 4 - test/unit/math/prim/prob/wiener_full_test.cpp | 4 - 5 files changed, 329 insertions(+), 390 deletions(-) diff --git a/stan/math/prim/fun/wiener5_lpdf.hpp b/stan/math/prim/fun/wiener5_lpdf.hpp index 22385b296ec..ff3282e3e0c 100644 --- a/stan/math/prim/fun/wiener5_lpdf.hpp +++ b/stan/math/prim/fun/wiener5_lpdf.hpp @@ -1,127 +1,104 @@ -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - #ifndef STAN_MATH_PRIM_FUN_WIENER5_LPDF_HPP #define STAN_MATH_PRIM_FUN_WIENER5_LPDF_HPP -#include +#include +#include +#include +#include #include namespace stan { namespace math { - -/* - * The log of the first passage time density function for a (Wiener) - * drift diffusion model with 5 parameters. - * -boundary separation (alpha), - * -drift rate (delta), - * -relative starting point (beta), - * -non-decision time (tau), - * -inter-trial variability in drift rate (sv). - * For details see wiener_full_lpdf. - */ - -//----------------------------------------------- -// DENSITY and derivatives -//----------------------------------------------- - namespace internal { -// calculate density in log -template -return_type_t dwiener5( - const T_y& q, const T_alpha& a, const T_delta& vn, const T_beta& wn, +return_type_t dwiener5( + const T_y& y, const T_a& a, const T_v& vn, const T_w& wn, const T_sv& sv, const double& err) { - using T_return_type = return_type_t; - using std::ceil; - using std::log; - using std::pow; - using std::sqrt; - - static const double PISQ = square(pi()); // pi*pi + using T_return_type = return_type_t; T_return_type kll, kss, ans, v, w; w = 1.0 - wn; v = -vn; - T_return_type q_asq = q / pow(a, 2); + T_return_type y_asq = y / square(a); ans = 0.0; // calculate the number of terms needed for short t T_return_type lg1; if (sv != 0) { - T_return_type eta_sqr = pow(sv, 2); - T_return_type temp = 1 + eta_sqr * q; - lg1 = (eta_sqr * pow(a * w, 2) - 2 * a * v * w - pow(v, 2) * q) / 2.0 / temp - - 2 * log(a) - 0.5 * log(temp); + T_return_type sv_sqr = square(sv); + T_return_type one_plus_svsqr_y = 1 + sv_sqr * y; + lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 / one_plus_svsqr_y + - 2 * log(a) - 0.5 * log(one_plus_svsqr_y); } else { - lg1 = (-2 * a * v * w - pow(v, 2) * q) / 2.0 - 2 * log(a); + lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - 2 * log(a); } T_return_type es = (err - lg1); - T_return_type K1 = (sqrt(2.0 * q_asq) + w) / 2.0; + T_return_type K1 = (sqrt(2.0 * y_asq) + w) / 2.0; T_return_type u_eps - = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log(q_asq) + 2.0 * (es)); - T_return_type arg = -q_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log(y_asq) + 2.0 * (es)); + T_return_type arg = -y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); T_return_type K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; kss = ceil(fmax(K1, K2)); // calculate the number of terms needed for large t T_return_type el = es; - K1 = 1.0 / (pi() * sqrt(q_asq)); + K1 = 1.0 / (pi() * sqrt(y_asq)); K2 = 0.0; - T_return_type temp_ = -2.0 * (log(pi() * q_asq) + el); - if (temp_ >= 0) - K2 = sqrt(temp_ / (PISQ * q_asq)); + T_return_type two_log_piy = -2.0 * (log(pi() * y_asq) + el); + static const double PISQ = square(pi()); // pi*pi + if (two_log_piy >= 0) { + K2 = sqrt(two_log_piy / (PISQ * y_asq)); + } kll = ceil(fmax(K1, K2)); // if small t is better if (2 * kss <= kll) { T_return_type fplus = NEGATIVE_INFTY; T_return_type fminus = NEGATIVE_INFTY; - T_return_type twot = 2.0 * q_asq; + T_return_type twoy = 2.0 * y_asq; if (static_cast(kss) > 0) { for (size_t k = static_cast(kss); k >= 1; k--) { - T_return_type temp1 = w + 2.0 * k; - T_return_type temp2 = w - 2.0 * k; + T_return_type w_plus_2k = w + 2.0 * k; + T_return_type w_minus_2k = w - 2.0 * k; - fplus = log_sum_exp(log(temp1) - pow(temp1, 2) / twot, fplus); - fminus = log_sum_exp(log(-temp2) - pow(temp2, 2) / twot, fminus); + fplus = log_sum_exp(log(w_plus_2k) - square(w_plus_2k) / twoy, fplus); + fminus = log_sum_exp(log(-w_minus_2k) - square(w_minus_2k) / twoy, fminus); } } - fplus = log_sum_exp(log(w) - pow(w, 2) / twot, fplus); + fplus = log_sum_exp(log(w) - square(w) / twoy, fplus); ans = lg1 - + (-0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log(q_asq) + + (-0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log(y_asq) + log_diff_exp(fplus, fminus)); // if large t is better } else { T_return_type fplus = NEGATIVE_INFTY; T_return_type fminus = NEGATIVE_INFTY; - T_return_type halfq = q_asq / 2.0; + T_return_type halfy = y_asq / 2.0; for (size_t k = static_cast(kll); k >= 1; k--) { - T_return_type temp = k * pi(); - T_return_type check = sin(temp * w); - if (check > 0) - fplus = log_sum_exp(log(static_cast(k)) - - pow(temp, 2) * halfq + log(check), + T_return_type pi_k = k * pi(); + T_return_type check = sin(pi_k * w); + if (check > 0) { + fplus = log_sum_exp(log(k) + - square(pi_k) * halfy + log(check), fplus); - else - fminus = log_sum_exp(log(static_cast(k)) - - pow(temp, 2) * halfq + log(-check), + } + else { + fminus = log_sum_exp(log(k) + - square(pi_k) * halfy + log(-check), fminus); + } } if (fplus < fminus) { ans = NEGATIVE_INFTY; } else { ans = lg1 + log_diff_exp(fplus, fminus) + LOG_PI; } - } + } return ans; } //----------------------------------------------- @@ -129,19 +106,12 @@ return_type_t dwiener5( // d/dt DENSITY // calculate derivative of density with respect to t (in log, ans = // d/dt(log(f))=d/dt f'/f; ans*exp(ld)=f' on normal scale) -template -return_type_t dtdwiener5( - const T_y& q, const T_alpha& a, const T_delta& vn, const T_beta& wn, +return_type_t dtdwiener5( + const T_y& y, const T_a& a, const T_v& vn, const T_w& wn, const T_sv& sv, const double& err) { - using T_return_type = return_type_t; - using std::ceil; - using std::exp; - using std::log; - using std::pow; - using std::sqrt; - - static const double PISQ = square(pi()); // pi*pi + using T_return_type = return_type_t; T_return_type kll, kss, ans, v, w; @@ -149,43 +119,44 @@ return_type_t dtdwiener5( v = -vn; // prepare some variables - T_return_type q_asq = q / pow(a, 2); + T_return_type y_asq = y / square(a); T_return_type la = 2.0 * log(a); T_return_type ans0, lg1; if (sv != 0) { - T_return_type eta_sqr = pow(sv, 2); - T_return_type temp = (1 + eta_sqr * q); + T_return_type sv_sqr = square(sv); + T_return_type one_plus_svsqr_y = (1 + sv_sqr * y); ans0 = -0.5 - * (pow(eta_sqr, 2) * (q + pow(a * w, 2)) - + eta_sqr * (1 - 2 * a * v * w) + pow(v, 2)) - / pow(temp, 2); - lg1 = (eta_sqr * pow(a * w, 2) - 2 * a * v * w - pow(v, 2) * q) / 2.0 / temp - - la - 0.5 * log(temp); + * (square(sv_sqr) * (y + square(a * w)) + + sv_sqr * (1 - 2 * a * v * w) + square(v)) + / square(one_plus_svsqr_y); + lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 / one_plus_svsqr_y + - la - 0.5 * log(one_plus_svsqr_y); } else { - ans0 = -0.5 * pow(v, 2); - lg1 = (-2 * a * v * w - pow(v, 2) * q) / 2.0 - la; + ans0 = -0.5 * square(v); + lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - la; } T_return_type factor = lg1 - la; - T_return_type ld = dwiener5(q, a, vn, wn, sv, - err - log(max(fabs(ans0 - 1.5 / q), fabs(ans0)))); + T_return_type ld = dwiener5(y, a, vn, wn, sv, + err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); // calculate the number of terms kss needed for small t T_return_type es = err - lg1; es = es + la; - T_return_type K1 = (sqrt(3.0 * q_asq) + w) / 2.0; + T_return_type K1 = (sqrt(3.0 * y_asq) + w) / 2.0; T_return_type u_eps = fmin( - -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(q_asq) + 2.0 * es) / 3.0); - T_return_type arg = -3.0 * q_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(y_asq) + 2.0 * es) / 3.0); + T_return_type arg = -3.0 * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); T_return_type K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; kss = ceil(fmax(K1, K2)); // calculate number of terms kll needed for large t T_return_type el = err - lg1; el = el + la; - K1 = sqrt(3.0 / q_asq) / pi(); - u_eps = fmin(-1.0, el + log(0.6) + LOG_PI + 2.0 * log(q_asq)); - arg = -2.0 / PISQ / q_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + K1 = sqrt(3.0 / y_asq) / pi(); + u_eps = fmin(-1.0, el + log(0.6) + LOG_PI + 2.0 * log(y_asq)); + static const double PISQ = square(pi()); // pi*pi + arg = -2.0 / PISQ / y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); T_return_type kl = (arg > 0) ? sqrt(arg) : K1; kll = ceil(fmax(kl, K1)); @@ -197,16 +168,16 @@ return_type_t dtdwiener5( // if small t is better if (2 * kss < kll) { // calculate terms of the sum for small t - T_return_type twot = 2.0 * q_asq; + T_return_type twoy = 2.0 * y_asq; if (static_cast(kss) > 0) { for (size_t k = static_cast(kss); k >= 1; k--) { - T_return_type temp1 = w + 2.0 * k; - T_return_type temp2 = w - 2.0 * k; - fplus = log_sum_exp(3.0 * log(temp1) - temp1 * temp1 / twot, fplus); - fminus = log_sum_exp(3.0 * log(-temp2) - temp2 * temp2 / twot, fminus); + T_return_type w_plus_2k = w + 2.0 * k; + T_return_type w_minus_2k = w - 2.0 * k; + fplus = log_sum_exp(3.0 * log(w_plus_2k) - w_plus_2k * w_plus_2k / twoy, fplus); + fminus = log_sum_exp(3.0 * log(-w_minus_2k) - w_minus_2k * w_minus_2k / twoy, fminus); } } - fplus = log_sum_exp(3.0 * log(w) - w * w / twot, fplus); + fplus = log_sum_exp(3.0 * log(w) - w * w / twoy, fplus); if (fplus < fminus) { newsign = -1; erg = log_diff_exp(fminus, fplus); @@ -214,25 +185,25 @@ return_type_t dtdwiener5( erg = log_diff_exp(fplus, fminus); } - ans = ans0 - 1.5 / q + ans = ans0 - 1.5 / y + newsign - * exp(factor - 1.5 * LOG_TWO - LOG_SQRT_PI - 3.5 * log(q_asq) + * exp(factor - 1.5 * LOG_TWO - LOG_SQRT_PI - 3.5 * log(y_asq) + erg - ld); // if large t is better } else { // calculate terms of the sum for large t - T_return_type halfq = q_asq / 2.0; + T_return_type halfy = y_asq / 2.0; for (size_t k = static_cast(kll); k >= 1; k--) { - T_return_type temp = pi() * k; - T_return_type zwi = sin(temp * w); + T_return_type pi_k = pi() * k; + T_return_type zwi = sin(pi_k * w); if (zwi > 0) { - fplus = log_sum_exp(3.0 * log(static_cast(k)) - - temp * temp * halfq + log(zwi), + fplus = log_sum_exp(3.0 * log(k) + - pi_k * pi_k * halfy + log(zwi), fplus); } if (zwi < 0) { - fminus = log_sum_exp(3.0 * log(static_cast(k)) - - temp * temp * halfq + log(-zwi), + fminus = log_sum_exp(3.0 * log(k) + - pi_k * pi_k * halfy + log(-zwi), fminus); } } @@ -252,65 +223,59 @@ return_type_t dtdwiener5( // d/da DENSITY // calculate derivative of density with respect to a (in log, ans = // d/da(log(f))=d/da f'/f; ans*exp(ld)=f' on normal scale) -template -return_type_t dadwiener5( - const T_y& q, const T_alpha& a, const T_delta& vn, const T_beta& wn, +return_type_t dadwiener5( + const T_y& y, const T_a& a, const T_v& vn, const T_w& wn, const T_sv& sv, const double& err, const int& normal_or_log) { - using T_return_type = return_type_t; - using std::ceil; - using std::exp; - using std::log; - using std::pow; - using std::sqrt; - - static const double PISQ = square(pi()); // pi*pi + using T_return_type = return_type_t; T_return_type kll, kss, ans, v, w; T_return_type la = log(a); - T_return_type lq = log(q); + T_return_type ly = log(y); w = 1.0 - wn; v = -vn; // prepare some variables - T_return_type q_asq = q / pow(a, 2); + T_return_type y_asq = y / square(a); T_return_type ans0, lg1; if (sv != 0) { - T_return_type eta_sqr = pow(sv, 2); - T_return_type temp = (1 + eta_sqr * q); - ans0 = (-v * w + eta_sqr * pow(w, 2) * a) / temp; - lg1 = (eta_sqr * pow(a * w, 2) - 2 * a * v * w - pow(v, 2) * q) / 2.0 / temp - - 2 * la - 0.5 * log(temp); + T_return_type sv_sqr = square(sv); + T_return_type one_plus_svsqr_y = (1 + sv_sqr * y); + ans0 = (-v * w + sv_sqr * square(w) * a) / one_plus_svsqr_y; + lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 / one_plus_svsqr_y + - 2 * la - 0.5 * log(one_plus_svsqr_y); } else { ans0 = -v * w; - lg1 = (-2 * a * v * w - pow(v, 2) * q) / 2.0 - 2 * la; + lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - 2 * la; } T_return_type factor = lg1 - 3 * la; T_return_type ld - = dwiener5(q, a, vn, wn, sv, + = dwiener5(y, a, vn, wn, sv, err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); // calculate the number of terms kss needed for small t T_return_type es = err - lg1; es = es + la; - es = es - LOG_TWO + 2.0 * la - lq; - T_return_type K1 = (sqrt(3.0 * q_asq) + w) / 2.0; + es = es - LOG_TWO + 2.0 * la - ly; + T_return_type K1 = (sqrt(3.0 * y_asq) + w) / 2.0; T_return_type u_eps = fmin( - -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(q_asq) + 2.0 * es) / 3.0); - T_return_type arg = -3.0 * q_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(y_asq) + 2.0 * es) / 3.0); + T_return_type arg = -3.0 * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); T_return_type K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; kss = ceil(fmax(K1, K2)); // calculate number of terms kll needed for large t T_return_type el = err - lg1; el = el + la; - el = el - LOG_TWO + 2.0 * la - lq; - K1 = sqrt(3.0 / q_asq) / pi(); - u_eps = fmin(-1.0, el + log(0.6) + LOG_PI + 2.0 * log(q_asq)); - arg = -2.0 / PISQ / q_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + el = el - LOG_TWO + 2.0 * la - ly; + K1 = sqrt(3.0 / y_asq) / pi(); + u_eps = fmin(-1.0, el + log(0.6) + LOG_PI + 2.0 * log(y_asq)); + static const double PISQ = square(pi()); // pi*pi + arg = -2.0 / PISQ / y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); T_return_type kl = (arg > 0) ? sqrt(arg) : K1; kll = ceil(fmax(kl, K1)); @@ -322,16 +287,16 @@ return_type_t dadwiener5( // if small t is better if (2 * kss < kll) { // calculate terms of the sum for short t - T_return_type twot = 2.0 * q_asq; + T_return_type twoy = 2.0 * y_asq; if (static_cast(kss) > 0) { for (size_t k = static_cast(kss); k >= 1; k--) { - T_return_type temp1 = w + 2.0 * k; - T_return_type temp2 = w - 2.0 * k; - fplus = log_sum_exp(3.0 * log(temp1) - temp1 * temp1 / twot, fplus); - fminus = log_sum_exp(3.0 * log(-temp2) - temp2 * temp2 / twot, fminus); + T_return_type w_plus_2k = w + 2.0 * k; + T_return_type w_minus_2k = w - 2.0 * k; + fplus = log_sum_exp(3.0 * log(w_plus_2k) - w_plus_2k * w_plus_2k / twoy, fplus); + fminus = log_sum_exp(3.0 * log(-w_minus_2k) - w_minus_2k * w_minus_2k / twoy, fminus); } } - fplus = log_sum_exp(3.0 * log(w) - w * w / twot, fplus); + fplus = log_sum_exp(3.0 * log(w) - w * w / twoy, fplus); if (fplus < fminus) { newsign = -1; erg = log_diff_exp(fminus, fplus); @@ -341,23 +306,23 @@ return_type_t dadwiener5( ans = ans0 + 1.0 / a - newsign - * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * lq + 4.0 * la + lg1 + * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * ly + 4.0 * la + lg1 + erg - ld); // if large t is better } else { // calculate terms of the sum for large t - T_return_type halfq = q_asq / 2.0; + T_return_type halfy = y_asq / 2.0; for (size_t k = static_cast(kll); k >= 1; k--) { - T_return_type temp = pi() * k; - T_return_type zwi = sin(temp * w); + T_return_type pi_k = pi() * k; + T_return_type zwi = sin(pi_k * w); if (zwi > 0) { - fplus = log_sum_exp(3.0 * log(static_cast(k)) - - temp * temp * halfq + log(zwi), + fplus = log_sum_exp(3.0 * log(k) + - pi_k * pi_k * halfy + log(zwi), fplus); } if (zwi < 0) { - fminus = log_sum_exp(3.0 * log(static_cast(k)) - - temp * temp * halfq + log(-zwi), + fminus = log_sum_exp(3.0 * log(k) + - pi_k * pi_k * halfy + log(-zwi), fminus); } } @@ -368,55 +333,49 @@ return_type_t dadwiener5( newsign = -1; } - ans = ans0 - 2.0 / a + newsign * exp(lq + factor + 3.0 * LOG_PI + erg - ld); + ans = ans0 - 2.0 / a + newsign * exp(ly + factor + 3.0 * LOG_PI + erg - ld); } - if (normal_or_log == 1) + if (normal_or_log == 1) { return ans * exp(ld); // derivative of f for hcubature - else + } + else { return ans; // derivative of log(f) + } } //----------------------------------------------- // d/dv DENSITY // calculate derivative of density with respect to v (in log, ans = // d/dv(log(f))=d/dv f'/f; ans*exp(ld)=f' on normal scale) -template -return_type_t dvdwiener5(const T_y& q, - const T_alpha& a, - const T_delta& vn, - const T_beta& wn, +return_type_t dvdwiener5(const T_y& y, + const T_a& a, + const T_v& vn, + const T_w& wn, const T_sv& sv) { - using T_return_type = return_type_t; - using std::pow; + using T_return_type = return_type_t; - T_return_type temp; + T_return_type ans; if (sv != 0) { - temp = 1 + pow(sv, 2) * q; - temp = (a * (1 - wn) - vn * q) / temp; + ans = 1 + square(sv) * y; + ans = (a * (1 - wn) - vn * y) / ans; } else { - temp = (a * (1 - wn) - vn * q); + ans = (a * (1 - wn) - vn * y); } - return temp; + return ans; } //----------------------------------------------- // d/dw DENSITY // calculate derivative of density with respect to w (in log, ans = // d/dw(log(f))=d/dw f'/f; ans*exp(ld)=f' on normal scale) -template -return_type_t dwdwiener5( - const T_y& q, const T_alpha& a, const T_delta& vn, const T_beta& wn, +return_type_t dwdwiener5( + const T_y& y, const T_a& a, const T_v& vn, const T_w& wn, const T_sv& sv, const double& err, const int& normal_or_log) { - using T_return_type = return_type_t; - using std::ceil; - using std::exp; - using std::log; - using std::pow; - using std::sqrt; - - static const double TWO_LOG_PI = 2.0 * LOG_PI; + using T_return_type = return_type_t; T_return_type kll, kss, ans, v, w; T_return_type sign = -1; @@ -425,37 +384,38 @@ return_type_t dwdwiener5( v = -vn; // prepare some variables - T_return_type q_asq = q / pow(a, 2); + T_return_type y_asq = y / square(a); T_return_type ans0, lg1; if (sv != 0) { - T_return_type eta_sqr = pow(sv, 2); - T_return_type temp = (1 + eta_sqr * q); - ans0 = (-v * a + eta_sqr * pow(a, 2) * w) / temp; - lg1 = (eta_sqr * pow(a * w, 2) - 2 * a * v * w - pow(v, 2) * q) / 2.0 / temp - - 2 * log(a) - 0.5 * log(temp); + T_return_type sv_sqr = square(sv); + T_return_type one_plus_svsqr_y = (1 + sv_sqr * y); + ans0 = (-v * a + sv_sqr * square(a) * w) / one_plus_svsqr_y; + lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 / one_plus_svsqr_y + - 2 * log(a) - 0.5 * log(one_plus_svsqr_y); } else { ans0 = -v * a; - lg1 = (-2 * a * v * w - pow(v, 2) * q) / 2.0 - 2 * log(a); + lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - 2 * log(a); } - T_return_type ld = dwiener5(q, a, vn, wn, sv, err - log(fabs(ans0))); + T_return_type ld = dwiener5(y, a, vn, wn, sv, err - log(fabs(ans0))); T_return_type ls = -lg1 + ld; T_return_type ll = -lg1 + ld; // calculate the number of terms kss needed for small t - T_return_type K1 = (sqrt(3.0 * q_asq) + w) / 2.0; + T_return_type K1 = (sqrt(3.0 * y_asq) + w) / 2.0; T_return_type u_eps - = fmin(-1.0, 2.0 * (err - lg1) + LOG_TWO + LOG_PI + 2.0 * log(q_asq)); - T_return_type arg = -q_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + = fmin(-1.0, 2.0 * (err - lg1) + LOG_TWO + LOG_PI + 2.0 * log(y_asq)); + T_return_type arg = -y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); T_return_type K2 = (arg > 0) ? 0.5 * (sqrt(arg) + w) : K1; kss = ceil(fmax(K1, K2)); // calculate number of terms kll needed for large t - K1 = sqrt(2.0 / q_asq) / pi(); + K1 = sqrt(2.0 / y_asq) / pi(); + static const double TWO_LOG_PI = 2.0 * LOG_PI; u_eps = fmin( - -1.0, log(4.0 / 9.0) + TWO_LOG_PI + 3.0 * log(q_asq) + 2.0 * (err - lg1)); + -1.0, log(4.0 / 9.0) + TWO_LOG_PI + 3.0 * log(y_asq) + 2.0 * (err - lg1)); arg = -(u_eps - sqrt(-2.0 * u_eps - 2.0)); - K2 = (arg > 0) ? 1.0 / pi() * sqrt(arg / q_asq) : K1; + K2 = (arg > 0) ? 1.0 / pi() * sqrt(arg / y_asq) : K1; kll = ceil(fmax(K1, K2)); T_return_type erg; @@ -466,27 +426,33 @@ return_type_t dwdwiener5( // if small t is better if (2 * kss < kll) { // calculate terms of the sum for short t - T_return_type twot = 2.0 * q_asq; + T_return_type twoy = 2.0 * y_asq; for (size_t k = static_cast(kss); k >= 1; k--) { - T_return_type temp1 = pow((w + 2 * k), 2); - T_return_type temp2 = pow((w - 2 * k), 2); - T_return_type temp3 = temp1 - q_asq; - T_return_type temp4 = temp2 - q_asq; - if (temp3 > 0) - fplus = log_sum_exp(log(temp3) - temp1 / twot, fplus); - else if (temp3 < 0) - fminus = log_sum_exp(log(-(temp3)) - temp1 / twot, fminus); - if (temp4 > 0) - fplus = log_sum_exp(log(temp4) - temp2 / twot, fplus); - else if (temp4 < 0) - fminus = log_sum_exp(log(-(temp4)) - temp2 / twot, fminus); + T_return_type sqrt_w_plus_2k = square(w + 2 * k); + T_return_type sqrt_w_minus_2k = square(w - 2 * k); + T_return_type wp2k_minusy = sqrt_w_plus_2k - y_asq; + T_return_type wm2k_minusy = sqrt_w_minus_2k - y_asq; + if (wp2k_minusy > 0) { + fplus = log_sum_exp(log(wp2k_minusy) - sqrt_w_plus_2k / twoy, fplus); + } + else if (wp2k_minusy < 0) { + fminus = log_sum_exp(log(-(wp2k_minusy)) - sqrt_w_plus_2k / twoy, fminus); + } + if (wm2k_minusy > 0) { + fplus = log_sum_exp(log(wm2k_minusy) - sqrt_w_minus_2k / twoy, fplus); + } + else if (wm2k_minusy < 0) { + fminus = log_sum_exp(log(-(wm2k_minusy)) - sqrt_w_minus_2k / twoy, fminus); + } } - T_return_type temp = pow(w, 2); - T_return_type temp1 = temp - q_asq; - if (temp1 > 0) - fplus = log_sum_exp(log(temp1) - temp / twot, fplus); - else if (temp1 < 0) - fminus = log_sum_exp(log(-(temp1)) - temp / twot, fminus); + T_return_type sqr_w = square(w); + T_return_type sqrt_w_plus_2k = sqr_w - y_asq; + if (sqrt_w_plus_2k > 0) { + fplus = log_sum_exp(log(sqrt_w_plus_2k) - sqr_w / twoy, fplus); + } + else if (sqrt_w_plus_2k < 0) { + fminus = log_sum_exp(log(-(sqrt_w_plus_2k)) - sqr_w / twoy, fminus); + } if (fplus < fminus) { newsign = -1; @@ -497,23 +463,25 @@ return_type_t dwdwiener5( ans = ans0 - newsign - * exp(erg - ls - 2.5 * log(q_asq) - 0.5 * LOG_TWO + * exp(erg - ls - 2.5 * log(y_asq) - 0.5 * LOG_TWO - 0.5 * LOG_PI); // if large t is better } else { // calculate terms of the sum for large t - T_return_type halfq = q_asq / 2.0; + T_return_type halfy = y_asq / 2.0; for (size_t k = static_cast(kll); k >= 1; k--) { - T_return_type temp = pi() * k; - T_return_type x = cos(temp * w); - if (x > 0) - fplus = log_sum_exp(2.0 * log(static_cast(k)) - - pow(temp, 2) * halfq + log(x), + T_return_type pi_k = pi() * k; + T_return_type x = cos(pi_k * w); + if (x > 0) { + fplus = log_sum_exp(2.0 * log(k) + - square(pi_k) * halfy + log(x), fplus); - else if (x < 0) - fminus = log_sum_exp(2.0 * log(static_cast(k)) - - pow(temp, 2) * halfq + log(-x), + } + else if (x < 0) { + fminus = log_sum_exp(2.0 * log(k) + - square(pi_k) * halfy + log(-x), fminus); + } } if (fplus < fminus) { erg = log_diff_exp(fminus, fplus); @@ -524,33 +492,34 @@ return_type_t dwdwiener5( ans = ans0 + newsign * exp(erg - ll + TWO_LOG_PI); } - if (normal_or_log == 1) + if (normal_or_log == 1) { return ans * sign * exp(ld); // derivative of f for hcubature - else + } + else { return ans * sign; // derivative of log(f) + } } //----------------------------------------------- // d/dsv DENSITY // calculate derivative of density with respect to sv (in log, ans = // d/dsv(log(f))=d/dsv f'/f; ans*exp(ld)=f' on normal scale) -template -return_type_t dsvdwiener5( - const T_y& q, const T_alpha& a, const T_delta& vn, const T_beta& wn, +return_type_t dsvdwiener5( + const T_y& y, const T_a& a, const T_v& vn, const T_w& wn, const T_sv& sv) { - using T_return_type = return_type_t; - using std::pow; + using T_return_type = return_type_t; T_return_type v, w; v = -vn; w = 1 - wn; - T_return_type temp = 1 + pow(sv, 2) * q; - T_return_type t1 = -q / temp; + T_return_type one_sqrsv_y = 1 + square(sv) * y; + T_return_type t1 = -y / one_sqrsv_y; T_return_type t2 - = (pow(a * w, 2) + 2 * a * v * w * q + pow(v * q, 2)) / pow(temp, 2); + = (square(a * w) + 2 * a * v * w * y + square(v * y)) / square(one_sqrsv_y); return sv * (t1 + t2); } //----------------------------------------------- diff --git a/stan/math/prim/fun/wiener7_lpdf.hpp b/stan/math/prim/fun/wiener7_lpdf.hpp index 8903bf36819..fb6ac125739 100644 --- a/stan/math/prim/fun/wiener7_lpdf.hpp +++ b/stan/math/prim/fun/wiener7_lpdf.hpp @@ -1,40 +1,26 @@ -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - #ifndef STAN_MATH_PRIM_FUN_WIENER7_LPDF_HPP #define STAN_MATH_PRIM_FUN_WIENER7_LPDF_HPP +#include +#include +#include #include +#include #include namespace stan { namespace math { - -/* - * Helper functions for the log of the first passage time density function for a - * (Wiener) drift diffusion model with 7 parameters. -boundary separation - * (alpha), -drift rate (delta), -relative starting point (beta), -non-decision - * time (tau), -inter-trial variability in drift rate (sv). -inter-trial - * variability in relative starting point (sw). -inter-trial variability in - * non-decition time (st0). For details see wiener_full_lpdf. - */ - namespace internal { // tools -template struct my_params { T_y y; - T_alpha a; - T_delta v; - T_beta w; + T_a a; + T_v v; + T_w w; T_t0 t0; T_sv sv; T_sw sw; @@ -42,17 +28,17 @@ struct my_params { T_err lerr; }; -template struct my_params2 { T_y y; - T_alpha a; - T_delta v; - T_beta w; - T_beta_lower w_lower; - T_beta_upper w_upper; + T_a a; + T_v v; + T_w w; + T_w_lower w_lower; + T_w_upper w_upper; T_t0 t0; T_sv sv; T_sw sw; @@ -61,14 +47,14 @@ struct my_params2 { T_err lerr; }; -template struct my_params3 { T_y y; - T_alpha a; - T_delta v; - T_beta w; + T_a a; + T_v v; + T_w w; T_t0 t0; T_t0_mean t0_mean; T_sv sv; @@ -80,60 +66,54 @@ struct my_params3 { // calculate derivative of density of wiener5 with respect to y (version for // wiener7) -template -return_type_t dtdwiener5_for_7( - const T_y& q, const T_alpha& a, const T_delta& v, const T_beta& w, +return_type_t dtdwiener5_for_7( + const T_y& y, const T_a& a, const T_v& v, const T_w& w, const T_sv& sv, const double& err) { - using T_return_type = return_type_t; - using std::ceil; - using std::exp; - using std::log; - using std::pow; - using std::sqrt; - - static const double PISQ = square(pi()); // pi*pi + using T_return_type = return_type_t; T_return_type kll, kss, ans; // prepare some variables - T_return_type q_asq = q / pow(a, 2); + T_return_type y_asq = y / square(a); T_return_type la = 2.0 * log(a); T_return_type ans0, lg1; if (sv != 0) { - T_return_type eta_sqr = pow(sv, 2); - T_return_type temp = (1 + eta_sqr * q); + T_return_type sv_sqr = square(sv); + T_return_type one_plus_svsqr_y = (1 + sv_sqr * y); ans0 = -0.5 - * (pow(eta_sqr, 2) * (q + pow(a * w, 2)) - + eta_sqr * (1 - 2 * a * v * w) + pow(v, 2)) - / pow(temp, 2); - lg1 = (eta_sqr * pow(a * w, 2) - 2 * a * v * w - pow(v, 2) * q) / 2.0 / temp - - la - 0.5 * log(temp); + * (square(sv_sqr) * (y + square(a * w)) + + sv_sqr * (1 - 2 * a * v * w) + square(v)) + / square(one_plus_svsqr_y); + lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 / one_plus_svsqr_y + - la - 0.5 * log(one_plus_svsqr_y); } else { - ans0 = -0.5 * pow(v, 2); - lg1 = (-2 * a * v * w - pow(v, 2) * q) / 2.0 - la; + ans0 = -0.5 * square(v); + lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - la; } T_return_type factor = lg1 - la; - T_return_type ld = dwiener5(q, a, -v, 1 - w, sv, - err - log(max(fabs(ans0), fabs(ans0 - 1.5 / q)))); + T_return_type ld = dwiener5(y, a, -v, 1 - w, sv, + err - log(max(fabs(ans0), fabs(ans0 - 1.5 / y)))); // calculate the number of terms kss needed for small y T_return_type es = err - lg1; es = es + la; - T_return_type K1 = (sqrt(3.0 * q_asq) + w) / 2.0; + T_return_type K1 = (sqrt(3.0 * y_asq) + w) / 2.0; T_return_type u_eps = fmin( - -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(q_asq) + 2.0 * es) / 3.0); - T_return_type arg = -3.0 * q_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(y_asq) + 2.0 * es) / 3.0); + T_return_type arg = -3.0 * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); T_return_type K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; kss = ceil(fmax(K1, K2)); // calculate number of terms kll needed for large y T_return_type el = err - lg1; el = el + la; - K1 = sqrt(3.0 / q_asq) / pi(); - u_eps = fmin(-1.0, el + log(0.6) + LOG_PI + 2.0 * log(q_asq)); - arg = -2.0 / PISQ / q_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + K1 = sqrt(3.0 / y_asq) / pi(); + u_eps = fmin(-1.0, el + log(0.6) + LOG_PI + 2.0 * log(y_asq)); + static const double PISQ = square(pi()); // pi*pi + arg = -2.0 / PISQ / y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); T_return_type kl = (arg > 0) ? sqrt(arg) : K1; kll = ceil(fmax(kl, K1)); @@ -145,13 +125,13 @@ return_type_t dtdwiener5_for_7( // if small y is better if (2 * kss < kll) { // calculate terms of the sum for small y - T_return_type twot = 2.0 * q_asq; + T_return_type twot = 2.0 * y_asq; if (static_cast(kss) > 0) { for (size_t k = static_cast(kss); k >= 1; k--) { - T_return_type temp1 = w + 2.0 * k; - T_return_type temp2 = w - 2.0 * k; - fplus = log_sum_exp(3.0 * log(temp1) - temp1 * temp1 / twot, fplus); - fminus = log_sum_exp(3.0 * log(-temp2) - temp2 * temp2 / twot, fminus); + T_return_type w_plus_2k = w + 2.0 * k; + T_return_type w_minus_2k = w - 2.0 * k; + fplus = log_sum_exp(3.0 * log(w_plus_2k) - w_plus_2k * w_plus_2k / twot, fplus); + fminus = log_sum_exp(3.0 * log(-w_minus_2k) - w_minus_2k * w_minus_2k / twot, fminus); } } fplus = log_sum_exp(3.0 * log(w) - w * w / twot, fplus); @@ -162,25 +142,25 @@ return_type_t dtdwiener5_for_7( erg = log_diff_exp(fplus, fminus); } - ans = ans0 - 1.5 / q + ans = ans0 - 1.5 / y + newsign - * exp(factor - 1.5 * LOG_TWO - LOG_SQRT_PI - 3.5 * log(q_asq) + * exp(factor - 1.5 * LOG_TWO - LOG_SQRT_PI - 3.5 * log(y_asq) + erg - ld); // if large y is better } else { // calculate terms of the sum for large y - T_return_type halfq = q_asq / 2.0; + T_return_type halfy = y_asq / 2.0; for (size_t k = static_cast(kll); k >= 1; k--) { - T_return_type temp = pi() * k; - T_return_type zwi = sin(temp * w); + T_return_type pi_k = pi() * k; + T_return_type zwi = sin(pi_k * w); if (zwi > 0) { - fplus = log_sum_exp(3.0 * log(static_cast(k)) - - temp * temp * halfq + log(zwi), + fplus = log_sum_exp(3.0 * log(k) + - pi_k * pi_k * halfy + log(zwi), fplus); } if (zwi < 0) { - fminus = log_sum_exp(3.0 * log(static_cast(k)) - - temp * temp * halfq + log(-zwi), + fminus = log_sum_exp(3.0 * log(k) + - pi_k * pi_k * halfy + log(-zwi), fminus); } } @@ -309,10 +289,9 @@ return_type_t int_daddiff(const T_x& x, const T_p& p) { retval = 0.0; } else { // prepare some variables for error estimation in density - T_return_type eta_sqr = pow(sv, 2); - T_return_type temp = (1 + eta_sqr * (y - t0_)); + T_return_type sv_sqr = square(sv); T_return_type ans0 - = (v * (1 - omega) + eta_sqr * pow((1 - omega), 2) * a) / temp; + = (v * (1 - omega) + sv_sqr * square(1 - omega) * a) / (1 + sv_sqr * (y - t0_)); T_return_type factor = max(ans0 + 1.0 / a, ans0 - 2.0 / a); // factor from small and large // representation, for same @@ -398,9 +377,8 @@ return_type_t int_dwddiff(const T_x& x, const T_p& p) { retval = 0.0; } else { // prepare some variables for error estimation in density - T_return_type eta_sqr = pow(sv, 2); - T_return_type temp = (1 + eta_sqr * (y - t0_)); - T_return_type ans0 = (v * a + eta_sqr * pow(a, 2) * (1 - omega)) / temp; + T_return_type sv_sqr = square(sv); + T_return_type ans0 = (v * a + sv_sqr * square(a) * (1 - omega)) / (1 + sv_sqr * (y - t0_)); // compute partial derivative retval = dwdwiener5(y - t0_, a, v, omega, sv, lerr, 1); } diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 93527ec065a..3a40b4fcc98 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -1,43 +1,31 @@ -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - #ifndef STAN_MATH_PRIM_PROB_WIENER_FULL_LPDF_HPP #define STAN_MATH_PRIM_PROB_WIENER_FULL_LPDF_HPP #include namespace stan { -namespace math { - +namespace math { namespace internal { -template -inline return_type_t +inline return_type_t wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, - const T_alpha& a, const T_delta& v, const T_beta& w, + const T_a& a, const T_v& v, const T_w& w, const T_t0& t0, const T_sv& sv, const T_sw& sw, const T_st0& st0, const double& prec) { - using T_partials_return = partials_return_t; using T_y_ref = ref_type_t; - using T_alpha_ref = ref_type_t; - using T_delta_ref = ref_type_t; - using T_beta_ref = ref_type_t; + using T_a_ref = ref_type_t; + using T_v_ref = ref_type_t; + using T_w_ref = ref_type_t; using T_t0_ref = ref_type_t; using T_sv_ref = ref_type_t; using T_sw_ref = ref_type_t; using T_st0_ref = ref_type_t; - static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; - static constexpr double LOG_POINT1 = -1; - check_consistent_sizes(function_name, "Random variable", y, "Boundary separation", a, "Drift rate", v, "A-priori bias", w, "Nondecision time", t0, @@ -58,9 +46,9 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, "Inter-trial variability in Nondecision time", st0, 1); T_y_ref y_ref = y; - T_alpha_ref alpha_ref = a; - T_delta_ref delta_ref = v; - T_beta_ref beta_ref = w; + T_a_ref alpha_ref = a; + T_v_ref delta_ref = v; + T_w_ref beta_ref = w; T_t0_ref t0_ref = t0; T_sv_ref sv_ref = sv; T_sw_ref sw_ref = sw; @@ -86,17 +74,19 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, check_finite(function_name, "Inter-trial variability in Nondecision time", value_of(st0_ref)); - if (size_zero(y, a, v, w, t0) || size_zero(sv, sw, st0)) + if (size_zero(y, a, v, w, t0) || size_zero(sv, sw, st0)) { return 0; + } size_t N = max_size(y, a, v, w, t0, sv, sw, st0); - if (!N) + if (!N) { return 0; + } scalar_seq_view y_vec(y_ref); - scalar_seq_view alpha_vec(alpha_ref); - scalar_seq_view delta_vec(delta_ref); - scalar_seq_view beta_vec(beta_ref); + scalar_seq_view alpha_vec(alpha_ref); + scalar_seq_view delta_vec(delta_ref); + scalar_seq_view beta_vec(beta_ref); scalar_seq_view t0_vec(t0_ref); scalar_seq_view sv_vec(sv_ref); scalar_seq_view sw_vec(sw_ref); @@ -134,9 +124,10 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, } } - if (!include_summand::value) + if (!include_summand::value) { return 0; + } // abstol_wiener5 z.B. 1e-12 on normal scale // T_partials_return error_bound = 1e-6; @@ -155,11 +146,14 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, int Meval = 6000; T_partials_return dens = 0.0; T_partials_return ld = 0.0; - operands_and_partials ops_partials(y_ref, alpha_ref, delta_ref, beta_ref, t0_ref, sv_ref, sw_ref, st0_ref); + static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; + static constexpr double LOG_POINT1 = -1; + // calculate density and partials for (size_t i = 0; i < N; i++) { // Calculate 4-parameter model without inter-trial variabilities (if @@ -175,10 +169,11 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, dens = internal::dwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, labstol_wiener5); - if (labstol_wiener5 > fabs(dens) + lerror_bound_dens - LOG_TWO) + if (labstol_wiener5 > fabs(dens) + lerror_bound_dens - LOG_TWO) { dens = internal::dwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, fabs(dens) + lerror_bound_dens - LOG_TWO); + } ld += dens; // computation of derivative for t and precision check in order to give @@ -186,39 +181,42 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, T_partials_return deriv_t = internal::dtdwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, labstol_wiener5); - if (labstol_wiener5 > log(fabs(deriv_t)) + dens + lerror_bound - LOG_TWO) + if (labstol_wiener5 > log(fabs(deriv_t)) + dens + lerror_bound - LOG_TWO) { deriv_t = internal::dtdwiener5( y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, log(fabs(deriv_t)) + dens + lerror_bound - LOG_FOUR); + } // computation of derivatives and precision checks if (!is_constant_all::value) { ops_partials.edge1_.partials_[i] = deriv_t; } - if (!is_constant_all::value) { + if (!is_constant_all::value) { T_partials_return deriv_a = internal::dadwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, labstol_wiener5, 0); if (labstol_wiener5 - > log(fabs(deriv_a)) + dens + lerror_bound - LOG_TWO) + > log(fabs(deriv_a)) + dens + lerror_bound - LOG_TWO) { deriv_a = internal::dadwiener5( y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, log(fabs(deriv_a)) + dens + lerror_bound - LOG_FOUR, 0); + } ops_partials.edge2_.partials_[i] = deriv_a; } - if (!is_constant_all::value) { + if (!is_constant_all::value) { ops_partials.edge3_.partials_[i] = internal::dvdwiener5( y_val - t0_val, alpha_val, delta_val, beta_val, sv_val); } - if (!is_constant_all::value) { + if (!is_constant_all::value) { T_partials_return deriv_w = internal::dwdwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, labstol_wiener5, 0); if (labstol_wiener5 - > log(fabs(deriv_w)) + dens + lerror_bound - LOG_TWO) + > log(fabs(deriv_w)) + dens + lerror_bound - LOG_TWO) { deriv_w = internal::dwdwiener5( y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, log(fabs(deriv_w)) + dens + lerror_bound - LOG_FOUR, 0); + } ops_partials.edge4_.partials_[i] = deriv_w; } if (!is_constant_all::value) { @@ -260,8 +258,9 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, std::vector xmin(dim, 0); std::vector xmax(dim, 1); - if (st0_val) + if (st0_val) { xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); + } dens = hcubature(internal::int_ddiff, void*>, ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); @@ -310,7 +309,7 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, if (!is_constant_all::value) { ops_partials.edge1_.partials_[i] = deriv_t_7; } - if (!is_constant_all::value) { + if (!is_constant_all::value) { deriv = 1 / dens * hcubature(internal::int_daddiff, void*>, @@ -333,7 +332,7 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, } ops_partials.edge2_.partials_[i] = deriv; } - if (!is_constant_all::value) { + if (!is_constant_all::value) { deriv = 1 / dens * hcubature(internal::int_dvddiff, void*>, @@ -356,7 +355,7 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, } ops_partials.edge3_.partials_[i] = deriv; } - if (!is_constant_all::value) { + if (!is_constant_all::value) { deriv = 1 / dens * hcubature(internal::int_dwddiff, void*>, @@ -484,11 +483,12 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, delta_val, beta_val, sv_val, labstol_wiener5)); if (labstol_wiener5 > log(fabs(f) + log(st0_val) - LOG_TWO - + lerror_bound - LOG_TWO)) + + lerror_bound - LOG_TWO)) { f = exp(internal::dwiener5(y_val - (t0_val + st0_val), alpha_val, delta_val, beta_val, sv_val, lerror_bound - LOG_TWO + log(st0_val) - LOG_TWO + log(fabs(f)))); + } deriv = 1 / st0_val * f; } else { T_partials_return new_error = labstol_wiener5 - LOG_TWO; @@ -585,9 +585,9 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * See \b Details below for more details on how to use \c wiener_full_lpdf(). * * @tparam T_y type of scalar - * @tparam T_alpha type of boundary - * @tparam T_delta type of drift rate - * @tparam T_beta type of relative starting point + * @tparam T_a type of boundary + * @tparam T_v type of drift rate + * @tparam T_w type of relative starting point * @tparam T_t0 type of non-decision time * @tparam T_sv type of inter-trial variability of drift rate * @tparam T_sw type of inter-trial variability of relative starting point @@ -678,25 +678,25 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * https://doi.org/10.1016/j.jmp.2009.02.003 */ -template -inline return_type_t -wiener_full_lpdf(const T_y& y, const T_alpha& a, const T_delta& v, - const T_beta& w, const T_t0& t0, const T_sv& sv, +inline return_type_t +wiener_full_lpdf(const T_y& y, const T_a& a, const T_v& v, + const T_w& w, const T_t0& t0, const T_sv& sv, const T_sw& sw, const T_st0& st0) { double precision = 1e-4; - return internal::wiener_full_prec_impl_lpdf( + return internal::wiener_full_prec_impl_lpdf( "wiener_full_lpdf", y, a, v, w, t0, sv, sw, st0, precision); } -template -inline return_type_t -wiener_full_lpdf(const T_y& y, const T_alpha& a, const T_delta& v, - const T_beta& w, const T_t0& t0, const T_sv& sv, +inline return_type_t +wiener_full_lpdf(const T_y& y, const T_a& a, const T_v& v, + const T_w& w, const T_t0& t0, const T_sv& sv, const T_sw& sw, const T_st0& st0) { double precision = 1e-4; @@ -713,23 +713,23 @@ wiener_full_lpdf(const T_y& y, const T_alpha& a, const T_delta& v, * functions are the same excpet of the control over the precision. */ -template -inline return_type_t -wiener_full_prec_lpdf(const T_y& y, const T_alpha& a, const T_delta& v, - const T_beta& w, const T_t0& t0, const T_sv& sv, +inline return_type_t +wiener_full_prec_lpdf(const T_y& y, const T_a& a, const T_v& v, + const T_w& w, const T_t0& t0, const T_sv& sv, const T_sw& sw, const T_st0& st0, const double& prec) { - return internal::wiener_full_prec_impl_lpdf( + return internal::wiener_full_prec_impl_lpdf( "wiener_full_prec_lpdf", y, a, v, w, t0, sv, sw, st0, prec); } -template -inline return_type_t -wiener_full_prec_lpdf(const T_y& y, const T_alpha& a, const T_delta& v, - const T_beta& w, const T_t0& t0, const T_sv& sv, +inline return_type_t +wiener_full_prec_lpdf(const T_y& y, const T_a& a, const T_v& v, + const T_w& w, const T_t0& t0, const T_sv& sv, const T_sw& sw, const T_st0& st0, const double& prec) { return internal::wiener_full_prec_impl_lpdf( "wiener_full_prec_lpdf", y, a, v, w, t0, sv, sw, st0, prec); diff --git a/test/unit/math/prim/prob/wiener_full_prec_test.cpp b/test/unit/math/prim/prob/wiener_full_prec_test.cpp index c788f7be599..a01be67a2bb 100644 --- a/test/unit/math/prim/prob/wiener_full_prec_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_prec_test.cpp @@ -6,10 +6,6 @@ #include #include -// signature: wiener_full_prec_lpdf(y, a, v, w, t0, sv, sw, st0, precision); - -// CHECKING FOR (IN)VALID INPUT - TEST(mathPrimScalProbWienerFullPrecScal, valid) { using stan::math::INFTY; using stan::math::wiener_full_prec_lpdf; diff --git a/test/unit/math/prim/prob/wiener_full_test.cpp b/test/unit/math/prim/prob/wiener_full_test.cpp index 4158b7537f7..96658f30dc4 100644 --- a/test/unit/math/prim/prob/wiener_full_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_test.cpp @@ -6,10 +6,6 @@ #include #include -// signature: wiener_full_lpdf(y, a, v, w, t0, sv, sw, st0); - -// CHECKING FOR (IN)VALID INPUT - TEST(mathPrimScalProbWienerFullScal, valid) { using stan::math::INFTY; using stan::math::wiener_full_lpdf; From 2bad948c2751114f266e3587c52e11cb141cd7db Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 23 Mar 2023 11:01:48 -0400 Subject: [PATCH 012/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/fun/wiener5_lpdf.hpp | 168 +++++++++++------------ stan/math/prim/fun/wiener7_lpdf.hpp | 47 ++++--- stan/math/prim/prob/wiener_full_lpdf.hpp | 82 ++++++----- 3 files changed, 144 insertions(+), 153 deletions(-) diff --git a/stan/math/prim/fun/wiener5_lpdf.hpp b/stan/math/prim/fun/wiener5_lpdf.hpp index ff3282e3e0c..b2143739814 100644 --- a/stan/math/prim/fun/wiener5_lpdf.hpp +++ b/stan/math/prim/fun/wiener5_lpdf.hpp @@ -11,12 +11,12 @@ namespace stan { namespace math { namespace internal { -// calculate density in log -template -return_type_t dwiener5( - const T_y& y, const T_a& a, const T_v& vn, const T_w& wn, - const T_sv& sv, const double& err) { +// calculate density in log +template +return_type_t dwiener5(const T_y& y, const T_a& a, + const T_v& vn, const T_w& wn, + const T_sv& sv, + const double& err) { using T_return_type = return_type_t; T_return_type kll, kss, ans, v, w; @@ -32,7 +32,8 @@ return_type_t dwiener5( if (sv != 0) { T_return_type sv_sqr = square(sv); T_return_type one_plus_svsqr_y = 1 + sv_sqr * y; - lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 / one_plus_svsqr_y + lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 + / one_plus_svsqr_y - 2 * log(a) - 0.5 * log(one_plus_svsqr_y); } else { lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - 2 * log(a); @@ -67,7 +68,8 @@ return_type_t dwiener5( T_return_type w_minus_2k = w - 2.0 * k; fplus = log_sum_exp(log(w_plus_2k) - square(w_plus_2k) / twoy, fplus); - fminus = log_sum_exp(log(-w_minus_2k) - square(w_minus_2k) / twoy, fminus); + fminus + = log_sum_exp(log(-w_minus_2k) - square(w_minus_2k) / twoy, fminus); } } fplus = log_sum_exp(log(w) - square(w) / twoy, fplus); @@ -83,22 +85,18 @@ return_type_t dwiener5( T_return_type pi_k = k * pi(); T_return_type check = sin(pi_k * w); if (check > 0) { - fplus = log_sum_exp(log(k) - - square(pi_k) * halfy + log(check), - fplus); - } - else { - fminus = log_sum_exp(log(k) - - square(pi_k) * halfy + log(-check), - fminus); - } + fplus = log_sum_exp(log(k) - square(pi_k) * halfy + log(check), fplus); + } else { + fminus + = log_sum_exp(log(k) - square(pi_k) * halfy + log(-check), fminus); + } } if (fplus < fminus) { ans = NEGATIVE_INFTY; } else { ans = lg1 + log_diff_exp(fplus, fminus) + LOG_PI; } - } + } return ans; } //----------------------------------------------- @@ -106,11 +104,11 @@ return_type_t dwiener5( // d/dt DENSITY // calculate derivative of density with respect to t (in log, ans = // d/dt(log(f))=d/dt f'/f; ans*exp(ld)=f' on normal scale) -template -return_type_t dtdwiener5( - const T_y& y, const T_a& a, const T_v& vn, const T_w& wn, - const T_sv& sv, const double& err) { +template +return_type_t dtdwiener5(const T_y& y, const T_a& a, + const T_v& vn, const T_w& wn, + const T_sv& sv, + const double& err) { using T_return_type = return_type_t; T_return_type kll, kss, ans, v, w; @@ -129,7 +127,8 @@ return_type_t dtdwiener5( * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - 2 * a * v * w) + square(v)) / square(one_plus_svsqr_y); - lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 / one_plus_svsqr_y + lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 + / one_plus_svsqr_y - la - 0.5 * log(one_plus_svsqr_y); } else { ans0 = -0.5 * square(v); @@ -173,8 +172,10 @@ return_type_t dtdwiener5( for (size_t k = static_cast(kss); k >= 1; k--) { T_return_type w_plus_2k = w + 2.0 * k; T_return_type w_minus_2k = w - 2.0 * k; - fplus = log_sum_exp(3.0 * log(w_plus_2k) - w_plus_2k * w_plus_2k / twoy, fplus); - fminus = log_sum_exp(3.0 * log(-w_minus_2k) - w_minus_2k * w_minus_2k / twoy, fminus); + fplus = log_sum_exp(3.0 * log(w_plus_2k) - w_plus_2k * w_plus_2k / twoy, + fplus); + fminus = log_sum_exp( + 3.0 * log(-w_minus_2k) - w_minus_2k * w_minus_2k / twoy, fminus); } } fplus = log_sum_exp(3.0 * log(w) - w * w / twoy, fplus); @@ -197,13 +198,11 @@ return_type_t dtdwiener5( T_return_type pi_k = pi() * k; T_return_type zwi = sin(pi_k * w); if (zwi > 0) { - fplus = log_sum_exp(3.0 * log(k) - - pi_k * pi_k * halfy + log(zwi), - fplus); + fplus + = log_sum_exp(3.0 * log(k) - pi_k * pi_k * halfy + log(zwi), fplus); } if (zwi < 0) { - fminus = log_sum_exp(3.0 * log(k) - - pi_k * pi_k * halfy + log(-zwi), + fminus = log_sum_exp(3.0 * log(k) - pi_k * pi_k * halfy + log(-zwi), fminus); } } @@ -223,11 +222,12 @@ return_type_t dtdwiener5( // d/da DENSITY // calculate derivative of density with respect to a (in log, ans = // d/da(log(f))=d/da f'/f; ans*exp(ld)=f' on normal scale) -template -return_type_t dadwiener5( - const T_y& y, const T_a& a, const T_v& vn, const T_w& wn, - const T_sv& sv, const double& err, const int& normal_or_log) { +template +return_type_t dadwiener5(const T_y& y, const T_a& a, + const T_v& vn, const T_w& wn, + const T_sv& sv, + const double& err, + const int& normal_or_log) { using T_return_type = return_type_t; T_return_type kll, kss, ans, v, w; @@ -245,7 +245,8 @@ return_type_t dadwiener5( T_return_type sv_sqr = square(sv); T_return_type one_plus_svsqr_y = (1 + sv_sqr * y); ans0 = (-v * w + sv_sqr * square(w) * a) / one_plus_svsqr_y; - lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 / one_plus_svsqr_y + lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 + / one_plus_svsqr_y - 2 * la - 0.5 * log(one_plus_svsqr_y); } else { ans0 = -v * w; @@ -292,8 +293,10 @@ return_type_t dadwiener5( for (size_t k = static_cast(kss); k >= 1; k--) { T_return_type w_plus_2k = w + 2.0 * k; T_return_type w_minus_2k = w - 2.0 * k; - fplus = log_sum_exp(3.0 * log(w_plus_2k) - w_plus_2k * w_plus_2k / twoy, fplus); - fminus = log_sum_exp(3.0 * log(-w_minus_2k) - w_minus_2k * w_minus_2k / twoy, fminus); + fplus = log_sum_exp(3.0 * log(w_plus_2k) - w_plus_2k * w_plus_2k / twoy, + fplus); + fminus = log_sum_exp( + 3.0 * log(-w_minus_2k) - w_minus_2k * w_minus_2k / twoy, fminus); } } fplus = log_sum_exp(3.0 * log(w) - w * w / twoy, fplus); @@ -316,13 +319,11 @@ return_type_t dadwiener5( T_return_type pi_k = pi() * k; T_return_type zwi = sin(pi_k * w); if (zwi > 0) { - fplus = log_sum_exp(3.0 * log(k) - - pi_k * pi_k * halfy + log(zwi), - fplus); + fplus + = log_sum_exp(3.0 * log(k) - pi_k * pi_k * halfy + log(zwi), fplus); } if (zwi < 0) { - fminus = log_sum_exp(3.0 * log(k) - - pi_k * pi_k * halfy + log(-zwi), + fminus = log_sum_exp(3.0 * log(k) - pi_k * pi_k * halfy + log(-zwi), fminus); } } @@ -337,8 +338,7 @@ return_type_t dadwiener5( } if (normal_or_log == 1) { return ans * exp(ld); // derivative of f for hcubature - } - else { + } else { return ans; // derivative of log(f) } } @@ -347,13 +347,10 @@ return_type_t dadwiener5( // d/dv DENSITY // calculate derivative of density with respect to v (in log, ans = // d/dv(log(f))=d/dv f'/f; ans*exp(ld)=f' on normal scale) -template -return_type_t dvdwiener5(const T_y& y, - const T_a& a, - const T_v& vn, - const T_w& wn, - const T_sv& sv) { +template +return_type_t dvdwiener5(const T_y& y, const T_a& a, + const T_v& vn, const T_w& wn, + const T_sv& sv) { using T_return_type = return_type_t; T_return_type ans; @@ -370,11 +367,12 @@ return_type_t dvdwiener5(const T_y& y, // d/dw DENSITY // calculate derivative of density with respect to w (in log, ans = // d/dw(log(f))=d/dw f'/f; ans*exp(ld)=f' on normal scale) -template -return_type_t dwdwiener5( - const T_y& y, const T_a& a, const T_v& vn, const T_w& wn, - const T_sv& sv, const double& err, const int& normal_or_log) { +template +return_type_t dwdwiener5(const T_y& y, const T_a& a, + const T_v& vn, const T_w& wn, + const T_sv& sv, + const double& err, + const int& normal_or_log) { using T_return_type = return_type_t; T_return_type kll, kss, ans, v, w; @@ -390,7 +388,8 @@ return_type_t dwdwiener5( T_return_type sv_sqr = square(sv); T_return_type one_plus_svsqr_y = (1 + sv_sqr * y); ans0 = (-v * a + sv_sqr * square(a) * w) / one_plus_svsqr_y; - lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 / one_plus_svsqr_y + lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 + / one_plus_svsqr_y - 2 * log(a) - 0.5 * log(one_plus_svsqr_y); } else { ans0 = -v * a; @@ -434,25 +433,24 @@ return_type_t dwdwiener5( T_return_type wm2k_minusy = sqrt_w_minus_2k - y_asq; if (wp2k_minusy > 0) { fplus = log_sum_exp(log(wp2k_minusy) - sqrt_w_plus_2k / twoy, fplus); - } - else if (wp2k_minusy < 0) { - fminus = log_sum_exp(log(-(wp2k_minusy)) - sqrt_w_plus_2k / twoy, fminus); - } + } else if (wp2k_minusy < 0) { + fminus + = log_sum_exp(log(-(wp2k_minusy)) - sqrt_w_plus_2k / twoy, fminus); + } if (wm2k_minusy > 0) { fplus = log_sum_exp(log(wm2k_minusy) - sqrt_w_minus_2k / twoy, fplus); - } - else if (wm2k_minusy < 0) { - fminus = log_sum_exp(log(-(wm2k_minusy)) - sqrt_w_minus_2k / twoy, fminus); - } + } else if (wm2k_minusy < 0) { + fminus + = log_sum_exp(log(-(wm2k_minusy)) - sqrt_w_minus_2k / twoy, fminus); + } } T_return_type sqr_w = square(w); T_return_type sqrt_w_plus_2k = sqr_w - y_asq; if (sqrt_w_plus_2k > 0) { fplus = log_sum_exp(log(sqrt_w_plus_2k) - sqr_w / twoy, fplus); - } - else if (sqrt_w_plus_2k < 0) { + } else if (sqrt_w_plus_2k < 0) { fminus = log_sum_exp(log(-(sqrt_w_plus_2k)) - sqr_w / twoy, fminus); - } + } if (fplus < fminus) { newsign = -1; @@ -473,15 +471,12 @@ return_type_t dwdwiener5( T_return_type pi_k = pi() * k; T_return_type x = cos(pi_k * w); if (x > 0) { - fplus = log_sum_exp(2.0 * log(k) - - square(pi_k) * halfy + log(x), - fplus); - } - else if (x < 0) { - fminus = log_sum_exp(2.0 * log(k) - - square(pi_k) * halfy + log(-x), + fplus + = log_sum_exp(2.0 * log(k) - square(pi_k) * halfy + log(x), fplus); + } else if (x < 0) { + fminus = log_sum_exp(2.0 * log(k) - square(pi_k) * halfy + log(-x), fminus); - } + } } if (fplus < fminus) { erg = log_diff_exp(fminus, fplus); @@ -494,8 +489,7 @@ return_type_t dwdwiener5( } if (normal_or_log == 1) { return ans * sign * exp(ld); // derivative of f for hcubature - } - else { + } else { return ans * sign; // derivative of log(f) } } @@ -504,11 +498,11 @@ return_type_t dwdwiener5( // d/dsv DENSITY // calculate derivative of density with respect to sv (in log, ans = // d/dsv(log(f))=d/dsv f'/f; ans*exp(ld)=f' on normal scale) -template -return_type_t dsvdwiener5( - const T_y& y, const T_a& a, const T_v& vn, const T_w& wn, - const T_sv& sv) { +template +return_type_t dsvdwiener5(const T_y& y, const T_a& a, + const T_v& vn, + const T_w& wn, + const T_sv& sv) { using T_return_type = return_type_t; T_return_type v, w; @@ -518,8 +512,8 @@ return_type_t dsvdwiener5( T_return_type one_sqrsv_y = 1 + square(sv) * y; T_return_type t1 = -y / one_sqrsv_y; - T_return_type t2 - = (square(a * w) + 2 * a * v * w * y + square(v * y)) / square(one_sqrsv_y); + T_return_type t2 = (square(a * w) + 2 * a * v * w * y + square(v * y)) + / square(one_sqrsv_y); return sv * (t1 + t2); } //----------------------------------------------- diff --git a/stan/math/prim/fun/wiener7_lpdf.hpp b/stan/math/prim/fun/wiener7_lpdf.hpp index fb6ac125739..7135beeb281 100644 --- a/stan/math/prim/fun/wiener7_lpdf.hpp +++ b/stan/math/prim/fun/wiener7_lpdf.hpp @@ -13,9 +13,8 @@ namespace math { namespace internal { // tools -template +template struct my_params { T_y y; T_a a; @@ -29,9 +28,8 @@ struct my_params { }; template + typename T_w_lower, typename T_w_upper, typename T_t0, typename T_sv, + typename T_sw, typename T_sw_mean, typename T_st0, typename T_err> struct my_params2 { T_y y; T_a a; @@ -47,9 +45,9 @@ struct my_params2 { T_err lerr; }; -template +template struct my_params3 { T_y y; T_a a; @@ -66,11 +64,10 @@ struct my_params3 { // calculate derivative of density of wiener5 with respect to y (version for // wiener7) -template +template return_type_t dtdwiener5_for_7( - const T_y& y, const T_a& a, const T_v& v, const T_w& w, - const T_sv& sv, const double& err) { + const T_y& y, const T_a& a, const T_v& v, const T_w& w, const T_sv& sv, + const double& err) { using T_return_type = return_type_t; T_return_type kll, kss, ans; @@ -86,7 +83,8 @@ return_type_t dtdwiener5_for_7( * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - 2 * a * v * w) + square(v)) / square(one_plus_svsqr_y); - lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 / one_plus_svsqr_y + lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 + / one_plus_svsqr_y - la - 0.5 * log(one_plus_svsqr_y); } else { ans0 = -0.5 * square(v); @@ -130,8 +128,10 @@ return_type_t dtdwiener5_for_7( for (size_t k = static_cast(kss); k >= 1; k--) { T_return_type w_plus_2k = w + 2.0 * k; T_return_type w_minus_2k = w - 2.0 * k; - fplus = log_sum_exp(3.0 * log(w_plus_2k) - w_plus_2k * w_plus_2k / twot, fplus); - fminus = log_sum_exp(3.0 * log(-w_minus_2k) - w_minus_2k * w_minus_2k / twot, fminus); + fplus = log_sum_exp(3.0 * log(w_plus_2k) - w_plus_2k * w_plus_2k / twot, + fplus); + fminus = log_sum_exp( + 3.0 * log(-w_minus_2k) - w_minus_2k * w_minus_2k / twot, fminus); } } fplus = log_sum_exp(3.0 * log(w) - w * w / twot, fplus); @@ -154,13 +154,11 @@ return_type_t dtdwiener5_for_7( T_return_type pi_k = pi() * k; T_return_type zwi = sin(pi_k * w); if (zwi > 0) { - fplus = log_sum_exp(3.0 * log(k) - - pi_k * pi_k * halfy + log(zwi), - fplus); + fplus + = log_sum_exp(3.0 * log(k) - pi_k * pi_k * halfy + log(zwi), fplus); } if (zwi < 0) { - fminus = log_sum_exp(3.0 * log(k) - - pi_k * pi_k * halfy + log(-zwi), + fminus = log_sum_exp(3.0 * log(k) - pi_k * pi_k * halfy + log(-zwi), fminus); } } @@ -290,8 +288,8 @@ return_type_t int_daddiff(const T_x& x, const T_p& p) { } else { // prepare some variables for error estimation in density T_return_type sv_sqr = square(sv); - T_return_type ans0 - = (v * (1 - omega) + sv_sqr * square(1 - omega) * a) / (1 + sv_sqr * (y - t0_)); + T_return_type ans0 = (v * (1 - omega) + sv_sqr * square(1 - omega) * a) + / (1 + sv_sqr * (y - t0_)); T_return_type factor = max(ans0 + 1.0 / a, ans0 - 2.0 / a); // factor from small and large // representation, for same @@ -378,7 +376,8 @@ return_type_t int_dwddiff(const T_x& x, const T_p& p) { } else { // prepare some variables for error estimation in density T_return_type sv_sqr = square(sv); - T_return_type ans0 = (v * a + sv_sqr * square(a) * (1 - omega)) / (1 + sv_sqr * (y - t0_)); + T_return_type ans0 + = (v * a + sv_sqr * square(a) * (1 - omega)) / (1 + sv_sqr * (y - t0_)); // compute partial derivative retval = dwdwiener5(y - t0_, a, v, omega, sv, lerr, 1); } diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 3a40b4fcc98..563a449890f 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -4,19 +4,18 @@ #include namespace stan { -namespace math { +namespace math { namespace internal { -template +template inline return_type_t wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, const T_a& a, const T_v& v, const T_w& w, const T_t0& t0, const T_sv& sv, const T_sw& sw, const T_st0& st0, const double& prec) { - using T_partials_return = partials_return_t; + using T_partials_return + = partials_return_t; using T_y_ref = ref_type_t; using T_a_ref = ref_type_t; using T_v_ref = ref_type_t; @@ -127,7 +126,7 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, if (!include_summand::value) { return 0; - } + } // abstol_wiener5 z.B. 1e-12 on normal scale // T_partials_return error_bound = 1e-6; @@ -146,8 +145,8 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, int Meval = 6000; T_partials_return dens = 0.0; T_partials_return ld = 0.0; - operands_and_partials + operands_and_partials ops_partials(y_ref, alpha_ref, delta_ref, beta_ref, t0_ref, sv_ref, sw_ref, st0_ref); @@ -173,7 +172,7 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, dens = internal::dwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, fabs(dens) + lerror_bound_dens - LOG_TWO); - } + } ld += dens; // computation of derivative for t and precision check in order to give @@ -181,11 +180,12 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, T_partials_return deriv_t = internal::dtdwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, labstol_wiener5); - if (labstol_wiener5 > log(fabs(deriv_t)) + dens + lerror_bound - LOG_TWO) { + if (labstol_wiener5 + > log(fabs(deriv_t)) + dens + lerror_bound - LOG_TWO) { deriv_t = internal::dtdwiener5( y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, log(fabs(deriv_t)) + dens + lerror_bound - LOG_FOUR); - } + } // computation of derivatives and precision checks if (!is_constant_all::value) { @@ -200,7 +200,7 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, deriv_a = internal::dadwiener5( y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, log(fabs(deriv_a)) + dens + lerror_bound - LOG_FOUR, 0); - } + } ops_partials.edge2_.partials_[i] = deriv_a; } if (!is_constant_all::value) { @@ -216,7 +216,7 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, deriv_w = internal::dwdwiener5( y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, log(fabs(deriv_w)) + dens + lerror_bound - LOG_FOUR, 0); - } + } ops_partials.edge4_.partials_[i] = deriv_w; } if (!is_constant_all::value) { @@ -260,7 +260,7 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, if (st0_val) { xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); - } + } dens = hcubature(internal::int_ddiff, void*>, ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); @@ -488,7 +488,7 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, delta_val, beta_val, sv_val, lerror_bound - LOG_TWO + log(st0_val) - LOG_TWO + log(fabs(f)))); - } + } deriv = 1 / st0_val * f; } else { T_partials_return new_error = labstol_wiener5 - LOG_TWO; @@ -678,26 +678,25 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * https://doi.org/10.1016/j.jmp.2009.02.003 */ -template +template inline return_type_t -wiener_full_lpdf(const T_y& y, const T_a& a, const T_v& v, - const T_w& w, const T_t0& t0, const T_sv& sv, - const T_sw& sw, const T_st0& st0) { +wiener_full_lpdf(const T_y& y, const T_a& a, const T_v& v, const T_w& w, + const T_t0& t0, const T_sv& sv, const T_sw& sw, + const T_st0& st0) { double precision = 1e-4; - return internal::wiener_full_prec_impl_lpdf( + return internal::wiener_full_prec_impl_lpdf( "wiener_full_lpdf", y, a, v, w, t0, sv, sw, st0, precision); } -template +template inline return_type_t -wiener_full_lpdf(const T_y& y, const T_a& a, const T_v& v, - const T_w& w, const T_t0& t0, const T_sv& sv, - const T_sw& sw, const T_st0& st0) { +wiener_full_lpdf(const T_y& y, const T_a& a, const T_v& v, const T_w& w, + const T_t0& t0, const T_sv& sv, const T_sw& sw, + const T_st0& st0) { double precision = 1e-4; return internal::wiener_full_prec_impl_lpdf( @@ -713,24 +712,23 @@ wiener_full_lpdf(const T_y& y, const T_a& a, const T_v& v, * functions are the same excpet of the control over the precision. */ -template +template inline return_type_t -wiener_full_prec_lpdf(const T_y& y, const T_a& a, const T_v& v, - const T_w& w, const T_t0& t0, const T_sv& sv, - const T_sw& sw, const T_st0& st0, const double& prec) { - return internal::wiener_full_prec_impl_lpdf( +wiener_full_prec_lpdf(const T_y& y, const T_a& a, const T_v& v, const T_w& w, + const T_t0& t0, const T_sv& sv, const T_sw& sw, + const T_st0& st0, const double& prec) { + return internal::wiener_full_prec_impl_lpdf( "wiener_full_prec_lpdf", y, a, v, w, t0, sv, sw, st0, prec); } -template +template inline return_type_t -wiener_full_prec_lpdf(const T_y& y, const T_a& a, const T_v& v, - const T_w& w, const T_t0& t0, const T_sv& sv, - const T_sw& sw, const T_st0& st0, const double& prec) { +wiener_full_prec_lpdf(const T_y& y, const T_a& a, const T_v& v, const T_w& w, + const T_t0& t0, const T_sv& sv, const T_sw& sw, + const T_st0& st0, const double& prec) { return internal::wiener_full_prec_impl_lpdf( "wiener_full_prec_lpdf", y, a, v, w, t0, sv, sw, st0, prec); } From 9cae1175909ca002802424e042641cc9bd542dd1 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 24 Mar 2023 09:03:20 +0100 Subject: [PATCH 013/179] #include constants.hpp --- stan/math/prim/fun/wiener5_lpdf.hpp | 1 + stan/math/prim/fun/wiener7_lpdf.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/stan/math/prim/fun/wiener5_lpdf.hpp b/stan/math/prim/fun/wiener5_lpdf.hpp index b2143739814..15cd2d347a3 100644 --- a/stan/math/prim/fun/wiener5_lpdf.hpp +++ b/stan/math/prim/fun/wiener5_lpdf.hpp @@ -2,6 +2,7 @@ #define STAN_MATH_PRIM_FUN_WIENER5_LPDF_HPP #include +#include #include #include #include diff --git a/stan/math/prim/fun/wiener7_lpdf.hpp b/stan/math/prim/fun/wiener7_lpdf.hpp index 7135beeb281..e337a5e5265 100644 --- a/stan/math/prim/fun/wiener7_lpdf.hpp +++ b/stan/math/prim/fun/wiener7_lpdf.hpp @@ -2,6 +2,7 @@ #define STAN_MATH_PRIM_FUN_WIENER7_LPDF_HPP #include +#include #include #include #include From 46558d43f0724954bf78dfd80cace72586e6da0a Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Mon, 27 Mar 2023 17:49:55 +0200 Subject: [PATCH 014/179] new structure, no obsolete templates, new ordering of arguments --- stan/math/prim/fun/wiener5_lpdf.hpp | 452 ++++++---- stan/math/prim/fun/wiener7_lpdf.hpp | 801 ++++++++++++------ stan/math/prim/prob/wiener_full_lpdf.hpp | 579 +------------ .../math/prim/prob/wiener_full_prec_test.cpp | 98 +-- test/unit/math/prim/prob/wiener_full_test.cpp | 98 +-- 5 files changed, 965 insertions(+), 1063 deletions(-) diff --git a/stan/math/prim/fun/wiener5_lpdf.hpp b/stan/math/prim/fun/wiener5_lpdf.hpp index 15cd2d347a3..0e0f709f1d6 100644 --- a/stan/math/prim/fun/wiener5_lpdf.hpp +++ b/stan/math/prim/fun/wiener5_lpdf.hpp @@ -13,45 +13,37 @@ namespace math { namespace internal { // calculate density in log -template -return_type_t dwiener5(const T_y& y, const T_a& a, - const T_v& vn, const T_w& wn, - const T_sv& sv, - const double& err) { - using T_return_type = return_type_t; - - T_return_type kll, kss, ans, v, w; - +double dwiener5(const double& y, const double& a, const double& vn, + const double& wn, const double& sv, const double& err) { + double kll, kss, ans, v, w; w = 1.0 - wn; v = -vn; - - T_return_type y_asq = y / square(a); + double y_asq = y / square(a); ans = 0.0; // calculate the number of terms needed for short t - T_return_type lg1; + double lg1; if (sv != 0) { - T_return_type sv_sqr = square(sv); - T_return_type one_plus_svsqr_y = 1 + sv_sqr * y; + double sv_sqr = square(sv); + double one_plus_svsqr_y = 1 + sv_sqr * y; lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 / one_plus_svsqr_y - 2 * log(a) - 0.5 * log(one_plus_svsqr_y); } else { lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - 2 * log(a); } - T_return_type es = (err - lg1); - T_return_type K1 = (sqrt(2.0 * y_asq) + w) / 2.0; - T_return_type u_eps - = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log(y_asq) + 2.0 * (es)); - T_return_type arg = -y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - T_return_type K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; + double es = (err - lg1); + double K1 = (sqrt(2.0 * y_asq) + w) / 2.0; + double u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log(y_asq) + 2.0 * (es)); + double arg = -y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + double K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; kss = ceil(fmax(K1, K2)); // calculate the number of terms needed for large t - T_return_type el = es; + double el = es; K1 = 1.0 / (pi() * sqrt(y_asq)); K2 = 0.0; - T_return_type two_log_piy = -2.0 * (log(pi() * y_asq) + el); + double two_log_piy = -2.0 * (log(pi() * y_asq) + el); static const double PISQ = square(pi()); // pi*pi if (two_log_piy >= 0) { K2 = sqrt(two_log_piy / (PISQ * y_asq)); @@ -60,13 +52,13 @@ return_type_t dwiener5(const T_y& y, const T_a& a, // if small t is better if (2 * kss <= kll) { - T_return_type fplus = NEGATIVE_INFTY; - T_return_type fminus = NEGATIVE_INFTY; - T_return_type twoy = 2.0 * y_asq; + double fplus = NEGATIVE_INFTY; + double fminus = NEGATIVE_INFTY; + double twoy = 2.0 * y_asq; if (static_cast(kss) > 0) { for (size_t k = static_cast(kss); k >= 1; k--) { - T_return_type w_plus_2k = w + 2.0 * k; - T_return_type w_minus_2k = w - 2.0 * k; + double w_plus_2k = w + 2.0 * k; + double w_minus_2k = w - 2.0 * k; fplus = log_sum_exp(log(w_plus_2k) - square(w_plus_2k) / twoy, fplus); fminus @@ -79,12 +71,12 @@ return_type_t dwiener5(const T_y& y, const T_a& a, + log_diff_exp(fplus, fminus)); // if large t is better } else { - T_return_type fplus = NEGATIVE_INFTY; - T_return_type fminus = NEGATIVE_INFTY; - T_return_type halfy = y_asq / 2.0; + double fplus = NEGATIVE_INFTY; + double fminus = NEGATIVE_INFTY; + double halfy = y_asq / 2.0; for (size_t k = static_cast(kll); k >= 1; k--) { - T_return_type pi_k = k * pi(); - T_return_type check = sin(pi_k * w); + double pi_k = k * pi(); + double check = sin(pi_k * w); if (check > 0) { fplus = log_sum_exp(log(k) - square(pi_k) * halfy + log(check), fplus); } else { @@ -105,25 +97,19 @@ return_type_t dwiener5(const T_y& y, const T_a& a, // d/dt DENSITY // calculate derivative of density with respect to t (in log, ans = // d/dt(log(f))=d/dt f'/f; ans*exp(ld)=f' on normal scale) -template -return_type_t dtdwiener5(const T_y& y, const T_a& a, - const T_v& vn, const T_w& wn, - const T_sv& sv, - const double& err) { - using T_return_type = return_type_t; - - T_return_type kll, kss, ans, v, w; - +double dtdwiener5(const double& y, const double& a, const double& vn, + const double& wn, const double& sv, const double& err) { + double kll, kss, ans, v, w; w = 1.0 - wn; v = -vn; // prepare some variables - T_return_type y_asq = y / square(a); - T_return_type la = 2.0 * log(a); - T_return_type ans0, lg1; + double y_asq = y / square(a); + double la = 2.0 * log(a); + double ans0, lg1; if (sv != 0) { - T_return_type sv_sqr = square(sv); - T_return_type one_plus_svsqr_y = (1 + sv_sqr * y); + double sv_sqr = square(sv); + double one_plus_svsqr_y = (1 + sv_sqr * y); ans0 = -0.5 * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - 2 * a * v * w) + square(v)) @@ -135,44 +121,43 @@ return_type_t dtdwiener5(const T_y& y, const T_a& a, ans0 = -0.5 * square(v); lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - la; } - T_return_type factor = lg1 - la; - - T_return_type ld = dwiener5(y, a, vn, wn, sv, - err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); + double factor = lg1 - la; + double ld = dwiener5(y, a, vn, wn, sv, + err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); // calculate the number of terms kss needed for small t - T_return_type es = err - lg1; + double es = err - lg1; es = es + la; - T_return_type K1 = (sqrt(3.0 * y_asq) + w) / 2.0; - T_return_type u_eps = fmin( + double K1 = (sqrt(3.0 * y_asq) + w) / 2.0; + double u_eps = fmin( -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(y_asq) + 2.0 * es) / 3.0); - T_return_type arg = -3.0 * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - T_return_type K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; + double arg = -3.0 * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + double K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; kss = ceil(fmax(K1, K2)); // calculate number of terms kll needed for large t - T_return_type el = err - lg1; + double el = err - lg1; el = el + la; K1 = sqrt(3.0 / y_asq) / pi(); u_eps = fmin(-1.0, el + log(0.6) + LOG_PI + 2.0 * log(y_asq)); static const double PISQ = square(pi()); // pi*pi arg = -2.0 / PISQ / y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - T_return_type kl = (arg > 0) ? sqrt(arg) : K1; + double kl = (arg > 0) ? sqrt(arg) : K1; kll = ceil(fmax(kl, K1)); - T_return_type erg; - T_return_type newsign = 1; - T_return_type fplus = NEGATIVE_INFTY; - T_return_type fminus = NEGATIVE_INFTY; + double erg; + double newsign = 1; + double fplus = NEGATIVE_INFTY; + double fminus = NEGATIVE_INFTY; // if small t is better if (2 * kss < kll) { // calculate terms of the sum for small t - T_return_type twoy = 2.0 * y_asq; + double twoy = 2.0 * y_asq; if (static_cast(kss) > 0) { for (size_t k = static_cast(kss); k >= 1; k--) { - T_return_type w_plus_2k = w + 2.0 * k; - T_return_type w_minus_2k = w - 2.0 * k; + double w_plus_2k = w + 2.0 * k; + double w_minus_2k = w - 2.0 * k; fplus = log_sum_exp(3.0 * log(w_plus_2k) - w_plus_2k * w_plus_2k / twoy, fplus); fminus = log_sum_exp( @@ -186,7 +171,6 @@ return_type_t dtdwiener5(const T_y& y, const T_a& a, } else { erg = log_diff_exp(fplus, fminus); } - ans = ans0 - 1.5 / y + newsign * exp(factor - 1.5 * LOG_TWO - LOG_SQRT_PI - 3.5 * log(y_asq) @@ -194,10 +178,10 @@ return_type_t dtdwiener5(const T_y& y, const T_a& a, // if large t is better } else { // calculate terms of the sum for large t - T_return_type halfy = y_asq / 2.0; + double halfy = y_asq / 2.0; for (size_t k = static_cast(kll); k >= 1; k--) { - T_return_type pi_k = pi() * k; - T_return_type zwi = sin(pi_k * w); + double pi_k = pi() * k; + double zwi = sin(pi_k * w); if (zwi > 0) { fplus = log_sum_exp(3.0 * log(k) - pi_k * pi_k * halfy + log(zwi), fplus); @@ -213,7 +197,6 @@ return_type_t dtdwiener5(const T_y& y, const T_a& a, } else { erg = log_diff_exp(fplus, fminus); } - ans = ans0 - newsign * exp(factor + 3.0 * LOG_PI - LOG_TWO + erg - ld); } return ans; @@ -223,28 +206,22 @@ return_type_t dtdwiener5(const T_y& y, const T_a& a, // d/da DENSITY // calculate derivative of density with respect to a (in log, ans = // d/da(log(f))=d/da f'/f; ans*exp(ld)=f' on normal scale) -template -return_type_t dadwiener5(const T_y& y, const T_a& a, - const T_v& vn, const T_w& wn, - const T_sv& sv, - const double& err, - const int& normal_or_log) { - using T_return_type = return_type_t; - - T_return_type kll, kss, ans, v, w; - - T_return_type la = log(a); - T_return_type ly = log(y); +double dadwiener5(const double& y, const double& a, const double& vn, + const double& wn, const double& sv, const double& err, + const int& normal_or_log) { + double kll, kss, ans, v, w; + double la = log(a); + double ly = log(y); w = 1.0 - wn; v = -vn; // prepare some variables - T_return_type y_asq = y / square(a); - T_return_type ans0, lg1; + double y_asq = y / square(a); + double ans0, lg1; if (sv != 0) { - T_return_type sv_sqr = square(sv); - T_return_type one_plus_svsqr_y = (1 + sv_sqr * y); + double sv_sqr = square(sv); + double one_plus_svsqr_y = (1 + sv_sqr * y); ans0 = (-v * w + sv_sqr * square(w) * a) / one_plus_svsqr_y; lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 / one_plus_svsqr_y @@ -253,47 +230,46 @@ return_type_t dadwiener5(const T_y& y, const T_a& a, ans0 = -v * w; lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - 2 * la; } - T_return_type factor = lg1 - 3 * la; - - T_return_type ld + double factor = lg1 - 3 * la; + double ld = dwiener5(y, a, vn, wn, sv, err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); // calculate the number of terms kss needed for small t - T_return_type es = err - lg1; + double es = err - lg1; es = es + la; es = es - LOG_TWO + 2.0 * la - ly; - T_return_type K1 = (sqrt(3.0 * y_asq) + w) / 2.0; - T_return_type u_eps = fmin( + double K1 = (sqrt(3.0 * y_asq) + w) / 2.0; + double u_eps = fmin( -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(y_asq) + 2.0 * es) / 3.0); - T_return_type arg = -3.0 * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - T_return_type K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; + double arg = -3.0 * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + double K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; kss = ceil(fmax(K1, K2)); // calculate number of terms kll needed for large t - T_return_type el = err - lg1; + double el = err - lg1; el = el + la; el = el - LOG_TWO + 2.0 * la - ly; K1 = sqrt(3.0 / y_asq) / pi(); u_eps = fmin(-1.0, el + log(0.6) + LOG_PI + 2.0 * log(y_asq)); static const double PISQ = square(pi()); // pi*pi arg = -2.0 / PISQ / y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - T_return_type kl = (arg > 0) ? sqrt(arg) : K1; + double kl = (arg > 0) ? sqrt(arg) : K1; kll = ceil(fmax(kl, K1)); - T_return_type erg; - T_return_type newsign = 1; - T_return_type fplus = NEGATIVE_INFTY; - T_return_type fminus = NEGATIVE_INFTY; + double erg; + double newsign = 1; + double fplus = NEGATIVE_INFTY; + double fminus = NEGATIVE_INFTY; // if small t is better if (2 * kss < kll) { // calculate terms of the sum for short t - T_return_type twoy = 2.0 * y_asq; + double twoy = 2.0 * y_asq; if (static_cast(kss) > 0) { for (size_t k = static_cast(kss); k >= 1; k--) { - T_return_type w_plus_2k = w + 2.0 * k; - T_return_type w_minus_2k = w - 2.0 * k; + double w_plus_2k = w + 2.0 * k; + double w_minus_2k = w - 2.0 * k; fplus = log_sum_exp(3.0 * log(w_plus_2k) - w_plus_2k * w_plus_2k / twoy, fplus); fminus = log_sum_exp( @@ -307,7 +283,6 @@ return_type_t dadwiener5(const T_y& y, const T_a& a, } else { erg = log_diff_exp(fplus, fminus); } - ans = ans0 + 1.0 / a - newsign * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * ly + 4.0 * la + lg1 @@ -315,10 +290,10 @@ return_type_t dadwiener5(const T_y& y, const T_a& a, // if large t is better } else { // calculate terms of the sum for large t - T_return_type halfy = y_asq / 2.0; + double halfy = y_asq / 2.0; for (size_t k = static_cast(kll); k >= 1; k--) { - T_return_type pi_k = pi() * k; - T_return_type zwi = sin(pi_k * w); + double pi_k = pi() * k; + double zwi = sin(pi_k * w); if (zwi > 0) { fplus = log_sum_exp(3.0 * log(k) - pi_k * pi_k * halfy + log(zwi), fplus); @@ -334,7 +309,6 @@ return_type_t dadwiener5(const T_y& y, const T_a& a, erg = log_diff_exp(fminus, fplus); newsign = -1; } - ans = ans0 - 2.0 / a + newsign * exp(ly + factor + 3.0 * LOG_PI + erg - ld); } if (normal_or_log == 1) { @@ -348,13 +322,9 @@ return_type_t dadwiener5(const T_y& y, const T_a& a, // d/dv DENSITY // calculate derivative of density with respect to v (in log, ans = // d/dv(log(f))=d/dv f'/f; ans*exp(ld)=f' on normal scale) -template -return_type_t dvdwiener5(const T_y& y, const T_a& a, - const T_v& vn, const T_w& wn, - const T_sv& sv) { - using T_return_type = return_type_t; - - T_return_type ans; +double dvdwiener5(const double& y, const double& a, const double& vn, + const double& wn, const double& sv) { + double ans; if (sv != 0) { ans = 1 + square(sv) * y; ans = (a * (1 - wn) - vn * y) / ans; @@ -368,26 +338,20 @@ return_type_t dvdwiener5(const T_y& y, const T_a& a, // d/dw DENSITY // calculate derivative of density with respect to w (in log, ans = // d/dw(log(f))=d/dw f'/f; ans*exp(ld)=f' on normal scale) -template -return_type_t dwdwiener5(const T_y& y, const T_a& a, - const T_v& vn, const T_w& wn, - const T_sv& sv, - const double& err, - const int& normal_or_log) { - using T_return_type = return_type_t; - - T_return_type kll, kss, ans, v, w; - T_return_type sign = -1; - +double dwdwiener5(const double& y, const double& a, const double& vn, + const double& wn, const double& sv, const double& err, + const int& normal_or_log) { + double kll, kss, ans, v, w; + double sign = -1; w = 1.0 - wn; v = -vn; // prepare some variables - T_return_type y_asq = y / square(a); - T_return_type ans0, lg1; + double y_asq = y / square(a); + double ans0, lg1; if (sv != 0) { - T_return_type sv_sqr = square(sv); - T_return_type one_plus_svsqr_y = (1 + sv_sqr * y); + double sv_sqr = square(sv); + double one_plus_svsqr_y = (1 + sv_sqr * y); ans0 = (-v * a + sv_sqr * square(a) * w) / one_plus_svsqr_y; lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 / one_plus_svsqr_y @@ -396,17 +360,16 @@ return_type_t dwdwiener5(const T_y& y, const T_a& a, ans0 = -v * a; lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - 2 * log(a); } - T_return_type ld = dwiener5(y, a, vn, wn, sv, err - log(fabs(ans0))); - - T_return_type ls = -lg1 + ld; - T_return_type ll = -lg1 + ld; + double ld = dwiener5(y, a, vn, wn, sv, err - log(fabs(ans0))); + double ls = -lg1 + ld; + double ll = -lg1 + ld; // calculate the number of terms kss needed for small t - T_return_type K1 = (sqrt(3.0 * y_asq) + w) / 2.0; - T_return_type u_eps + double K1 = (sqrt(3.0 * y_asq) + w) / 2.0; + double u_eps = fmin(-1.0, 2.0 * (err - lg1) + LOG_TWO + LOG_PI + 2.0 * log(y_asq)); - T_return_type arg = -y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - T_return_type K2 = (arg > 0) ? 0.5 * (sqrt(arg) + w) : K1; + double arg = -y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + double K2 = (arg > 0) ? 0.5 * (sqrt(arg) + w) : K1; kss = ceil(fmax(K1, K2)); // calculate number of terms kll needed for large t @@ -418,20 +381,20 @@ return_type_t dwdwiener5(const T_y& y, const T_a& a, K2 = (arg > 0) ? 1.0 / pi() * sqrt(arg / y_asq) : K1; kll = ceil(fmax(K1, K2)); - T_return_type erg; - T_return_type newsign = 1; - T_return_type fplus = NEGATIVE_INFTY; - T_return_type fminus = NEGATIVE_INFTY; + double erg; + double newsign = 1; + double fplus = NEGATIVE_INFTY; + double fminus = NEGATIVE_INFTY; // if small t is better if (2 * kss < kll) { // calculate terms of the sum for short t - T_return_type twoy = 2.0 * y_asq; + double twoy = 2.0 * y_asq; for (size_t k = static_cast(kss); k >= 1; k--) { - T_return_type sqrt_w_plus_2k = square(w + 2 * k); - T_return_type sqrt_w_minus_2k = square(w - 2 * k); - T_return_type wp2k_minusy = sqrt_w_plus_2k - y_asq; - T_return_type wm2k_minusy = sqrt_w_minus_2k - y_asq; + double sqrt_w_plus_2k = square(w + 2 * k); + double sqrt_w_minus_2k = square(w - 2 * k); + double wp2k_minusy = sqrt_w_plus_2k - y_asq; + double wm2k_minusy = sqrt_w_minus_2k - y_asq; if (wp2k_minusy > 0) { fplus = log_sum_exp(log(wp2k_minusy) - sqrt_w_plus_2k / twoy, fplus); } else if (wp2k_minusy < 0) { @@ -445,21 +408,19 @@ return_type_t dwdwiener5(const T_y& y, const T_a& a, = log_sum_exp(log(-(wm2k_minusy)) - sqrt_w_minus_2k / twoy, fminus); } } - T_return_type sqr_w = square(w); - T_return_type sqrt_w_plus_2k = sqr_w - y_asq; + double sqr_w = square(w); + double sqrt_w_plus_2k = sqr_w - y_asq; if (sqrt_w_plus_2k > 0) { fplus = log_sum_exp(log(sqrt_w_plus_2k) - sqr_w / twoy, fplus); } else if (sqrt_w_plus_2k < 0) { fminus = log_sum_exp(log(-(sqrt_w_plus_2k)) - sqr_w / twoy, fminus); } - if (fplus < fminus) { newsign = -1; erg = log_diff_exp(fminus, fplus); } else { erg = log_diff_exp(fplus, fminus); } - ans = ans0 - newsign * exp(erg - ls - 2.5 * log(y_asq) - 0.5 * LOG_TWO @@ -467,10 +428,10 @@ return_type_t dwdwiener5(const T_y& y, const T_a& a, // if large t is better } else { // calculate terms of the sum for large t - T_return_type halfy = y_asq / 2.0; + double halfy = y_asq / 2.0; for (size_t k = static_cast(kll); k >= 1; k--) { - T_return_type pi_k = pi() * k; - T_return_type x = cos(pi_k * w); + double pi_k = pi() * k; + double x = cos(pi_k * w); if (x > 0) { fplus = log_sum_exp(2.0 * log(k) - square(pi_k) * halfy + log(x), fplus); @@ -485,7 +446,6 @@ return_type_t dwdwiener5(const T_y& y, const T_a& a, } else { erg = log_diff_exp(fplus, fminus); } - ans = ans0 + newsign * exp(erg - ll + TWO_LOG_PI); } if (normal_or_log == 1) { @@ -499,27 +459,183 @@ return_type_t dwdwiener5(const T_y& y, const T_a& a, // d/dsv DENSITY // calculate derivative of density with respect to sv (in log, ans = // d/dsv(log(f))=d/dsv f'/f; ans*exp(ld)=f' on normal scale) -template -return_type_t dsvdwiener5(const T_y& y, const T_a& a, - const T_v& vn, - const T_w& wn, - const T_sv& sv) { - using T_return_type = return_type_t; - - T_return_type v, w; - +double dsvdwiener5(const double& y, const double& a, const double& vn, + const double& wn, const double& sv) { + double v, w; v = -vn; w = 1 - wn; - - T_return_type one_sqrsv_y = 1 + square(sv) * y; - T_return_type t1 = -y / one_sqrsv_y; - T_return_type t2 = (square(a * w) + 2 * a * v * w * y + square(v * y)) - / square(one_sqrsv_y); + double one_sqrsv_y = 1 + square(sv) * y; + double t1 = -y / one_sqrsv_y; + double t2 = (square(a * w) + 2 * a * v * w * y + square(v * y)) + / square(one_sqrsv_y); return sv * (t1 + t2); } //----------------------------------------------- } // namespace internal + +template +inline return_type_t wiener5_lpdf( + const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, + const T_sv& sv, const double& prec) { + using T_y_ref = ref_type_t; + using T_a_ref = ref_type_t; + using T_t0_ref = ref_type_t; + using T_w_ref = ref_type_t; + using T_v_ref = ref_type_t; + using T_sv_ref = ref_type_t; + + const char* function_name = "wiener5_lpdf"; + check_consistent_sizes(function_name, "Random variable", y, + "Boundary separation", a, "Drift rate", v, + "A-priori bias", w, "Nondecision time", t0, + "Inter-trial variability in drift rate", sv); + check_consistent_size(function_name, "Random variable", y, 1); + check_consistent_size(function_name, "Boundary separation", a, 1); + check_consistent_size(function_name, "Nondecision time", t0, 1); + check_consistent_size(function_name, "A-priori bias", w, 1); + check_consistent_size(function_name, "Drift rate", v, 1); + check_consistent_size(function_name, "Inter-trial variability in drift rate", + sv, 1); + + T_y_ref y_ref = y; + T_a_ref a_ref = a; + T_t0_ref t0_ref = t0; + T_w_ref w_ref = w; + T_v_ref v_ref = v; + T_sv_ref sv_ref = sv; + + check_positive_finite(function_name, "Random variable", value_of(y_ref)); + check_positive_finite(function_name, "Boundary separation", value_of(a_ref)); + check_nonnegative(function_name, "Nondecision time", value_of(t0_ref)); + check_finite(function_name, "Nondecision time", value_of(t0_ref)); + check_less(function_name, "A-priori bias", value_of(w_ref), 1); + check_greater(function_name, "A-priori bias", value_of(w_ref), 0); + check_finite(function_name, "Drift rate", value_of(v_ref)); + check_nonnegative(function_name, "Inter-trial variability in drift rate", + value_of(sv_ref)); + check_finite(function_name, "Inter-trial variability in drift rate", + value_of(sv_ref)); + + if (size_zero(y, a, t0, w, v) || size_zero(sv)) { + return 0; + } + size_t N = max_size(y, a, t0, w, v, sv); + if (!N) { + return 0; + } + scalar_seq_view y_vec(y_ref); + scalar_seq_view a_vec(a_ref); + scalar_seq_view t0_vec(t0_ref); + scalar_seq_view w_vec(w_ref); + scalar_seq_view v_vec(v_ref); + scalar_seq_view sv_vec(sv_ref); + size_t N_y_t0 = max_size(y, t0); + + for (size_t i = 0; i < N_y_t0; ++i) { + if (y_vec[i] <= t0_vec[i]) { + std::stringstream msg; + msg << ", but must be greater than nondecision time = " << t0_vec[i]; + std::string msg_str(msg.str()); + throw_domain_error(function_name, "Random variable", y_vec[i], " = ", + msg_str.c_str()); + } + } + + if (!include_summand::value) { + return 0; + } + + double error_bound_dens = 1e-6; // precision for density + double lerror_bound_dens = log(error_bound_dens); + double error_bound = prec; // precision for + // derivatives (controllable by user) + double lerror_bound = log(error_bound); // log(alpha) + double abstol = 0.0; + double reltol = .9 * error_bound; // eps_rel(Integration) + double abstol_wiener5 = 1e-12; // eps_abs(wiener5) + double labstol_wiener5 = log(abstol_wiener5); + // log(eps_abs(wiener5) + int Meval = 6000; + double dens = 0.0; + double ld = 0.0; + operands_and_partials + ops_partials(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref); + + static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; + static constexpr double LOG_POINT1 = -1; + + // calculate density and partials + for (size_t i = 0; i < N; i++) { + // Calculate 4-parameter model without inter-trial variabilities (if + // sv_vec[i] == 0) or 5-parameter model with inter-trial variability in + // drift rate (if sv_vec[i] != 0) + const double y_val = y_vec.val(i); + const double a_val = a_vec.val(i); + const double t0_val = t0_vec.val(i); + const double w_val = w_vec.val(i); + const double v_val = v_vec.val(i); + const double sv_val = sv_vec.val(i); + + dens = internal::dwiener5(y_val - t0_val, a_val, v_val, w_val, sv_val, + labstol_wiener5); + if (labstol_wiener5 > fabs(dens) + lerror_bound_dens - LOG_TWO) { + dens = internal::dwiener5(y_val - t0_val, a_val, v_val, w_val, sv_val, + fabs(dens) + lerror_bound_dens - LOG_TWO); + } + ld += dens; + + // computation of derivative for t and precision check in order to give + // the value as deriv_y to edge1 and as -deriv_y to edge5 + double deriv_y = internal::dtdwiener5(y_val - t0_val, a_val, v_val, w_val, + sv_val, labstol_wiener5); + if (labstol_wiener5 > log(fabs(deriv_y)) + dens + lerror_bound - LOG_TWO) { + deriv_y = internal::dtdwiener5( + y_val - t0_val, a_val, v_val, w_val, sv_val, + log(fabs(deriv_y)) + dens + lerror_bound - LOG_FOUR); + } + + // computation of derivatives and precision checks + if (!is_constant_all::value) { + ops_partials.edge1_.partials_[i] = deriv_y; + } + if (!is_constant_all::value) { + double deriv_a = internal::dadwiener5(y_val - t0_val, a_val, v_val, w_val, + sv_val, labstol_wiener5, 0); + if (labstol_wiener5 + > log(fabs(deriv_a)) + dens + lerror_bound - LOG_TWO) { + deriv_a = internal::dadwiener5( + y_val - t0_val, a_val, v_val, w_val, sv_val, + log(fabs(deriv_a)) + dens + lerror_bound - LOG_FOUR, 0); + } + ops_partials.edge2_.partials_[i] = deriv_a; + } + if (!is_constant_all::value) { + ops_partials.edge3_.partials_[i] = -deriv_y; + } + if (!is_constant_all::value) { + double deriv_w = internal::dwdwiener5(y_val - t0_val, a_val, v_val, w_val, + sv_val, labstol_wiener5, 0); + if (labstol_wiener5 + > log(fabs(deriv_w)) + dens + lerror_bound - LOG_TWO) { + deriv_w = internal::dwdwiener5( + y_val - t0_val, a_val, v_val, w_val, sv_val, + log(fabs(deriv_w)) + dens + lerror_bound - LOG_FOUR, 0); + } + ops_partials.edge4_.partials_[i] = deriv_w; + } + if (!is_constant_all::value) { + ops_partials.edge5_.partials_[i] + = internal::dvdwiener5(y_val - t0_val, a_val, v_val, w_val, sv_val); + } + if (!is_constant_all::value) { + ops_partials.edge6_.partials_[i] + = internal::dsvdwiener5(y_val - t0_val, a_val, v_val, w_val, sv_val); + } + } // end for loop + return ops_partials.build(ld); +} // end wiener5_lpdf } // namespace math } // namespace stan #endif diff --git a/stan/math/prim/fun/wiener7_lpdf.hpp b/stan/math/prim/fun/wiener7_lpdf.hpp index e337a5e5265..4ee2995dd1f 100644 --- a/stan/math/prim/fun/wiener7_lpdf.hpp +++ b/stan/math/prim/fun/wiener7_lpdf.hpp @@ -14,72 +14,31 @@ namespace math { namespace internal { // tools -template struct my_params { - T_y y; - T_a a; - T_v v; - T_w w; - T_t0 t0; - T_sv sv; - T_sw sw; - T_st0 st0; - T_err lerr; + double y, a, v, w, t0, sv, sw, st0, lerr; }; -template struct my_params2 { - T_y y; - T_a a; - T_v v; - T_w w; - T_w_lower w_lower; - T_w_upper w_upper; - T_t0 t0; - T_sv sv; - T_sw sw; - T_sw_mean sw_mean; - T_st0 st0; - T_err lerr; + double y, a, v, w, w_lower, w_upper, t0, sv, sw, sw_mean, st0, lerr; }; -template struct my_params3 { - T_y y; - T_a a; - T_v v; - T_w w; - T_t0 t0; - T_t0_mean t0_mean; - T_sv sv; - T_sw sw; - T_st0 st0; - T_st0_mean st0_mean; - T_err lerr; + double y, a, v, w, t0, t0_mean, sv, sw, st0, st0_mean, lerr; }; // calculate derivative of density of wiener5 with respect to y (version for // wiener7) -template -return_type_t dtdwiener5_for_7( - const T_y& y, const T_a& a, const T_v& v, const T_w& w, const T_sv& sv, - const double& err) { - using T_return_type = return_type_t; - - T_return_type kll, kss, ans; +double dtdwiener5_for_7(const double& y, const double& a, const double& v, + const double& w, const double& sv, const double& err) { + double kll, kss, ans; // prepare some variables - T_return_type y_asq = y / square(a); - T_return_type la = 2.0 * log(a); - T_return_type ans0, lg1; + double y_asq = y / square(a); + double la = 2.0 * log(a); + double ans0, lg1; if (sv != 0) { - T_return_type sv_sqr = square(sv); - T_return_type one_plus_svsqr_y = (1 + sv_sqr * y); + double sv_sqr = square(sv); + double one_plus_svsqr_y = (1 + sv_sqr * y); ans0 = -0.5 * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - 2 * a * v * w) + square(v)) @@ -91,44 +50,43 @@ return_type_t dtdwiener5_for_7( ans0 = -0.5 * square(v); lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - la; } - T_return_type factor = lg1 - la; - - T_return_type ld = dwiener5(y, a, -v, 1 - w, sv, - err - log(max(fabs(ans0), fabs(ans0 - 1.5 / y)))); + double factor = lg1 - la; + double ld = dwiener5(y, a, -v, 1 - w, sv, + err - log(max(fabs(ans0), fabs(ans0 - 1.5 / y)))); // calculate the number of terms kss needed for small y - T_return_type es = err - lg1; + double es = err - lg1; es = es + la; - T_return_type K1 = (sqrt(3.0 * y_asq) + w) / 2.0; - T_return_type u_eps = fmin( + double K1 = (sqrt(3.0 * y_asq) + w) / 2.0; + double u_eps = fmin( -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(y_asq) + 2.0 * es) / 3.0); - T_return_type arg = -3.0 * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - T_return_type K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; + double arg = -3.0 * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + double K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; kss = ceil(fmax(K1, K2)); // calculate number of terms kll needed for large y - T_return_type el = err - lg1; + double el = err - lg1; el = el + la; K1 = sqrt(3.0 / y_asq) / pi(); u_eps = fmin(-1.0, el + log(0.6) + LOG_PI + 2.0 * log(y_asq)); static const double PISQ = square(pi()); // pi*pi arg = -2.0 / PISQ / y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - T_return_type kl = (arg > 0) ? sqrt(arg) : K1; + double kl = (arg > 0) ? sqrt(arg) : K1; kll = ceil(fmax(kl, K1)); - T_return_type erg; - T_return_type newsign = 1; - T_return_type fplus = NEGATIVE_INFTY; - T_return_type fminus = NEGATIVE_INFTY; + double erg; + double newsign = 1; + double fplus = NEGATIVE_INFTY; + double fminus = NEGATIVE_INFTY; // if small y is better if (2 * kss < kll) { // calculate terms of the sum for small y - T_return_type twot = 2.0 * y_asq; + double twot = 2.0 * y_asq; if (static_cast(kss) > 0) { for (size_t k = static_cast(kss); k >= 1; k--) { - T_return_type w_plus_2k = w + 2.0 * k; - T_return_type w_minus_2k = w - 2.0 * k; + double w_plus_2k = w + 2.0 * k; + double w_minus_2k = w - 2.0 * k; fplus = log_sum_exp(3.0 * log(w_plus_2k) - w_plus_2k * w_plus_2k / twot, fplus); fminus = log_sum_exp( @@ -142,7 +100,6 @@ return_type_t dtdwiener5_for_7( } else { erg = log_diff_exp(fplus, fminus); } - ans = ans0 - 1.5 / y + newsign * exp(factor - 1.5 * LOG_TWO - LOG_SQRT_PI - 3.5 * log(y_asq) @@ -150,10 +107,10 @@ return_type_t dtdwiener5_for_7( // if large y is better } else { // calculate terms of the sum for large y - T_return_type halfy = y_asq / 2.0; + double halfy = y_asq / 2.0; for (size_t k = static_cast(kll); k >= 1; k--) { - T_return_type pi_k = pi() * k; - T_return_type zwi = sin(pi_k * w); + double pi_k = pi() * k; + double zwi = sin(pi_k * w); if (zwi > 0) { fplus = log_sum_exp(3.0 * log(k) - pi_k * pi_k * halfy + log(zwi), fplus); @@ -169,7 +126,6 @@ return_type_t dtdwiener5_for_7( } else { erg = log_diff_exp(fplus, fminus); } - ans = ans0 - newsign * exp(factor + 3.0 * LOG_PI - LOG_TWO + erg - ld); } return ans * exp(ld); @@ -179,36 +135,28 @@ return_type_t dtdwiener5_for_7( // integrand density (on normal scale) template return_type_t int_ddiff(const T_x& x, const T_p& p) { - using T_return_type = return_type_t; - my_params* params - = static_cast*>(p); - T_return_type y = (params->y); - T_return_type a = (params->a); - T_return_type v = (params->v); - T_return_type t0 = (params->t0); - T_return_type w = (params->w); - T_return_type sw = (params->sw); - T_return_type sv = (params->sv); - T_return_type st0 = (params->st0); - T_return_type lerr = (params->lerr); + my_params* params = static_cast(p); + double y = (params->y); + double a = (params->a); + double v = (params->v); + double t0 = (params->t0); + double w = (params->w); + double sw = (params->sw); + double sv = (params->sv); + double st0 = (params->st0); + double lerr = (params->lerr); using T_x_ref = ref_type_t; T_x_ref x_ref = x; scalar_seq_view x_vec(x_ref); - - T_return_type retval; - - T_return_type omega = sw ? w + sw * (x_vec[0] - 0.5) : w; - T_return_type t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); + double retval; + double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; + double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); if (y - t0_ <= 0) { retval = 0.0; } else { - T_return_type ldW = dwiener5(y - t0_, a, v, omega, sv, lerr); + double ldW = dwiener5(y - t0_, a, v, omega, sv, lerr); retval = exp(ldW); } return retval; @@ -218,33 +166,25 @@ return_type_t int_ddiff(const T_x& x, const T_p& p) { // integrand d/dt (on normal scale) template return_type_t int_dtddiff(const T_x& x, const T_p& p) { - using T_return_type = return_type_t; - my_params* params - = static_cast*>(p); - T_return_type y = (params->y); - T_return_type a = (params->a); - T_return_type v = (params->v); - T_return_type t0 = (params->t0); - T_return_type w = (params->w); - T_return_type sw = (params->sw); - T_return_type sv = (params->sv); - T_return_type st0 = (params->st0); - T_return_type lerr = (params->lerr); + my_params* params = static_cast(p); + double y = (params->y); + double a = (params->a); + double v = (params->v); + double t0 = (params->t0); + double w = (params->w); + double sw = (params->sw); + double sv = (params->sv); + double st0 = (params->st0); + double lerr = (params->lerr); using T_x_ref = ref_type_t; T_x_ref x_ref = x; scalar_seq_view x_vec(x_ref); - T_return_type retval; - - T_return_type omega = sw ? w + sw * (x_vec[0] - 0.5) : w; - T_return_type t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); - + double retval; + double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; + double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); if (y - t0_ <= 0) { retval = 0.0; } else { @@ -257,41 +197,33 @@ return_type_t int_dtddiff(const T_x& x, const T_p& p) { // integrand d/da (on normal scale) template return_type_t int_daddiff(const T_x& x, const T_p& p) { - using T_return_type = return_type_t; - my_params* params - = static_cast*>(p); - T_return_type y = (params->y); - T_return_type a = (params->a); - T_return_type v = (params->v); - T_return_type t0 = (params->t0); - T_return_type w = (params->w); - T_return_type sw = (params->sw); - T_return_type sv = (params->sv); - T_return_type st0 = (params->st0); - T_return_type lerr = (params->lerr); + my_params* params = static_cast(p); + double y = (params->y); + double a = (params->a); + double v = (params->v); + double t0 = (params->t0); + double w = (params->w); + double sw = (params->sw); + double sv = (params->sv); + double st0 = (params->st0); + double lerr = (params->lerr); using T_x_ref = ref_type_t; T_x_ref x_ref = x; scalar_seq_view x_vec(x_ref); - T_return_type retval; - - T_return_type omega = sw ? w + sw * (x_vec[0] - 0.5) : w; - T_return_type t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); - + double retval; + double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; + double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); if (y - t0_ <= 0) { retval = 0.0; } else { // prepare some variables for error estimation in density - T_return_type sv_sqr = square(sv); - T_return_type ans0 = (v * (1 - omega) + sv_sqr * square(1 - omega) * a) - / (1 + sv_sqr * (y - t0_)); - T_return_type factor + double sv_sqr = square(sv); + double ans0 = (v * (1 - omega) + sv_sqr * square(1 - omega) * a) + / (1 + sv_sqr * (y - t0_)); + double factor = max(ans0 + 1.0 / a, ans0 - 2.0 / a); // factor from small and large // representation, for same // computation as in dadwiener5 @@ -305,33 +237,25 @@ return_type_t int_daddiff(const T_x& x, const T_p& p) { // integrand d/dv (on normal scale) template return_type_t int_dvddiff(const T_x& x, const T_p& p) { - using T_return_type = return_type_t; - my_params* params - = static_cast*>(p); - T_return_type y = (params->y); - T_return_type a = (params->a); - T_return_type v = (params->v); - T_return_type t0 = (params->t0); - T_return_type w = (params->w); - T_return_type sw = (params->sw); - T_return_type sv = (params->sv); - T_return_type st0 = (params->st0); - T_return_type lerr = (params->lerr); + my_params* params = static_cast(p); + double y = (params->y); + double a = (params->a); + double v = (params->v); + double t0 = (params->t0); + double w = (params->w); + double sw = (params->sw); + double sv = (params->sv); + double st0 = (params->st0); + double lerr = (params->lerr); using T_x_ref = ref_type_t; T_x_ref x_ref = x; scalar_seq_view x_vec(x_ref); - T_return_type retval; - - T_return_type omega = sw ? w + sw * (x_vec[0] - 0.5) : w; - T_return_type t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); - + double retval; + double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; + double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); if (y - t0_ <= 0) { retval = 0.0; } else { @@ -345,39 +269,31 @@ return_type_t int_dvddiff(const T_x& x, const T_p& p) { // integrand d/dw (on normal scale) template return_type_t int_dwddiff(const T_x& x, const T_p& p) { - using T_return_type = return_type_t; - my_params* params - = static_cast*>(p); - T_return_type y = (params->y); - T_return_type a = (params->a); - T_return_type v = (params->v); - T_return_type t0 = (params->t0); - T_return_type w = (params->w); - T_return_type sw = (params->sw); - T_return_type sv = (params->sv); - T_return_type st0 = (params->st0); - T_return_type lerr = (params->lerr); + my_params* params = static_cast(p); + double y = (params->y); + double a = (params->a); + double v = (params->v); + double t0 = (params->t0); + double w = (params->w); + double sw = (params->sw); + double sv = (params->sv); + double st0 = (params->st0); + double lerr = (params->lerr); using T_x_ref = ref_type_t; T_x_ref x_ref = x; scalar_seq_view x_vec(x_ref); - T_return_type retval; - - T_return_type omega = sw ? w + sw * (x_vec[0] - 0.5) : w; - T_return_type t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); - + double retval; + double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; + double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); if (y - t0_ <= 0) { retval = 0.0; } else { // prepare some variables for error estimation in density - T_return_type sv_sqr = square(sv); - T_return_type ans0 + double sv_sqr = square(sv); + double ans0 = (v * a + sv_sqr * square(a) * (1 - omega)) / (1 + sv_sqr * (y - t0_)); // compute partial derivative retval = dwdwiener5(y - t0_, a, v, omega, sv, lerr, 1); @@ -389,33 +305,25 @@ return_type_t int_dwddiff(const T_x& x, const T_p& p) { // integrand d/dsv (on normal scale) template return_type_t int_dsvddiff(const T_x& x, const T_p& p) { - using T_return_type = return_type_t; - my_params* params - = static_cast*>(p); - T_return_type y = (params->y); - T_return_type a = (params->a); - T_return_type v = (params->v); - T_return_type t0 = (params->t0); - T_return_type w = (params->w); - T_return_type sw = (params->sw); - T_return_type sv = (params->sv); - T_return_type st0 = (params->st0); - T_return_type lerr = (params->lerr); + my_params* params = static_cast(p); + double y = (params->y); + double a = (params->a); + double v = (params->v); + double t0 = (params->t0); + double w = (params->w); + double sw = (params->sw); + double sv = (params->sv); + double st0 = (params->st0); + double lerr = (params->lerr); using T_x_ref = ref_type_t; T_x_ref x_ref = x; scalar_seq_view x_vec(x_ref); - T_return_type retval; - - T_return_type omega = sw ? w + sw * (x_vec[0] - 0.5) : w; - T_return_type t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); - + double retval; + double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; + double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); if (y - t0_ <= 0) { retval = 0.0; } else { @@ -429,36 +337,26 @@ return_type_t int_dsvddiff(const T_x& x, const T_p& p) { // integrand d/dsw (on normal scale) template return_type_t int_dswddiff(const T_x& x, const T_p& p) { - using T_return_type = return_type_t; - my_params2* params - = static_cast*>( - p); - T_return_type y = (params->y); - T_return_type a = (params->a); - T_return_type v = (params->v); - T_return_type t0 = (params->t0); - T_return_type w = (params->w); - T_return_type w_lower = (params->w_lower); - T_return_type w_upper = (params->w_upper); - T_return_type sw = (params->sw); - T_return_type sw_mean = (params->sw_mean); - T_return_type sv = (params->sv); - T_return_type st0 = (params->st0); - T_return_type lerr = (params->lerr); + my_params2* params = static_cast(p); + double y = (params->y); + double a = (params->a); + double v = (params->v); + double t0 = (params->t0); + double w = (params->w); + double w_lower = (params->w_lower); + double w_upper = (params->w_upper); + double sw = (params->sw); + double sw_mean = (params->sw_mean); + double sv = (params->sv); + double st0 = (params->st0); + double lerr = (params->lerr); using T_x_ref = ref_type_t; T_x_ref x_ref = x; scalar_seq_view x_vec(x_ref); - - T_return_type t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); - - T_return_type f, fl, fu; + double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); + double f, fl, fu; if (y - t0_ <= 0) { return 0.0; } else { @@ -472,36 +370,27 @@ return_type_t int_dswddiff(const T_x& x, const T_p& p) { // integrand d/dst0 (on normal scale) template return_type_t int_dst0ddiff(const T_x& x, const T_p& p) { - using T_return_type = return_type_t; - my_params3* params - = static_cast< - my_params3*>(p); - T_return_type y = (params->y); - T_return_type a = (params->a); - T_return_type v = (params->v); - T_return_type t0 = (params->t0); - T_return_type t0_mean = (params->t0_mean); - T_return_type w = (params->w); - T_return_type sw = (params->sw); - T_return_type sv = (params->sv); - T_return_type st0 = (params->st0); - T_return_type st0_mean = (params->st0_mean); - T_return_type lerr = (params->lerr); + my_params3* params = static_cast(p); + double y = (params->y); + double a = (params->a); + double v = (params->v); + double t0 = (params->t0); + double t0_mean = (params->t0_mean); + double w = (params->w); + double sw = (params->sw); + double sv = (params->sv); + double st0 = (params->st0); + double st0_mean = (params->st0_mean); + double lerr = (params->lerr); using T_x_ref = ref_type_t; T_x_ref x_ref = x; scalar_seq_view x_vec(x_ref); - T_return_type t0_ = sw ? (st0_mean ? t0_mean + st0_mean * x_vec[1] : t0_mean) - : (st0_mean ? t0_mean + st0_mean * x_vec[0] : t0_mean); - - T_return_type omega = sw ? w + sw * (x_vec[0] - 0.5) : w; - - T_return_type f; + double t0_ = sw ? (st0_mean ? t0_mean + st0_mean * x_vec[1] : t0_mean) + : (st0_mean ? t0_mean + st0_mean * x_vec[0] : t0_mean); + double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; + double f; if (y - t0_ <= 0) { return 0.0; } else { @@ -512,6 +401,388 @@ return_type_t int_dst0ddiff(const T_x& x, const T_p& p) { //----------------------------------------------- } // namespace internal + +template +inline return_type_t wiener7_lpdf( + const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, + const T_sv& sv, const T_sw& sw, const T_st0& st0, const double& prec) { + using T_y_ref = ref_type_t; + using T_a_ref = ref_type_t; + using T_v_ref = ref_type_t; + using T_w_ref = ref_type_t; + using T_t0_ref = ref_type_t; + using T_sv_ref = ref_type_t; + using T_sw_ref = ref_type_t; + using T_st0_ref = ref_type_t; + + const char* function_name = "wiener7_lpdf"; + check_consistent_sizes(function_name, "Random variable", y, + "Boundary separation", a, "Drift rate", v, + "A-priori bias", w, "Nondecision time", t0, + "Inter-trial variability in drift rate", sv, + "Inter-trial variability in A-priori bias", sw, + "Inter-trial variability in Nondecision time", st0); + check_consistent_size(function_name, "Random variable", y, 1); + check_consistent_size(function_name, "Boundary separation", a, 1); + check_consistent_size(function_name, "Drift rate", v, 1); + check_consistent_size(function_name, "A-priori bias", w, 1); + check_consistent_size(function_name, "Nondecision time", t0, 1); + check_consistent_size(function_name, "Inter-trial variability in drift rate", + sv, 1); + check_consistent_size(function_name, + "Inter-trial variability in A-priori bias", sw, 1); + check_consistent_size(function_name, + "Inter-trial variability in Nondecision time", st0, 1); + + T_y_ref y_ref = y; + T_a_ref a_ref = a; + T_v_ref v_ref = v; + T_w_ref w_ref = w; + T_t0_ref t0_ref = t0; + T_sv_ref sv_ref = sv; + T_sw_ref sw_ref = sw; + T_st0_ref st0_ref = st0; + + check_positive_finite(function_name, "Random variable", value_of(y_ref)); + check_positive_finite(function_name, "Boundary separation", + value_of(a_ref)); + check_finite(function_name, "Drift rate", value_of(v_ref)); + check_less(function_name, "A-priori bias", value_of(w_ref), 1); + check_greater(function_name, "A-priori bias", value_of(w_ref), 0); + check_nonnegative(function_name, "Nondecision time", value_of(t0_ref)); + check_finite(function_name, "Nondecision time", value_of(t0_ref)); + check_nonnegative(function_name, "Inter-trial variability in drift rate", + value_of(sv_ref)); + check_finite(function_name, "Inter-trial variability in drift rate", + value_of(sv_ref)); + check_bounded(function_name, "Inter-trial variability in A-priori bias", + value_of(sw_ref), 0, 1); + check_nonnegative(function_name, + "Inter-trial variability in Nondecision time", + value_of(st0_ref)); + check_finite(function_name, "Inter-trial variability in Nondecision time", + value_of(st0_ref)); + + if (size_zero(y, a, v, w, t0) || size_zero(sv, sw, st0)) { + return 0; + } + size_t N = max_size(y, a, v, w, t0, sv, sw, st0); + if (!N) { + return 0; + } + scalar_seq_view y_vec(y_ref); + scalar_seq_view a_vec(a_ref); + scalar_seq_view v_vec(v_ref); + scalar_seq_view w_vec(w_ref); + scalar_seq_view t0_vec(t0_ref); + scalar_seq_view sv_vec(sv_ref); + scalar_seq_view sw_vec(sw_ref); + scalar_seq_view st0_vec(st0_ref); + size_t N_y_t0 = max_size(y, t0, st0); + + for (size_t i = 0; i < N_y_t0; ++i) { + if (y_vec[i] <= t0_vec[i]) { + std::stringstream msg; + msg << ", but must be greater than nondecision time = " << t0_vec[i]; + std::string msg_str(msg.str()); + throw_domain_error(function_name, "Random variable", y_vec[i], " = ", + msg_str.c_str()); + } + } + size_t N_beta_sw = max_size(w, sw); + for (size_t i = 0; i < N_beta_sw; ++i) { + if (w_vec[i] - .5 * sw_vec[i] <= 0) { + std::stringstream msg; + msg << ", but must be smaller than 2*(A-priori bias) = " + << 2 * w_vec[i]; + std::string msg_str(msg.str()); + throw_domain_error(function_name, + "Inter-trial variability in A-priori bias", sw_vec[i], + " = ", msg_str.c_str()); + } + if (w_vec[i] + .5 * sw_vec[i] >= 1) { + std::stringstream msg; + msg << ", but must be smaller than 2*(1-A-priori bias) = " + << 2 * (1 - w_vec[i]); + std::string msg_str(msg.str()); + throw_domain_error(function_name, + "Inter-trial variability in A-priori bias", sw_vec[i], + " = ", msg_str.c_str()); + } + } + if (!include_summand::value) { + return 0; + } + + double error_bound_dens = 1e-6; // precision for density + double lerror_bound_dens = log(error_bound_dens); + double error_bound = prec; // precision for + // derivatives (controllable by user) + double lerror_bound = log(error_bound); // log(alpha) + double abstol = 0.0; + double reltol = .9 * error_bound; // eps_rel(Integration) + double abstol_wiener5 = 1e-12; // eps_abs(wiener5) + double labstol_wiener5 = log(abstol_wiener5); + // log(eps_abs(wiener5) + int Meval = 6000; + double dens = 0.0; + double ld = 0.0; + operands_and_partials + ops_partials(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref, + sw_ref, st0_ref); + static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; + static constexpr double LOG_POINT1 = -1; + + // calculate density and partials + for (size_t i = 0; i < N; i++) { + const double y_val = y_vec.val(i); + const double a_val = a_vec.val(i); + const double v_val = v_vec.val(i); + const double w_val = w_vec.val(i); + const double t0_val = t0_vec.val(i); + const double sv_val = sv_vec.val(i); + const double sw_val = sw_vec.val(i); + const double st0_val = st0_vec.val(i); + internal::my_params params + = {y_val, a_val, v_val, + w_val, t0_val, sv_val, + sw_val, st0_val, labstol_wiener5 - LOG_TWO}; + int dim = (sw_val != 0) + (st0_val != 0); + check_positive(function_name, + "(Inter-trial variability in A-priori bias) + " + "(Inter-trial variability in nondecision time)", + dim); + + std::vector xmin(dim, 0); + std::vector xmax(dim, 1); + if (st0_val) { + xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); + } + + dens = hcubature(internal::int_ddiff, void*>, ¶ms, + dim, xmin, xmax, Meval, abstol, reltol / 2); + if (labstol_wiener5 + > fabs(log(dens)) + LOG_POINT1 + lerror_bound_dens - LOG_TWO) { + double new_error + = LOG_POINT1 + lerror_bound_dens - LOG_TWO + log(fabs(dens)); + internal::my_params params_new_error + = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; + dens = hcubature(internal::int_ddiff, void*>, + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, + reltol); + } + ld += log(dens); + + // computation of derivative for t and precision check in order to give + // the value as deriv_t to edge1 and as -deriv_t to edge5 + double deriv_t_7; + deriv_t_7 + = 1 / dens + * hcubature(internal::int_dtddiff, void*>, + ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); + if (labstol_wiener5 + > log(fabs(deriv_t_7)) + LOG_POINT1 + lerror_bound - LOG_TWO) { + double new_error + = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv_t_7)); + internal::my_params params_new_error + = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; + deriv_t_7 = 1 / dens + * hcubature(internal::int_dtddiff, void*>, + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, + reltol / 2); + } + + // computation of derivatives and precision checks + double deriv; + if (!is_constant_all::value) { + ops_partials.edge1_.partials_[i] = deriv_t_7; + } + if (!is_constant_all::value) { + deriv = 1 / dens + * hcubature(internal::int_daddiff, void*>, + ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); + if (labstol_wiener5 + > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { + double new_error + = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv)); + internal::my_params params_new_error + = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; + deriv = 1 / dens + * hcubature(internal::int_daddiff, void*>, + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, + reltol / 2); + } + ops_partials.edge2_.partials_[i] = deriv; + } + if (!is_constant_all::value) { + ops_partials.edge3_.partials_[i] = -deriv_t_7; + } + if (!is_constant_all::value) { + deriv = 1 / dens + * hcubature(internal::int_dwddiff, void*>, + ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); + if (labstol_wiener5 + > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { + double new_error + = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv)); + internal::my_params params_new_error + = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; + deriv = 1 / dens + * hcubature(internal::int_dwddiff, void*>, + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, + reltol / 2); + } + ops_partials.edge4_.partials_[i] = deriv; + } + if (!is_constant_all::value) { + deriv = 1 / dens + * hcubature(internal::int_dvddiff, void*>, + ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); + if (labstol_wiener5 + > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { + double new_error + = LOG_POINT1 + lerror_bound - LOG_TWO + log(fabs(deriv)); + internal::my_params params_new_error + = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; + deriv = 1 / dens + * hcubature(internal::int_dvddiff, void*>, + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, + reltol / 2); + } + ops_partials.edge5_.partials_[i] = deriv; + } + if (!is_constant_all::value) { + deriv = 1 / dens + * hcubature(internal::int_dsvddiff, void*>, + ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); + if (labstol_wiener5 + > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { + double new_error + = LOG_POINT1 + lerror_bound - LOG_TWO + log(fabs(deriv)); + internal::my_params params_new_error + = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; + deriv = 1 / dens + * hcubature(internal::int_dsvddiff, void*>, + ¶ms_new_error, dim, xmin, xmax, Meval, abstol, + reltol / 2); + } + ops_partials.edge6_.partials_[i] = deriv; + } + if (!is_constant_all::value) { + if (sw_val == 0) { + ops_partials.edge7_.partials_[i] = 0; + } else { + double lower, upper, width, fl, fu; + lower = w_val - sw_val / 2; + lower = (0 > lower) ? 0 : lower; + upper = w_val + sw_val / 2; + upper = (1 < upper) ? 1 : upper; + width = upper - lower; + + int dim_ = (st0_val != 0); + if (dim_ == 0) { + fl = exp(internal::dwiener5(y_val - t0_val, a_val, v_val, + lower, sv_val, labstol_wiener5)); + fu = exp(internal::dwiener5(y_val - t0_val, a_val, v_val, + upper, sv_val, labstol_wiener5)); + if (labstol_wiener5 > log(fabs(fl + fu) + log(sw_val) - LOG_TWO + + lerror_bound - LOG_TWO)) { + fl = exp(internal::dwiener5(y_val - t0_val, a_val, v_val, + lower, sv_val, + lerror_bound - LOG_TWO + log(sw_val) + - LOG_TWO + log(fabs(fl + fu)))); + fu = exp(internal::dwiener5(y_val - t0_val, a_val, v_val, + upper, sv_val, + lerror_bound - LOG_TWO + log(sw_val) + - LOG_TWO + log(fabs(fl + fu)))); + } + deriv = 1 / width * 0.5 * (fl + fu); + } else { + internal::my_params2 params_sw + = {y_val, a_val, v_val, w_val, + lower, upper, t0_val, sv_val, + 0, sw_val, st0_val, labstol_wiener5 - LOG_TWO}; + deriv = hcubature(internal::int_dswddiff, void*>, + ¶ms_sw, dim_, xmin, xmax, Meval, abstol, + reltol / 2); + if (labstol_wiener5 + > log(fabs(deriv) + LOG_POINT1 + lerror_bound - LOG_TWO)) { + double new_error + = log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO; + internal::my_params2 params_new_error_sw + = {y_val, a_val, v_val, w_val, lower, upper, + t0_val, sv_val, 0, sw_val, st0_val, new_error}; + deriv + = hcubature(internal::int_dswddiff, void*>, + ¶ms_new_error_sw, dim_, xmin, xmax, Meval, + abstol, reltol / 2); + } + } + ops_partials.edge7_.partials_[i] = deriv / dens - 1 / sw_val; + } + } + if (!is_constant_all::value) { + double f; + if (st0_val == 0) { + ops_partials.edge8_.partials_[i] = 0; + } else if (y_val - (t0_val + st0_val) <= 0) { + ops_partials.edge8_.partials_[i] = -1 / st0_val; + } else { + int dim_ = (sw_val != 0); + if (dim_ == 0) { + f = exp(internal::dwiener5(y_val - (t0_val + st0_val), a_val, + v_val, w_val, sv_val, + labstol_wiener5)); + if (labstol_wiener5 > log(fabs(f) + log(st0_val) - LOG_TWO + + lerror_bound - LOG_TWO)) { + f = exp(internal::dwiener5(y_val - (t0_val + st0_val), a_val, + v_val, w_val, sv_val, + lerror_bound - LOG_TWO + log(st0_val) + - LOG_TWO + log(fabs(f)))); + } + deriv = 1 / st0_val * f; + } else { + double new_error = labstol_wiener5 - LOG_TWO; + internal::my_params3 params_st + = {y_val, a_val, v_val, + w_val, t0_val, t0_val + st0_val, + sv_val, sw_val, st0_val, + 0, new_error}; + deriv = hcubature(internal::int_dst0ddiff, void*>, + ¶ms_st, dim_, xmin, xmax, Meval, abstol, + reltol / 2); + if (labstol_wiener5 + > log(fabs(deriv) + LOG_POINT1 + lerror_bound - LOG_TWO)) { + double new_error + = log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO; + internal::my_params3 params_new_error_st + = {y_val, a_val, v_val, + w_val, t0_val, t0_val + st0_val, + sv_val, sw_val, st0_val, + 0, new_error}; + deriv + = hcubature(internal::int_dst0ddiff, void*>, + ¶ms_new_error_st, dim_, xmin, xmax, Meval, + abstol, reltol / 2); + } + } + ops_partials.edge8_.partials_[i] = -1 / st0_val + deriv / dens; + } + } + std::vector().swap(xmin); + std::vector().swap(xmax); + } + return ops_partials.build(ld); +} } // namespace math } // namespace stan #endif diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 563a449890f..024389645ff 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -7,151 +7,31 @@ namespace stan { namespace math { namespace internal { -template -inline return_type_t +template +inline return_type_t wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, - const T_a& a, const T_v& v, const T_w& w, - const T_t0& t0, const T_sv& sv, const T_sw& sw, + const T_a& a, const T_t0& t0, const T_w& w, + const T_v& v, const T_sv& sv, const T_sw& sw, const T_st0& st0, const double& prec) { - using T_partials_return - = partials_return_t; - using T_y_ref = ref_type_t; - using T_a_ref = ref_type_t; - using T_v_ref = ref_type_t; - using T_w_ref = ref_type_t; - using T_t0_ref = ref_type_t; - using T_sv_ref = ref_type_t; using T_sw_ref = ref_type_t; using T_st0_ref = ref_type_t; - check_consistent_sizes(function_name, "Random variable", y, - "Boundary separation", a, "Drift rate", v, - "A-priori bias", w, "Nondecision time", t0, - "Inter-trial variability in drift rate", sv, - "Inter-trial variability in A-priori bias", sw, - "Inter-trial variability in Nondecision time", st0); - - check_consistent_size(function_name, "Random variable", y, 1); - check_consistent_size(function_name, "Boundary separation", a, 1); - check_consistent_size(function_name, "Drift rate", v, 1); - check_consistent_size(function_name, "A-priori bias", w, 1); - check_consistent_size(function_name, "Nondecision time", t0, 1); - check_consistent_size(function_name, "Inter-trial variability in drift rate", - sv, 1); check_consistent_size(function_name, "Inter-trial variability in A-priori bias", sw, 1); check_consistent_size(function_name, "Inter-trial variability in Nondecision time", st0, 1); - T_y_ref y_ref = y; - T_a_ref alpha_ref = a; - T_v_ref delta_ref = v; - T_w_ref beta_ref = w; - T_t0_ref t0_ref = t0; - T_sv_ref sv_ref = sv; T_sw_ref sw_ref = sw; T_st0_ref st0_ref = st0; - check_positive_finite(function_name, "Random variable", value_of(y_ref)); - check_positive_finite(function_name, "Boundary separation", - value_of(alpha_ref)); - check_finite(function_name, "Drift rate", value_of(delta_ref)); - check_less(function_name, "A-priori bias", value_of(beta_ref), 1); - check_greater(function_name, "A-priori bias", value_of(beta_ref), 0); - check_nonnegative(function_name, "Nondecision time", value_of(t0_ref)); - check_finite(function_name, "Nondecision time", value_of(t0_ref)); - check_nonnegative(function_name, "Inter-trial variability in drift rate", - value_of(sv_ref)); - check_finite(function_name, "Inter-trial variability in drift rate", - value_of(sv_ref)); - check_bounded(function_name, "Inter-trial variability in A-priori bias", - value_of(sw_ref), 0, 1); - check_nonnegative(function_name, - "Inter-trial variability in Nondecision time", - value_of(st0_ref)); - check_finite(function_name, "Inter-trial variability in Nondecision time", - value_of(st0_ref)); - - if (size_zero(y, a, v, w, t0) || size_zero(sv, sw, st0)) { - return 0; - } - - size_t N = max_size(y, a, v, w, t0, sv, sw, st0); + size_t N = max_size(y, a, t0, w, v, sv, sw, st0); if (!N) { return 0; } - scalar_seq_view y_vec(y_ref); - scalar_seq_view alpha_vec(alpha_ref); - scalar_seq_view delta_vec(delta_ref); - scalar_seq_view beta_vec(beta_ref); - scalar_seq_view t0_vec(t0_ref); - scalar_seq_view sv_vec(sv_ref); scalar_seq_view sw_vec(sw_ref); scalar_seq_view st0_vec(st0_ref); - size_t N_y_t0 = max_size(y, t0, st0); - - for (size_t i = 0; i < N_y_t0; ++i) { - if (y_vec[i] <= t0_vec[i]) { - std::stringstream msg; - msg << ", but must be greater than nondecision time = " << t0_vec[i]; - std::string msg_str(msg.str()); - throw_domain_error(function_name, "Random variable", y_vec[i], " = ", - msg_str.c_str()); - } - } - size_t N_beta_sw = max_size(w, sw); - for (size_t i = 0; i < N_beta_sw; ++i) { - if (beta_vec[i] - .5 * sw_vec[i] <= 0) { - std::stringstream msg; - msg << ", but must be smaller than 2*(A-priori bias) = " - << 2 * beta_vec[i]; - std::string msg_str(msg.str()); - throw_domain_error(function_name, - "Inter-trial variability in A-priori bias", sw_vec[i], - " = ", msg_str.c_str()); - } - if (beta_vec[i] + .5 * sw_vec[i] >= 1) { - std::stringstream msg; - msg << ", but must be smaller than 2*(1-A-priori bias) = " - << 2 * (1 - beta_vec[i]); - std::string msg_str(msg.str()); - throw_domain_error(function_name, - "Inter-trial variability in A-priori bias", sw_vec[i], - " = ", msg_str.c_str()); - } - } - - if (!include_summand::value) { - return 0; - } - - // abstol_wiener5 z.B. 1e-12 on normal scale - // T_partials_return error_bound = 1e-6; - // alpha in Skizze - T_partials_return error_bound_dens = 1e-6; // precision for - // density (fixed here, test with 1e-6 and 1e-2) - T_partials_return lerror_bound_dens = log(error_bound_dens); - T_partials_return error_bound = prec; // precision for - // derivatives (controllable by user) - T_partials_return lerror_bound = log(error_bound); // log(alpha) - T_partials_return abstol = 0.0; - T_partials_return reltol = .9 * error_bound; // eps_rel(Integration) - T_partials_return abstol_wiener5 = 1e-12; // eps_abs(wiener5) - T_partials_return labstol_wiener5 = log(abstol_wiener5); - // log(eps_abs(wiener5) - int Meval = 6000; - T_partials_return dens = 0.0; - T_partials_return ld = 0.0; - operands_and_partials - ops_partials(y_ref, alpha_ref, delta_ref, beta_ref, t0_ref, sv_ref, - sw_ref, st0_ref); - - static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; - static constexpr double LOG_POINT1 = -1; // calculate density and partials for (size_t i = 0; i < N; i++) { @@ -159,379 +39,13 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, // sv_vec[i] == 0) or 5-parameter model with inter-trial variability in // drift rate (if sv_vec[i] != 0) if (sw_vec[i] == 0 && st0_vec[i] == 0) { - const T_partials_return y_val = y_vec.val(i); - const T_partials_return alpha_val = alpha_vec.val(i); - const T_partials_return delta_val = delta_vec.val(i); - const T_partials_return beta_val = beta_vec.val(i); - const T_partials_return t0_val = t0_vec.val(i); - const T_partials_return sv_val = sv_vec.val(i); - - dens = internal::dwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, - sv_val, labstol_wiener5); - if (labstol_wiener5 > fabs(dens) + lerror_bound_dens - LOG_TWO) { - dens = internal::dwiener5(y_val - t0_val, alpha_val, delta_val, - beta_val, sv_val, - fabs(dens) + lerror_bound_dens - LOG_TWO); - } - ld += dens; - - // computation of derivative for t and precision check in order to give - // the value as deriv_t to edge1 and as -deriv_t to edge5 - T_partials_return deriv_t - = internal::dtdwiener5(y_val - t0_val, alpha_val, delta_val, beta_val, - sv_val, labstol_wiener5); - if (labstol_wiener5 - > log(fabs(deriv_t)) + dens + lerror_bound - LOG_TWO) { - deriv_t = internal::dtdwiener5( - y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, - log(fabs(deriv_t)) + dens + lerror_bound - LOG_FOUR); - } - - // computation of derivatives and precision checks - if (!is_constant_all::value) { - ops_partials.edge1_.partials_[i] = deriv_t; - } - if (!is_constant_all::value) { - T_partials_return deriv_a - = internal::dadwiener5(y_val - t0_val, alpha_val, delta_val, - beta_val, sv_val, labstol_wiener5, 0); - if (labstol_wiener5 - > log(fabs(deriv_a)) + dens + lerror_bound - LOG_TWO) { - deriv_a = internal::dadwiener5( - y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, - log(fabs(deriv_a)) + dens + lerror_bound - LOG_FOUR, 0); - } - ops_partials.edge2_.partials_[i] = deriv_a; - } - if (!is_constant_all::value) { - ops_partials.edge3_.partials_[i] = internal::dvdwiener5( - y_val - t0_val, alpha_val, delta_val, beta_val, sv_val); - } - if (!is_constant_all::value) { - T_partials_return deriv_w - = internal::dwdwiener5(y_val - t0_val, alpha_val, delta_val, - beta_val, sv_val, labstol_wiener5, 0); - if (labstol_wiener5 - > log(fabs(deriv_w)) + dens + lerror_bound - LOG_TWO) { - deriv_w = internal::dwdwiener5( - y_val - t0_val, alpha_val, delta_val, beta_val, sv_val, - log(fabs(deriv_w)) + dens + lerror_bound - LOG_FOUR, 0); - } - ops_partials.edge4_.partials_[i] = deriv_w; - } - if (!is_constant_all::value) { - ops_partials.edge5_.partials_[i] = -deriv_t; - } - if (!is_constant_all::value) { - ops_partials.edge6_.partials_[i] = internal::dsvdwiener5( - y_val - t0_val, alpha_val, delta_val, beta_val, sv_val); - } - if (!is_constant_all::value) { - ops_partials.edge7_.partials_[i] = 0; - } - if (!is_constant_all::value) { - ops_partials.edge8_.partials_[i] = 0; - } + return wiener5_lpdf(y, a, t0, w, v, sv, prec); // Calculate 6-, or 7-parameter model } else { - const T_partials_return y_val = y_vec.val(i); - const T_partials_return alpha_val = alpha_vec.val(i); - const T_partials_return delta_val = delta_vec.val(i); - const T_partials_return beta_val = beta_vec.val(i); - const T_partials_return t0_val = t0_vec.val(i); - const T_partials_return sv_val = sv_vec.val(i); - const T_partials_return sw_val = sw_vec.val(i); - const T_partials_return st0_val = st0_vec.val(i); - internal::my_params< - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return> - params = {y_val, alpha_val, delta_val, - beta_val, t0_val, sv_val, - sw_val, st0_val, labstol_wiener5 - LOG_TWO}; - int dim = (sw_val != 0) + (st0_val != 0); - check_positive(function_name, - "(Inter-trial variability in A-priori bias) + " - "(Inter-trial variability in nondecision time)", - dim); - - std::vector xmin(dim, 0); - std::vector xmax(dim, 1); - - if (st0_val) { - xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); - } - - dens = hcubature(internal::int_ddiff, void*>, ¶ms, - dim, xmin, xmax, Meval, abstol, reltol / 2); - if (labstol_wiener5 - > fabs(log(dens)) + LOG_POINT1 + lerror_bound_dens - LOG_TWO) { - T_partials_return new_error - = LOG_POINT1 + lerror_bound_dens - LOG_TWO + log(fabs(dens)); - internal::my_params< - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return> - params_new_error = {y_val, alpha_val, delta_val, beta_val, t0_val, - sv_val, sw_val, st0_val, new_error}; - dens = hcubature(internal::int_ddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, - reltol); - } - ld += log(dens); - - // computation of derivative for t and precision check in order to give - // the value as deriv_t to edge1 and as -deriv_t to edge5 - T_partials_return deriv_t_7; - deriv_t_7 - = 1 / dens - * hcubature(internal::int_dtddiff, void*>, - ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); - if (labstol_wiener5 - > log(fabs(deriv_t_7)) + LOG_POINT1 + lerror_bound - LOG_TWO) { - T_partials_return new_error - = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv_t_7)); - internal::my_params< - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return> - params_new_error = {y_val, alpha_val, delta_val, beta_val, t0_val, - sv_val, sw_val, st0_val, new_error}; - deriv_t_7 - = 1 / dens - * hcubature(internal::int_dtddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, - reltol / 2); - } - - // computation of derivatives and precision checks - T_partials_return deriv; - if (!is_constant_all::value) { - ops_partials.edge1_.partials_[i] = deriv_t_7; - } - if (!is_constant_all::value) { - deriv - = 1 / dens - * hcubature(internal::int_daddiff, void*>, - ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); - if (labstol_wiener5 - > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { - T_partials_return new_error - = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv)); - internal::my_params< - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return> - params_new_error - = {y_val, alpha_val, delta_val, beta_val, t0_val, - sv_val, sw_val, st0_val, new_error}; - deriv = 1 / dens - * hcubature(internal::int_daddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, - reltol / 2); - } - ops_partials.edge2_.partials_[i] = deriv; - } - if (!is_constant_all::value) { - deriv - = 1 / dens - * hcubature(internal::int_dvddiff, void*>, - ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); - if (labstol_wiener5 - > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { - T_partials_return new_error - = LOG_POINT1 + lerror_bound - LOG_TWO + log(fabs(deriv)); - internal::my_params< - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return> - params_new_error - = {y_val, alpha_val, delta_val, beta_val, t0_val, - sv_val, sw_val, st0_val, new_error}; - deriv = 1 / dens - * hcubature(internal::int_dvddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, - reltol / 2); - } - ops_partials.edge3_.partials_[i] = deriv; - } - if (!is_constant_all::value) { - deriv - = 1 / dens - * hcubature(internal::int_dwddiff, void*>, - ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); - if (labstol_wiener5 - > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { - T_partials_return new_error - = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv)); - internal::my_params< - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return> - params_new_error - = {y_val, alpha_val, delta_val, beta_val, t0_val, - sv_val, sw_val, st0_val, new_error}; - deriv = 1 / dens - * hcubature(internal::int_dwddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, - reltol / 2); - } - ops_partials.edge4_.partials_[i] = deriv; - } - if (!is_constant_all::value) { - ops_partials.edge5_.partials_[i] = -deriv_t_7; - } - if (!is_constant_all::value) { - deriv - = 1 / dens - * hcubature(internal::int_dsvddiff, void*>, - ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); - if (labstol_wiener5 - > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { - T_partials_return new_error - = LOG_POINT1 + lerror_bound - LOG_TWO + log(fabs(deriv)); - internal::my_params< - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return> - params_new_error - = {y_val, alpha_val, delta_val, beta_val, t0_val, - sv_val, sw_val, st0_val, new_error}; - deriv - = 1 / dens - * hcubature(internal::int_dsvddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, - reltol / 2); - } - ops_partials.edge6_.partials_[i] = deriv; - } - if (!is_constant_all::value) { - if (sw_val == 0) { - ops_partials.edge7_.partials_[i] = 0; - } else { - T_partials_return lower, upper, width, fl, fu; - - lower = beta_val - sw_val / 2; - lower = (0 > lower) ? 0 : lower; - upper = beta_val + sw_val / 2; - upper = (1 < upper) ? 1 : upper; - width = upper - lower; - - int dim_ = (st0_val != 0); - if (dim_ == 0) { - fl = exp(internal::dwiener5(y_val - t0_val, alpha_val, delta_val, - lower, sv_val, labstol_wiener5)); - fu = exp(internal::dwiener5(y_val - t0_val, alpha_val, delta_val, - upper, sv_val, labstol_wiener5)); - if (labstol_wiener5 > log(fabs(fl + fu) + log(sw_val) - LOG_TWO - + lerror_bound - LOG_TWO)) { - fl = exp(internal::dwiener5(y_val - t0_val, alpha_val, delta_val, - lower, sv_val, - lerror_bound - LOG_TWO + log(sw_val) - - LOG_TWO + log(fabs(fl + fu)))); - fu = exp(internal::dwiener5(y_val - t0_val, alpha_val, delta_val, - upper, sv_val, - lerror_bound - LOG_TWO + log(sw_val) - - LOG_TWO + log(fabs(fl + fu)))); - } - deriv = 1 / width * 0.5 * (fl + fu); - } else { - internal::my_params2< - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return> - params_sw - = {y_val, alpha_val, delta_val, beta_val, - lower, upper, t0_val, sv_val, - 0, sw_val, st0_val, labstol_wiener5 - LOG_TWO}; - deriv = hcubature( - internal::int_dswddiff, void*>, ¶ms_sw, - dim_, xmin, xmax, Meval, abstol, reltol / 2); - if (labstol_wiener5 - > log(fabs(deriv) + LOG_POINT1 + lerror_bound - LOG_TWO)) { - T_partials_return new_error - = log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO; - internal::my_params2< - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return> - params_new_error_sw - = {y_val, alpha_val, delta_val, beta_val, - lower, upper, t0_val, sv_val, - 0, sw_val, st0_val, new_error}; - deriv = hcubature( - internal::int_dswddiff, void*>, - ¶ms_new_error_sw, dim_, xmin, xmax, Meval, abstol, - reltol / 2); - } - } - ops_partials.edge7_.partials_[i] = deriv / dens - 1 / sw_val; - } - } - if (!is_constant_all::value) { - T_partials_return f; - if (st0_val == 0) { - ops_partials.edge8_.partials_[i] = 0; - } else if (y_val - (t0_val + st0_val) <= 0) { - ops_partials.edge8_.partials_[i] = -1 / st0_val; - } else { - int dim_ = (sw_val != 0); - if (dim_ == 0) { - f = exp(internal::dwiener5(y_val - (t0_val + st0_val), alpha_val, - delta_val, beta_val, sv_val, - labstol_wiener5)); - if (labstol_wiener5 > log(fabs(f) + log(st0_val) - LOG_TWO - + lerror_bound - LOG_TWO)) { - f = exp(internal::dwiener5(y_val - (t0_val + st0_val), alpha_val, - delta_val, beta_val, sv_val, - lerror_bound - LOG_TWO + log(st0_val) - - LOG_TWO + log(fabs(f)))); - } - deriv = 1 / st0_val * f; - } else { - T_partials_return new_error = labstol_wiener5 - LOG_TWO; - internal::my_params3< - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return> - params_st = {y_val, alpha_val, delta_val, - beta_val, t0_val, t0_val + st0_val, - sv_val, sw_val, st0_val, - 0, new_error}; - deriv = hcubature( - internal::int_dst0ddiff, void*>, ¶ms_st, - dim_, xmin, xmax, Meval, abstol, reltol / 2); - if (labstol_wiener5 - > log(fabs(deriv) + LOG_POINT1 + lerror_bound - LOG_TWO)) { - T_partials_return new_error - = log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO; - internal::my_params3< - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return, - T_partials_return, T_partials_return> - params_new_error_st = {y_val, alpha_val, delta_val, - beta_val, t0_val, t0_val + st0_val, - sv_val, sw_val, st0_val, - 0, new_error}; - deriv = hcubature( - internal::int_dst0ddiff, void*>, - ¶ms_new_error_st, dim_, xmin, xmax, Meval, abstol, - reltol / 2); - } - } - ops_partials.edge8_.partials_[i] = -1 / st0_val + deriv / dens; - } - } - std::vector().swap(xmin); - std::vector().swap(xmax); + return wiener7_lpdf(y, a, t0, w, v, sv, sw, st0, prec); } } - - return ops_partials.build(ld); + return 0; } //----------------------------------------------- @@ -541,9 +55,9 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * The log of the first passage time density function for a (Wiener) * drift diffusion model with up to 7 parameters, where * \f$y\in \mathbb{R}_{+}\f$ is the reacion time, \f$a \in \mathbb{R}_{+}\f$ - * the boundary separation, \f$v \in \mathbb{R}\f$ the drifte rate, + * the boundary separation, \f$t_0 \in \mathbb{R}_{\geq 0}\f$ the non-decision time, * \f$w \in (0, 1)\f$ the relative starting point (aka a-priori bias), - * \f$t_0 \in \mathbb{R}_{\geq 0}\f$ the non-decision time, \f$s_v \in + * \f$v \in \mathbb{R}\f$ the drifte rate, \f$s_v \in * \mathbb{R}_{\geq 0}\f$ the inter-trial variability of the drift rate, * \f$s_w \in [0, 1)\f$ the inter-trial variability of the relative starting * point, and \f$s_{t_0} \in \mathbb{R}_{\geq 0}\f$ the inter-trial variability @@ -552,7 +66,7 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * * \f{eqnarray*}{ - y &\sim& \text{wiener_full}(a,v,w,t_0,s_v,s_w,s_{t_0}) \\ + y &\sim& \text{wiener_full}(a,t_0,w,v,s_v,s_w,s_{t_0}) \\ \log(p(y|a,v,w,t_0,s_v,s_w,s_{t_0})) &=& \log(\frac{1}{s_{t_0}} \int_{t_0}^{t_o + s_{t_0}} \frac{1}{s_{w}}\int_{w -0.5s_w}^{w + 0.5s_{w}} \int_{-\infty}^{\infty} p_3(y-\tau_0|a,\nu,\omega) \\ @@ -586,18 +100,18 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * * @tparam T_y type of scalar * @tparam T_a type of boundary - * @tparam T_v type of drift rate - * @tparam T_w type of relative starting point * @tparam T_t0 type of non-decision time + * @tparam T_w type of relative starting point + * @tparam T_v type of drift rate * @tparam T_sv type of inter-trial variability of drift rate * @tparam T_sw type of inter-trial variability of relative starting point * @tparam T_st0 type of inter-trial variability of non-decision time * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation - * @param v The drift rate - * @param w The relative starting point * @param t0 The non-decision time + * @param w The relative starting point + * @param v The drift rate * @param sv The inter-trial variability of the drift rate * @param sw The inter-trial variability of the relative starting point * @param st0 The inter-trial variability of the non-decision time @@ -614,11 +128,11 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * * The function can be called by @code - target += wiener_full_lpdf(y, a, v, w, t0, sv, sw, st0); + target += wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); @endcode * or @code - y ~ wiener_full(a, v, w, t0, sv, sw, st0); + y ~ wiener_full(a, t0, w, v, sv, sw, st0); @endcode * * By default \c wiener_full_lpdf() gives the log of the @@ -636,22 +150,22 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * variability for the relative starting point is needed one can write something like: @code - target += wiener_full_lpdf(y, a, v, w, t0, sv, 0, st0) + target += wiener_full_lpdf(y, a, t0, w, v, sv, 0, st0) @endcode * If no inter-trial variability is needed at all one can write something like: @code - target += wiener_full_lpdf(y, a, v, w, t0, 0, 0, 0) + target += wiener_full_lpdf(y, a, t0, w, v, 0, 0, 0) @endcode * If for some reason no non-decision time is assumed one can write something like: @code - target += wiener_full_lpdf(y, a, v, w, 0, sv, sw, 0) + target += wiener_full_lpdf(y, a, 0, w, v, sv, sw, 0) @endcode * * To also control the precision in the estimation of the partial derivatives, * call the function \c wiener_full_prec_lpdf(), analogously: @code - target += wiener_full__prec_lpdf(y, a, v, w, t0, sv, sw, st0, precision); + target += wiener_full__prec_lpdf(y, a, t0, w, v, sv, sw, st0, precision); @endcode * * @@ -678,29 +192,29 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * https://doi.org/10.1016/j.jmp.2009.02.003 */ -template -inline return_type_t -wiener_full_lpdf(const T_y& y, const T_a& a, const T_v& v, const T_w& w, - const T_t0& t0, const T_sv& sv, const T_sw& sw, +template +inline return_type_t +wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, + const T_v& v, const T_sv& sv, const T_sw& sw, const T_st0& st0) { double precision = 1e-4; - return internal::wiener_full_prec_impl_lpdf( - "wiener_full_lpdf", y, a, v, w, t0, sv, sw, st0, precision); + "wiener_full_lpdf", y, a, t0, w, v, sv, sw, st0, precision); } -template -inline return_type_t -wiener_full_lpdf(const T_y& y, const T_a& a, const T_v& v, const T_w& w, - const T_t0& t0, const T_sv& sv, const T_sw& sw, +inline return_type_t +wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, + const T_v& v, const T_sv& sv, const T_sw& sw, const T_st0& st0) { double precision = 1e-4; return internal::wiener_full_prec_impl_lpdf( - "wiener_full_lpdf", y, a, v, w, t0, sv, sw, st0, precision); + "wiener_full_lpdf", y, a, t0, w, v, sv, sw, st0, precision); } /** \ingroup prob_dists @@ -712,27 +226,28 @@ wiener_full_lpdf(const T_y& y, const T_a& a, const T_v& v, const T_w& w, * functions are the same excpet of the control over the precision. */ -template -inline return_type_t -wiener_full_prec_lpdf(const T_y& y, const T_a& a, const T_v& v, const T_w& w, - const T_t0& t0, const T_sv& sv, const T_sw& sw, +template +inline return_type_t +wiener_full_prec_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, + const T_v& v, const T_sv& sv, const T_sw& sw, const T_st0& st0, const double& prec) { - return internal::wiener_full_prec_impl_lpdf( - "wiener_full_prec_lpdf", y, a, v, w, t0, sv, sw, st0, prec); + "wiener_full_prec_lpdf", y, a, t0, w, v, sv, sw, st0, prec); } -template -inline return_type_t -wiener_full_prec_lpdf(const T_y& y, const T_a& a, const T_v& v, const T_w& w, - const T_t0& t0, const T_sv& sv, const T_sw& sw, +inline return_type_t +wiener_full_prec_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, + const T_v& v, const T_sv& sv, const T_sw& sw, const T_st0& st0, const double& prec) { return internal::wiener_full_prec_impl_lpdf( - "wiener_full_prec_lpdf", y, a, v, w, t0, sv, sw, st0, prec); + "wiener_full_prec_lpdf", y, a, t0, w, v, sv, sw, st0, prec); } } // namespace math } // namespace stan #endif + diff --git a/test/unit/math/prim/prob/wiener_full_prec_test.cpp b/test/unit/math/prim/prob/wiener_full_prec_test.cpp index a01be67a2bb..76599089b9a 100644 --- a/test/unit/math/prim/prob/wiener_full_prec_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_prec_test.cpp @@ -11,7 +11,7 @@ TEST(mathPrimScalProbWienerFullPrecScal, valid) { using stan::math::wiener_full_prec_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_NO_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, sw, st0, 1e-4)); + EXPECT_NO_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, sw, st0, 1e-4)); rt = 5; a = 1; v = 1; @@ -20,7 +20,7 @@ TEST(mathPrimScalProbWienerFullPrecScal, valid) { sv = 0.0; sw = 0.0; st0 = 0.0; - EXPECT_NO_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, sw, st0, 1e-4)); + EXPECT_NO_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, sw, st0, 1e-4)); } // rt @@ -28,15 +28,15 @@ TEST(mathPrimScalProbWienerFullPrecScal, invalid_rt) { using stan::math::INFTY; using stan::math::wiener_full_prec_lpdf; double a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(0, a, v, w, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(0, a, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(-1, a, v, w, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(-1, a, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(INFTY, a, v, w, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(INFTY, a, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(-INFTY, a, v, w, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(-INFTY, a, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(NAN, a, v, w, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(NAN, a, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); } @@ -45,15 +45,15 @@ TEST(mathPrimScalProbWienerFullPrecScal, invalid_a) { using stan::math::INFTY; using stan::math::wiener_full_prec_lpdf; double rt = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, 0, v, w, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, 0, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, -1, v, w, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, -1, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, INFTY, v, w, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, INFTY, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, -INFTY, v, w, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, -INFTY, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, NAN, v, w, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, NAN, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); } @@ -63,11 +63,11 @@ TEST(mathPrimScalProbWienerFullPrecScal, invalid_v) { using stan::math::wiener_full_prec_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, INFTY, w, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, INFTY, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, -INFTY, w, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, -INFTY, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, NAN, w, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, NAN, sv, sw, st0, 1e-4), std::domain_error); } @@ -76,19 +76,19 @@ TEST(mathPrimScalProbWienerFullPrecScal, invalid_w) { using stan::math::INFTY; using stan::math::wiener_full_prec_lpdf; double rt = 1, a = 1, v = -1, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, -0.1, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, -0.1, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 0, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, 0, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 1, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, 1, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 1.1, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, 1.1, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, INFTY, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, INFTY, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, -INFTY, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, -INFTY, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, NAN, t0, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, NAN, v, sv, sw, st0, 1e-4), std::domain_error); } @@ -97,15 +97,15 @@ TEST(mathPrimScalProbWienerFullPrecScal, invalid_t0) { using stan::math::INFTY; using stan::math::wiener_full_prec_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, 2, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, 2, w, v, sv, sw, st0, 1e-4), std::domain_error); // rt must be greater than t0 - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, -1, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, -1, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, INFTY, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, INFTY, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, -INFTY, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, -INFTY, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, NAN, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, NAN, w, v, sv, sw, st0, 1e-4), std::domain_error); } @@ -114,13 +114,13 @@ TEST(mathPrimScalProbWienerFullPrecScal, invalid_sv) { using stan::math::INFTY; using stan::math::wiener_full_prec_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, -1, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, -1, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, INFTY, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, INFTY, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, -INFTY, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, -INFTY, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, NAN, sw, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, NAN, sw, st0, 1e-4), std::domain_error); } @@ -129,17 +129,17 @@ TEST(mathPrimScalProbWienerFullPrecScal, invalid_sw) { using stan::math::INFTY; using stan::math::wiener_full_prec_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, -1, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, -1, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 0.8, t0, sv, 0.5, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, 0.8, v, sv, 0.5, st0, 1e-4), std::domain_error); // sw must be smaller than 2*(1-w) - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, 0.3, t0, sv, 0.7, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, 0.3, v, sv, 0.7, st0, 1e-4), std::domain_error); // sw must be smaller than 2*w - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, INFTY, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, INFTY, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, -INFTY, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, -INFTY, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, NAN, st0, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, NAN, st0, 1e-4), std::domain_error); } @@ -148,13 +148,13 @@ TEST(mathPrimScalProbWienerFullPrecScal, invalid_st0) { using stan::math::INFTY; using stan::math::wiener_full_prec_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, sw, -1, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, sw, -1, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, sw, INFTY, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, sw, INFTY, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, sw, -INFTY, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, sw, -INFTY, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, v, w, t0, sv, sw, NAN, 1e-4), + EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, sw, NAN, 1e-4), std::domain_error); } @@ -222,49 +222,49 @@ TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { for (int i = 0; i < result.size(); i++) { // rt auto f_rt = [=](auto value) { - return wiener_full_prec_lpdf(value, a[i], v[i], w[i], t0[i], sv[i], sw[i], + return wiener_full_prec_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types_2(f_rt, rt[i], result[i], drt[i]); // a auto f_a = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], value, v[i], w[i], t0[i], sv[i], + return wiener_full_prec_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types_2(f_a, a[i], result[i], da[i]); // v auto f_v = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], value, w[i], t0[i], sv[i], + return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i],value, sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types_2(f_v, v[i], result[i], dv[i]); // w auto f_w = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], v[i], value, t0[i], sv[i], + return wiener_full_prec_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types_2(f_w, w[i], result[i], dw[i]); // t0 auto f_t0 = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], v[i], w[i], value, sv[i], sw[i], + return wiener_full_prec_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types_2(f_t0, t0[i], result[i], dt0[i]); // sv auto f_sv = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], v[i], w[i], t0[i], value, sw[i], + return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], st0[i], 1e-6); }; check_scalar_types_2(f_sv, sv[i], result[i], dsv[i]); // sw auto f_sw = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], v[i], w[i], t0[i], sv[i], value, + return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, st0[i], 1e-6); }; check_scalar_types_2(f_sw, sw[i], result[i], dsw[i]); // st0 auto f_st0 = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], v[i], w[i], t0[i], sv[i], sw[i], + return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], value, 1e-6); }; check_scalar_types_2(f_st0, st0[i], result[i], dst0[i]); diff --git a/test/unit/math/prim/prob/wiener_full_test.cpp b/test/unit/math/prim/prob/wiener_full_test.cpp index 96658f30dc4..6a5e1d20dd9 100644 --- a/test/unit/math/prim/prob/wiener_full_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_test.cpp @@ -11,7 +11,7 @@ TEST(mathPrimScalProbWienerFullScal, valid) { using stan::math::wiener_full_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_NO_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, sw, st0)); + EXPECT_NO_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, st0)); rt = 5; a = 1; v = 1; @@ -20,7 +20,7 @@ TEST(mathPrimScalProbWienerFullScal, valid) { sv = 0.0; sw = 0.0; st0 = 0.0; - EXPECT_NO_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, sw, st0)); + EXPECT_NO_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, st0)); } // rt @@ -28,15 +28,15 @@ TEST(mathPrimScalProbWienerFullScal, invalid_rt) { using stan::math::INFTY; using stan::math::wiener_full_lpdf; double a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(0, a, v, w, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(0, a, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(-1, a, v, w, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(-1, a, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(INFTY, a, v, w, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(INFTY, a, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(-INFTY, a, v, w, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(-INFTY, a, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(NAN, a, v, w, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(NAN, a, t0, w, v, sv, sw, st0), std::domain_error); } @@ -45,15 +45,15 @@ TEST(mathPrimScalProbWienerFullScal, invalid_a) { using stan::math::INFTY; using stan::math::wiener_full_lpdf; double rt = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, 0, v, w, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, 0, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, -1, v, w, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, -1, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, INFTY, v, w, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, INFTY, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, -INFTY, v, w, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, -INFTY, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, NAN, v, w, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, NAN, t0, w, v, sv, sw, st0), std::domain_error); } @@ -63,11 +63,11 @@ TEST(mathPrimScalProbWienerFullScal, invalid_v) { using stan::math::wiener_full_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, INFTY, w, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, INFTY, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, -INFTY, w, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, -INFTY, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, NAN, w, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, NAN, sv, sw, st0), std::domain_error); } @@ -76,19 +76,19 @@ TEST(mathPrimScalProbWienerFullScal, invalid_w) { using stan::math::INFTY; using stan::math::wiener_full_lpdf; double rt = 1, a = 1, v = -1, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, v, -0.1, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, -0.1, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, 0, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, 1, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 1, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, 1.1, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 1.1, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, INFTY, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, INFTY, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, -INFTY, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, -INFTY, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, NAN, t0, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, NAN, v, sv, sw, st0), std::domain_error); } @@ -97,15 +97,15 @@ TEST(mathPrimScalProbWienerFullScal, invalid_t0) { using stan::math::INFTY; using stan::math::wiener_full_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, 2, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, 2, w, v, sv, sw, st0), std::domain_error); // rt must be greater than t0 - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, -1, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, -1, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, INFTY, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, INFTY, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, -INFTY, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, -INFTY, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, NAN, sv, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, NAN, w, v, sv, sw, st0), std::domain_error); } @@ -114,13 +114,13 @@ TEST(mathPrimScalProbWienerFullScal, invalid_sv) { using stan::math::INFTY; using stan::math::wiener_full_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, -1, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, -1, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, INFTY, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, INFTY, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, -INFTY, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, -INFTY, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, NAN, sw, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, NAN, sw, st0), std::domain_error); } @@ -129,17 +129,17 @@ TEST(mathPrimScalProbWienerFullScal, invalid_sw) { using stan::math::INFTY; using stan::math::wiener_full_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, -1, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, -1, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, 0.8, t0, sv, 0.5, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0.8, v, sv, 0.5, st0), std::domain_error); // sw must be smaller than 2*(1-w) - EXPECT_THROW(wiener_full_lpdf(rt, a, v, 0.3, t0, sv, 0.7, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0.3, v, sv, 0.7, st0), std::domain_error); // sw must be smaller than 2*w - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, INFTY, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, INFTY, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, -INFTY, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, -INFTY, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, NAN, st0), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, NAN, st0), std::domain_error); } @@ -148,13 +148,13 @@ TEST(mathPrimScalProbWienerFullScal, invalid_st0) { using stan::math::INFTY; using stan::math::wiener_full_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2; - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, sw, -1), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, -1), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, sw, INFTY), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, INFTY), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, sw, -INFTY), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, -INFTY), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, v, w, t0, sv, sw, NAN), + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, NAN), std::domain_error); } @@ -221,49 +221,49 @@ TEST(ProbWienerFull, wiener_full_all_scalar) { for (int i = 0; i < result.size(); i++) { // rt auto f_rt = [=](auto value) { - return wiener_full_lpdf(value, a[i], v[i], w[i], t0[i], sv[i], sw[i], + return wiener_full_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_rt, rt[i], result[i], drt[i]); // a auto f_a = [=](auto value) { - return wiener_full_lpdf(rt[i], value, v[i], w[i], t0[i], sv[i], sw[i], + return wiener_full_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_a, a[i], result[i], da[i]); // v auto f_v = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], value, w[i], t0[i], sv[i], sw[i], + return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], st0[i]); }; check_scalar_types(f_v, v[i], result[i], dv[i]); // w auto f_w = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], v[i], value, t0[i], sv[i], sw[i], + return wiener_full_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_w, w[i], result[i], dw[i]); // t0 auto f_t0 = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], v[i], w[i], value, sv[i], sw[i], + return wiener_full_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_t0, t0[i], result[i], dt0[i]); // sv auto f_sv = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], v[i], w[i], t0[i], value, sw[i], + return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], st0[i]); }; check_scalar_types(f_sv, sv[i], result[i], dsv[i]); // sw auto f_sw = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], v[i], w[i], t0[i], sv[i], value, + return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, st0[i]); }; check_scalar_types(f_sw, sw[i], result[i], dsw[i]); // st0 auto f_st0 = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], v[i], w[i], t0[i], sv[i], sw[i], + return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], value); }; check_scalar_types(f_st0, st0[i], result[i], dst0[i]); From e222428edec7b59901b1a71bbdcfc6de68d5e19f Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 27 Mar 2023 11:51:35 -0400 Subject: [PATCH 015/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/fun/wiener7_lpdf.hpp | 87 +++++++++---------- stan/math/prim/prob/wiener_full_lpdf.hpp | 4 +- .../math/prim/prob/wiener_full_prec_test.cpp | 2 +- 3 files changed, 42 insertions(+), 51 deletions(-) diff --git a/stan/math/prim/fun/wiener7_lpdf.hpp b/stan/math/prim/fun/wiener7_lpdf.hpp index 4ee2995dd1f..50531d37647 100644 --- a/stan/math/prim/fun/wiener7_lpdf.hpp +++ b/stan/math/prim/fun/wiener7_lpdf.hpp @@ -445,8 +445,7 @@ inline return_type_t wiener7_lpdf( T_st0_ref st0_ref = st0; check_positive_finite(function_name, "Random variable", value_of(y_ref)); - check_positive_finite(function_name, "Boundary separation", - value_of(a_ref)); + check_positive_finite(function_name, "Boundary separation", value_of(a_ref)); check_finite(function_name, "Drift rate", value_of(v_ref)); check_less(function_name, "A-priori bias", value_of(w_ref), 1); check_greater(function_name, "A-priori bias", value_of(w_ref), 0); @@ -494,8 +493,7 @@ inline return_type_t wiener7_lpdf( for (size_t i = 0; i < N_beta_sw; ++i) { if (w_vec[i] - .5 * sw_vec[i] <= 0) { std::stringstream msg; - msg << ", but must be smaller than 2*(A-priori bias) = " - << 2 * w_vec[i]; + msg << ", but must be smaller than 2*(A-priori bias) = " << 2 * w_vec[i]; std::string msg_str(msg.str()); throw_domain_error(function_name, "Inter-trial variability in A-priori bias", sw_vec[i], @@ -531,8 +529,7 @@ inline return_type_t wiener7_lpdf( double ld = 0.0; operands_and_partials - ops_partials(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref, - sw_ref, st0_ref); + ops_partials(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref, sw_ref, st0_ref); static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; static constexpr double LOG_POINT1 = -1; @@ -546,10 +543,9 @@ inline return_type_t wiener7_lpdf( const double sv_val = sv_vec.val(i); const double sw_val = sw_vec.val(i); const double st0_val = st0_vec.val(i); - internal::my_params params - = {y_val, a_val, v_val, - w_val, t0_val, sv_val, - sw_val, st0_val, labstol_wiener5 - LOG_TWO}; + internal::my_params params = {y_val, a_val, v_val, + w_val, t0_val, sv_val, + sw_val, st0_val, labstol_wiener5 - LOG_TWO}; int dim = (sw_val != 0) + (st0_val != 0); check_positive(function_name, "(Inter-trial variability in A-priori bias) + " @@ -569,8 +565,8 @@ inline return_type_t wiener7_lpdf( double new_error = LOG_POINT1 + lerror_bound_dens - LOG_TWO + log(fabs(dens)); internal::my_params params_new_error - = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; + = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; dens = hcubature(internal::int_ddiff, void*>, ¶ms_new_error, dim, xmin, xmax, Meval, abstol, reltol); @@ -589,8 +585,8 @@ inline return_type_t wiener7_lpdf( double new_error = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv_t_7)); internal::my_params params_new_error - = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; + = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; deriv_t_7 = 1 / dens * hcubature(internal::int_dtddiff, void*>, ¶ms_new_error, dim, xmin, xmax, Meval, abstol, @@ -611,8 +607,8 @@ inline return_type_t wiener7_lpdf( double new_error = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv)); internal::my_params params_new_error - = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; + = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; deriv = 1 / dens * hcubature(internal::int_daddiff, void*>, ¶ms_new_error, dim, xmin, xmax, Meval, abstol, @@ -632,8 +628,8 @@ inline return_type_t wiener7_lpdf( double new_error = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv)); internal::my_params params_new_error - = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; + = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; deriv = 1 / dens * hcubature(internal::int_dwddiff, void*>, ¶ms_new_error, dim, xmin, xmax, Meval, abstol, @@ -650,8 +646,8 @@ inline return_type_t wiener7_lpdf( double new_error = LOG_POINT1 + lerror_bound - LOG_TWO + log(fabs(deriv)); internal::my_params params_new_error - = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; + = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; deriv = 1 / dens * hcubature(internal::int_dvddiff, void*>, ¶ms_new_error, dim, xmin, xmax, Meval, abstol, @@ -668,8 +664,8 @@ inline return_type_t wiener7_lpdf( double new_error = LOG_POINT1 + lerror_bound - LOG_TWO + log(fabs(deriv)); internal::my_params params_new_error - = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; + = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; deriv = 1 / dens * hcubature(internal::int_dsvddiff, void*>, ¶ms_new_error, dim, xmin, xmax, Meval, abstol, @@ -690,27 +686,27 @@ inline return_type_t wiener7_lpdf( int dim_ = (st0_val != 0); if (dim_ == 0) { - fl = exp(internal::dwiener5(y_val - t0_val, a_val, v_val, - lower, sv_val, labstol_wiener5)); - fu = exp(internal::dwiener5(y_val - t0_val, a_val, v_val, - upper, sv_val, labstol_wiener5)); + fl = exp(internal::dwiener5(y_val - t0_val, a_val, v_val, lower, + sv_val, labstol_wiener5)); + fu = exp(internal::dwiener5(y_val - t0_val, a_val, v_val, upper, + sv_val, labstol_wiener5)); if (labstol_wiener5 > log(fabs(fl + fu) + log(sw_val) - LOG_TWO + lerror_bound - LOG_TWO)) { - fl = exp(internal::dwiener5(y_val - t0_val, a_val, v_val, - lower, sv_val, + fl = exp(internal::dwiener5(y_val - t0_val, a_val, v_val, lower, + sv_val, lerror_bound - LOG_TWO + log(sw_val) - LOG_TWO + log(fabs(fl + fu)))); - fu = exp(internal::dwiener5(y_val - t0_val, a_val, v_val, - upper, sv_val, + fu = exp(internal::dwiener5(y_val - t0_val, a_val, v_val, upper, + sv_val, lerror_bound - LOG_TWO + log(sw_val) - LOG_TWO + log(fabs(fl + fu)))); } deriv = 1 / width * 0.5 * (fl + fu); } else { internal::my_params2 params_sw - = {y_val, a_val, v_val, w_val, - lower, upper, t0_val, sv_val, - 0, sw_val, st0_val, labstol_wiener5 - LOG_TWO}; + = {y_val, a_val, v_val, w_val, + lower, upper, t0_val, sv_val, + 0, sw_val, st0_val, labstol_wiener5 - LOG_TWO}; deriv = hcubature(internal::int_dswddiff, void*>, ¶ms_sw, dim_, xmin, xmax, Meval, abstol, reltol / 2); @@ -719,8 +715,8 @@ inline return_type_t wiener7_lpdf( double new_error = log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO; internal::my_params2 params_new_error_sw - = {y_val, a_val, v_val, w_val, lower, upper, - t0_val, sv_val, 0, sw_val, st0_val, new_error}; + = {y_val, a_val, v_val, w_val, lower, upper, + t0_val, sv_val, 0, sw_val, st0_val, new_error}; deriv = hcubature(internal::int_dswddiff, void*>, ¶ms_new_error_sw, dim_, xmin, xmax, Meval, @@ -739,13 +735,12 @@ inline return_type_t wiener7_lpdf( } else { int dim_ = (sw_val != 0); if (dim_ == 0) { - f = exp(internal::dwiener5(y_val - (t0_val + st0_val), a_val, - v_val, w_val, sv_val, - labstol_wiener5)); + f = exp(internal::dwiener5(y_val - (t0_val + st0_val), a_val, v_val, + w_val, sv_val, labstol_wiener5)); if (labstol_wiener5 > log(fabs(f) + log(st0_val) - LOG_TWO + lerror_bound - LOG_TWO)) { - f = exp(internal::dwiener5(y_val - (t0_val + st0_val), a_val, - v_val, w_val, sv_val, + f = exp(internal::dwiener5(y_val - (t0_val + st0_val), a_val, v_val, + w_val, sv_val, lerror_bound - LOG_TWO + log(st0_val) - LOG_TWO + log(fabs(f)))); } @@ -753,10 +748,8 @@ inline return_type_t wiener7_lpdf( } else { double new_error = labstol_wiener5 - LOG_TWO; internal::my_params3 params_st - = {y_val, a_val, v_val, - w_val, t0_val, t0_val + st0_val, - sv_val, sw_val, st0_val, - 0, new_error}; + = {y_val, a_val, v_val, w_val, t0_val, t0_val + st0_val, + sv_val, sw_val, st0_val, 0, new_error}; deriv = hcubature(internal::int_dst0ddiff, void*>, ¶ms_st, dim_, xmin, xmax, Meval, abstol, reltol / 2); @@ -765,10 +758,8 @@ inline return_type_t wiener7_lpdf( double new_error = log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO; internal::my_params3 params_new_error_st - = {y_val, a_val, v_val, - w_val, t0_val, t0_val + st0_val, - sv_val, sw_val, st0_val, - 0, new_error}; + = {y_val, a_val, v_val, w_val, t0_val, t0_val + st0_val, + sv_val, sw_val, st0_val, 0, new_error}; deriv = hcubature(internal::int_dst0ddiff, void*>, ¶ms_new_error_st, dim_, xmin, xmax, Meval, diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 024389645ff..f2e17809b5e 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -55,7 +55,8 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, * The log of the first passage time density function for a (Wiener) * drift diffusion model with up to 7 parameters, where * \f$y\in \mathbb{R}_{+}\f$ is the reacion time, \f$a \in \mathbb{R}_{+}\f$ - * the boundary separation, \f$t_0 \in \mathbb{R}_{\geq 0}\f$ the non-decision time, + * the boundary separation, \f$t_0 \in \mathbb{R}_{\geq 0}\f$ the non-decision + time, * \f$w \in (0, 1)\f$ the relative starting point (aka a-priori bias), * \f$v \in \mathbb{R}\f$ the drifte rate, \f$s_v \in * \mathbb{R}_{\geq 0}\f$ the inter-trial variability of the drift rate, @@ -250,4 +251,3 @@ wiener_full_prec_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, } // namespace math } // namespace stan #endif - diff --git a/test/unit/math/prim/prob/wiener_full_prec_test.cpp b/test/unit/math/prim/prob/wiener_full_prec_test.cpp index 76599089b9a..8c8dca9281f 100644 --- a/test/unit/math/prim/prob/wiener_full_prec_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_prec_test.cpp @@ -234,7 +234,7 @@ TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { check_scalar_types_2(f_a, a[i], result[i], da[i]); // v auto f_v = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i],value, sv[i], + return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types_2(f_v, v[i], result[i], dv[i]); From a44b3ef883d62a36cc40cf79e83c89386639853d Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 28 Mar 2023 10:11:25 +0200 Subject: [PATCH 016/179] headers, fun->prob --- stan/math/prim/fun.hpp | 2 - stan/math/prim/prob.hpp | 2 + stan/math/prim/{fun => prob}/wiener5_lpdf.hpp | 7 +- stan/math/prim/{fun => prob}/wiener7_lpdf.hpp | 71 +++++++++++++------ stan/math/prim/prob/wiener_full_lpdf.hpp | 2 + 5 files changed, 55 insertions(+), 29 deletions(-) rename stan/math/prim/{fun => prob}/wiener5_lpdf.hpp (98%) rename stan/math/prim/{fun => prob}/wiener7_lpdf.hpp (95%) diff --git a/stan/math/prim/fun.hpp b/stan/math/prim/fun.hpp index b5816f7141a..00cb17a13a6 100644 --- a/stan/math/prim/fun.hpp +++ b/stan/math/prim/fun.hpp @@ -368,8 +368,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/stan/math/prim/prob.hpp b/stan/math/prim/prob.hpp index 9d5446eab4f..2c6f75cfd0e 100644 --- a/stan/math/prim/prob.hpp +++ b/stan/math/prim/prob.hpp @@ -366,6 +366,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/stan/math/prim/fun/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp similarity index 98% rename from stan/math/prim/fun/wiener5_lpdf.hpp rename to stan/math/prim/prob/wiener5_lpdf.hpp index 0e0f709f1d6..03a68419ffa 100644 --- a/stan/math/prim/fun/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -1,12 +1,7 @@ #ifndef STAN_MATH_PRIM_FUN_WIENER5_LPDF_HPP #define STAN_MATH_PRIM_FUN_WIENER5_LPDF_HPP -#include -#include -#include -#include -#include -#include +#include namespace stan { namespace math { diff --git a/stan/math/prim/fun/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp similarity index 95% rename from stan/math/prim/fun/wiener7_lpdf.hpp rename to stan/math/prim/prob/wiener7_lpdf.hpp index 50531d37647..25446c2f36a 100644 --- a/stan/math/prim/fun/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -1,30 +1,26 @@ #ifndef STAN_MATH_PRIM_FUN_WIENER7_LPDF_HPP #define STAN_MATH_PRIM_FUN_WIENER7_LPDF_HPP -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include namespace stan { namespace math { namespace internal { // tools -struct my_params { +/*struct my_params { double y, a, v, w, t0, sv, sw, st0, lerr; }; -struct my_params2 { +/*struct my_params2 { double y, a, v, w, w_lower, w_upper, t0, sv, sw, sw_mean, st0, lerr; }; struct my_params3 { double y, a, v, w, t0, t0_mean, sv, sw, st0, st0_mean, lerr; -}; +};*/ // calculate derivative of density of wiener5 with respect to y (version for // wiener7) @@ -135,6 +131,9 @@ double dtdwiener5_for_7(const double& y, const double& a, const double& v, // integrand density (on normal scale) template return_type_t int_ddiff(const T_x& x, const T_p& p) { + struct my_params { + double y, a, v, w, t0, sv, sw, st0, lerr; +}; my_params* params = static_cast(p); double y = (params->y); double a = (params->a); @@ -166,6 +165,9 @@ return_type_t int_ddiff(const T_x& x, const T_p& p) { // integrand d/dt (on normal scale) template return_type_t int_dtddiff(const T_x& x, const T_p& p) { + struct my_params { + double y, a, v, w, t0, sv, sw, st0, lerr; +}; my_params* params = static_cast(p); double y = (params->y); double a = (params->a); @@ -197,6 +199,9 @@ return_type_t int_dtddiff(const T_x& x, const T_p& p) { // integrand d/da (on normal scale) template return_type_t int_daddiff(const T_x& x, const T_p& p) { + struct my_params { + double y, a, v, w, t0, sv, sw, st0, lerr; +}; my_params* params = static_cast(p); double y = (params->y); double a = (params->a); @@ -237,6 +242,9 @@ return_type_t int_daddiff(const T_x& x, const T_p& p) { // integrand d/dv (on normal scale) template return_type_t int_dvddiff(const T_x& x, const T_p& p) { + struct my_params { + double y, a, v, w, t0, sv, sw, st0, lerr; +}; my_params* params = static_cast(p); double y = (params->y); double a = (params->a); @@ -269,6 +277,9 @@ return_type_t int_dvddiff(const T_x& x, const T_p& p) { // integrand d/dw (on normal scale) template return_type_t int_dwddiff(const T_x& x, const T_p& p) { + struct my_params { + double y, a, v, w, t0, sv, sw, st0, lerr; +}; my_params* params = static_cast(p); double y = (params->y); double a = (params->a); @@ -305,6 +316,9 @@ return_type_t int_dwddiff(const T_x& x, const T_p& p) { // integrand d/dsv (on normal scale) template return_type_t int_dsvddiff(const T_x& x, const T_p& p) { + struct my_params { + double y, a, v, w, t0, sv, sw, st0, lerr; +}; my_params* params = static_cast(p); double y = (params->y); double a = (params->a); @@ -337,6 +351,9 @@ return_type_t int_dsvddiff(const T_x& x, const T_p& p) { // integrand d/dsw (on normal scale) template return_type_t int_dswddiff(const T_x& x, const T_p& p) { +struct my_params2 { + double y, a, v, w, w_lower, w_upper, t0, sv, sw, sw_mean, st0, lerr; +}; my_params2* params = static_cast(p); double y = (params->y); double a = (params->a); @@ -370,6 +387,9 @@ return_type_t int_dswddiff(const T_x& x, const T_p& p) { // integrand d/dst0 (on normal scale) template return_type_t int_dst0ddiff(const T_x& x, const T_p& p) { + struct my_params3 { + double y, a, v, w, t0, t0_mean, sv, sw, st0, st0_mean, lerr; +}; my_params3* params = static_cast(p); double y = (params->y); double a = (params->a); @@ -532,6 +552,15 @@ inline return_type_t wiener7_lpdf( ops_partials(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref, sw_ref, st0_ref); static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; static constexpr double LOG_POINT1 = -1; + struct my_params { + double y, a, v, w, t0, sv, sw, st0, lerr; +}; + struct my_params2 { + double y, a, v, w, w_lower, w_upper, t0, sv, sw, sw_mean, st0, lerr; +}; + struct my_params3 { + double y, a, v, w, t0, t0_mean, sv, sw, st0, st0_mean, lerr; +}; // calculate density and partials for (size_t i = 0; i < N; i++) { @@ -543,7 +572,7 @@ inline return_type_t wiener7_lpdf( const double sv_val = sv_vec.val(i); const double sw_val = sw_vec.val(i); const double st0_val = st0_vec.val(i); - internal::my_params params = {y_val, a_val, v_val, + my_params params = {y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, st0_val, labstol_wiener5 - LOG_TWO}; int dim = (sw_val != 0) + (st0_val != 0); @@ -564,7 +593,7 @@ inline return_type_t wiener7_lpdf( > fabs(log(dens)) + LOG_POINT1 + lerror_bound_dens - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound_dens - LOG_TWO + log(fabs(dens)); - internal::my_params params_new_error + my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, st0_val, new_error}; dens = hcubature(internal::int_ddiff, void*>, @@ -584,7 +613,7 @@ inline return_type_t wiener7_lpdf( > log(fabs(deriv_t_7)) + LOG_POINT1 + lerror_bound - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv_t_7)); - internal::my_params params_new_error + my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, st0_val, new_error}; deriv_t_7 = 1 / dens @@ -606,7 +635,7 @@ inline return_type_t wiener7_lpdf( > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv)); - internal::my_params params_new_error + my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, st0_val, new_error}; deriv = 1 / dens @@ -627,7 +656,7 @@ inline return_type_t wiener7_lpdf( > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv)); - internal::my_params params_new_error + my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, st0_val, new_error}; deriv = 1 / dens @@ -645,7 +674,7 @@ inline return_type_t wiener7_lpdf( > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound - LOG_TWO + log(fabs(deriv)); - internal::my_params params_new_error + my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, st0_val, new_error}; deriv = 1 / dens @@ -663,7 +692,7 @@ inline return_type_t wiener7_lpdf( > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound - LOG_TWO + log(fabs(deriv)); - internal::my_params params_new_error + my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, st0_val, new_error}; deriv = 1 / dens @@ -703,7 +732,7 @@ inline return_type_t wiener7_lpdf( } deriv = 1 / width * 0.5 * (fl + fu); } else { - internal::my_params2 params_sw + my_params2 params_sw = {y_val, a_val, v_val, w_val, lower, upper, t0_val, sv_val, 0, sw_val, st0_val, labstol_wiener5 - LOG_TWO}; @@ -714,7 +743,7 @@ inline return_type_t wiener7_lpdf( > log(fabs(deriv) + LOG_POINT1 + lerror_bound - LOG_TWO)) { double new_error = log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO; - internal::my_params2 params_new_error_sw + my_params2 params_new_error_sw = {y_val, a_val, v_val, w_val, lower, upper, t0_val, sv_val, 0, sw_val, st0_val, new_error}; deriv @@ -747,7 +776,7 @@ inline return_type_t wiener7_lpdf( deriv = 1 / st0_val * f; } else { double new_error = labstol_wiener5 - LOG_TWO; - internal::my_params3 params_st + my_params3 params_st = {y_val, a_val, v_val, w_val, t0_val, t0_val + st0_val, sv_val, sw_val, st0_val, 0, new_error}; deriv = hcubature(internal::int_dst0ddiff, void*>, @@ -757,7 +786,7 @@ inline return_type_t wiener7_lpdf( > log(fabs(deriv) + LOG_POINT1 + lerror_bound - LOG_TWO)) { double new_error = log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO; - internal::my_params3 params_new_error_st + my_params3 params_new_error_st = {y_val, a_val, v_val, w_val, t0_val, t0_val + st0_val, sv_val, sw_val, st0_val, 0, new_error}; deriv diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index f2e17809b5e..feb8d65f266 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -2,6 +2,8 @@ #define STAN_MATH_PRIM_PROB_WIENER_FULL_LPDF_HPP #include +#include +#include namespace stan { namespace math { From 8d346fb1539ac0ddc1ac058b911e3a446141ac9f Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 28 Mar 2023 04:17:23 -0400 Subject: [PATCH 017/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener7_lpdf.hpp | 92 +++++++++++++--------------- 1 file changed, 43 insertions(+), 49 deletions(-) diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index 25446c2f36a..f819ee56c52 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -131,9 +131,9 @@ double dtdwiener5_for_7(const double& y, const double& a, const double& v, // integrand density (on normal scale) template return_type_t int_ddiff(const T_x& x, const T_p& p) { - struct my_params { - double y, a, v, w, t0, sv, sw, st0, lerr; -}; + struct my_params { + double y, a, v, w, t0, sv, sw, st0, lerr; + }; my_params* params = static_cast(p); double y = (params->y); double a = (params->a); @@ -165,9 +165,9 @@ return_type_t int_ddiff(const T_x& x, const T_p& p) { // integrand d/dt (on normal scale) template return_type_t int_dtddiff(const T_x& x, const T_p& p) { - struct my_params { - double y, a, v, w, t0, sv, sw, st0, lerr; -}; + struct my_params { + double y, a, v, w, t0, sv, sw, st0, lerr; + }; my_params* params = static_cast(p); double y = (params->y); double a = (params->a); @@ -199,9 +199,9 @@ return_type_t int_dtddiff(const T_x& x, const T_p& p) { // integrand d/da (on normal scale) template return_type_t int_daddiff(const T_x& x, const T_p& p) { - struct my_params { - double y, a, v, w, t0, sv, sw, st0, lerr; -}; + struct my_params { + double y, a, v, w, t0, sv, sw, st0, lerr; + }; my_params* params = static_cast(p); double y = (params->y); double a = (params->a); @@ -242,9 +242,9 @@ return_type_t int_daddiff(const T_x& x, const T_p& p) { // integrand d/dv (on normal scale) template return_type_t int_dvddiff(const T_x& x, const T_p& p) { - struct my_params { - double y, a, v, w, t0, sv, sw, st0, lerr; -}; + struct my_params { + double y, a, v, w, t0, sv, sw, st0, lerr; + }; my_params* params = static_cast(p); double y = (params->y); double a = (params->a); @@ -277,9 +277,9 @@ return_type_t int_dvddiff(const T_x& x, const T_p& p) { // integrand d/dw (on normal scale) template return_type_t int_dwddiff(const T_x& x, const T_p& p) { - struct my_params { - double y, a, v, w, t0, sv, sw, st0, lerr; -}; + struct my_params { + double y, a, v, w, t0, sv, sw, st0, lerr; + }; my_params* params = static_cast(p); double y = (params->y); double a = (params->a); @@ -316,9 +316,9 @@ return_type_t int_dwddiff(const T_x& x, const T_p& p) { // integrand d/dsv (on normal scale) template return_type_t int_dsvddiff(const T_x& x, const T_p& p) { - struct my_params { - double y, a, v, w, t0, sv, sw, st0, lerr; -}; + struct my_params { + double y, a, v, w, t0, sv, sw, st0, lerr; + }; my_params* params = static_cast(p); double y = (params->y); double a = (params->a); @@ -351,9 +351,9 @@ return_type_t int_dsvddiff(const T_x& x, const T_p& p) { // integrand d/dsw (on normal scale) template return_type_t int_dswddiff(const T_x& x, const T_p& p) { -struct my_params2 { - double y, a, v, w, w_lower, w_upper, t0, sv, sw, sw_mean, st0, lerr; -}; + struct my_params2 { + double y, a, v, w, w_lower, w_upper, t0, sv, sw, sw_mean, st0, lerr; + }; my_params2* params = static_cast(p); double y = (params->y); double a = (params->a); @@ -388,8 +388,8 @@ struct my_params2 { template return_type_t int_dst0ddiff(const T_x& x, const T_p& p) { struct my_params3 { - double y, a, v, w, t0, t0_mean, sv, sw, st0, st0_mean, lerr; -}; + double y, a, v, w, t0, t0_mean, sv, sw, st0, st0_mean, lerr; + }; my_params3* params = static_cast(p); double y = (params->y); double a = (params->a); @@ -553,14 +553,14 @@ inline return_type_t wiener7_lpdf( static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; static constexpr double LOG_POINT1 = -1; struct my_params { - double y, a, v, w, t0, sv, sw, st0, lerr; -}; + double y, a, v, w, t0, sv, sw, st0, lerr; + }; struct my_params2 { - double y, a, v, w, w_lower, w_upper, t0, sv, sw, sw_mean, st0, lerr; -}; + double y, a, v, w, w_lower, w_upper, t0, sv, sw, sw_mean, st0, lerr; + }; struct my_params3 { - double y, a, v, w, t0, t0_mean, sv, sw, st0, st0_mean, lerr; -}; + double y, a, v, w, t0, t0_mean, sv, sw, st0, st0_mean, lerr; + }; // calculate density and partials for (size_t i = 0; i < N; i++) { @@ -573,8 +573,8 @@ inline return_type_t wiener7_lpdf( const double sw_val = sw_vec.val(i); const double st0_val = st0_vec.val(i); my_params params = {y_val, a_val, v_val, - w_val, t0_val, sv_val, - sw_val, st0_val, labstol_wiener5 - LOG_TWO}; + w_val, t0_val, sv_val, + sw_val, st0_val, labstol_wiener5 - LOG_TWO}; int dim = (sw_val != 0) + (st0_val != 0); check_positive(function_name, "(Inter-trial variability in A-priori bias) + " @@ -593,9 +593,8 @@ inline return_type_t wiener7_lpdf( > fabs(log(dens)) + LOG_POINT1 + lerror_bound_dens - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound_dens - LOG_TWO + log(fabs(dens)); - my_params params_new_error - = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; + my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; dens = hcubature(internal::int_ddiff, void*>, ¶ms_new_error, dim, xmin, xmax, Meval, abstol, reltol); @@ -613,9 +612,8 @@ inline return_type_t wiener7_lpdf( > log(fabs(deriv_t_7)) + LOG_POINT1 + lerror_bound - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv_t_7)); - my_params params_new_error - = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; + my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; deriv_t_7 = 1 / dens * hcubature(internal::int_dtddiff, void*>, ¶ms_new_error, dim, xmin, xmax, Meval, abstol, @@ -635,9 +633,8 @@ inline return_type_t wiener7_lpdf( > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv)); - my_params params_new_error - = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; + my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; deriv = 1 / dens * hcubature(internal::int_daddiff, void*>, ¶ms_new_error, dim, xmin, xmax, Meval, abstol, @@ -656,9 +653,8 @@ inline return_type_t wiener7_lpdf( > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv)); - my_params params_new_error - = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; + my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; deriv = 1 / dens * hcubature(internal::int_dwddiff, void*>, ¶ms_new_error, dim, xmin, xmax, Meval, abstol, @@ -674,9 +670,8 @@ inline return_type_t wiener7_lpdf( > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound - LOG_TWO + log(fabs(deriv)); - my_params params_new_error - = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; + my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; deriv = 1 / dens * hcubature(internal::int_dvddiff, void*>, ¶ms_new_error, dim, xmin, xmax, Meval, abstol, @@ -692,9 +687,8 @@ inline return_type_t wiener7_lpdf( > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound - LOG_TWO + log(fabs(deriv)); - my_params params_new_error - = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; + my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, + sv_val, sw_val, st0_val, new_error}; deriv = 1 / dens * hcubature(internal::int_dsvddiff, void*>, ¶ms_new_error, dim, xmin, xmax, Meval, abstol, From c4787c1f0d08ba27501760ea4a7e5560d6789499 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 28 Mar 2023 10:27:55 +0200 Subject: [PATCH 018/179] delete obsolete comments --- stan/math/prim/prob/wiener7_lpdf.hpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index f819ee56c52..37c0fa787f6 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -9,19 +9,6 @@ namespace stan { namespace math { namespace internal { -// tools -/*struct my_params { - double y, a, v, w, t0, sv, sw, st0, lerr; -}; - -/*struct my_params2 { - double y, a, v, w, w_lower, w_upper, t0, sv, sw, sw_mean, st0, lerr; -}; - -struct my_params3 { - double y, a, v, w, t0, t0_mean, sv, sw, st0, st0_mean, lerr; -};*/ - // calculate derivative of density of wiener5 with respect to y (version for // wiener7) double dtdwiener5_for_7(const double& y, const double& a, const double& v, From 7415ba1f92c362261628f87b2d9f654d8eccd973 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 4 Apr 2023 11:20:00 +0200 Subject: [PATCH 019/179] insert inline --- stan/math/prim/prob/wiener5_lpdf.hpp | 16 ++++++++-------- stan/math/prim/prob/wiener7_lpdf.hpp | 22 +++++++++++----------- stan/math/prim/prob/wiener_full_lpdf.hpp | 2 ++ 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 03a68419ffa..83fe7a84a4c 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -1,5 +1,5 @@ -#ifndef STAN_MATH_PRIM_FUN_WIENER5_LPDF_HPP -#define STAN_MATH_PRIM_FUN_WIENER5_LPDF_HPP +#ifndef STAN_MATH_PRIM_PROB_WIENER5_LPDF_HPP +#define STAN_MATH_PRIM_PROB_WIENER5_LPDF_HPP #include @@ -8,7 +8,7 @@ namespace math { namespace internal { // calculate density in log -double dwiener5(const double& y, const double& a, const double& vn, +inline double dwiener5(const double& y, const double& a, const double& vn, const double& wn, const double& sv, const double& err) { double kll, kss, ans, v, w; w = 1.0 - wn; @@ -92,7 +92,7 @@ double dwiener5(const double& y, const double& a, const double& vn, // d/dt DENSITY // calculate derivative of density with respect to t (in log, ans = // d/dt(log(f))=d/dt f'/f; ans*exp(ld)=f' on normal scale) -double dtdwiener5(const double& y, const double& a, const double& vn, +inline double dtdwiener5(const double& y, const double& a, const double& vn, const double& wn, const double& sv, const double& err) { double kll, kss, ans, v, w; w = 1.0 - wn; @@ -201,7 +201,7 @@ double dtdwiener5(const double& y, const double& a, const double& vn, // d/da DENSITY // calculate derivative of density with respect to a (in log, ans = // d/da(log(f))=d/da f'/f; ans*exp(ld)=f' on normal scale) -double dadwiener5(const double& y, const double& a, const double& vn, +inline double dadwiener5(const double& y, const double& a, const double& vn, const double& wn, const double& sv, const double& err, const int& normal_or_log) { double kll, kss, ans, v, w; @@ -317,7 +317,7 @@ double dadwiener5(const double& y, const double& a, const double& vn, // d/dv DENSITY // calculate derivative of density with respect to v (in log, ans = // d/dv(log(f))=d/dv f'/f; ans*exp(ld)=f' on normal scale) -double dvdwiener5(const double& y, const double& a, const double& vn, +inline double dvdwiener5(const double& y, const double& a, const double& vn, const double& wn, const double& sv) { double ans; if (sv != 0) { @@ -333,7 +333,7 @@ double dvdwiener5(const double& y, const double& a, const double& vn, // d/dw DENSITY // calculate derivative of density with respect to w (in log, ans = // d/dw(log(f))=d/dw f'/f; ans*exp(ld)=f' on normal scale) -double dwdwiener5(const double& y, const double& a, const double& vn, +inline double dwdwiener5(const double& y, const double& a, const double& vn, const double& wn, const double& sv, const double& err, const int& normal_or_log) { double kll, kss, ans, v, w; @@ -454,7 +454,7 @@ double dwdwiener5(const double& y, const double& a, const double& vn, // d/dsv DENSITY // calculate derivative of density with respect to sv (in log, ans = // d/dsv(log(f))=d/dsv f'/f; ans*exp(ld)=f' on normal scale) -double dsvdwiener5(const double& y, const double& a, const double& vn, +inline double dsvdwiener5(const double& y, const double& a, const double& vn, const double& wn, const double& sv) { double v, w; v = -vn; diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index 37c0fa787f6..d8761e1b9d5 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -1,5 +1,5 @@ -#ifndef STAN_MATH_PRIM_FUN_WIENER7_LPDF_HPP -#define STAN_MATH_PRIM_FUN_WIENER7_LPDF_HPP +#ifndef STAN_MATH_PRIM_PROB_WIENER7_LPDF_HPP +#define STAN_MATH_PRIM_PROB_WIENER7_LPDF_HPP #include #include @@ -11,7 +11,7 @@ namespace internal { // calculate derivative of density of wiener5 with respect to y (version for // wiener7) -double dtdwiener5_for_7(const double& y, const double& a, const double& v, +inline double dtdwiener5_for_7(const double& y, const double& a, const double& v, const double& w, const double& sv, const double& err) { double kll, kss, ans; @@ -117,7 +117,7 @@ double dtdwiener5_for_7(const double& y, const double& a, const double& v, // integrand density (on normal scale) template -return_type_t int_ddiff(const T_x& x, const T_p& p) { +inline return_type_t int_ddiff(const T_x& x, const T_p& p) { struct my_params { double y, a, v, w, t0, sv, sw, st0, lerr; }; @@ -151,7 +151,7 @@ return_type_t int_ddiff(const T_x& x, const T_p& p) { // integrand d/dt (on normal scale) template -return_type_t int_dtddiff(const T_x& x, const T_p& p) { +inline return_type_t int_dtddiff(const T_x& x, const T_p& p) { struct my_params { double y, a, v, w, t0, sv, sw, st0, lerr; }; @@ -185,7 +185,7 @@ return_type_t int_dtddiff(const T_x& x, const T_p& p) { // integrand d/da (on normal scale) template -return_type_t int_daddiff(const T_x& x, const T_p& p) { +inline return_type_t int_daddiff(const T_x& x, const T_p& p) { struct my_params { double y, a, v, w, t0, sv, sw, st0, lerr; }; @@ -228,7 +228,7 @@ return_type_t int_daddiff(const T_x& x, const T_p& p) { // integrand d/dv (on normal scale) template -return_type_t int_dvddiff(const T_x& x, const T_p& p) { +inline return_type_t int_dvddiff(const T_x& x, const T_p& p) { struct my_params { double y, a, v, w, t0, sv, sw, st0, lerr; }; @@ -263,7 +263,7 @@ return_type_t int_dvddiff(const T_x& x, const T_p& p) { // integrand d/dw (on normal scale) template -return_type_t int_dwddiff(const T_x& x, const T_p& p) { +inline return_type_t int_dwddiff(const T_x& x, const T_p& p) { struct my_params { double y, a, v, w, t0, sv, sw, st0, lerr; }; @@ -302,7 +302,7 @@ return_type_t int_dwddiff(const T_x& x, const T_p& p) { // integrand d/dsv (on normal scale) template -return_type_t int_dsvddiff(const T_x& x, const T_p& p) { +inline return_type_t int_dsvddiff(const T_x& x, const T_p& p) { struct my_params { double y, a, v, w, t0, sv, sw, st0, lerr; }; @@ -337,7 +337,7 @@ return_type_t int_dsvddiff(const T_x& x, const T_p& p) { // integrand d/dsw (on normal scale) template -return_type_t int_dswddiff(const T_x& x, const T_p& p) { +inline return_type_t int_dswddiff(const T_x& x, const T_p& p) { struct my_params2 { double y, a, v, w, w_lower, w_upper, t0, sv, sw, sw_mean, st0, lerr; }; @@ -373,7 +373,7 @@ return_type_t int_dswddiff(const T_x& x, const T_p& p) { // integrand d/dst0 (on normal scale) template -return_type_t int_dst0ddiff(const T_x& x, const T_p& p) { +inline return_type_t int_dst0ddiff(const T_x& x, const T_p& p) { struct my_params3 { double y, a, v, w, t0, t0_mean, sv, sw, st0, st0_mean, lerr; }; diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index feb8d65f266..cf1c339da2a 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -5,6 +5,8 @@ #include #include + + namespace stan { namespace math { namespace internal { From 4780078fa8c56a9e915b1a3d5582243c671a8d8f Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 4 Apr 2023 05:21:24 -0400 Subject: [PATCH 020/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 17 +++++++++-------- stan/math/prim/prob/wiener7_lpdf.hpp | 5 +++-- stan/math/prim/prob/wiener_full_lpdf.hpp | 2 -- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 83fe7a84a4c..132b713765d 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -9,7 +9,7 @@ namespace internal { // calculate density in log inline double dwiener5(const double& y, const double& a, const double& vn, - const double& wn, const double& sv, const double& err) { + const double& wn, const double& sv, const double& err) { double kll, kss, ans, v, w; w = 1.0 - wn; v = -vn; @@ -93,7 +93,8 @@ inline double dwiener5(const double& y, const double& a, const double& vn, // calculate derivative of density with respect to t (in log, ans = // d/dt(log(f))=d/dt f'/f; ans*exp(ld)=f' on normal scale) inline double dtdwiener5(const double& y, const double& a, const double& vn, - const double& wn, const double& sv, const double& err) { + const double& wn, const double& sv, + const double& err) { double kll, kss, ans, v, w; w = 1.0 - wn; v = -vn; @@ -202,8 +203,8 @@ inline double dtdwiener5(const double& y, const double& a, const double& vn, // calculate derivative of density with respect to a (in log, ans = // d/da(log(f))=d/da f'/f; ans*exp(ld)=f' on normal scale) inline double dadwiener5(const double& y, const double& a, const double& vn, - const double& wn, const double& sv, const double& err, - const int& normal_or_log) { + const double& wn, const double& sv, const double& err, + const int& normal_or_log) { double kll, kss, ans, v, w; double la = log(a); @@ -318,7 +319,7 @@ inline double dadwiener5(const double& y, const double& a, const double& vn, // calculate derivative of density with respect to v (in log, ans = // d/dv(log(f))=d/dv f'/f; ans*exp(ld)=f' on normal scale) inline double dvdwiener5(const double& y, const double& a, const double& vn, - const double& wn, const double& sv) { + const double& wn, const double& sv) { double ans; if (sv != 0) { ans = 1 + square(sv) * y; @@ -334,8 +335,8 @@ inline double dvdwiener5(const double& y, const double& a, const double& vn, // calculate derivative of density with respect to w (in log, ans = // d/dw(log(f))=d/dw f'/f; ans*exp(ld)=f' on normal scale) inline double dwdwiener5(const double& y, const double& a, const double& vn, - const double& wn, const double& sv, const double& err, - const int& normal_or_log) { + const double& wn, const double& sv, const double& err, + const int& normal_or_log) { double kll, kss, ans, v, w; double sign = -1; w = 1.0 - wn; @@ -455,7 +456,7 @@ inline double dwdwiener5(const double& y, const double& a, const double& vn, // calculate derivative of density with respect to sv (in log, ans = // d/dsv(log(f))=d/dsv f'/f; ans*exp(ld)=f' on normal scale) inline double dsvdwiener5(const double& y, const double& a, const double& vn, - const double& wn, const double& sv) { + const double& wn, const double& sv) { double v, w; v = -vn; w = 1 - wn; diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index d8761e1b9d5..d95193e13ed 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -11,8 +11,9 @@ namespace internal { // calculate derivative of density of wiener5 with respect to y (version for // wiener7) -inline double dtdwiener5_for_7(const double& y, const double& a, const double& v, - const double& w, const double& sv, const double& err) { +inline double dtdwiener5_for_7(const double& y, const double& a, + const double& v, const double& w, + const double& sv, const double& err) { double kll, kss, ans; // prepare some variables diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index cf1c339da2a..feb8d65f266 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -5,8 +5,6 @@ #include #include - - namespace stan { namespace math { namespace internal { From e025a3b4b2b6836f97f29e26f656761f26b950cf Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 4 Apr 2023 12:10:32 +0200 Subject: [PATCH 021/179] restructure tests: var->rev --- .../math/prim/prob/wiener_full_prec_test.cpp | 113 ----------------- test/unit/math/prim/prob/wiener_full_test.cpp | 110 ---------------- .../math/rev/prob/wiener_full_prec_test.cpp | 120 ++++++++++++++++++ test/unit/math/rev/prob/wiener_full_test.cpp | 120 ++++++++++++++++++ 4 files changed, 240 insertions(+), 223 deletions(-) create mode 100644 test/unit/math/rev/prob/wiener_full_prec_test.cpp create mode 100644 test/unit/math/rev/prob/wiener_full_test.cpp diff --git a/test/unit/math/prim/prob/wiener_full_prec_test.cpp b/test/unit/math/prim/prob/wiener_full_prec_test.cpp index 8c8dca9281f..e71d704a373 100644 --- a/test/unit/math/prim/prob/wiener_full_prec_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_prec_test.cpp @@ -157,116 +157,3 @@ TEST(mathPrimScalProbWienerFullPrecScal, invalid_st0) { EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, sw, NAN, 1e-4), std::domain_error); } - -// CHECK THAT ALL VALID SCALAR TYPES ARE ACCEPTED -template -void check_scalar_types_2(F& f, double value, double res, double deriv) { - // - f: Function with a single parameter exposed, all others - // have to be scalars - // - value: value to be used for the parameter - // - res: expected result of calling `f` with `value` - // - deriv: expected result of partial of f with respect to the - // parameter in `value` - using stan::math::var; - double err_tol = 2e-6; - - // type double - EXPECT_NEAR(f(value), res, err_tol); - - // type var with derivative - var value_var = value; - var result_var = f(value_var); - result_var.grad(); - EXPECT_NEAR(value_of(result_var), res, err_tol); - EXPECT_NEAR(value_var.adj(), deriv, err_tol); -} - -TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { - // tests all parameter types individually, with other parameters - // set to double - using stan::math::wiener_full_prec_lpdf; - double err_tol = 2e-6; - - std::vector rt{1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector a{1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector v{1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector w{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; - std::vector t0{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0}; - std::vector sv{0.1, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0}; - std::vector sw{0.1, 0.1, 0, 0.1, 0, 0.1, 0, 0, 0}; - std::vector st0{0.1, 0, 0.1, 0.1, 0, 0, 0.1, 0, 0}; - - std::vector result{-2.426204, -2.710348, -2.422505, - -2.422795, -2.70665, -2.706812, - -2.419095, -2.703112, -3.790072}; - std::vector drt{-5.437337, -5.436798, -5.437332, -5.434799, -5.436791, - -5.434801, -5.434802, -5.434802, -5.434802}; - std::vector da{5.857318, 6.395031, 5.856484, 5.858549, 6.394195, - 6.396512, 5.857722, 6.395684, 8.369604}; - std::vector dv{-0.2428443, -0.2967977, -0.2436664, - -0.2446629, -0.297619, -0.2991696, - -0.2454931, -0.3, -0.5}; - std::vector dw{-0.9891369, -0.9887305, -0.9973428, - -0.9915453, -0.9969335, -0.991674, - -0.9997794, -0.9999097, -0.9999953}; - std::vector dt0{5.437337, 5.436798, 5.437332, 5.434799, 5.436791, - 5.434801, 5.434802, 5.434802, 5.434802}; - std::vector dsv{-0.06793703, -0.07047449, -0.06797882, - 0.0, -0.07050737, 0.0, - 0.0, 0.0, 0.0}; - std::vector dsw{-0.07406705, -0.07407386, 0.0, -0.07410901, 0.0, - -0.07410686, 0.0, 0.0, 0.0}; - std::vector dst0{2.963915, 0.0, 2.963912, 2.962338, 0.0, - 0.0, 2.96234, 0.0, 0.0}; - - for (int i = 0; i < result.size(); i++) { - // rt - auto f_rt = [=](auto value) { - return wiener_full_prec_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], - st0[i], 1e-6); - }; - check_scalar_types_2(f_rt, rt[i], result[i], drt[i]); - // a - auto f_a = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], - sw[i], st0[i], 1e-6); - }; - check_scalar_types_2(f_a, a[i], result[i], da[i]); - // v - auto f_v = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], - sw[i], st0[i], 1e-6); - }; - check_scalar_types_2(f_v, v[i], result[i], dv[i]); - // w - auto f_w = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], - sw[i], st0[i], 1e-6); - }; - check_scalar_types_2(f_w, w[i], result[i], dw[i]); - // t0 - auto f_t0 = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], - st0[i], 1e-6); - }; - check_scalar_types_2(f_t0, t0[i], result[i], dt0[i]); - // sv - auto f_sv = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], - st0[i], 1e-6); - }; - check_scalar_types_2(f_sv, sv[i], result[i], dsv[i]); - // sw - auto f_sw = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, - st0[i], 1e-6); - }; - check_scalar_types_2(f_sw, sw[i], result[i], dsw[i]); - // st0 - auto f_st0 = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], - value, 1e-6); - }; - check_scalar_types_2(f_st0, st0[i], result[i], dst0[i]); - } -} diff --git a/test/unit/math/prim/prob/wiener_full_test.cpp b/test/unit/math/prim/prob/wiener_full_test.cpp index 6a5e1d20dd9..4ade8b16608 100644 --- a/test/unit/math/prim/prob/wiener_full_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_test.cpp @@ -158,114 +158,4 @@ TEST(mathPrimScalProbWienerFullScal, invalid_st0) { std::domain_error); } -// CHECK THAT ALL VALID SCALAR TYPES ARE ACCEPTED -template -void check_scalar_types(F& f, double value, double res, double deriv) { - // - f: Function with a single parameter exposed, all others - // have to be scalars - // - value: value to be used for the parameter - // - res: expected result of calling `f` with `value` - // - deriv: expected result of partial of f with respect to - // the parameter in `value` - using stan::math::var; - double err_tol = 2e-4; - // type double - EXPECT_NEAR(f(value), res, err_tol); - - // type var with derivative - var value_var = value; - var result_var = f(value_var); - result_var.grad(); - EXPECT_NEAR(value_of(result_var), res, err_tol); - EXPECT_NEAR(value_var.adj(), deriv, err_tol); -} - -TEST(ProbWienerFull, wiener_full_all_scalar) { - // tests all parameter types individually, with other - // parameters set to double - using stan::math::wiener_full_lpdf; - - std::vector rt{1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector a{1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector v{1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector w{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; - std::vector t0{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0}; - std::vector sv{0.1, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0}; - std::vector sw{0.1, 0.1, 0, 0.1, 0, 0.1, 0, 0, 0}; - std::vector st0{0.1, 0, 0.1, 0.1, 0, 0, 0.1, 0, 0}; - - std::vector result{-2.426204, -2.710348, -2.422505, - -2.422795, -2.70665, -2.706812, - -2.419095, -2.703112, -3.790072}; - std::vector drt{-5.437337, -5.436798, -5.437332, -5.434799, -5.436791, - -5.434801, -5.434802, -5.434802, -5.434802}; - std::vector da{5.857318, 6.395031, 5.856484, 5.858549, 6.394195, - 6.396512, 5.857722, 6.395684, 8.369604}; - std::vector dv{-0.2428443, -0.2967977, -0.2436664, - -0.2446629, -0.297619, -0.2991696, - -0.2454931, -0.3, -0.5}; - std::vector dw{-0.9891369, -0.9887305, -0.9973428, - -0.9915453, -0.9969335, -0.991674, - -0.9997794, -0.9999097, -0.9999953}; - std::vector dt0{5.437337, 5.436798, 5.437332, 5.434799, 5.436791, - 5.434801, 5.434802, 5.434802, 5.434802}; - std::vector dsv{-0.06793703, -0.07047449, -0.06797882, - 0.0, -0.07050737, 0.0, - 0.0, 0.0, 0.0}; - std::vector dsw{-0.07406705, -0.07407386, 0.0, -0.07410901, 0.0, - -0.07410686, 0.0, 0.0, 0.0}; - std::vector dst0{2.963915, 0.0, 2.963912, 2.962338, 0.0, - 0.0, 2.96234, 0.0, 0.0}; - - for (int i = 0; i < result.size(); i++) { - // rt - auto f_rt = [=](auto value) { - return wiener_full_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], - st0[i]); - }; - check_scalar_types(f_rt, rt[i], result[i], drt[i]); - // a - auto f_a = [=](auto value) { - return wiener_full_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], - st0[i]); - }; - check_scalar_types(f_a, a[i], result[i], da[i]); - // v - auto f_v = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], - st0[i]); - }; - check_scalar_types(f_v, v[i], result[i], dv[i]); - // w - auto f_w = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], - st0[i]); - }; - check_scalar_types(f_w, w[i], result[i], dw[i]); - // t0 - auto f_t0 = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], - st0[i]); - }; - check_scalar_types(f_t0, t0[i], result[i], dt0[i]); - // sv - auto f_sv = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], - st0[i]); - }; - check_scalar_types(f_sv, sv[i], result[i], dsv[i]); - // sw - auto f_sw = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, - st0[i]); - }; - check_scalar_types(f_sw, sw[i], result[i], dsw[i]); - // st0 - auto f_st0 = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], - value); - }; - check_scalar_types(f_st0, st0[i], result[i], dst0[i]); - } -} diff --git a/test/unit/math/rev/prob/wiener_full_prec_test.cpp b/test/unit/math/rev/prob/wiener_full_prec_test.cpp new file mode 100644 index 00000000000..5acfc7461d8 --- /dev/null +++ b/test/unit/math/rev/prob/wiener_full_prec_test.cpp @@ -0,0 +1,120 @@ +#include +#include +#include +#include + +#include +#include + +// CHECK THAT ALL VALID SCALAR TYPES ARE ACCEPTED +template +void check_scalar_types_2(F& f, double value, double res, double deriv) { + // - f: Function with a single parameter exposed, all others + // have to be scalars + // - value: value to be used for the parameter + // - res: expected result of calling `f` with `value` + // - deriv: expected result of partial of f with respect to the + // parameter in `value` + using stan::math::var; + double err_tol = 2e-6; + + // type double + EXPECT_NEAR(f(value), res, err_tol); + + // type var with derivative + var value_var = value; + var result_var = f(value_var); + result_var.grad(); + EXPECT_NEAR(value_of(result_var), res, err_tol); + EXPECT_NEAR(value_var.adj(), deriv, err_tol); +} + +TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { + // tests all parameter types individually, with other parameters + // set to double + using stan::math::wiener_full_prec_lpdf; + double err_tol = 2e-6; + + std::vector rt{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector a{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector v{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector w{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; + std::vector t0{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0}; + std::vector sv{0.1, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0}; + std::vector sw{0.1, 0.1, 0, 0.1, 0, 0.1, 0, 0, 0}; + std::vector st0{0.1, 0, 0.1, 0.1, 0, 0, 0.1, 0, 0}; + + std::vector result{-2.426204, -2.710348, -2.422505, + -2.422795, -2.70665, -2.706812, + -2.419095, -2.703112, -3.790072}; + std::vector drt{-5.437337, -5.436798, -5.437332, -5.434799, -5.436791, + -5.434801, -5.434802, -5.434802, -5.434802}; + std::vector da{5.857318, 6.395031, 5.856484, 5.858549, 6.394195, + 6.396512, 5.857722, 6.395684, 8.369604}; + std::vector dv{-0.2428443, -0.2967977, -0.2436664, + -0.2446629, -0.297619, -0.2991696, + -0.2454931, -0.3, -0.5}; + std::vector dw{-0.9891369, -0.9887305, -0.9973428, + -0.9915453, -0.9969335, -0.991674, + -0.9997794, -0.9999097, -0.9999953}; + std::vector dt0{5.437337, 5.436798, 5.437332, 5.434799, 5.436791, + 5.434801, 5.434802, 5.434802, 5.434802}; + std::vector dsv{-0.06793703, -0.07047449, -0.06797882, + 0.0, -0.07050737, 0.0, + 0.0, 0.0, 0.0}; + std::vector dsw{-0.07406705, -0.07407386, 0.0, -0.07410901, 0.0, + -0.07410686, 0.0, 0.0, 0.0}; + std::vector dst0{2.963915, 0.0, 2.963912, 2.962338, 0.0, + 0.0, 2.96234, 0.0, 0.0}; + + for (int i = 0; i < result.size(); i++) { + // rt + auto f_rt = [=](auto value) { + return wiener_full_prec_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], + st0[i], 1e-6); + }; + check_scalar_types_2(f_rt, rt[i], result[i], drt[i]); + // a + auto f_a = [=](auto value) { + return wiener_full_prec_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], + sw[i], st0[i], 1e-6); + }; + check_scalar_types_2(f_a, a[i], result[i], da[i]); + // v + auto f_v = [=](auto value) { + return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], + sw[i], st0[i], 1e-6); + }; + check_scalar_types_2(f_v, v[i], result[i], dv[i]); + // w + auto f_w = [=](auto value) { + return wiener_full_prec_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], + sw[i], st0[i], 1e-6); + }; + check_scalar_types_2(f_w, w[i], result[i], dw[i]); + // t0 + auto f_t0 = [=](auto value) { + return wiener_full_prec_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], + st0[i], 1e-6); + }; + check_scalar_types_2(f_t0, t0[i], result[i], dt0[i]); + // sv + auto f_sv = [=](auto value) { + return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], + st0[i], 1e-6); + }; + check_scalar_types_2(f_sv, sv[i], result[i], dsv[i]); + // sw + auto f_sw = [=](auto value) { + return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, + st0[i], 1e-6); + }; + check_scalar_types_2(f_sw, sw[i], result[i], dsw[i]); + // st0 + auto f_st0 = [=](auto value) { + return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], + value, 1e-6); + }; + check_scalar_types_2(f_st0, st0[i], result[i], dst0[i]); + } +} diff --git a/test/unit/math/rev/prob/wiener_full_test.cpp b/test/unit/math/rev/prob/wiener_full_test.cpp new file mode 100644 index 00000000000..633ac5bed5e --- /dev/null +++ b/test/unit/math/rev/prob/wiener_full_test.cpp @@ -0,0 +1,120 @@ +#include +#include +#include +#include + +#include +#include + + +// CHECK THAT ALL VALID SCALAR TYPES ARE ACCEPTED +template +void check_scalar_types(F& f, double value, double res, double deriv) { + // - f: Function with a single parameter exposed, all others + // have to be scalars + // - value: value to be used for the parameter + // - res: expected result of calling `f` with `value` + // - deriv: expected result of partial of f with respect to + // the parameter in `value` + using stan::math::var; + double err_tol = 2e-4; + + // type double + EXPECT_NEAR(f(value), res, err_tol); + + // type var with derivative + var value_var = value; + var result_var = f(value_var); + result_var.grad(); + EXPECT_NEAR(value_of(result_var), res, err_tol); + EXPECT_NEAR(value_var.adj(), deriv, err_tol); +} + +TEST(ProbWienerFull, wiener_full_all_scalar) { + // tests all parameter types individually, with other + // parameters set to double + using stan::math::wiener_full_lpdf; + + std::vector rt{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector a{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector v{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector w{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; + std::vector t0{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0}; + std::vector sv{0.1, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0}; + std::vector sw{0.1, 0.1, 0, 0.1, 0, 0.1, 0, 0, 0}; + std::vector st0{0.1, 0, 0.1, 0.1, 0, 0, 0.1, 0, 0}; + + std::vector result{-2.426204, -2.710348, -2.422505, + -2.422795, -2.70665, -2.706812, + -2.419095, -2.703112, -3.790072}; + std::vector drt{-5.437337, -5.436798, -5.437332, -5.434799, -5.436791, + -5.434801, -5.434802, -5.434802, -5.434802}; + std::vector da{5.857318, 6.395031, 5.856484, 5.858549, 6.394195, + 6.396512, 5.857722, 6.395684, 8.369604}; + std::vector dv{-0.2428443, -0.2967977, -0.2436664, + -0.2446629, -0.297619, -0.2991696, + -0.2454931, -0.3, -0.5}; + std::vector dw{-0.9891369, -0.9887305, -0.9973428, + -0.9915453, -0.9969335, -0.991674, + -0.9997794, -0.9999097, -0.9999953}; + std::vector dt0{5.437337, 5.436798, 5.437332, 5.434799, 5.436791, + 5.434801, 5.434802, 5.434802, 5.434802}; + std::vector dsv{-0.06793703, -0.07047449, -0.06797882, + 0.0, -0.07050737, 0.0, + 0.0, 0.0, 0.0}; + std::vector dsw{-0.07406705, -0.07407386, 0.0, -0.07410901, 0.0, + -0.07410686, 0.0, 0.0, 0.0}; + std::vector dst0{2.963915, 0.0, 2.963912, 2.962338, 0.0, + 0.0, 2.96234, 0.0, 0.0}; + + for (int i = 0; i < result.size(); i++) { + // rt + auto f_rt = [=](auto value) { + return wiener_full_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], + st0[i]); + }; + check_scalar_types(f_rt, rt[i], result[i], drt[i]); + // a + auto f_a = [=](auto value) { + return wiener_full_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], + st0[i]); + }; + check_scalar_types(f_a, a[i], result[i], da[i]); + // v + auto f_v = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], + st0[i]); + }; + check_scalar_types(f_v, v[i], result[i], dv[i]); + // w + auto f_w = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], + st0[i]); + }; + check_scalar_types(f_w, w[i], result[i], dw[i]); + // t0 + auto f_t0 = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], + st0[i]); + }; + check_scalar_types(f_t0, t0[i], result[i], dt0[i]); + // sv + auto f_sv = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], + st0[i]); + }; + check_scalar_types(f_sv, sv[i], result[i], dsv[i]); + // sw + auto f_sw = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, + st0[i]); + }; + check_scalar_types(f_sw, sw[i], result[i], dsw[i]); + // st0 + auto f_st0 = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], + value); + }; + check_scalar_types(f_st0, st0[i], result[i], dst0[i]); + } +} From a83da48532fbdf5ee29b1476cc9f965b23557a49 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 4 Apr 2023 06:12:00 -0400 Subject: [PATCH 022/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- test/unit/math/prim/prob/wiener_full_test.cpp | 2 -- test/unit/math/rev/prob/wiener_full_test.cpp | 1 - 2 files changed, 3 deletions(-) diff --git a/test/unit/math/prim/prob/wiener_full_test.cpp b/test/unit/math/prim/prob/wiener_full_test.cpp index 4ade8b16608..40c25b02f9c 100644 --- a/test/unit/math/prim/prob/wiener_full_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_test.cpp @@ -157,5 +157,3 @@ TEST(mathPrimScalProbWienerFullScal, invalid_st0) { EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, NAN), std::domain_error); } - - diff --git a/test/unit/math/rev/prob/wiener_full_test.cpp b/test/unit/math/rev/prob/wiener_full_test.cpp index 633ac5bed5e..45edcda9d8b 100644 --- a/test/unit/math/rev/prob/wiener_full_test.cpp +++ b/test/unit/math/rev/prob/wiener_full_test.cpp @@ -6,7 +6,6 @@ #include #include - // CHECK THAT ALL VALID SCALAR TYPES ARE ACCEPTED template void check_scalar_types(F& f, double value, double res, double deriv) { From a006c4e3999fc98faef95f4e5a652796dcecccae Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 4 May 2023 15:32:52 +0300 Subject: [PATCH 023/179] hcubature struct to tuple --- stan/math/prim/functor/hcubature.hpp | 53 ++++--- .../unit/math/prim/functor/hcubature_test.cpp | 134 +++++++----------- 2 files changed, 88 insertions(+), 99 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index b5859780b8e..c87f9891dc0 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -189,23 +189,30 @@ inline void signcombos(const int& k, const double& lambda, const int& dim, * @param pars parameters for the integrand * @return numeric integral of the integrand and error */ -template +template std::tuple gauss_kronrod(const F& integrand, const double& a, - const double& b, T_pars& pars) { + const double& b, ParsTupleT& pars_tuple) { std::vector c(1, 0); std::vector cp(1, 0); std::vector cm(1, 0); c[0] = 0.5 * (a + b); double delta = 0.5 * (b - a); - double f0 = integrand(c, pars); + double f0 = math::apply([&](auto&&... args) { + return integrand(c, args...); + }, pars_tuple); + double I = f0 * wd7[7]; double Idash = f0 * gwd7[3]; for (std::size_t i = 0; i != 7; i++) { double deltax = delta * xd7[i]; cp[0] = c[0] + deltax; cm[0] = c[0] - deltax; - double fx = integrand(cp, pars); - double temp = integrand(cm, pars); + double fx = math::apply([&](auto&&... args) { + return integrand(cp, args...); + }, pars_tuple); + double temp = math::apply([&](auto&&... args) { + return integrand(cm, args...); + }, pars_tuple); fx += temp; I += fx * wd7[i]; if (i % 2 == 1) { @@ -270,11 +277,11 @@ inline void make_GenzMalik(const int& dim, * @return numeric integral of the integrand, error, and suggested coordinate to * subdivide next */ -template +template std::tuple integrate_GenzMalik( const F& integrand, std::vector>>& p, std::vector& w, std::vector& wd, const int& dim, - const std::vector& a, const std::vector& b, T_pars& pars) { + const std::vector& a, const std::vector& b, ParsTupleT& pars_tuple) { std::vector c(dim, 0); std::vector deltac(dim); @@ -294,7 +301,9 @@ std::tuple integrate_GenzMalik( return std::make_tuple(0.0, 0.0, 0); } - double f1 = integrand(c, pars); + double f1 = math::apply([&](auto&&... args) { + return integrand(c, args...); + }, pars_tuple); double f2 = 0.0; double f3 = 0.0; double twelvef1 = 12 * f1; @@ -313,11 +322,15 @@ std::tuple integrate_GenzMalik( for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] + p2[j]; } - double f2i = integrand(cc, pars); + double f2i = math::apply([&](auto&&... args) { + return integrand(cc, args...); + }, pars_tuple); for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] - p2[j]; } - double temp = integrand(cc, pars); + double temp = math::apply([&](auto&&... args) { + return integrand(cc, args...); + }, pars_tuple); f2i += temp; for (std::size_t j = 0; j != dim; j++) { @@ -326,11 +339,15 @@ std::tuple integrate_GenzMalik( for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] + p3[j]; } - double f3i = integrand(cc, pars); + double f3i = math::apply([&](auto&&... args) { + return integrand(cc, args...); + }, pars_tuple); for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] - p3[j]; } - temp = integrand(cc, pars); + temp = math::apply([&](auto&&... args) { + return integrand(cc, args...); + }, pars_tuple); f3i += temp; f2 += f2i; f3 += f3i; @@ -345,7 +362,9 @@ std::tuple integrate_GenzMalik( for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] + p4[j]; } - double temp = integrand(cc, pars); + double temp = math::apply([&](auto&&... args) { + return integrand(cc, args...); + }, pars_tuple); f4 += temp; } double f5 = 0.0; @@ -358,7 +377,9 @@ std::tuple integrate_GenzMalik( for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] + p5[j]; } - double temp = integrand(cc, pars); + double temp = math::apply([&](auto&&... args) { + return integrand(cc, args...); + }, pars_tuple); f5 += temp; } @@ -438,8 +459,8 @@ struct Box { \f$b\f$. * @throw std::domain_error no errors will be thrown. */ -template -double hcubature(const F& integrand, const T_pars& pars, const int& dim, +template +double hcubature(const F& integrand, const ParsTuple& pars, const int& dim, const std::vector& a, const std::vector& b, int& maxEval, const double& reqAbsError, const double& reqRelError) { diff --git a/test/unit/math/prim/functor/hcubature_test.cpp b/test/unit/math/prim/functor/hcubature_test.cpp index d8f09925581..e153066c342 100644 --- a/test/unit/math/prim/functor/hcubature_test.cpp +++ b/test/unit/math/prim/functor/hcubature_test.cpp @@ -6,91 +6,61 @@ namespace hcubature_test { -struct my_params { - long double x; - double y; -}; - -template -stan::return_type_t f1(const T_x& x, const T_p& p) { - using T_x_ref = stan::ref_type_t; - T_x_ref x_ref = x; - stan::scalar_seq_view x_vec(x_ref); - return cos(x_vec[0]); +template +stan::return_type_t f1(const T_x& x) { + return stan::math::sum(stan::math::cos(x)); } -template -stan::return_type_t f2(const T_x& x, const T_p& p) { - using T_x_ref = stan::ref_type_t; - T_x_ref x_ref = x; - stan::scalar_seq_view x_vec(x_ref); - return cos(x_vec[0]) * cos(x_vec[1]); +template +stan::return_type_t f2(const T_x& x) { + return stan::math::prod(stan::math::cos(x)); } -template -stan::return_type_t f3(const T_x& x, const T_p& p) { - using T_x_ref = stan::ref_type_t; - T_x_ref x_ref = x; - stan::scalar_seq_view x_vec(x_ref); - my_params* pars = static_cast(p); - long double radius = (pars->x); - double result; - if (std::pow(x_vec[0], 2) + std::pow(x_vec[1], 2) < std::pow(radius, 2)) { - result = 1; +template +stan::return_type_t f3(const T_x& x, double radius) { + using stan::math::square; + + if (stan::math::sum(square(x)) < square(radius)) { + return 1; } else { - result = 0; + return 0; } - return result; } -template -stan::return_type_t f4(const T_x& x, const T_p& p) { - using T_x_ref = stan::ref_type_t; - using namespace stan::math; - T_x_ref x_ref = x; - stan::scalar_seq_view x_vec(x_ref); - my_params* pars = static_cast(p); - double sigma = (pars->y); - double numerator = std::pow(x_vec[0] - 0.5, 2) + std::pow(x_vec[1] - 0.5, 2); - return std::pow(TWO_OVER_SQRT_PI / (2.0 * sigma), 2) - * exp(-numerator / std::pow(sigma, 2)); +template +stan::return_type_t f4(const T_x& x, double sigma) { + using stan::math::square; + using stan::math::sum; + using stan::math::as_array_or_scalar; + using stan::math::TWO_OVER_SQRT_PI; + + double numerator = sum(square(as_array_or_scalar(x) - 0.5)); + return square(TWO_OVER_SQRT_PI / (2.0 * sigma)) + * exp(-numerator / square(sigma)); } -template -stan::return_type_t f5(const T_x& x, const T_p& p) { - using T_x_ref = stan::ref_type_t; - using namespace stan::math; - T_x_ref x_ref = x; - stan::scalar_seq_view x_vec(x_ref); - double val = std::pow((1 - x_vec[0]) / x_vec[0], 2) - + std::pow((1 - x_vec[1]) / x_vec[1], 2) - + std::pow((1 - x_vec[2]) / x_vec[2], 2); - double scale = TWO_OVER_SQRT_PI / std::pow(x_vec[0], 2) * TWO_OVER_SQRT_PI - / std::pow(x_vec[1], 2) * TWO_OVER_SQRT_PI - / std::pow(x_vec[2], 2); +template +stan::return_type_t f5(const T_x& x) { + using stan::math::square; + using stan::math::prod; + using stan::math::TWO_OVER_SQRT_PI; + + const auto& x_arr = stan::math::as_array_or_scalar(x); + double val = stan::math::sum(square((1 - x_arr) / x_arr)); + double scale = prod(TWO_OVER_SQRT_PI / square(x_arr)); return exp(-val) * scale; } -template -stan::return_type_t f6(const T_x& x, const T_p& p) { - using T_x_ref = stan::ref_type_t; - T_x_ref x_ref = x; - stan::scalar_seq_view x_vec(x_ref); - return 2 * x_vec[0] * 2 * x_vec[1] * 2 * x_vec[2]; +template +stan::return_type_t f6(const T_x& x) { + const auto& x_arr = stan::math::as_array_or_scalar(x); + return stan::math::prod(2 * x_arr); } -template -stan::return_type_t f7(const T_x& x, const T_p& p) { - using T_x_ref = stan::ref_type_t; - T_x_ref x_ref = x; - stan::scalar_seq_view x_vec(x_ref); - my_params* pars = static_cast(p); - double a = (pars->y); - double result = (a / (a + 1) * std::pow((a + 1) / (a + x_vec[0]), 2)) - * (a / (a + 1) * std::pow((a + 1) / (a + x_vec[1]), 2)) - * (a / (a + 1) * std::pow((a + 1) / (a + x_vec[2]), 2)) - * (a / (a + 1) * std::pow((a + 1) / (a + x_vec[3]), 2)); - return result; +template +stan::return_type_t f7(const T_x& x, double a) { + const auto& x_arr = stan::math::as_array_or_scalar(x); + return stan::math::prod(a / (a + 1) * stan::math::square((a + 1) / (a + x_arr))); } } // namespace hcubature_test @@ -132,8 +102,8 @@ stan::return_type_t f7(const T_x& x, const T_p& p) { * @param val correct value of integral */ -template -void test_integration(const F& f, hcubature_test::my_params* pars, int dim, +template +void test_integration(const F& f, const ArgsTupleT& pars, int dim, std::vector a, std::vector b, int maxEval, double reqAbsError, std::vector reqRelError, double val) { @@ -154,37 +124,35 @@ TEST(StanMath_hcubature_prim, test1) { std::vector a = {0.0}; std::vector b = {1.0}; std::vector reqRelError = {1e-4, 1e-6, 1e-7}; - hcubature_test::my_params pars = {}; - test_integration(hcubature_test::f1, void*>, &pars, dim, + test_integration(hcubature_test::f1>, std::make_tuple(), dim, a, b, 6000, 0.0, reqRelError, 0.841471); dim = 2; a = {0.0, 0.0}; b = {1.0, 1.0}; reqRelError = {1e-4, 1e-6, 1e-7}; - test_integration(hcubature_test::f2, void*>, &pars, dim, + test_integration(hcubature_test::f2>, std::make_tuple(), dim, a, b, 6000, 0.0, reqRelError, 0.7080734); reqRelError = {1e-4}; - pars = {0.50124145262344534123412, 0.0}; - test_integration(hcubature_test::f3, void*>, &pars, dim, + test_integration(hcubature_test::f3>, + std::make_tuple(0.50124145262344534123412), dim, a, b, 10000, 0.0, reqRelError, 0.1972807); // (Gaussian centered at 1/2) reqRelError = {1e-4, 1e-6, 1e-7}; - pars = {0.0, 0.1}; - test_integration(hcubature_test::f4, void*>, &pars, dim, + test_integration(hcubature_test::f4>, std::make_tuple(0.1), dim, a, b, 6000, 0.0, reqRelError, 1); dim = 3; a = {0.0, 0.0, 0.0}; b = {1.0, 1.0, 1.0}; reqRelError = {1e-4, 1e-6}; - test_integration(hcubature_test::f5, void*>, &pars, dim, + test_integration(hcubature_test::f5>, std::make_tuple(), dim, a, b, 6000, 0.0, reqRelError, 1.00001); reqRelError = {1e-4, 1e-6, 1e-8}; - test_integration(hcubature_test::f6, void*>, &pars, dim, + test_integration(hcubature_test::f6>, std::make_tuple(), dim, a, b, 6000, 0.0, reqRelError, 1); // (Tsuda's example) @@ -192,7 +160,7 @@ TEST(StanMath_hcubature_prim, test1) { a = {0.0, 0.0, 0.0, 0.0}; b = {1.0, 1.0, 1.0, 1.0}; reqRelError = {1e-4, 1e-6}; - pars = {0.0, (1 + sqrt(10.0)) / 9.0}; - test_integration(hcubature_test::f7, void*>, &pars, dim, + test_integration(hcubature_test::f7>, + std::make_tuple((1 + sqrt(10.0)) / 9.0), dim, a, b, 20000, 0.0, reqRelError, 0.999998); } From d7d0eada828211a69a886bf1a7d59987576456ea Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 4 May 2023 18:42:01 +0300 Subject: [PATCH 024/179] Simplify wiener7 functors --- stan/math/prim/prob/wiener7_lpdf.hpp | 422 ++++++--------------------- 1 file changed, 97 insertions(+), 325 deletions(-) diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index d95193e13ed..b50598c0dd1 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -116,281 +116,70 @@ inline double dtdwiener5_for_7(const double& y, const double& a, } //----------------------------------------------- -// integrand density (on normal scale) -template -inline return_type_t int_ddiff(const T_x& x, const T_p& p) { - struct my_params { - double y, a, v, w, t0, sv, sw, st0, lerr; +template +auto wiener7_integrand(const F& integrand_fun, TArgs&&... args) { + const auto& wiener7_integrand_impl2 = [&](auto&& x, double y, double a, double v, double w, + double t0, double sv, double sw, double st0, double lerr, auto&&... args_int) { + using T_x_ref = ref_type_t; + T_x_ref x_ref = x; + scalar_seq_view x_vec(x_ref); + double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; + double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); + if (y - t0_ <= 0) { + return 0.0; + } else { + return integrand_fun(t0_, omega, y, a, v, t0, w, sw, sv, st0, lerr, args_int...); + } }; - my_params* params = static_cast(p); - double y = (params->y); - double a = (params->a); - double v = (params->v); - double t0 = (params->t0); - double w = (params->w); - double sw = (params->sw); - double sv = (params->sv); - double st0 = (params->st0); - double lerr = (params->lerr); - - using T_x_ref = ref_type_t; - T_x_ref x_ref = x; - scalar_seq_view x_vec(x_ref); - double retval; - double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; - double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); - if (y - t0_ <= 0) { - retval = 0.0; - } else { - double ldW = dwiener5(y - t0_, a, v, omega, sv, lerr); - retval = exp(ldW); - } - return retval; + return hcubature(wiener7_integrand_impl2, args...); } -//----------------------------------------------- -// integrand d/dt (on normal scale) -template -inline return_type_t int_dtddiff(const T_x& x, const T_p& p) { - struct my_params { - double y, a, v, w, t0, sv, sw, st0, lerr; - }; - my_params* params = static_cast(p); - double y = (params->y); - double a = (params->a); - double v = (params->v); - double t0 = (params->t0); - double w = (params->w); - double sw = (params->sw); - double sv = (params->sv); - double st0 = (params->st0); - double lerr = (params->lerr); - - using T_x_ref = ref_type_t; - T_x_ref x_ref = x; - scalar_seq_view x_vec(x_ref); - - double retval; - double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; - double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); - if (y - t0_ <= 0) { - retval = 0.0; - } else { - retval = dtdwiener5_for_7(y - t0_, a, -v, 1 - omega, sv, lerr); - } - return retval; +double wiener7_lpdf_impl(double t0_, double omega, double y, double a, double v, double w, double t0, + double sv, double sw, double st0, double lerr) { + return exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); } -//----------------------------------------------- - -// integrand d/da (on normal scale) -template -inline return_type_t int_daddiff(const T_x& x, const T_p& p) { - struct my_params { - double y, a, v, w, t0, sv, sw, st0, lerr; - }; - my_params* params = static_cast(p); - double y = (params->y); - double a = (params->a); - double v = (params->v); - double t0 = (params->t0); - double w = (params->w); - double sw = (params->sw); - double sv = (params->sv); - double st0 = (params->st0); - double lerr = (params->lerr); - using T_x_ref = ref_type_t; - T_x_ref x_ref = x; - scalar_seq_view x_vec(x_ref); - - double retval; - double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; - double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); - if (y - t0_ <= 0) { - retval = 0.0; - } else { - // prepare some variables for error estimation in density - double sv_sqr = square(sv); - double ans0 = (v * (1 - omega) + sv_sqr * square(1 - omega) * a) - / (1 + sv_sqr * (y - t0_)); - double factor - = max(ans0 + 1.0 / a, ans0 - 2.0 / a); // factor from small and large - // representation, for same - // computation as in dadwiener5 - // compute partial derivative - retval = dadwiener5(y - t0_, a, v, omega, sv, lerr, 1); - } - return retval; +double int_dtddiff(double t0_, double omega, double y, double a, double v, double w, double t0, + double sv, double sw, double st0, double lerr) { + return dtdwiener5_for_7(y - t0_, a, -v, 1 - omega, sv, lerr); } -//----------------------------------------------- -// integrand d/dv (on normal scale) -template -inline return_type_t int_dvddiff(const T_x& x, const T_p& p) { - struct my_params { - double y, a, v, w, t0, sv, sw, st0, lerr; - }; - my_params* params = static_cast(p); - double y = (params->y); - double a = (params->a); - double v = (params->v); - double t0 = (params->t0); - double w = (params->w); - double sw = (params->sw); - double sv = (params->sv); - double st0 = (params->st0); - double lerr = (params->lerr); - - using T_x_ref = ref_type_t; - T_x_ref x_ref = x; - scalar_seq_view x_vec(x_ref); +double int_daddiff(double t0_, double omega, double y, double a, double v, double w, double t0, + double sv, double sw, double st0, double lerr) { + return dadwiener5(y - t0_, a, v, omega, sv, lerr, 1); +} - double retval; - double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; - double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); - if (y - t0_ <= 0) { - retval = 0.0; - } else { - retval = dvdwiener5(y - t0_, a, v, omega, sv) +double int_dvddiff(double t0_, double omega, double y, double a, double v, double w, double t0, + double sv, double sw, double st0, double lerr) { + return dvdwiener5(y - t0_, a, v, omega, sv) * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); - } - return retval; } -//----------------------------------------------- -// integrand d/dw (on normal scale) -template -inline return_type_t int_dwddiff(const T_x& x, const T_p& p) { - struct my_params { - double y, a, v, w, t0, sv, sw, st0, lerr; - }; - my_params* params = static_cast(p); - double y = (params->y); - double a = (params->a); - double v = (params->v); - double t0 = (params->t0); - double w = (params->w); - double sw = (params->sw); - double sv = (params->sv); - double st0 = (params->st0); - double lerr = (params->lerr); - - using T_x_ref = ref_type_t; - T_x_ref x_ref = x; - scalar_seq_view x_vec(x_ref); - - double retval; - double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; - double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); - if (y - t0_ <= 0) { - retval = 0.0; - } else { - // prepare some variables for error estimation in density - double sv_sqr = square(sv); - double ans0 - = (v * a + sv_sqr * square(a) * (1 - omega)) / (1 + sv_sqr * (y - t0_)); - // compute partial derivative - retval = dwdwiener5(y - t0_, a, v, omega, sv, lerr, 1); - } - return retval; +double int_dwddiff(double t0_, double omega, double y, double a, double v, double w, double t0, + double sv, double sw, double st0, double lerr) { + return dwdwiener5(y - t0_, a, v, omega, sv, lerr, 1); } -//----------------------------------------------- - -// integrand d/dsv (on normal scale) -template -inline return_type_t int_dsvddiff(const T_x& x, const T_p& p) { - struct my_params { - double y, a, v, w, t0, sv, sw, st0, lerr; - }; - my_params* params = static_cast(p); - double y = (params->y); - double a = (params->a); - double v = (params->v); - double t0 = (params->t0); - double w = (params->w); - double sw = (params->sw); - double sv = (params->sv); - double st0 = (params->st0); - double lerr = (params->lerr); - - using T_x_ref = ref_type_t; - T_x_ref x_ref = x; - scalar_seq_view x_vec(x_ref); - double retval; - double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; - double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); - if (y - t0_ <= 0) { - retval = 0.0; - } else { - retval = dsvdwiener5(y - t0_, a, v, omega, sv) +double int_dsvddiff(double t0_, double omega, double y, double a, double v, double w, double t0, + double sv, double sw, double st0, double lerr) { + return dsvdwiener5(y - t0_, a, v, omega, sv) * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); - } - return retval; } -//----------------------------------------------- -// integrand d/dsw (on normal scale) -template -inline return_type_t int_dswddiff(const T_x& x, const T_p& p) { - struct my_params2 { - double y, a, v, w, w_lower, w_upper, t0, sv, sw, sw_mean, st0, lerr; - }; - my_params2* params = static_cast(p); - double y = (params->y); - double a = (params->a); - double v = (params->v); - double t0 = (params->t0); - double w = (params->w); - double w_lower = (params->w_lower); - double w_upper = (params->w_upper); - double sw = (params->sw); - double sw_mean = (params->sw_mean); - double sv = (params->sv); - double st0 = (params->st0); - double lerr = (params->lerr); - - using T_x_ref = ref_type_t; - T_x_ref x_ref = x; - scalar_seq_view x_vec(x_ref); - double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); - double f, fl, fu; - if (y - t0_ <= 0) { - return 0.0; - } else { - fl = exp(internal::dwiener5(y - t0_, a, v, w_lower, sv, lerr)); - fu = exp(internal::dwiener5(y - t0_, a, v, w_upper, sv, lerr)); - } +double int_dswddiff(double t0_, double omega, double y, double a, double v, double w, double t0, + double sv, double sw, double st0, double lerr, + double w_lower, double w_upper, double sw_mean) { + double fl = exp(internal::dwiener5(y - t0_, a, v, w_lower, sv, lerr)); + double fu = exp(internal::dwiener5(y - t0_, a, v, w_upper, sv, lerr)); return 1 / sw_mean * 0.5 * (fl + fu); } -//----------------------------------------------- // integrand d/dst0 (on normal scale) -template -inline return_type_t int_dst0ddiff(const T_x& x, const T_p& p) { - struct my_params3 { - double y, a, v, w, t0, t0_mean, sv, sw, st0, st0_mean, lerr; - }; - my_params3* params = static_cast(p); - double y = (params->y); - double a = (params->a); - double v = (params->v); - double t0 = (params->t0); - double t0_mean = (params->t0_mean); - double w = (params->w); - double sw = (params->sw); - double sv = (params->sv); - double st0 = (params->st0); - double st0_mean = (params->st0_mean); - double lerr = (params->lerr); - +template +inline return_type_t int_dst0ddiff(const T_x& x, double y, double a, double v, double w, + double t0, double t0_mean, double sv, double sw, double st0, + double st0_mean, double lerr) { using T_x_ref = ref_type_t; T_x_ref x_ref = x; scalar_seq_view x_vec(x_ref); @@ -540,15 +329,6 @@ inline return_type_t wiener7_lpdf( ops_partials(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref, sw_ref, st0_ref); static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; static constexpr double LOG_POINT1 = -1; - struct my_params { - double y, a, v, w, t0, sv, sw, st0, lerr; - }; - struct my_params2 { - double y, a, v, w, w_lower, w_upper, t0, sv, sw, sw_mean, st0, lerr; - }; - struct my_params3 { - double y, a, v, w, t0, t0_mean, sv, sw, st0, st0_mean, lerr; - }; // calculate density and partials for (size_t i = 0; i < N; i++) { @@ -560,9 +340,9 @@ inline return_type_t wiener7_lpdf( const double sv_val = sv_vec.val(i); const double sw_val = sw_vec.val(i); const double st0_val = st0_vec.val(i); - my_params params = {y_val, a_val, v_val, - w_val, t0_val, sv_val, - sw_val, st0_val, labstol_wiener5 - LOG_TWO}; + const auto params = std::make_tuple(y_val, a_val, v_val, + w_val, t0_val, sv_val, + sw_val, st0_val, labstol_wiener5 - LOG_TWO); int dim = (sw_val != 0) + (st0_val != 0); check_positive(function_name, "(Inter-trial variability in A-priori bias) + " @@ -575,17 +355,16 @@ inline return_type_t wiener7_lpdf( xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); } - dens = hcubature(internal::int_ddiff, void*>, ¶ms, - dim, xmin, xmax, Meval, abstol, reltol / 2); + dens = internal::wiener7_integrand(internal::wiener7_lpdf_impl, params, dim, xmin, xmax, Meval, abstol, reltol / 2); + if (labstol_wiener5 > fabs(log(dens)) + LOG_POINT1 + lerror_bound_dens - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound_dens - LOG_TWO + log(fabs(dens)); - my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; - dens = hcubature(internal::int_ddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, - reltol); + const auto params_new_error = std::make_tuple(y_val, a_val, v_val, + w_val, t0_val, sv_val, + sw_val, st0_val, new_error); + dens = internal::wiener7_integrand(internal::wiener7_lpdf_impl, params_new_error, dim, xmin, xmax, Meval, abstol, reltol); } ld += log(dens); @@ -594,17 +373,16 @@ inline return_type_t wiener7_lpdf( double deriv_t_7; deriv_t_7 = 1 / dens - * hcubature(internal::int_dtddiff, void*>, - ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); + * internal::wiener7_integrand(internal::int_dtddiff, params, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 > log(fabs(deriv_t_7)) + LOG_POINT1 + lerror_bound - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv_t_7)); - my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; + const auto params_new_error = std::make_tuple(y_val, a_val, v_val, + w_val, t0_val, sv_val, + sw_val, st0_val, new_error); deriv_t_7 = 1 / dens - * hcubature(internal::int_dtddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, + * internal::wiener7_integrand(internal::int_dtddiff, params_new_error, dim, xmin, xmax, Meval, abstol, reltol / 2); } @@ -615,17 +393,16 @@ inline return_type_t wiener7_lpdf( } if (!is_constant_all::value) { deriv = 1 / dens - * hcubature(internal::int_daddiff, void*>, - ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); + * internal::wiener7_integrand(internal::int_daddiff, params, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv)); - my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; + const auto params_new_error = std::make_tuple(y_val, a_val, v_val, + w_val, t0_val, sv_val, + sw_val, st0_val, new_error); deriv = 1 / dens - * hcubature(internal::int_daddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, + * internal::wiener7_integrand(internal::int_daddiff, params_new_error, dim, xmin, xmax, Meval, abstol, reltol / 2); } ops_partials.edge2_.partials_[i] = deriv; @@ -635,51 +412,48 @@ inline return_type_t wiener7_lpdf( } if (!is_constant_all::value) { deriv = 1 / dens - * hcubature(internal::int_dwddiff, void*>, - ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); + * internal::wiener7_integrand(internal::int_dwddiff, params, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv)); - my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; + const auto params_new_error = std::make_tuple(y_val, a_val, v_val, + w_val, t0_val, sv_val, + sw_val, st0_val, new_error); deriv = 1 / dens - * hcubature(internal::int_dwddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, + * internal::wiener7_integrand(internal::int_dwddiff, params_new_error, dim, xmin, xmax, Meval, abstol, reltol / 2); } ops_partials.edge4_.partials_[i] = deriv; } if (!is_constant_all::value) { deriv = 1 / dens - * hcubature(internal::int_dvddiff, void*>, - ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); + * internal::wiener7_integrand(internal::int_dvddiff, params, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound - LOG_TWO + log(fabs(deriv)); - my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; + const auto params_new_error = std::make_tuple(y_val, a_val, v_val, + w_val, t0_val, sv_val, + sw_val, st0_val, new_error); deriv = 1 / dens - * hcubature(internal::int_dvddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, + * internal::wiener7_integrand(internal::int_dvddiff, params_new_error, dim, xmin, xmax, Meval, abstol, reltol / 2); } ops_partials.edge5_.partials_[i] = deriv; } if (!is_constant_all::value) { deriv = 1 / dens - * hcubature(internal::int_dsvddiff, void*>, - ¶ms, dim, xmin, xmax, Meval, abstol, reltol / 2); + * internal::wiener7_integrand(internal::int_dsvddiff, params, dim, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { double new_error = LOG_POINT1 + lerror_bound - LOG_TWO + log(fabs(deriv)); - my_params params_new_error = {y_val, a_val, v_val, w_val, t0_val, - sv_val, sw_val, st0_val, new_error}; + const auto params_new_error = std::make_tuple(y_val, a_val, v_val, + w_val, t0_val, sv_val, + sw_val, st0_val, new_error); deriv = 1 / dens - * hcubature(internal::int_dsvddiff, void*>, - ¶ms_new_error, dim, xmin, xmax, Meval, abstol, + * internal::wiener7_integrand(internal::int_dsvddiff, params_new_error, dim, xmin, xmax, Meval, abstol, reltol / 2); } ops_partials.edge6_.partials_[i] = deriv; @@ -714,23 +488,21 @@ inline return_type_t wiener7_lpdf( } deriv = 1 / width * 0.5 * (fl + fu); } else { - my_params2 params_sw - = {y_val, a_val, v_val, w_val, - lower, upper, t0_val, sv_val, - 0, sw_val, st0_val, labstol_wiener5 - LOG_TWO}; - deriv = hcubature(internal::int_dswddiff, void*>, - ¶ms_sw, dim_, xmin, xmax, Meval, abstol, + const auto& params_sw = std::make_tuple(y_val, a_val, v_val, + w_val, t0_val, sv_val, + 0, st0_val, labstol_wiener5 - LOG_TWO, + lower, upper, sw_val); + deriv = internal::wiener7_integrand(internal::int_dswddiff, params_sw, dim_, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 > log(fabs(deriv) + LOG_POINT1 + lerror_bound - LOG_TWO)) { double new_error = log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO; - my_params2 params_new_error_sw - = {y_val, a_val, v_val, w_val, lower, upper, - t0_val, sv_val, 0, sw_val, st0_val, new_error}; + const auto& params_new_error_sw + = std::make_tuple(y_val, a_val, v_val, w_val, + t0_val, sv_val, 0, st0_val, new_error, lower, upper, sw_val); deriv - = hcubature(internal::int_dswddiff, void*>, - ¶ms_new_error_sw, dim_, xmin, xmax, Meval, + = internal::wiener7_integrand(internal::int_dswddiff, params_new_error_sw, dim_, xmin, xmax, Meval, abstol, reltol / 2); } } @@ -758,22 +530,22 @@ inline return_type_t wiener7_lpdf( deriv = 1 / st0_val * f; } else { double new_error = labstol_wiener5 - LOG_TWO; - my_params3 params_st - = {y_val, a_val, v_val, w_val, t0_val, t0_val + st0_val, - sv_val, sw_val, st0_val, 0, new_error}; - deriv = hcubature(internal::int_dst0ddiff, void*>, - ¶ms_st, dim_, xmin, xmax, Meval, abstol, + const auto& params_st + = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, t0_val + st0_val, + sv_val, sw_val, st0_val, 0, new_error); + deriv = hcubature(internal::int_dst0ddiff>, + params_st, dim_, xmin, xmax, Meval, abstol, reltol / 2); if (labstol_wiener5 > log(fabs(deriv) + LOG_POINT1 + lerror_bound - LOG_TWO)) { double new_error = log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO; - my_params3 params_new_error_st - = {y_val, a_val, v_val, w_val, t0_val, t0_val + st0_val, - sv_val, sw_val, st0_val, 0, new_error}; + const auto& params_new_error_st + = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, t0_val + st0_val, + sv_val, sw_val, st0_val, 0, new_error); deriv - = hcubature(internal::int_dst0ddiff, void*>, - ¶ms_new_error_st, dim_, xmin, xmax, Meval, + = hcubature(internal::int_dst0ddiff>, + params_new_error_st, dim_, xmin, xmax, Meval, abstol, reltol / 2); } } From f376dd307086624a9da57fdbe449de155b5b3006 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 5 May 2023 15:32:00 +0300 Subject: [PATCH 025/179] First pass refactoring wiener7 --- stan/math/prim/functor/hcubature.hpp | 7 +- stan/math/prim/prob/wiener7_lpdf.hpp | 339 +++++++----------- stan/math/prim/prob/wiener_full_lpdf.hpp | 117 ++---- .../unit/math/prim/functor/hcubature_test.cpp | 28 +- .../math/rev/prob/wiener_full_prec_test.cpp | 120 ------- test/unit/math/rev/prob/wiener_full_test.cpp | 90 +++++ 6 files changed, 284 insertions(+), 417 deletions(-) delete mode 100644 test/unit/math/rev/prob/wiener_full_prec_test.cpp diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index c87f9891dc0..4533293f7ba 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -191,7 +192,8 @@ inline void signcombos(const int& k, const double& lambda, const int& dim, */ template std::tuple gauss_kronrod(const F& integrand, const double& a, - const double& b, ParsTupleT& pars_tuple) { + const double& b, + ParsTupleT& pars_tuple) { std::vector c(1, 0); std::vector cp(1, 0); std::vector cm(1, 0); @@ -281,7 +283,8 @@ template std::tuple integrate_GenzMalik( const F& integrand, std::vector>>& p, std::vector& w, std::vector& wd, const int& dim, - const std::vector& a, const std::vector& b, ParsTupleT& pars_tuple) { + const std::vector& a, const std::vector& b, + ParsTupleT& pars_tuple) { std::vector c(dim, 0); std::vector deltac(dim); diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index b50598c0dd1..95d34507c0d 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -116,87 +116,102 @@ inline double dtdwiener5_for_7(const double& y, const double& a, } //----------------------------------------------- +template +void assign_err(std::tuple& args_tuple, double err) { + std::get<8>(args_tuple) = err; +} +void assign_err(double arg, double err) { + arg = err; +} + +template +double estimate_with_err_check(const F& functor, double err, + ArgsTupleT&& args_tuple) { + double result = math::apply([&](auto&&... args) { return functor(args...); }, + args_tuple); + double lfabs_result = log(fabs(result)); + if (lfabs_result < err) { + ArgsTupleT err_args_tuple = args_tuple; + assign_err(std::get(err_args_tuple), err + lfabs_result); + result = math::apply([&](auto&&... args) { return functor(args...); }, + err_args_tuple); + } + return result; +} + template -auto wiener7_integrand(const F& integrand_fun, TArgs&&... args) { - const auto& wiener7_integrand_impl2 = [&](auto&& x, double y, double a, double v, double w, - double t0, double sv, double sw, double st0, double lerr, auto&&... args_int) { - using T_x_ref = ref_type_t; - T_x_ref x_ref = x; - scalar_seq_view x_vec(x_ref); +auto wiener7_integrand(const F& integrand_fun, double labstol_wiener5, + double lerr_bound, TArgs&&... args) { + const auto& wiener7_integrand_impl = [&](std::vector x, double y, + double a, double v, double w, + double t0, double sv, double sw, + double st0, double lerr, + auto&&... args_int) { + scalar_seq_view x_vec(x); double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) : (st0 ? t0 + st0 * x_vec[0] : t0); if (y - t0_ <= 0) { return 0.0; } else { - return integrand_fun(t0_, omega, y, a, v, t0, w, sw, sv, st0, lerr, args_int...); + return integrand_fun(t0_, omega, y, a, v, w, t0, sv, sw, st0, lerr, + args_int...); } }; - return hcubature(wiener7_integrand_impl2, args...); + + double err = labstol_wiener5 - lerr_bound + LOG_TWO + 1; + const auto& functor = [&](auto&&... int_args) { + return hcubature(wiener7_integrand_impl, int_args...); + }; + return estimate_with_err_check<0>(functor, err, std::make_tuple(args...)); } -double wiener7_lpdf_impl(double t0_, double omega, double y, double a, double v, double w, double t0, - double sv, double sw, double st0, double lerr) { +double wiener7_lpdf_impl(double t0_, double omega, double y, double a, + double v, double w, double t0, double sv, + double sw, double st0, double lerr) { return exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); } -double int_dtddiff(double t0_, double omega, double y, double a, double v, double w, double t0, - double sv, double sw, double st0, double lerr) { +double int_dtddiff(double t0_, double omega, double y, double a, double v, + double w, double t0, double sv, double sw, double st0, + double lerr) { return dtdwiener5_for_7(y - t0_, a, -v, 1 - omega, sv, lerr); } -double int_daddiff(double t0_, double omega, double y, double a, double v, double w, double t0, - double sv, double sw, double st0, double lerr) { +double int_daddiff(double t0_, double omega, double y, double a, double v, + double w, double t0, double sv, double sw, double st0, + double lerr) { return dadwiener5(y - t0_, a, v, omega, sv, lerr, 1); } -double int_dvddiff(double t0_, double omega, double y, double a, double v, double w, double t0, - double sv, double sw, double st0, double lerr) { +double int_dvddiff(double t0_, double omega, double y, double a, double v, + double w, double t0, double sv, double sw, double st0, + double lerr) { return dvdwiener5(y - t0_, a, v, omega, sv) * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); } -double int_dwddiff(double t0_, double omega, double y, double a, double v, double w, double t0, - double sv, double sw, double st0, double lerr) { +double int_dwddiff(double t0_, double omega, double y, double a, double v, + double w, double t0, double sv, double sw, double st0, + double lerr) { return dwdwiener5(y - t0_, a, v, omega, sv, lerr, 1); } -double int_dsvddiff(double t0_, double omega, double y, double a, double v, double w, double t0, - double sv, double sw, double st0, double lerr) { +double int_dsvddiff(double t0_, double omega, double y, double a, double v, + double w, double t0, double sv, double sw, double st0, + double lerr) { return dsvdwiener5(y - t0_, a, v, omega, sv) * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); } -double int_dswddiff(double t0_, double omega, double y, double a, double v, double w, double t0, - double sv, double sw, double st0, double lerr, - double w_lower, double w_upper, double sw_mean) { +double int_dswddiff(double t0_, double omega, double y, double a, double v, + double w, double t0, double sv, double sw, double st0, + double lerr, double w_lower, double w_upper, + double sw_mean) { double fl = exp(internal::dwiener5(y - t0_, a, v, w_lower, sv, lerr)); double fu = exp(internal::dwiener5(y - t0_, a, v, w_upper, sv, lerr)); - return 1 / sw_mean * 0.5 * (fl + fu); -} - -// integrand d/dst0 (on normal scale) -template -inline return_type_t int_dst0ddiff(const T_x& x, double y, double a, double v, double w, - double t0, double t0_mean, double sv, double sw, double st0, - double st0_mean, double lerr) { - using T_x_ref = ref_type_t; - T_x_ref x_ref = x; - scalar_seq_view x_vec(x_ref); - - double t0_ = sw ? (st0_mean ? t0_mean + st0_mean * x_vec[1] : t0_mean) - : (st0_mean ? t0_mean + st0_mean * x_vec[0] : t0_mean); - double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; - double f; - if (y - t0_ <= 0) { - return 0.0; - } else { - f = exp(internal::dwiener5(y - t0_, a, v, omega, sv, lerr)); - } - return 1 / st0 * f; + return 0.5 * (fl + fu) / sw_mean; } -//----------------------------------------------- - } // namespace internal template wiener7_lpdf( const double st0_val = st0_vec.val(i); const auto params = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, - sw_val, st0_val, labstol_wiener5 - LOG_TWO); + sw_val, st0_val, + labstol_wiener5 - LOG_TWO); int dim = (sw_val != 0) + (st0_val != 0); check_positive(function_name, "(Inter-trial variability in A-priori bias) + " @@ -355,36 +371,21 @@ inline return_type_t wiener7_lpdf( xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); } - dens = internal::wiener7_integrand(internal::wiener7_lpdf_impl, params, dim, xmin, xmax, Meval, abstol, reltol / 2); - - if (labstol_wiener5 - > fabs(log(dens)) + LOG_POINT1 + lerror_bound_dens - LOG_TWO) { - double new_error - = LOG_POINT1 + lerror_bound_dens - LOG_TWO + log(fabs(dens)); - const auto params_new_error = std::make_tuple(y_val, a_val, v_val, - w_val, t0_val, sv_val, - sw_val, st0_val, new_error); - dens = internal::wiener7_integrand(internal::wiener7_lpdf_impl, params_new_error, dim, xmin, xmax, Meval, abstol, reltol); - } - ld += log(dens); + dens = internal::wiener7_integrand(internal::wiener7_lpdf_impl, + labstol_wiener5, lerror_bound_dens, + params, dim, xmin, xmax, Meval, + abstol, reltol / 2); + double log_dens = log(dens); + ld += log_dens; // computation of derivative for t and precision check in order to give // the value as deriv_t to edge1 and as -deriv_t to edge5 - double deriv_t_7; - deriv_t_7 - = 1 / dens - * internal::wiener7_integrand(internal::int_dtddiff, params, dim, xmin, xmax, Meval, abstol, reltol / 2); - if (labstol_wiener5 - > log(fabs(deriv_t_7)) + LOG_POINT1 + lerror_bound - LOG_TWO) { - double new_error - = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv_t_7)); - const auto params_new_error = std::make_tuple(y_val, a_val, v_val, - w_val, t0_val, sv_val, - sw_val, st0_val, new_error); - deriv_t_7 = 1 / dens - * internal::wiener7_integrand(internal::int_dtddiff, params_new_error, dim, xmin, xmax, Meval, abstol, - reltol / 2); - } + double deriv_t_7 + = internal::wiener7_integrand(internal::int_dtddiff, + labstol_wiener5, + lerror_bound + log_dens, + params, dim, xmin, xmax, + Meval, abstol, reltol / 2) / dens; // computation of derivatives and precision checks double deriv; @@ -392,119 +393,65 @@ inline return_type_t wiener7_lpdf( ops_partials.edge1_.partials_[i] = deriv_t_7; } if (!is_constant_all::value) { - deriv = 1 / dens - * internal::wiener7_integrand(internal::int_daddiff, params, dim, xmin, xmax, Meval, abstol, reltol / 2); - if (labstol_wiener5 - > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { - double new_error - = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv)); - const auto params_new_error = std::make_tuple(y_val, a_val, v_val, - w_val, t0_val, sv_val, - sw_val, st0_val, new_error); - deriv = 1 / dens - * internal::wiener7_integrand(internal::int_daddiff, params_new_error, dim, xmin, xmax, Meval, abstol, - reltol / 2); - } - ops_partials.edge2_.partials_[i] = deriv; + ops_partials.edge2_.partials_[i] + = internal::wiener7_integrand(internal::int_daddiff, + labstol_wiener5, + lerror_bound + log_dens, params, + dim, xmin, xmax, Meval, + abstol, reltol / 2) / dens; } if (!is_constant_all::value) { ops_partials.edge3_.partials_[i] = -deriv_t_7; } if (!is_constant_all::value) { - deriv = 1 / dens - * internal::wiener7_integrand(internal::int_dwddiff, params, dim, xmin, xmax, Meval, abstol, reltol / 2); - if (labstol_wiener5 - > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { - double new_error - = LOG_POINT1 + lerror_bound - LOG_FOUR + log(fabs(deriv)); - const auto params_new_error = std::make_tuple(y_val, a_val, v_val, - w_val, t0_val, sv_val, - sw_val, st0_val, new_error); - deriv = 1 / dens - * internal::wiener7_integrand(internal::int_dwddiff, params_new_error, dim, xmin, xmax, Meval, abstol, - reltol / 2); - } - ops_partials.edge4_.partials_[i] = deriv; + ops_partials.edge4_.partials_[i] + = internal::wiener7_integrand(internal::int_dwddiff, + labstol_wiener5, + lerror_bound + log_dens, params, + dim, xmin, xmax, Meval, abstol, + reltol / 2) / dens; } if (!is_constant_all::value) { - deriv = 1 / dens - * internal::wiener7_integrand(internal::int_dvddiff, params, dim, xmin, xmax, Meval, abstol, reltol / 2); - if (labstol_wiener5 - > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { - double new_error - = LOG_POINT1 + lerror_bound - LOG_TWO + log(fabs(deriv)); - const auto params_new_error = std::make_tuple(y_val, a_val, v_val, - w_val, t0_val, sv_val, - sw_val, st0_val, new_error); - deriv = 1 / dens - * internal::wiener7_integrand(internal::int_dvddiff, params_new_error, dim, xmin, xmax, Meval, abstol, - reltol / 2); - } - ops_partials.edge5_.partials_[i] = deriv; + ops_partials.edge5_.partials_[i] + = internal::wiener7_integrand(internal::int_dvddiff, + labstol_wiener5, + lerror_bound + log_dens, params, + dim, xmin, xmax, Meval, abstol, + reltol / 2) / dens; } if (!is_constant_all::value) { - deriv = 1 / dens - * internal::wiener7_integrand(internal::int_dsvddiff, params, dim, xmin, xmax, Meval, abstol, reltol / 2); - if (labstol_wiener5 - > log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO) { - double new_error - = LOG_POINT1 + lerror_bound - LOG_TWO + log(fabs(deriv)); - const auto params_new_error = std::make_tuple(y_val, a_val, v_val, - w_val, t0_val, sv_val, - sw_val, st0_val, new_error); - deriv = 1 / dens - * internal::wiener7_integrand(internal::int_dsvddiff, params_new_error, dim, xmin, xmax, Meval, abstol, - reltol / 2); - } - ops_partials.edge6_.partials_[i] = deriv; + ops_partials.edge6_.partials_[i] + = internal::wiener7_integrand(internal::int_dsvddiff, + labstol_wiener5, + lerror_bound + log_dens, params, + dim, xmin, xmax, Meval, abstol, + reltol / 2) / dens; } if (!is_constant_all::value) { if (sw_val == 0) { ops_partials.edge7_.partials_[i] = 0; } else { - double lower, upper, width, fl, fu; - lower = w_val - sw_val / 2; - lower = (0 > lower) ? 0 : lower; - upper = w_val + sw_val / 2; - upper = (1 < upper) ? 1 : upper; - width = upper - lower; - - int dim_ = (st0_val != 0); - if (dim_ == 0) { - fl = exp(internal::dwiener5(y_val - t0_val, a_val, v_val, lower, - sv_val, labstol_wiener5)); - fu = exp(internal::dwiener5(y_val - t0_val, a_val, v_val, upper, - sv_val, labstol_wiener5)); - if (labstol_wiener5 > log(fabs(fl + fu) + log(sw_val) - LOG_TWO - + lerror_bound - LOG_TWO)) { - fl = exp(internal::dwiener5(y_val - t0_val, a_val, v_val, lower, - sv_val, - lerror_bound - LOG_TWO + log(sw_val) - - LOG_TWO + log(fabs(fl + fu)))); - fu = exp(internal::dwiener5(y_val - t0_val, a_val, v_val, upper, - sv_val, - lerror_bound - LOG_TWO + log(sw_val) - - LOG_TWO + log(fabs(fl + fu)))); - } - deriv = 1 / width * 0.5 * (fl + fu); + double lower = w_val - sw_val / 2; + double upper = w_val + sw_val / 2; + + const auto& params_sw = std::make_tuple(y_val, a_val, v_val, + w_val, t0_val, sv_val, + 0, st0_val, + labstol_wiener5 - LOG_TWO, + (0 > lower) ? 0 : lower, + (1 < upper) ? 1 : upper, + sw_val); + if (st0_val == 0) { + const auto& dswddif_args = std::tuple_cat(std::make_tuple(t0_val, 0), + params_sw); + deriv = internal::estimate_with_err_check<8>(internal::int_dswddiff, + lerror_bound - LOG_TWO, + dswddif_args); } else { - const auto& params_sw = std::make_tuple(y_val, a_val, v_val, - w_val, t0_val, sv_val, - 0, st0_val, labstol_wiener5 - LOG_TWO, - lower, upper, sw_val); - deriv = internal::wiener7_integrand(internal::int_dswddiff, params_sw, dim_, xmin, xmax, Meval, abstol, - reltol / 2); - if (labstol_wiener5 - > log(fabs(deriv) + LOG_POINT1 + lerror_bound - LOG_TWO)) { - double new_error - = log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO; - const auto& params_new_error_sw - = std::make_tuple(y_val, a_val, v_val, w_val, - t0_val, sv_val, 0, st0_val, new_error, lower, upper, sw_val); - deriv - = internal::wiener7_integrand(internal::int_dswddiff, params_new_error_sw, dim_, xmin, xmax, Meval, - abstol, reltol / 2); - } + deriv = internal::wiener7_integrand(internal::int_dswddiff, + labstol_wiener5, lerror_bound, + params_sw, 1, xmin, xmax, + Meval, abstol, reltol / 2); } ops_partials.edge7_.partials_[i] = deriv / dens - 1 / sw_val; } @@ -516,40 +463,24 @@ inline return_type_t wiener7_lpdf( } else if (y_val - (t0_val + st0_val) <= 0) { ops_partials.edge8_.partials_[i] = -1 / st0_val; } else { - int dim_ = (sw_val != 0); - if (dim_ == 0) { - f = exp(internal::dwiener5(y_val - (t0_val + st0_val), a_val, v_val, - w_val, sv_val, labstol_wiener5)); - if (labstol_wiener5 > log(fabs(f) + log(st0_val) - LOG_TWO - + lerror_bound - LOG_TWO)) { - f = exp(internal::dwiener5(y_val - (t0_val + st0_val), a_val, v_val, - w_val, sv_val, - lerror_bound - LOG_TWO + log(st0_val) - - LOG_TWO + log(fabs(f)))); - } - deriv = 1 / st0_val * f; + if (sw_val == 0) { + const auto& dst0_params + = std::tuple_cat(std::make_tuple(t0_val + st0_val, w_val), params); + f = internal::estimate_with_err_check<8>(internal::wiener7_lpdf_impl, + lerror_bound + log(st0_val), + dst0_params); } else { double new_error = labstol_wiener5 - LOG_TWO; - const auto& params_st - = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, t0_val + st0_val, - sv_val, sw_val, st0_val, 0, new_error); - deriv = hcubature(internal::int_dst0ddiff>, - params_st, dim_, xmin, xmax, Meval, abstol, - reltol / 2); - if (labstol_wiener5 - > log(fabs(deriv) + LOG_POINT1 + lerror_bound - LOG_TWO)) { - double new_error - = log(fabs(deriv)) + LOG_POINT1 + lerror_bound - LOG_TWO; - const auto& params_new_error_st - = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, t0_val + st0_val, - sv_val, sw_val, st0_val, 0, new_error); - deriv - = hcubature(internal::int_dst0ddiff>, - params_new_error_st, dim_, xmin, xmax, Meval, - abstol, reltol / 2); - } + + const auto& params_st = std::make_tuple(y_val, a_val, v_val, w_val, + t0_val + st0_val, sv_val, + sw_val, 0, new_error); + f = internal::wiener7_integrand(internal::wiener7_lpdf_impl, + labstol_wiener5, lerror_bound, + params_st, 1, xmin, xmax, + Meval, abstol, reltol / 2); } - ops_partials.edge8_.partials_[i] = -1 / st0_val + deriv / dens; + ops_partials.edge8_.partials_[i] = -1 / st0_val + f / st0_val / dens; } } std::vector().swap(xmin); diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index feb8d65f266..7da065c541a 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -9,46 +9,7 @@ namespace stan { namespace math { namespace internal { -template -inline return_type_t -wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, - const T_a& a, const T_t0& t0, const T_w& w, - const T_v& v, const T_sv& sv, const T_sw& sw, - const T_st0& st0, const double& prec) { - using T_sw_ref = ref_type_t; - using T_st0_ref = ref_type_t; - check_consistent_size(function_name, - "Inter-trial variability in A-priori bias", sw, 1); - check_consistent_size(function_name, - "Inter-trial variability in Nondecision time", st0, 1); - - T_sw_ref sw_ref = sw; - T_st0_ref st0_ref = st0; - - size_t N = max_size(y, a, t0, w, v, sv, sw, st0); - if (!N) { - return 0; - } - - scalar_seq_view sw_vec(sw_ref); - scalar_seq_view st0_vec(st0_ref); - - // calculate density and partials - for (size_t i = 0; i < N; i++) { - // Calculate 4-parameter model without inter-trial variabilities (if - // sv_vec[i] == 0) or 5-parameter model with inter-trial variability in - // drift rate (if sv_vec[i] != 0) - if (sw_vec[i] == 0 && st0_vec[i] == 0) { - return wiener5_lpdf(y, a, t0, w, v, sv, prec); - // Calculate 6-, or 7-parameter model - } else { - return wiener7_lpdf(y, a, t0, w, v, sv, sw, st0, prec); - } - } - return 0; -} //----------------------------------------------- } // namespace internal @@ -198,58 +159,54 @@ wiener_full_prec_impl_lpdf(const char* function_name, const T_y& y, template inline return_type_t -wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, - const T_v& v, const T_sv& sv, const T_sw& sw, - const T_st0& st0) { - double precision = 1e-4; +wiener_full_lpdf(const T_y& y, + const T_a& a, const T_t0& t0, const T_w& w, + const T_v& v, const T_sv& sv, const T_sw& sw, + const T_st0& st0, + double precision = 1e-4) { + const char* function_name = "wiener_full_lpdf"; + using T_sw_ref = ref_type_t; + using T_st0_ref = ref_type_t; - return internal::wiener_full_prec_impl_lpdf( - "wiener_full_lpdf", y, a, t0, w, v, sv, sw, st0, precision); -} + check_consistent_size(function_name, + "Inter-trial variability in A-priori bias", sw, 1); + check_consistent_size(function_name, + "Inter-trial variability in Nondecision time", st0, 1); -template -inline return_type_t -wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, - const T_v& v, const T_sv& sv, const T_sw& sw, - const T_st0& st0) { - double precision = 1e-4; + T_sw_ref sw_ref = sw; + T_st0_ref st0_ref = st0; - return internal::wiener_full_prec_impl_lpdf( - "wiener_full_lpdf", y, a, t0, w, v, sv, sw, st0, precision); -} + size_t N = max_size(y, a, t0, w, v, sv, sw, st0); + if (!N) { + return 0; + } -/** \ingroup prob_dists - * The log of the first passage time density function for a (Wiener) - * drift diffusion model with up to 7 parameters with the option - * to control for the precision in the estimation of the partial derivatives. - * - * For \b Details see \c wiener_full_lpdf(). The usage and behavior of these - * functions are the same excpet of the control over the precision. - */ + scalar_seq_view sw_vec(sw_ref); + scalar_seq_view st0_vec(st0_ref); -template -inline return_type_t -wiener_full_prec_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, - const T_v& v, const T_sv& sv, const T_sw& sw, - const T_st0& st0, const double& prec) { - return internal::wiener_full_prec_impl_lpdf( - "wiener_full_prec_lpdf", y, a, t0, w, v, sv, sw, st0, prec); + // calculate density and partials + for (size_t i = 0; i < N; i++) { + // Calculate 4-parameter model without inter-trial variabilities (if + // sv_vec[i] == 0) or 5-parameter model with inter-trial variability in + // drift rate (if sv_vec[i] != 0) + if (sw_vec[i] == 0 && st0_vec[i] == 0) { + return wiener5_lpdf(y, a, t0, w, v, sv, precision); + // Calculate 6-, or 7-parameter model + } else { + return wiener7_lpdf(y, a, t0, w, v, sv, sw, st0, precision); + } + } + return 0; } template inline return_type_t -wiener_full_prec_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, - const T_v& v, const T_sv& sv, const T_sw& sw, - const T_st0& st0, const double& prec) { - return internal::wiener_full_prec_impl_lpdf( - "wiener_full_prec_lpdf", y, a, t0, w, v, sv, sw, st0, prec); +wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, + const T_v& v, const T_sv& sv, const T_sw& sw, + const T_st0& st0, double precision = 1e-4) { + return wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0, precision); } - } // namespace math } // namespace stan #endif diff --git a/test/unit/math/prim/functor/hcubature_test.cpp b/test/unit/math/prim/functor/hcubature_test.cpp index e153066c342..84fc31f5edb 100644 --- a/test/unit/math/prim/functor/hcubature_test.cpp +++ b/test/unit/math/prim/functor/hcubature_test.cpp @@ -60,7 +60,8 @@ stan::return_type_t f6(const T_x& x) { template stan::return_type_t f7(const T_x& x, double a) { const auto& x_arr = stan::math::as_array_or_scalar(x); - return stan::math::prod(a / (a + 1) * stan::math::square((a + 1) / (a + x_arr))); + return stan::math::prod(a / (a + 1) + * stan::math::square((a + 1) / (a + x_arr))); } } // namespace hcubature_test @@ -124,15 +125,17 @@ TEST(StanMath_hcubature_prim, test1) { std::vector a = {0.0}; std::vector b = {1.0}; std::vector reqRelError = {1e-4, 1e-6, 1e-7}; - test_integration(hcubature_test::f1>, std::make_tuple(), dim, - a, b, 6000, 0.0, reqRelError, 0.841471); + test_integration(hcubature_test::f1>, + std::make_tuple(), dim, + a, b, 6000, 0.0, reqRelError, 0.841471); dim = 2; a = {0.0, 0.0}; b = {1.0, 1.0}; reqRelError = {1e-4, 1e-6, 1e-7}; - test_integration(hcubature_test::f2>, std::make_tuple(), dim, - a, b, 6000, 0.0, reqRelError, 0.7080734); + test_integration(hcubature_test::f2>, + std::make_tuple(), dim, + a, b, 6000, 0.0, reqRelError, 0.7080734); reqRelError = {1e-4}; test_integration(hcubature_test::f3>, @@ -141,19 +144,22 @@ TEST(StanMath_hcubature_prim, test1) { // (Gaussian centered at 1/2) reqRelError = {1e-4, 1e-6, 1e-7}; - test_integration(hcubature_test::f4>, std::make_tuple(0.1), dim, - a, b, 6000, 0.0, reqRelError, 1); + test_integration(hcubature_test::f4>, + std::make_tuple(0.1), dim, + a, b, 6000, 0.0, reqRelError, 1); dim = 3; a = {0.0, 0.0, 0.0}; b = {1.0, 1.0, 1.0}; reqRelError = {1e-4, 1e-6}; - test_integration(hcubature_test::f5>, std::make_tuple(), dim, - a, b, 6000, 0.0, reqRelError, 1.00001); + test_integration(hcubature_test::f5>, + std::make_tuple(), dim, + a, b, 6000, 0.0, reqRelError, 1.00001); reqRelError = {1e-4, 1e-6, 1e-8}; - test_integration(hcubature_test::f6>, std::make_tuple(), dim, - a, b, 6000, 0.0, reqRelError, 1); + test_integration(hcubature_test::f6>, + std::make_tuple(), dim, + a, b, 6000, 0.0, reqRelError, 1); // (Tsuda's example) dim = 4; diff --git a/test/unit/math/rev/prob/wiener_full_prec_test.cpp b/test/unit/math/rev/prob/wiener_full_prec_test.cpp deleted file mode 100644 index 5acfc7461d8..00000000000 --- a/test/unit/math/rev/prob/wiener_full_prec_test.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include -#include -#include -#include - -#include -#include - -// CHECK THAT ALL VALID SCALAR TYPES ARE ACCEPTED -template -void check_scalar_types_2(F& f, double value, double res, double deriv) { - // - f: Function with a single parameter exposed, all others - // have to be scalars - // - value: value to be used for the parameter - // - res: expected result of calling `f` with `value` - // - deriv: expected result of partial of f with respect to the - // parameter in `value` - using stan::math::var; - double err_tol = 2e-6; - - // type double - EXPECT_NEAR(f(value), res, err_tol); - - // type var with derivative - var value_var = value; - var result_var = f(value_var); - result_var.grad(); - EXPECT_NEAR(value_of(result_var), res, err_tol); - EXPECT_NEAR(value_var.adj(), deriv, err_tol); -} - -TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { - // tests all parameter types individually, with other parameters - // set to double - using stan::math::wiener_full_prec_lpdf; - double err_tol = 2e-6; - - std::vector rt{1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector a{1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector v{1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector w{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; - std::vector t0{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0}; - std::vector sv{0.1, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0}; - std::vector sw{0.1, 0.1, 0, 0.1, 0, 0.1, 0, 0, 0}; - std::vector st0{0.1, 0, 0.1, 0.1, 0, 0, 0.1, 0, 0}; - - std::vector result{-2.426204, -2.710348, -2.422505, - -2.422795, -2.70665, -2.706812, - -2.419095, -2.703112, -3.790072}; - std::vector drt{-5.437337, -5.436798, -5.437332, -5.434799, -5.436791, - -5.434801, -5.434802, -5.434802, -5.434802}; - std::vector da{5.857318, 6.395031, 5.856484, 5.858549, 6.394195, - 6.396512, 5.857722, 6.395684, 8.369604}; - std::vector dv{-0.2428443, -0.2967977, -0.2436664, - -0.2446629, -0.297619, -0.2991696, - -0.2454931, -0.3, -0.5}; - std::vector dw{-0.9891369, -0.9887305, -0.9973428, - -0.9915453, -0.9969335, -0.991674, - -0.9997794, -0.9999097, -0.9999953}; - std::vector dt0{5.437337, 5.436798, 5.437332, 5.434799, 5.436791, - 5.434801, 5.434802, 5.434802, 5.434802}; - std::vector dsv{-0.06793703, -0.07047449, -0.06797882, - 0.0, -0.07050737, 0.0, - 0.0, 0.0, 0.0}; - std::vector dsw{-0.07406705, -0.07407386, 0.0, -0.07410901, 0.0, - -0.07410686, 0.0, 0.0, 0.0}; - std::vector dst0{2.963915, 0.0, 2.963912, 2.962338, 0.0, - 0.0, 2.96234, 0.0, 0.0}; - - for (int i = 0; i < result.size(); i++) { - // rt - auto f_rt = [=](auto value) { - return wiener_full_prec_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], - st0[i], 1e-6); - }; - check_scalar_types_2(f_rt, rt[i], result[i], drt[i]); - // a - auto f_a = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], - sw[i], st0[i], 1e-6); - }; - check_scalar_types_2(f_a, a[i], result[i], da[i]); - // v - auto f_v = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], - sw[i], st0[i], 1e-6); - }; - check_scalar_types_2(f_v, v[i], result[i], dv[i]); - // w - auto f_w = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], - sw[i], st0[i], 1e-6); - }; - check_scalar_types_2(f_w, w[i], result[i], dw[i]); - // t0 - auto f_t0 = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], - st0[i], 1e-6); - }; - check_scalar_types_2(f_t0, t0[i], result[i], dt0[i]); - // sv - auto f_sv = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], - st0[i], 1e-6); - }; - check_scalar_types_2(f_sv, sv[i], result[i], dsv[i]); - // sw - auto f_sw = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, - st0[i], 1e-6); - }; - check_scalar_types_2(f_sw, sw[i], result[i], dsw[i]); - // st0 - auto f_st0 = [=](auto value) { - return wiener_full_prec_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], - value, 1e-6); - }; - check_scalar_types_2(f_st0, st0[i], result[i], dst0[i]); - } -} diff --git a/test/unit/math/rev/prob/wiener_full_test.cpp b/test/unit/math/rev/prob/wiener_full_test.cpp index 45edcda9d8b..076f5fe282d 100644 --- a/test/unit/math/rev/prob/wiener_full_test.cpp +++ b/test/unit/math/rev/prob/wiener_full_test.cpp @@ -117,3 +117,93 @@ TEST(ProbWienerFull, wiener_full_all_scalar) { check_scalar_types(f_st0, st0[i], result[i], dst0[i]); } } + +TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { + // tests all parameter types individually, with other parameters + // set to double + using stan::math::wiener_full_lpdf; + double err_tol = 2e-6; + + std::vector rt{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector a{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector v{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector w{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; + std::vector t0{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0}; + std::vector sv{0.1, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0}; + std::vector sw{0.1, 0.1, 0, 0.1, 0, 0.1, 0, 0, 0}; + std::vector st0{0.1, 0, 0.1, 0.1, 0, 0, 0.1, 0, 0}; + + std::vector result{-2.426204, -2.710348, -2.422505, + -2.422795, -2.70665, -2.706812, + -2.419095, -2.703112, -3.790072}; + std::vector drt{-5.437337, -5.436798, -5.437332, -5.434799, -5.436791, + -5.434801, -5.434802, -5.434802, -5.434802}; + std::vector da{5.857318, 6.395031, 5.856484, 5.858549, 6.394195, + 6.396512, 5.857722, 6.395684, 8.369604}; + std::vector dv{-0.2428443, -0.2967977, -0.2436664, + -0.2446629, -0.297619, -0.2991696, + -0.2454931, -0.3, -0.5}; + std::vector dw{-0.9891369, -0.9887305, -0.9973428, + -0.9915453, -0.9969335, -0.991674, + -0.9997794, -0.9999097, -0.9999953}; + std::vector dt0{5.437337, 5.436798, 5.437332, 5.434799, 5.436791, + 5.434801, 5.434802, 5.434802, 5.434802}; + std::vector dsv{-0.06793703, -0.07047449, -0.06797882, + 0.0, -0.07050737, 0.0, + 0.0, 0.0, 0.0}; + std::vector dsw{-0.07406705, -0.07407386, 0.0, -0.07410901, 0.0, + -0.07410686, 0.0, 0.0, 0.0}; + std::vector dst0{2.963915, 0.0, 2.963912, 2.962338, 0.0, + 0.0, 2.96234, 0.0, 0.0}; + + for (int i = 0; i < result.size(); i++) { + // rt + auto f_rt = [=](auto value) { + return wiener_full_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], + st0[i], 1e-6); + }; + check_scalar_types(f_rt, rt[i], result[i], drt[i]); + // a + auto f_a = [=](auto value) { + return wiener_full_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], + sw[i], st0[i], 1e-6); + }; + check_scalar_types(f_a, a[i], result[i], da[i]); + // v + auto f_v = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], + sw[i], st0[i], 1e-6); + }; + check_scalar_types(f_v, v[i], result[i], dv[i]); + // w + auto f_w = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], + sw[i], st0[i], 1e-6); + }; + check_scalar_types(f_w, w[i], result[i], dw[i]); + // t0 + auto f_t0 = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], + st0[i], 1e-6); + }; + check_scalar_types(f_t0, t0[i], result[i], dt0[i]); + // sv + auto f_sv = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], + st0[i], 1e-6); + }; + check_scalar_types(f_sv, sv[i], result[i], dsv[i]); + // sw + auto f_sw = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, + st0[i], 1e-6); + }; + check_scalar_types(f_sw, sw[i], result[i], dsw[i]); + // st0 + auto f_st0 = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], + value, 1e-6); + }; + check_scalar_types(f_st0, st0[i], result[i], dst0[i]); + } +} From 62dc99bc5752395480a1de66838a1305a817f2ff Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Fri, 5 May 2023 08:37:19 -0400 Subject: [PATCH 026/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/functor/hcubature.hpp | 50 ++--- stan/math/prim/prob/wiener7_lpdf.hpp | 174 ++++++++---------- stan/math/prim/prob/wiener_full_lpdf.hpp | 13 +- .../unit/math/prim/functor/hcubature_test.cpp | 35 ++-- test/unit/math/rev/prob/wiener_full_test.cpp | 22 +-- 5 files changed, 130 insertions(+), 164 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 4533293f7ba..1420b0a4040 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -199,9 +199,8 @@ std::tuple gauss_kronrod(const F& integrand, const double& a, std::vector cm(1, 0); c[0] = 0.5 * (a + b); double delta = 0.5 * (b - a); - double f0 = math::apply([&](auto&&... args) { - return integrand(c, args...); - }, pars_tuple); + double f0 = math::apply([&](auto&&... args) { return integrand(c, args...); }, + pars_tuple); double I = f0 * wd7[7]; double Idash = f0 * gwd7[3]; @@ -209,12 +208,10 @@ std::tuple gauss_kronrod(const F& integrand, const double& a, double deltax = delta * xd7[i]; cp[0] = c[0] + deltax; cm[0] = c[0] - deltax; - double fx = math::apply([&](auto&&... args) { - return integrand(cp, args...); - }, pars_tuple); - double temp = math::apply([&](auto&&... args) { - return integrand(cm, args...); - }, pars_tuple); + double fx = math::apply( + [&](auto&&... args) { return integrand(cp, args...); }, pars_tuple); + double temp = math::apply( + [&](auto&&... args) { return integrand(cm, args...); }, pars_tuple); fx += temp; I += fx * wd7[i]; if (i % 2 == 1) { @@ -304,9 +301,8 @@ std::tuple integrate_GenzMalik( return std::make_tuple(0.0, 0.0, 0); } - double f1 = math::apply([&](auto&&... args) { - return integrand(c, args...); - }, pars_tuple); + double f1 = math::apply([&](auto&&... args) { return integrand(c, args...); }, + pars_tuple); double f2 = 0.0; double f3 = 0.0; double twelvef1 = 12 * f1; @@ -325,15 +321,13 @@ std::tuple integrate_GenzMalik( for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] + p2[j]; } - double f2i = math::apply([&](auto&&... args) { - return integrand(cc, args...); - }, pars_tuple); + double f2i = math::apply( + [&](auto&&... args) { return integrand(cc, args...); }, pars_tuple); for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] - p2[j]; } - double temp = math::apply([&](auto&&... args) { - return integrand(cc, args...); - }, pars_tuple); + double temp = math::apply( + [&](auto&&... args) { return integrand(cc, args...); }, pars_tuple); f2i += temp; for (std::size_t j = 0; j != dim; j++) { @@ -342,15 +336,13 @@ std::tuple integrate_GenzMalik( for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] + p3[j]; } - double f3i = math::apply([&](auto&&... args) { - return integrand(cc, args...); - }, pars_tuple); + double f3i = math::apply( + [&](auto&&... args) { return integrand(cc, args...); }, pars_tuple); for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] - p3[j]; } - temp = math::apply([&](auto&&... args) { - return integrand(cc, args...); - }, pars_tuple); + temp = math::apply([&](auto&&... args) { return integrand(cc, args...); }, + pars_tuple); f3i += temp; f2 += f2i; f3 += f3i; @@ -365,9 +357,8 @@ std::tuple integrate_GenzMalik( for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] + p4[j]; } - double temp = math::apply([&](auto&&... args) { - return integrand(cc, args...); - }, pars_tuple); + double temp = math::apply( + [&](auto&&... args) { return integrand(cc, args...); }, pars_tuple); f4 += temp; } double f5 = 0.0; @@ -380,9 +371,8 @@ std::tuple integrate_GenzMalik( for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] + p5[j]; } - double temp = math::apply([&](auto&&... args) { - return integrand(cc, args...); - }, pars_tuple); + double temp = math::apply( + [&](auto&&... args) { return integrand(cc, args...); }, pars_tuple); f5 += temp; } diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index 95d34507c0d..7889d98de01 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -120,13 +120,11 @@ template void assign_err(std::tuple& args_tuple, double err) { std::get<8>(args_tuple) = err; } -void assign_err(double arg, double err) { - arg = err; -} +void assign_err(double arg, double err) { arg = err; } template double estimate_with_err_check(const F& functor, double err, - ArgsTupleT&& args_tuple) { + ArgsTupleT&& args_tuple) { double result = math::apply([&](auto&&... args) { return functor(args...); }, args_tuple); double lfabs_result = log(fabs(result)); @@ -134,30 +132,29 @@ double estimate_with_err_check(const F& functor, double err, ArgsTupleT err_args_tuple = args_tuple; assign_err(std::get(err_args_tuple), err + lfabs_result); result = math::apply([&](auto&&... args) { return functor(args...); }, - err_args_tuple); + err_args_tuple); } return result; } template auto wiener7_integrand(const F& integrand_fun, double labstol_wiener5, - double lerr_bound, TArgs&&... args) { - const auto& wiener7_integrand_impl = [&](std::vector x, double y, - double a, double v, double w, - double t0, double sv, double sw, - double st0, double lerr, - auto&&... args_int) { - scalar_seq_view x_vec(x); - double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; - double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); - if (y - t0_ <= 0) { - return 0.0; - } else { - return integrand_fun(t0_, omega, y, a, v, w, t0, sv, sw, st0, lerr, - args_int...); - } - }; + double lerr_bound, TArgs&&... args) { + const auto& wiener7_integrand_impl + = [&](std::vector x, double y, double a, double v, double w, + double t0, double sv, double sw, double st0, double lerr, + auto&&... args_int) { + scalar_seq_view x_vec(x); + double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; + double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); + if (y - t0_ <= 0) { + return 0.0; + } else { + return integrand_fun(t0_, omega, y, a, v, w, t0, sv, sw, st0, lerr, + args_int...); + } + }; double err = labstol_wiener5 - lerr_bound + LOG_TWO + 1; const auto& functor = [&](auto&&... int_args) { @@ -166,34 +163,34 @@ auto wiener7_integrand(const F& integrand_fun, double labstol_wiener5, return estimate_with_err_check<0>(functor, err, std::make_tuple(args...)); } -double wiener7_lpdf_impl(double t0_, double omega, double y, double a, - double v, double w, double t0, double sv, - double sw, double st0, double lerr) { +double wiener7_lpdf_impl(double t0_, double omega, double y, double a, double v, + double w, double t0, double sv, double sw, double st0, + double lerr) { return exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); } double int_dtddiff(double t0_, double omega, double y, double a, double v, - double w, double t0, double sv, double sw, double st0, - double lerr) { + double w, double t0, double sv, double sw, double st0, + double lerr) { return dtdwiener5_for_7(y - t0_, a, -v, 1 - omega, sv, lerr); } double int_daddiff(double t0_, double omega, double y, double a, double v, - double w, double t0, double sv, double sw, double st0, - double lerr) { + double w, double t0, double sv, double sw, double st0, + double lerr) { return dadwiener5(y - t0_, a, v, omega, sv, lerr, 1); } double int_dvddiff(double t0_, double omega, double y, double a, double v, - double w, double t0, double sv, double sw, double st0, - double lerr) { + double w, double t0, double sv, double sw, double st0, + double lerr) { return dvdwiener5(y - t0_, a, v, omega, sv) - * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); + * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); } double int_dwddiff(double t0_, double omega, double y, double a, double v, - double w, double t0, double sv, double sw, double st0, - double lerr) { + double w, double t0, double sv, double sw, double st0, + double lerr) { return dwdwiener5(y - t0_, a, v, omega, sv, lerr, 1); } @@ -201,7 +198,7 @@ double int_dsvddiff(double t0_, double omega, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double lerr) { return dsvdwiener5(y - t0_, a, v, omega, sv) - * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); + * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); } double int_dswddiff(double t0_, double omega, double y, double a, double v, @@ -355,10 +352,9 @@ inline return_type_t wiener7_lpdf( const double sv_val = sv_vec.val(i); const double sw_val = sw_vec.val(i); const double st0_val = st0_vec.val(i); - const auto params = std::make_tuple(y_val, a_val, v_val, - w_val, t0_val, sv_val, - sw_val, st0_val, - labstol_wiener5 - LOG_TWO); + const auto params + = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, + st0_val, labstol_wiener5 - LOG_TWO); int dim = (sw_val != 0) + (st0_val != 0); check_positive(function_name, "(Inter-trial variability in A-priori bias) + " @@ -371,21 +367,19 @@ inline return_type_t wiener7_lpdf( xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); } - dens = internal::wiener7_integrand(internal::wiener7_lpdf_impl, - labstol_wiener5, lerror_bound_dens, - params, dim, xmin, xmax, Meval, - abstol, reltol / 2); + dens = internal::wiener7_integrand( + internal::wiener7_lpdf_impl, labstol_wiener5, lerror_bound_dens, params, + dim, xmin, xmax, Meval, abstol, reltol / 2); double log_dens = log(dens); ld += log_dens; // computation of derivative for t and precision check in order to give // the value as deriv_t to edge1 and as -deriv_t to edge5 double deriv_t_7 - = internal::wiener7_integrand(internal::int_dtddiff, - labstol_wiener5, - lerror_bound + log_dens, - params, dim, xmin, xmax, - Meval, abstol, reltol / 2) / dens; + = internal::wiener7_integrand(internal::int_dtddiff, labstol_wiener5, + lerror_bound + log_dens, params, dim, + xmin, xmax, Meval, abstol, reltol / 2) + / dens; // computation of derivatives and precision checks double deriv; @@ -394,38 +388,34 @@ inline return_type_t wiener7_lpdf( } if (!is_constant_all::value) { ops_partials.edge2_.partials_[i] - = internal::wiener7_integrand(internal::int_daddiff, - labstol_wiener5, - lerror_bound + log_dens, params, - dim, xmin, xmax, Meval, - abstol, reltol / 2) / dens; + = internal::wiener7_integrand(internal::int_daddiff, labstol_wiener5, + lerror_bound + log_dens, params, dim, + xmin, xmax, Meval, abstol, reltol / 2) + / dens; } if (!is_constant_all::value) { ops_partials.edge3_.partials_[i] = -deriv_t_7; } if (!is_constant_all::value) { ops_partials.edge4_.partials_[i] - = internal::wiener7_integrand(internal::int_dwddiff, - labstol_wiener5, - lerror_bound + log_dens, params, - dim, xmin, xmax, Meval, abstol, - reltol / 2) / dens; + = internal::wiener7_integrand(internal::int_dwddiff, labstol_wiener5, + lerror_bound + log_dens, params, dim, + xmin, xmax, Meval, abstol, reltol / 2) + / dens; } if (!is_constant_all::value) { ops_partials.edge5_.partials_[i] - = internal::wiener7_integrand(internal::int_dvddiff, - labstol_wiener5, - lerror_bound + log_dens, params, - dim, xmin, xmax, Meval, abstol, - reltol / 2) / dens; + = internal::wiener7_integrand(internal::int_dvddiff, labstol_wiener5, + lerror_bound + log_dens, params, dim, + xmin, xmax, Meval, abstol, reltol / 2) + / dens; } if (!is_constant_all::value) { ops_partials.edge6_.partials_[i] - = internal::wiener7_integrand(internal::int_dsvddiff, - labstol_wiener5, - lerror_bound + log_dens, params, - dim, xmin, xmax, Meval, abstol, - reltol / 2) / dens; + = internal::wiener7_integrand(internal::int_dsvddiff, labstol_wiener5, + lerror_bound + log_dens, params, dim, + xmin, xmax, Meval, abstol, reltol / 2) + / dens; } if (!is_constant_all::value) { if (sw_val == 0) { @@ -434,24 +424,19 @@ inline return_type_t wiener7_lpdf( double lower = w_val - sw_val / 2; double upper = w_val + sw_val / 2; - const auto& params_sw = std::make_tuple(y_val, a_val, v_val, - w_val, t0_val, sv_val, - 0, st0_val, - labstol_wiener5 - LOG_TWO, - (0 > lower) ? 0 : lower, - (1 < upper) ? 1 : upper, - sw_val); + const auto& params_sw = std::make_tuple( + y_val, a_val, v_val, w_val, t0_val, sv_val, 0, st0_val, + labstol_wiener5 - LOG_TWO, (0 > lower) ? 0 : lower, + (1 < upper) ? 1 : upper, sw_val); if (st0_val == 0) { - const auto& dswddif_args = std::tuple_cat(std::make_tuple(t0_val, 0), - params_sw); - deriv = internal::estimate_with_err_check<8>(internal::int_dswddiff, - lerror_bound - LOG_TWO, - dswddif_args); + const auto& dswddif_args + = std::tuple_cat(std::make_tuple(t0_val, 0), params_sw); + deriv = internal::estimate_with_err_check<8>( + internal::int_dswddiff, lerror_bound - LOG_TWO, dswddif_args); } else { - deriv = internal::wiener7_integrand(internal::int_dswddiff, - labstol_wiener5, lerror_bound, - params_sw, 1, xmin, xmax, - Meval, abstol, reltol / 2); + deriv = internal::wiener7_integrand( + internal::int_dswddiff, labstol_wiener5, lerror_bound, params_sw, + 1, xmin, xmax, Meval, abstol, reltol / 2); } ops_partials.edge7_.partials_[i] = deriv / dens - 1 / sw_val; } @@ -464,21 +449,20 @@ inline return_type_t wiener7_lpdf( ops_partials.edge8_.partials_[i] = -1 / st0_val; } else { if (sw_val == 0) { - const auto& dst0_params - = std::tuple_cat(std::make_tuple(t0_val + st0_val, w_val), params); + const auto& dst0_params = std::tuple_cat( + std::make_tuple(t0_val + st0_val, w_val), params); f = internal::estimate_with_err_check<8>(internal::wiener7_lpdf_impl, - lerror_bound + log(st0_val), - dst0_params); + lerror_bound + log(st0_val), + dst0_params); } else { double new_error = labstol_wiener5 - LOG_TWO; - const auto& params_st = std::make_tuple(y_val, a_val, v_val, w_val, - t0_val + st0_val, sv_val, - sw_val, 0, new_error); - f = internal::wiener7_integrand(internal::wiener7_lpdf_impl, - labstol_wiener5, lerror_bound, - params_st, 1, xmin, xmax, - Meval, abstol, reltol / 2); + const auto& params_st + = std::make_tuple(y_val, a_val, v_val, w_val, t0_val + st0_val, + sv_val, sw_val, 0, new_error); + f = internal::wiener7_integrand( + internal::wiener7_lpdf_impl, labstol_wiener5, lerror_bound, + params_st, 1, xmin, xmax, Meval, abstol, reltol / 2); } ops_partials.edge8_.partials_[i] = -1 / st0_val + f / st0_val / dens; } diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 7da065c541a..d78f8a3b537 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -9,7 +9,6 @@ namespace stan { namespace math { namespace internal { - //----------------------------------------------- } // namespace internal @@ -159,11 +158,9 @@ namespace internal { template inline return_type_t -wiener_full_lpdf(const T_y& y, - const T_a& a, const T_t0& t0, const T_w& w, - const T_v& v, const T_sv& sv, const T_sw& sw, - const T_st0& st0, - double precision = 1e-4) { +wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, + const T_v& v, const T_sv& sv, const T_sw& sw, const T_st0& st0, + double precision = 1e-4) { const char* function_name = "wiener_full_lpdf"; using T_sw_ref = ref_type_t; using T_st0_ref = ref_type_t; @@ -203,8 +200,8 @@ template inline return_type_t wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, - const T_v& v, const T_sv& sv, const T_sw& sw, - const T_st0& st0, double precision = 1e-4) { + const T_v& v, const T_sv& sv, const T_sw& sw, const T_st0& st0, + double precision = 1e-4) { return wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0, precision); } } // namespace math diff --git a/test/unit/math/prim/functor/hcubature_test.cpp b/test/unit/math/prim/functor/hcubature_test.cpp index 84fc31f5edb..26e0b647a91 100644 --- a/test/unit/math/prim/functor/hcubature_test.cpp +++ b/test/unit/math/prim/functor/hcubature_test.cpp @@ -29,9 +29,9 @@ stan::return_type_t f3(const T_x& x, double radius) { template stan::return_type_t f4(const T_x& x, double sigma) { + using stan::math::as_array_or_scalar; using stan::math::square; using stan::math::sum; - using stan::math::as_array_or_scalar; using stan::math::TWO_OVER_SQRT_PI; double numerator = sum(square(as_array_or_scalar(x) - 0.5)); @@ -41,8 +41,8 @@ stan::return_type_t f4(const T_x& x, double sigma) { template stan::return_type_t f5(const T_x& x) { - using stan::math::square; using stan::math::prod; + using stan::math::square; using stan::math::TWO_OVER_SQRT_PI; const auto& x_arr = stan::math::as_array_or_scalar(x); @@ -125,41 +125,36 @@ TEST(StanMath_hcubature_prim, test1) { std::vector a = {0.0}; std::vector b = {1.0}; std::vector reqRelError = {1e-4, 1e-6, 1e-7}; - test_integration(hcubature_test::f1>, - std::make_tuple(), dim, - a, b, 6000, 0.0, reqRelError, 0.841471); + test_integration(hcubature_test::f1>, std::make_tuple(), + dim, a, b, 6000, 0.0, reqRelError, 0.841471); dim = 2; a = {0.0, 0.0}; b = {1.0, 1.0}; reqRelError = {1e-4, 1e-6, 1e-7}; - test_integration(hcubature_test::f2>, - std::make_tuple(), dim, - a, b, 6000, 0.0, reqRelError, 0.7080734); + test_integration(hcubature_test::f2>, std::make_tuple(), + dim, a, b, 6000, 0.0, reqRelError, 0.7080734); reqRelError = {1e-4}; test_integration(hcubature_test::f3>, - std::make_tuple(0.50124145262344534123412), dim, - a, b, 10000, 0.0, reqRelError, 0.1972807); + std::make_tuple(0.50124145262344534123412), dim, a, b, 10000, + 0.0, reqRelError, 0.1972807); // (Gaussian centered at 1/2) reqRelError = {1e-4, 1e-6, 1e-7}; test_integration(hcubature_test::f4>, - std::make_tuple(0.1), dim, - a, b, 6000, 0.0, reqRelError, 1); + std::make_tuple(0.1), dim, a, b, 6000, 0.0, reqRelError, 1); dim = 3; a = {0.0, 0.0, 0.0}; b = {1.0, 1.0, 1.0}; reqRelError = {1e-4, 1e-6}; - test_integration(hcubature_test::f5>, - std::make_tuple(), dim, - a, b, 6000, 0.0, reqRelError, 1.00001); + test_integration(hcubature_test::f5>, std::make_tuple(), + dim, a, b, 6000, 0.0, reqRelError, 1.00001); reqRelError = {1e-4, 1e-6, 1e-8}; - test_integration(hcubature_test::f6>, - std::make_tuple(), dim, - a, b, 6000, 0.0, reqRelError, 1); + test_integration(hcubature_test::f6>, std::make_tuple(), + dim, a, b, 6000, 0.0, reqRelError, 1); // (Tsuda's example) dim = 4; @@ -167,6 +162,6 @@ TEST(StanMath_hcubature_prim, test1) { b = {1.0, 1.0, 1.0, 1.0}; reqRelError = {1e-4, 1e-6}; test_integration(hcubature_test::f7>, - std::make_tuple((1 + sqrt(10.0)) / 9.0), dim, - a, b, 20000, 0.0, reqRelError, 0.999998); + std::make_tuple((1 + sqrt(10.0)) / 9.0), dim, a, b, 20000, + 0.0, reqRelError, 0.999998); } diff --git a/test/unit/math/rev/prob/wiener_full_test.cpp b/test/unit/math/rev/prob/wiener_full_test.cpp index 076f5fe282d..3097afefefe 100644 --- a/test/unit/math/rev/prob/wiener_full_test.cpp +++ b/test/unit/math/rev/prob/wiener_full_test.cpp @@ -160,49 +160,49 @@ TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { // rt auto f_rt = [=](auto value) { return wiener_full_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], - st0[i], 1e-6); + st0[i], 1e-6); }; check_scalar_types(f_rt, rt[i], result[i], drt[i]); // a auto f_a = [=](auto value) { - return wiener_full_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], - sw[i], st0[i], 1e-6); + return wiener_full_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], + st0[i], 1e-6); }; check_scalar_types(f_a, a[i], result[i], da[i]); // v auto f_v = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], - sw[i], st0[i], 1e-6); + return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], + st0[i], 1e-6); }; check_scalar_types(f_v, v[i], result[i], dv[i]); // w auto f_w = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], - sw[i], st0[i], 1e-6); + return wiener_full_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], + st0[i], 1e-6); }; check_scalar_types(f_w, w[i], result[i], dw[i]); // t0 auto f_t0 = [=](auto value) { return wiener_full_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], - st0[i], 1e-6); + st0[i], 1e-6); }; check_scalar_types(f_t0, t0[i], result[i], dt0[i]); // sv auto f_sv = [=](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], - st0[i], 1e-6); + st0[i], 1e-6); }; check_scalar_types(f_sv, sv[i], result[i], dsv[i]); // sw auto f_sw = [=](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, - st0[i], 1e-6); + st0[i], 1e-6); }; check_scalar_types(f_sw, sw[i], result[i], dsw[i]); // st0 auto f_st0 = [=](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], - value, 1e-6); + value, 1e-6); }; check_scalar_types(f_st0, st0[i], result[i], dst0[i]); } From 31cccef8f812284cb9aca45da80de4e9197225a9 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 5 May 2023 15:44:06 +0300 Subject: [PATCH 027/179] Fix wiener_prec test --- .../math/prim/prob/wiener_full_prec_test.cpp | 159 ------------------ test/unit/math/prim/prob/wiener_full_test.cpp | 152 +++++++++++++++++ 2 files changed, 152 insertions(+), 159 deletions(-) delete mode 100644 test/unit/math/prim/prob/wiener_full_prec_test.cpp diff --git a/test/unit/math/prim/prob/wiener_full_prec_test.cpp b/test/unit/math/prim/prob/wiener_full_prec_test.cpp deleted file mode 100644 index e71d704a373..00000000000 --- a/test/unit/math/prim/prob/wiener_full_prec_test.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include -#include -#include -#include - -#include -#include - -TEST(mathPrimScalProbWienerFullPrecScal, valid) { - using stan::math::INFTY; - using stan::math::wiener_full_prec_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, - st0 = 0.1; - EXPECT_NO_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, sw, st0, 1e-4)); - rt = 5; - a = 1; - v = 1; - w = 0.5; - t0 = 0.0; - sv = 0.0; - sw = 0.0; - st0 = 0.0; - EXPECT_NO_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, sw, st0, 1e-4)); -} - -// rt -TEST(mathPrimScalProbWienerFullPrecScal, invalid_rt) { - using stan::math::INFTY; - using stan::math::wiener_full_prec_lpdf; - double a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(0, a, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(-1, a, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(INFTY, a, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(-INFTY, a, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(NAN, a, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); -} - -// a -TEST(mathPrimScalProbWienerFullPrecScal, invalid_a) { - using stan::math::INFTY; - using stan::math::wiener_full_prec_lpdf; - double rt = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, 0, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, -1, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, INFTY, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, -INFTY, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, NAN, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); -} - -// v -TEST(mathPrimScalProbWienerFullPrecScal, invalid_v) { - using stan::math::INFTY; - using stan::math::wiener_full_prec_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, - st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, INFTY, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, -INFTY, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, NAN, sv, sw, st0, 1e-4), - std::domain_error); -} - -// w -TEST(mathPrimScalProbWienerFullPrecScal, invalid_w) { - using stan::math::INFTY; - using stan::math::wiener_full_prec_lpdf; - double rt = 1, a = 1, v = -1, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, -0.1, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, 0, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, 1, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, 1.1, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, INFTY, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, -INFTY, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, NAN, v, sv, sw, st0, 1e-4), - std::domain_error); -} - -// t0 -TEST(mathPrimScalProbWienerFullPrecScal, invalid_t0) { - using stan::math::INFTY; - using stan::math::wiener_full_prec_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, 2, w, v, sv, sw, st0, 1e-4), - std::domain_error); // rt must be greater than t0 - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, -1, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, INFTY, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, -INFTY, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, NAN, w, v, sv, sw, st0, 1e-4), - std::domain_error); -} - -// sv -TEST(mathPrimScalProbWienerFullPrecScal, invalid_sv) { - using stan::math::INFTY; - using stan::math::wiener_full_prec_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, -1, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, INFTY, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, -INFTY, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, NAN, sw, st0, 1e-4), - std::domain_error); -} - -// sw -TEST(mathPrimScalProbWienerFullPrecScal, invalid_sw) { - using stan::math::INFTY; - using stan::math::wiener_full_prec_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, -1, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, 0.8, v, sv, 0.5, st0, 1e-4), - std::domain_error); // sw must be smaller than 2*(1-w) - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, 0.3, v, sv, 0.7, st0, 1e-4), - std::domain_error); // sw must be smaller than 2*w - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, INFTY, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, -INFTY, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, NAN, st0, 1e-4), - std::domain_error); -} - -// st0 -TEST(mathPrimScalProbWienerFullPrecScal, invalid_st0) { - using stan::math::INFTY; - using stan::math::wiener_full_prec_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2; - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, sw, -1, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, sw, INFTY, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, sw, -INFTY, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_prec_lpdf(rt, a, t0, w, v, sv, sw, NAN, 1e-4), - std::domain_error); -} diff --git a/test/unit/math/prim/prob/wiener_full_test.cpp b/test/unit/math/prim/prob/wiener_full_test.cpp index 40c25b02f9c..6f23c4d5f4f 100644 --- a/test/unit/math/prim/prob/wiener_full_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_test.cpp @@ -157,3 +157,155 @@ TEST(mathPrimScalProbWienerFullScal, invalid_st0) { EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, NAN), std::domain_error); } + +TEST(mathPrimScalProbWienerFullPrecScal, valid) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, + st0 = 0.1; + EXPECT_NO_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, st0, 1e-4)); + rt = 5; + a = 1; + v = 1; + w = 0.5; + t0 = 0.0; + sv = 0.0; + sw = 0.0; + st0 = 0.0; + EXPECT_NO_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, st0, 1e-4)); +} + +// rt +TEST(mathPrimScalProbWienerFullPrecScal, invalid_rt) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(0, a, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(-1, a, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(INFTY, a, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(-INFTY, a, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(NAN, a, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); +} + +// a +TEST(mathPrimScalProbWienerFullPrecScal, invalid_a) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, 0, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, -1, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, INFTY, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, -INFTY, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, NAN, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); +} + +// v +TEST(mathPrimScalProbWienerFullPrecScal, invalid_v) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, + st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, INFTY, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, -INFTY, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, NAN, sv, sw, st0, 1e-4), + std::domain_error); +} + +// w +TEST(mathPrimScalProbWienerFullPrecScal, invalid_w) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, -0.1, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 1, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 1.1, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, INFTY, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, -INFTY, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, NAN, v, sv, sw, st0, 1e-4), + std::domain_error); +} + +// t0 +TEST(mathPrimScalProbWienerFullPrecScal, invalid_t0) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, 2, w, v, sv, sw, st0, 1e-4), + std::domain_error); // rt must be greater than t0 + EXPECT_THROW(wiener_full_lpdf(rt, a, -1, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, INFTY, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, -INFTY, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, NAN, w, v, sv, sw, st0, 1e-4), + std::domain_error); +} + +// sv +TEST(mathPrimScalProbWienerFullPrecScal, invalid_sv) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, -1, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, INFTY, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, -INFTY, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, NAN, sw, st0, 1e-4), + std::domain_error); +} + +// sw +TEST(mathPrimScalProbWienerFullPrecScal, invalid_sw) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, -1, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0.8, v, sv, 0.5, st0, 1e-4), + std::domain_error); // sw must be smaller than 2*(1-w) + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0.3, v, sv, 0.7, st0, 1e-4), + std::domain_error); // sw must be smaller than 2*w + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, INFTY, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, -INFTY, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, NAN, st0, 1e-4), + std::domain_error); +} + +// st0 +TEST(mathPrimScalProbWienerFullPrecScal, invalid_st0) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2; + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, -1, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, INFTY, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, -INFTY, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, NAN, 1e-4), + std::domain_error); +} From 44bcbbac54f59b7e86eadb70a1f78c064249be17 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 5 May 2023 16:11:19 +0300 Subject: [PATCH 028/179] Multiple translation units fix --- stan/math/prim/prob/wiener7_lpdf.hpp | 18 +++++++++--------- stan/math/prim/prob/wiener_full_lpdf.hpp | 5 ----- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index 7889d98de01..58c9781f98e 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -117,10 +117,10 @@ inline double dtdwiener5_for_7(const double& y, const double& a, //----------------------------------------------- template -void assign_err(std::tuple& args_tuple, double err) { +inline void assign_err(std::tuple& args_tuple, double err) { std::get<8>(args_tuple) = err; } -void assign_err(double arg, double err) { arg = err; } +inline void assign_err(double arg, double err) { arg = err; } template double estimate_with_err_check(const F& functor, double err, @@ -163,45 +163,45 @@ auto wiener7_integrand(const F& integrand_fun, double labstol_wiener5, return estimate_with_err_check<0>(functor, err, std::make_tuple(args...)); } -double wiener7_lpdf_impl(double t0_, double omega, double y, double a, double v, +inline double wiener7_lpdf_impl(double t0_, double omega, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double lerr) { return exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); } -double int_dtddiff(double t0_, double omega, double y, double a, double v, +inline double int_dtddiff(double t0_, double omega, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double lerr) { return dtdwiener5_for_7(y - t0_, a, -v, 1 - omega, sv, lerr); } -double int_daddiff(double t0_, double omega, double y, double a, double v, +inline double int_daddiff(double t0_, double omega, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double lerr) { return dadwiener5(y - t0_, a, v, omega, sv, lerr, 1); } -double int_dvddiff(double t0_, double omega, double y, double a, double v, +inline double int_dvddiff(double t0_, double omega, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double lerr) { return dvdwiener5(y - t0_, a, v, omega, sv) * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); } -double int_dwddiff(double t0_, double omega, double y, double a, double v, +inline double int_dwddiff(double t0_, double omega, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double lerr) { return dwdwiener5(y - t0_, a, v, omega, sv, lerr, 1); } -double int_dsvddiff(double t0_, double omega, double y, double a, double v, +inline double int_dsvddiff(double t0_, double omega, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double lerr) { return dsvdwiener5(y - t0_, a, v, omega, sv) * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); } -double int_dswddiff(double t0_, double omega, double y, double a, double v, +inline double int_dswddiff(double t0_, double omega, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double lerr, double w_lower, double w_upper, double sw_mean) { diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index d78f8a3b537..2561c18bb94 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -7,11 +7,6 @@ namespace stan { namespace math { -namespace internal { - -//----------------------------------------------- - -} // namespace internal /** \ingroup prob_dists * The log of the first passage time density function for a (Wiener) From 91b88ec71102540c00bc1703276ec345bfad5dea Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Fri, 5 May 2023 09:12:31 -0400 Subject: [PATCH 029/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener7_lpdf.hpp | 44 ++++++++++++++-------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index 58c9781f98e..e79d1ffa03e 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -163,48 +163,48 @@ auto wiener7_integrand(const F& integrand_fun, double labstol_wiener5, return estimate_with_err_check<0>(functor, err, std::make_tuple(args...)); } -inline double wiener7_lpdf_impl(double t0_, double omega, double y, double a, double v, - double w, double t0, double sv, double sw, double st0, - double lerr) { +inline double wiener7_lpdf_impl(double t0_, double omega, double y, double a, + double v, double w, double t0, double sv, + double sw, double st0, double lerr) { return exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); } -inline double int_dtddiff(double t0_, double omega, double y, double a, double v, - double w, double t0, double sv, double sw, double st0, - double lerr) { +inline double int_dtddiff(double t0_, double omega, double y, double a, + double v, double w, double t0, double sv, double sw, + double st0, double lerr) { return dtdwiener5_for_7(y - t0_, a, -v, 1 - omega, sv, lerr); } -inline double int_daddiff(double t0_, double omega, double y, double a, double v, - double w, double t0, double sv, double sw, double st0, - double lerr) { +inline double int_daddiff(double t0_, double omega, double y, double a, + double v, double w, double t0, double sv, double sw, + double st0, double lerr) { return dadwiener5(y - t0_, a, v, omega, sv, lerr, 1); } -inline double int_dvddiff(double t0_, double omega, double y, double a, double v, - double w, double t0, double sv, double sw, double st0, - double lerr) { +inline double int_dvddiff(double t0_, double omega, double y, double a, + double v, double w, double t0, double sv, double sw, + double st0, double lerr) { return dvdwiener5(y - t0_, a, v, omega, sv) * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); } -inline double int_dwddiff(double t0_, double omega, double y, double a, double v, - double w, double t0, double sv, double sw, double st0, - double lerr) { +inline double int_dwddiff(double t0_, double omega, double y, double a, + double v, double w, double t0, double sv, double sw, + double st0, double lerr) { return dwdwiener5(y - t0_, a, v, omega, sv, lerr, 1); } -inline double int_dsvddiff(double t0_, double omega, double y, double a, double v, - double w, double t0, double sv, double sw, double st0, - double lerr) { +inline double int_dsvddiff(double t0_, double omega, double y, double a, + double v, double w, double t0, double sv, double sw, + double st0, double lerr) { return dsvdwiener5(y - t0_, a, v, omega, sv) * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); } -inline double int_dswddiff(double t0_, double omega, double y, double a, double v, - double w, double t0, double sv, double sw, double st0, - double lerr, double w_lower, double w_upper, - double sw_mean) { +inline double int_dswddiff(double t0_, double omega, double y, double a, + double v, double w, double t0, double sv, double sw, + double st0, double lerr, double w_lower, + double w_upper, double sw_mean) { double fl = exp(internal::dwiener5(y - t0_, a, v, w_lower, sv, lerr)); double fu = exp(internal::dwiener5(y - t0_, a, v, w_upper, sv, lerr)); return 0.5 * (fl + fu) / sw_mean; From fdbedd3a6324bdbe8bed29e7ec6c08b5789752dd Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 6 May 2023 14:40:18 +0300 Subject: [PATCH 030/179] Simplify wiener7 functions --- stan/math/prim/prob/wiener7_lpdf.hpp | 122 +++++++++++++-------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index e79d1ffa03e..69e52069667 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -163,42 +163,36 @@ auto wiener7_integrand(const F& integrand_fun, double labstol_wiener5, return estimate_with_err_check<0>(functor, err, std::make_tuple(args...)); } -inline double wiener7_lpdf_impl(double t0_, double omega, double y, double a, +enum class FunType { Density, GradT, GradA, GradV, GradW, GradSV }; + +template +inline double wiener7_impl(double t0_, double omega, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double lerr) { - return exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); -} - -inline double int_dtddiff(double t0_, double omega, double y, double a, - double v, double w, double t0, double sv, double sw, - double st0, double lerr) { - return dtdwiener5_for_7(y - t0_, a, -v, 1 - omega, sv, lerr); -} - -inline double int_daddiff(double t0_, double omega, double y, double a, - double v, double w, double t0, double sv, double sw, - double st0, double lerr) { - return dadwiener5(y - t0_, a, v, omega, sv, lerr, 1); -} - -inline double int_dvddiff(double t0_, double omega, double y, double a, - double v, double w, double t0, double sv, double sw, - double st0, double lerr) { - return dvdwiener5(y - t0_, a, v, omega, sv) - * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); -} - -inline double int_dwddiff(double t0_, double omega, double y, double a, - double v, double w, double t0, double sv, double sw, - double st0, double lerr) { - return dwdwiener5(y - t0_, a, v, omega, sv, lerr, 1); -} - -inline double int_dsvddiff(double t0_, double omega, double y, double a, - double v, double w, double t0, double sv, double sw, - double st0, double lerr) { - return dsvdwiener5(y - t0_, a, v, omega, sv) - * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); + double result; + switch(FunTypeEnum) { + case FunType::Density: + result = exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); + break; + case FunType::GradT: + result = dtdwiener5_for_7(y - t0_, a, -v, 1 - omega, sv, lerr); + break; + case FunType::GradA: + result = dadwiener5(y - t0_, a, v, omega, sv, lerr, 1); + break; + case FunType::GradW: + result = dwdwiener5(y - t0_, a, v, omega, sv, lerr, 1); + break; + case FunType::GradV: + result = dvdwiener5(y - t0_, a, v, omega, sv) + * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); + break; + case FunType::GradSV: + result = dsvdwiener5(y - t0_, a, v, omega, sv) + * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); + break; + } + return result; } inline double int_dswddiff(double t0_, double omega, double y, double a, @@ -368,7 +362,8 @@ inline return_type_t wiener7_lpdf( } dens = internal::wiener7_integrand( - internal::wiener7_lpdf_impl, labstol_wiener5, lerror_bound_dens, params, + internal::wiener7_impl, + labstol_wiener5, lerror_bound_dens, params, dim, xmin, xmax, Meval, abstol, reltol / 2); double log_dens = log(dens); ld += log_dens; @@ -376,9 +371,10 @@ inline return_type_t wiener7_lpdf( // computation of derivative for t and precision check in order to give // the value as deriv_t to edge1 and as -deriv_t to edge5 double deriv_t_7 - = internal::wiener7_integrand(internal::int_dtddiff, labstol_wiener5, - lerror_bound + log_dens, params, dim, - xmin, xmax, Meval, abstol, reltol / 2) + = internal::wiener7_integrand( + internal::wiener7_impl, + labstol_wiener5, lerror_bound + log_dens, params, dim, xmin, xmax, + Meval, abstol, reltol / 2) / dens; // computation of derivatives and precision checks @@ -388,9 +384,10 @@ inline return_type_t wiener7_lpdf( } if (!is_constant_all::value) { ops_partials.edge2_.partials_[i] - = internal::wiener7_integrand(internal::int_daddiff, labstol_wiener5, - lerror_bound + log_dens, params, dim, - xmin, xmax, Meval, abstol, reltol / 2) + = internal::wiener7_integrand( + internal::wiener7_impl, + labstol_wiener5, lerror_bound + log_dens, params, dim, + xmin, xmax, Meval, abstol, reltol / 2) / dens; } if (!is_constant_all::value) { @@ -398,23 +395,26 @@ inline return_type_t wiener7_lpdf( } if (!is_constant_all::value) { ops_partials.edge4_.partials_[i] - = internal::wiener7_integrand(internal::int_dwddiff, labstol_wiener5, - lerror_bound + log_dens, params, dim, - xmin, xmax, Meval, abstol, reltol / 2) + = internal::wiener7_integrand( + internal::wiener7_impl, + labstol_wiener5, lerror_bound + log_dens, params, dim, + xmin, xmax, Meval, abstol, reltol / 2) / dens; } if (!is_constant_all::value) { ops_partials.edge5_.partials_[i] - = internal::wiener7_integrand(internal::int_dvddiff, labstol_wiener5, - lerror_bound + log_dens, params, dim, - xmin, xmax, Meval, abstol, reltol / 2) + = internal::wiener7_integrand( + internal::wiener7_impl, + labstol_wiener5, lerror_bound + log_dens, params, dim, + xmin, xmax, Meval, abstol, reltol / 2) / dens; } if (!is_constant_all::value) { ops_partials.edge6_.partials_[i] - = internal::wiener7_integrand(internal::int_dsvddiff, labstol_wiener5, - lerror_bound + log_dens, params, dim, - xmin, xmax, Meval, abstol, reltol / 2) + = internal::wiener7_integrand( + internal::wiener7_impl, + labstol_wiener5, lerror_bound + log_dens, params, dim, + xmin, xmax, Meval, abstol, reltol / 2) / dens; } if (!is_constant_all::value) { @@ -429,10 +429,9 @@ inline return_type_t wiener7_lpdf( labstol_wiener5 - LOG_TWO, (0 > lower) ? 0 : lower, (1 < upper) ? 1 : upper, sw_val); if (st0_val == 0) { - const auto& dswddif_args - = std::tuple_cat(std::make_tuple(t0_val, 0), params_sw); deriv = internal::estimate_with_err_check<8>( - internal::int_dswddiff, lerror_bound - LOG_TWO, dswddif_args); + internal::int_dswddiff, lerror_bound - LOG_TWO, + std::tuple_cat(std::make_tuple(t0_val, 0), params_sw)); } else { deriv = internal::wiener7_integrand( internal::int_dswddiff, labstol_wiener5, lerror_bound, params_sw, @@ -449,20 +448,21 @@ inline return_type_t wiener7_lpdf( ops_partials.edge8_.partials_[i] = -1 / st0_val; } else { if (sw_val == 0) { - const auto& dst0_params = std::tuple_cat( - std::make_tuple(t0_val + st0_val, w_val), params); - f = internal::estimate_with_err_check<8>(internal::wiener7_lpdf_impl, - lerror_bound + log(st0_val), - dst0_params); + double t0_st0 = t0_val + st0_val; + f = internal::estimate_with_err_check<8>( + internal::wiener7_impl, + lerror_bound + log(st0_val), + std::tuple_cat(std::make_tuple(t0_st0, w_val), params)); } else { double new_error = labstol_wiener5 - LOG_TWO; const auto& params_st - = std::make_tuple(y_val, a_val, v_val, w_val, t0_val + st0_val, + = std::make_tuple(y_val, a_val, v_val, w_val, t0_st0, sv_val, sw_val, 0, new_error); f = internal::wiener7_integrand( - internal::wiener7_lpdf_impl, labstol_wiener5, lerror_bound, - params_st, 1, xmin, xmax, Meval, abstol, reltol / 2); + internal::wiener7_impl, + labstol_wiener5, lerror_bound, params_st, 1, xmin, + xmax, Meval, abstol, reltol / 2); } ops_partials.edge8_.partials_[i] = -1 / st0_val + f / st0_val / dens; } From bd726b7c48bcbb26c411f52e151d443a98b095b6 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 6 May 2023 14:42:28 +0300 Subject: [PATCH 031/179] cpplint --- stan/math/prim/prob/wiener7_lpdf.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index 69e52069667..8f1d7c2f8b1 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -170,7 +170,7 @@ inline double wiener7_impl(double t0_, double omega, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double lerr) { double result; - switch(FunTypeEnum) { + switch (FunTypeEnum) { case FunType::Density: result = exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); break; From baf04acfce9bc188ec9755ea3ac1c66b254342aa Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sat, 6 May 2023 07:43:56 -0400 Subject: [PATCH 032/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener7_lpdf.hpp | 65 +++++++++++++--------------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index 8f1d7c2f8b1..ef82710f9c8 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -167,8 +167,8 @@ enum class FunType { Density, GradT, GradA, GradV, GradW, GradSV }; template inline double wiener7_impl(double t0_, double omega, double y, double a, - double v, double w, double t0, double sv, - double sw, double st0, double lerr) { + double v, double w, double t0, double sv, double sw, + double st0, double lerr) { double result; switch (FunTypeEnum) { case FunType::Density: @@ -185,11 +185,11 @@ inline double wiener7_impl(double t0_, double omega, double y, double a, break; case FunType::GradV: result = dvdwiener5(y - t0_, a, v, omega, sv) - * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); + * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); break; case FunType::GradSV: result = dsvdwiener5(y - t0_, a, v, omega, sv) - * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); + * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); break; } return result; @@ -362,20 +362,18 @@ inline return_type_t wiener7_lpdf( } dens = internal::wiener7_integrand( - internal::wiener7_impl, - labstol_wiener5, lerror_bound_dens, params, - dim, xmin, xmax, Meval, abstol, reltol / 2); + internal::wiener7_impl, labstol_wiener5, + lerror_bound_dens, params, dim, xmin, xmax, Meval, abstol, reltol / 2); double log_dens = log(dens); ld += log_dens; // computation of derivative for t and precision check in order to give // the value as deriv_t to edge1 and as -deriv_t to edge5 - double deriv_t_7 - = internal::wiener7_integrand( - internal::wiener7_impl, - labstol_wiener5, lerror_bound + log_dens, params, dim, xmin, xmax, - Meval, abstol, reltol / 2) - / dens; + double deriv_t_7 = internal::wiener7_integrand( + internal::wiener7_impl, + labstol_wiener5, lerror_bound + log_dens, params, + dim, xmin, xmax, Meval, abstol, reltol / 2) + / dens; // computation of derivatives and precision checks double deriv; @@ -385,9 +383,9 @@ inline return_type_t wiener7_lpdf( if (!is_constant_all::value) { ops_partials.edge2_.partials_[i] = internal::wiener7_integrand( - internal::wiener7_impl, - labstol_wiener5, lerror_bound + log_dens, params, dim, - xmin, xmax, Meval, abstol, reltol / 2) + internal::wiener7_impl, + labstol_wiener5, lerror_bound + log_dens, params, dim, xmin, + xmax, Meval, abstol, reltol / 2) / dens; } if (!is_constant_all::value) { @@ -396,25 +394,25 @@ inline return_type_t wiener7_lpdf( if (!is_constant_all::value) { ops_partials.edge4_.partials_[i] = internal::wiener7_integrand( - internal::wiener7_impl, - labstol_wiener5, lerror_bound + log_dens, params, dim, - xmin, xmax, Meval, abstol, reltol / 2) + internal::wiener7_impl, + labstol_wiener5, lerror_bound + log_dens, params, dim, xmin, + xmax, Meval, abstol, reltol / 2) / dens; } if (!is_constant_all::value) { ops_partials.edge5_.partials_[i] = internal::wiener7_integrand( - internal::wiener7_impl, - labstol_wiener5, lerror_bound + log_dens, params, dim, - xmin, xmax, Meval, abstol, reltol / 2) + internal::wiener7_impl, + labstol_wiener5, lerror_bound + log_dens, params, dim, xmin, + xmax, Meval, abstol, reltol / 2) / dens; } if (!is_constant_all::value) { ops_partials.edge6_.partials_[i] = internal::wiener7_integrand( - internal::wiener7_impl, - labstol_wiener5, lerror_bound + log_dens, params, dim, - xmin, xmax, Meval, abstol, reltol / 2) + internal::wiener7_impl, + labstol_wiener5, lerror_bound + log_dens, params, dim, xmin, + xmax, Meval, abstol, reltol / 2) / dens; } if (!is_constant_all::value) { @@ -450,19 +448,18 @@ inline return_type_t wiener7_lpdf( if (sw_val == 0) { double t0_st0 = t0_val + st0_val; f = internal::estimate_with_err_check<8>( - internal::wiener7_impl, - lerror_bound + log(st0_val), - std::tuple_cat(std::make_tuple(t0_st0, w_val), params)); + internal::wiener7_impl, + lerror_bound + log(st0_val), + std::tuple_cat(std::make_tuple(t0_st0, w_val), params)); } else { double new_error = labstol_wiener5 - LOG_TWO; - const auto& params_st - = std::make_tuple(y_val, a_val, v_val, w_val, t0_st0, - sv_val, sw_val, 0, new_error); + const auto& params_st = std::make_tuple( + y_val, a_val, v_val, w_val, t0_st0, sv_val, sw_val, 0, new_error); f = internal::wiener7_integrand( - internal::wiener7_impl, - labstol_wiener5, lerror_bound, params_st, 1, xmin, - xmax, Meval, abstol, reltol / 2); + internal::wiener7_impl, + labstol_wiener5, lerror_bound, params_st, 1, xmin, xmax, Meval, + abstol, reltol / 2); } ops_partials.edge8_.partials_[i] = -1 / st0_val + f / st0_val / dens; } From cc5f66b3a783fecc995a04893d67da8bb8dd45a2 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 6 May 2023 14:49:50 +0300 Subject: [PATCH 033/179] Scope --- stan/math/prim/prob/wiener7_lpdf.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index ef82710f9c8..3dd2f8b6d6f 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -445,8 +445,8 @@ inline return_type_t wiener7_lpdf( } else if (y_val - (t0_val + st0_val) <= 0) { ops_partials.edge8_.partials_[i] = -1 / st0_val; } else { + double t0_st0 = t0_val + st0_val; if (sw_val == 0) { - double t0_st0 = t0_val + st0_val; f = internal::estimate_with_err_check<8>( internal::wiener7_impl, lerror_bound + log(st0_val), From 29a17dd6a3e41c6a097d50c07f240c84f29a73e9 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 6 May 2023 19:31:57 +0300 Subject: [PATCH 034/179] First pass refactor wiener5 --- stan/math/prim/prob/wiener5_lpdf.hpp | 184 ++++++++++++--------------- stan/math/prim/prob/wiener7_lpdf.hpp | 2 - 2 files changed, 83 insertions(+), 103 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 132b713765d..83ce47ec4e7 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -7,14 +7,13 @@ namespace stan { namespace math { namespace internal { -// calculate density in log -inline double dwiener5(const double& y, const double& a, const double& vn, - const double& wn, const double& sv, const double& err) { - double kll, kss, ans, v, w; - w = 1.0 - wn; - v = -vn; +enum class FunType { Density, GradT, GradA, GradV, GradW, GradSV }; +template +inline auto wiener5_helper(const double& y, const double& a, const double& vn, + const double& wn, const double& sv, const double& err) { + double w = 1.0 - wn; + double v = -vn; double y_asq = y / square(a); - ans = 0.0; // calculate the number of terms needed for short t double lg1; @@ -27,23 +26,68 @@ inline double dwiener5(const double& y, const double& a, const double& vn, } else { lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - 2 * log(a); } + double es = (err - lg1); - double K1 = (sqrt(2.0 * y_asq) + w) / 2.0; - double u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log(y_asq) + 2.0 * (es)); - double arg = -y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + if (FunTypeEnum == FunType::GradT) { + es += 2.0 * log(a); + } + double K1, u_eps, arg; + if (FunTypeEnum == FunType::Density) { + K1 = (sqrt(2.0 * y_asq) + w) / 2.0; + u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log(y_asq) + 2.0 * (es)); + arg = -y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + } else { + K1 = (sqrt(3.0 * y_asq) + w) / 2.0; + if (FunTypeEnum == FunType::GradW) { + u_eps + = fmin(-1.0, 2.0 * (err - lg1) + LOG_TWO + LOG_PI + 2.0 * log(y_asq)); + } else { + u_eps = fmin( + -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(y_asq) + 2.0 * es) / 3.0); + } + arg = -3.0 * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + } + double K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; - kss = ceil(fmax(K1, K2)); + double kss = ceil(fmax(K1, K2)); // calculate the number of terms needed for large t double el = es; - K1 = 1.0 / (pi() * sqrt(y_asq)); - K2 = 0.0; - double two_log_piy = -2.0 * (log(pi() * y_asq) + el); static const double PISQ = square(pi()); // pi*pi - if (two_log_piy >= 0) { - K2 = sqrt(two_log_piy / (PISQ * y_asq)); + if (FunTypeEnum == FunType::Density) { + K1 = 1.0 / (pi() * sqrt(y_asq)); + double two_log_piy = -2.0 * (log(pi() * y_asq) + el); + K2 = (two_log_piy >= 0) ? sqrt(two_log_piy / (PISQ * y_asq)) : 0.0; + } else if (FunTypeEnum == FunType::GradT) { + K1 = sqrt(3.0 / y_asq) / pi(); + u_eps = fmin(-1.0, el + log(0.6) + LOG_PI + 2.0 * log(y_asq)); + arg = -2.0 / PISQ / y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + K2 = (arg > 0) ? sqrt(arg) : K1; + } else if (FunTypeEnum == FunType::GradW) { + K1 = sqrt(2.0 / y_asq) / pi(); + static const double TWO_LOG_PI = 2.0 * LOG_PI; + u_eps = fmin( + -1.0, log(4.0 / 9.0) + TWO_LOG_PI + 3.0 * log(y_asq) + 2.0 * (err - lg1)); + arg = -(u_eps - sqrt(-2.0 * u_eps - 2.0)); + K2 = (arg > 0) ? 1.0 / pi() * sqrt(arg / y_asq) : K1; } - kll = ceil(fmax(K1, K2)); + double kll = ceil(fmax(K1, K2)); + return std::make_tuple(kss, kll, lg1); +} + +// calculate density in log +inline double dwiener5(const double& y, const double& a, const double& vn, + const double& wn, const double& sv, const double& err) { + double kll, kss, ans, v, w; + w = 1.0 - wn; + v = -vn; + double y_asq = y / square(a); + ans = 0.0; + + // calculate the number of terms needed for short t + double lg1; + + std::forward_as_tuple(kss, kll, lg1) = wiener5_helper(y, a, vn, wn, sv, err); // if small t is better if (2 * kss <= kll) { @@ -110,44 +154,22 @@ inline double dtdwiener5(const double& y, const double& a, const double& vn, * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - 2 * a * v * w) + square(v)) / square(one_plus_svsqr_y); - lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 - / one_plus_svsqr_y - - la - 0.5 * log(one_plus_svsqr_y); } else { ans0 = -0.5 * square(v); - lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - la; } - double factor = lg1 - la; - double ld = dwiener5(y, a, vn, wn, sv, - err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); - - // calculate the number of terms kss needed for small t - double es = err - lg1; - es = es + la; - double K1 = (sqrt(3.0 * y_asq) + w) / 2.0; - double u_eps = fmin( - -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(y_asq) + 2.0 * es) / 3.0); - double arg = -3.0 * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - double K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; - kss = ceil(fmax(K1, K2)); - - // calculate number of terms kll needed for large t - double el = err - lg1; - el = el + la; - K1 = sqrt(3.0 / y_asq) / pi(); - u_eps = fmin(-1.0, el + log(0.6) + LOG_PI + 2.0 * log(y_asq)); - static const double PISQ = square(pi()); // pi*pi - arg = -2.0 / PISQ / y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - double kl = (arg > 0) ? sqrt(arg) : K1; - kll = ceil(fmax(kl, K1)); double erg; double newsign = 1; double fplus = NEGATIVE_INFTY; double fminus = NEGATIVE_INFTY; + std::forward_as_tuple(kss, kll, lg1) = wiener5_helper(y, a, vn, wn, sv, err); + double factor = lg1 - la; + double ld = dwiener5(y, a, vn, wn, sv, + err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); + // if small t is better - if (2 * kss < kll) { + if (2 * kss <= kll) { // calculate terms of the sum for small t double twoy = 2.0 * y_asq; if (static_cast(kss) > 0) { @@ -219,47 +241,25 @@ inline double dadwiener5(const double& y, const double& a, const double& vn, double sv_sqr = square(sv); double one_plus_svsqr_y = (1 + sv_sqr * y); ans0 = (-v * w + sv_sqr * square(w) * a) / one_plus_svsqr_y; - lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 - / one_plus_svsqr_y - - 2 * la - 0.5 * log(one_plus_svsqr_y); } else { ans0 = -v * w; - lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - 2 * la; } - double factor = lg1 - 3 * la; - double ld - = dwiener5(y, a, vn, wn, sv, - err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); - - // calculate the number of terms kss needed for small t - double es = err - lg1; - es = es + la; - es = es - LOG_TWO + 2.0 * la - ly; - double K1 = (sqrt(3.0 * y_asq) + w) / 2.0; - double u_eps = fmin( - -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(y_asq) + 2.0 * es) / 3.0); - double arg = -3.0 * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - double K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; - kss = ceil(fmax(K1, K2)); - - // calculate number of terms kll needed for large t - double el = err - lg1; - el = el + la; - el = el - LOG_TWO + 2.0 * la - ly; - K1 = sqrt(3.0 / y_asq) / pi(); - u_eps = fmin(-1.0, el + log(0.6) + LOG_PI + 2.0 * log(y_asq)); - static const double PISQ = square(pi()); // pi*pi - arg = -2.0 / PISQ / y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - double kl = (arg > 0) ? sqrt(arg) : K1; - kll = ceil(fmax(kl, K1)); double erg; double newsign = 1; double fplus = NEGATIVE_INFTY; double fminus = NEGATIVE_INFTY; + double lg2; + bool small_t; + std::forward_as_tuple(kss, kll, lg1) = wiener5_helper(y, a, vn, wn, sv, err); + double factor = lg1 - 3 * la; + double ld + = dwiener5(y, a, vn, wn, sv, + err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); + // if small t is better - if (2 * kss < kll) { + if (2 * kss <= kll) { // calculate terms of the sum for short t double twoy = 2.0 * y_asq; if (static_cast(kss) > 0) { @@ -349,41 +349,23 @@ inline double dwdwiener5(const double& y, const double& a, const double& vn, double sv_sqr = square(sv); double one_plus_svsqr_y = (1 + sv_sqr * y); ans0 = (-v * a + sv_sqr * square(a) * w) / one_plus_svsqr_y; - lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 - / one_plus_svsqr_y - - 2 * log(a) - 0.5 * log(one_plus_svsqr_y); } else { ans0 = -v * a; - lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - 2 * log(a); } - double ld = dwiener5(y, a, vn, wn, sv, err - log(fabs(ans0))); - double ls = -lg1 + ld; - double ll = -lg1 + ld; - // calculate the number of terms kss needed for small t - double K1 = (sqrt(3.0 * y_asq) + w) / 2.0; - double u_eps - = fmin(-1.0, 2.0 * (err - lg1) + LOG_TWO + LOG_PI + 2.0 * log(y_asq)); - double arg = -y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - double K2 = (arg > 0) ? 0.5 * (sqrt(arg) + w) : K1; - kss = ceil(fmax(K1, K2)); - - // calculate number of terms kll needed for large t - K1 = sqrt(2.0 / y_asq) / pi(); - static const double TWO_LOG_PI = 2.0 * LOG_PI; - u_eps = fmin( - -1.0, log(4.0 / 9.0) + TWO_LOG_PI + 3.0 * log(y_asq) + 2.0 * (err - lg1)); - arg = -(u_eps - sqrt(-2.0 * u_eps - 2.0)); - K2 = (arg > 0) ? 1.0 / pi() * sqrt(arg / y_asq) : K1; - kll = ceil(fmax(K1, K2)); double erg; double newsign = 1; double fplus = NEGATIVE_INFTY; double fminus = NEGATIVE_INFTY; + std::forward_as_tuple(kss, kll, lg1) = wiener5_helper(y, a, vn, wn, sv, err); + double ld = dwiener5(y, a, vn, wn, sv, err - log(fabs(ans0))); + double ls = -lg1 + ld; + double ll = -lg1 + ld; + // if small t is better - if (2 * kss < kll) { + if (2 * kss <= kll) { // calculate terms of the sum for short t double twoy = 2.0 * y_asq; for (size_t k = static_cast(kss); k >= 1; k--) { @@ -442,7 +424,7 @@ inline double dwdwiener5(const double& y, const double& a, const double& vn, } else { erg = log_diff_exp(fplus, fminus); } - ans = ans0 + newsign * exp(erg - ll + TWO_LOG_PI); + ans = ans0 + newsign * exp(erg - ll + 2 * LOG_PI); } if (normal_or_log == 1) { return ans * sign * exp(ld); // derivative of f for hcubature diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index 3dd2f8b6d6f..0e2f2d321ed 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -163,8 +163,6 @@ auto wiener7_integrand(const F& integrand_fun, double labstol_wiener5, return estimate_with_err_check<0>(functor, err, std::make_tuple(args...)); } -enum class FunType { Density, GradT, GradA, GradV, GradW, GradSV }; - template inline double wiener7_impl(double t0_, double omega, double y, double a, double v, double w, double t0, double sv, double sw, From b2fa83efbc137f209e9a884031b60554f4b1542c Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sun, 7 May 2023 15:58:35 +0300 Subject: [PATCH 035/179] First pass simplify wiener5 refactor --- stan/math/prim/prob/wiener5_lpdf.hpp | 613 +++++++++++---------------- stan/math/prim/prob/wiener7_lpdf.hpp | 21 - 2 files changed, 258 insertions(+), 376 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 83ce47ec4e7..6e9830b0f76 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -7,30 +7,173 @@ namespace stan { namespace math { namespace internal { +template +inline void assign_err(std::tuple& args_tuple, double err) { + std::get<8>(args_tuple) = err; +} +inline void assign_err(double arg, double err) { arg = err; } + +template +double estimate_with_err_check(const F& functor, double err, + ArgsTupleT&& args_tuple, + bool log_result = true) { + double result = math::apply([&](auto&&... args) { return functor(args...); }, + args_tuple); + double lfabs_result = log_result ? log(fabs(result)) : fabs(result); + if (lfabs_result < err) { + ArgsTupleT err_args_tuple = args_tuple; + assign_err(std::get(err_args_tuple), err + lfabs_result); + result = math::apply([&](auto&&... args) { return functor(args...); }, + err_args_tuple); + } + return result; +} + enum class FunType { Density, GradT, GradA, GradV, GradW, GradSV }; + +inline auto erg_sign(double fminus, double fplus) { + double erg = (fplus < fminus) ? log_diff_exp(fminus, fplus) + : log_diff_exp(fplus, fminus); + int newsign = (fplus < fminus) ? -1 : 1; + return std::make_tuple(erg, newsign); +} + template -inline auto wiener5_helper(const double& y, const double& a, const double& vn, - const double& wn, const double& sv, const double& err) { +inline auto calc_erg_kss(const double& y, const double& a, const double& vn, + const double& wn, size_t kss) { double w = 1.0 - wn; double v = -vn; double y_asq = y / square(a); - // calculate the number of terms needed for short t + double fplus = NEGATIVE_INFTY; + double fminus = NEGATIVE_INFTY; + double twoy = 2.0 * y_asq; + + if (FunTypeEnum != FunType::GradW) { + double mult = (FunTypeEnum == FunType::Density) ? 1 : 3; + if (kss > 0) { + for (size_t k = kss; k >= 1; k--) { + double w_plus_2k = w + 2.0 * k; + double w_minus_2k = w - 2.0 * k; + + fplus = log_sum_exp(mult * log(w_plus_2k) - square(w_plus_2k) / twoy, + fplus); + fminus + = log_sum_exp(mult * log(-w_minus_2k) - square(w_minus_2k) / twoy, + fminus); + } + } + fplus = log_sum_exp(mult * log(w) - square(w) / twoy, fplus); + } else { + for (size_t k = kss; k >= 1; k--) { + double sqrt_w_plus_2k = square(w + 2 * k); + double sqrt_w_minus_2k = square(w - 2 * k); + double wp2k_minusy = sqrt_w_plus_2k - y_asq; + double wm2k_minusy = sqrt_w_minus_2k - y_asq; + if (wp2k_minusy > 0) { + fplus = log_sum_exp(log(wp2k_minusy) - sqrt_w_plus_2k / twoy, fplus); + } else if (wp2k_minusy < 0) { + fminus + = log_sum_exp(log(-(wp2k_minusy)) - sqrt_w_plus_2k / twoy, fminus); + } + if (wm2k_minusy > 0) { + fplus = log_sum_exp(log(wm2k_minusy) - sqrt_w_minus_2k / twoy, fplus); + } else if (wm2k_minusy < 0) { + fminus + = log_sum_exp(log(-(wm2k_minusy)) - sqrt_w_minus_2k / twoy, fminus); + } + } + double sqr_w = square(w); + double sqrt_w_plus_2k = sqr_w - y_asq; + if (sqrt_w_plus_2k > 0) { + fplus = log_sum_exp(log(sqrt_w_plus_2k) - sqr_w / twoy, fplus); + } else if (sqrt_w_plus_2k < 0) { + fminus = log_sum_exp(log(-(sqrt_w_plus_2k)) - sqr_w / twoy, fminus); + } + } + return erg_sign(fminus, fplus); +} + +template +inline auto calc_erg_kll(const double& y, const double& a, const double& vn, + const double& wn, size_t kll) { + double w = 1.0 - wn; + double v = -vn; + double y_asq = y / square(a); + + double fplus = NEGATIVE_INFTY; + double fminus = NEGATIVE_INFTY; + double twoy = 2.0 * y_asq; + double erg; + int newsign = 1; + + double mult; + if (FunTypeEnum == FunType::Density) { + mult = 1; + } else if (FunTypeEnum == FunType::GradW) { + mult = 2; + } else { + mult = 3; + } + double halfy = y_asq / 2.0; + for (size_t k = kll; k >= 1; k--) { + double pi_k = k * pi(); + double check = (FunTypeEnum == FunType::GradW) ? cos(pi_k * w) + : sin(pi_k * w); + if (check > 0) { + fplus = log_sum_exp(mult * log(k) - square(pi_k) * halfy + log(check), + fplus); + } else { + fminus + = log_sum_exp(mult * log(k) - square(pi_k) * halfy + log(-check), + fminus); + } + } + return erg_sign(fminus, fplus); +} + +template +inline auto wiener5_helper(const double& y, const double& a, const double& vn, + const double& wn, const double& sv, + const double& err, const KSSFuncType& kss_functor, + const KLLFuncType& kll_functor) { + double w = 1.0 - wn; + double v = -vn; + double sv_sqr = square(sv); + double one_plus_svsqr_y = 1 + sv_sqr * y; double lg1; if (sv != 0) { - double sv_sqr = square(sv); - double one_plus_svsqr_y = 1 + sv_sqr * y; lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 / one_plus_svsqr_y - - 2 * log(a) - 0.5 * log(one_plus_svsqr_y); + - 2 * log(a) - 0.5 * log(one_plus_svsqr_y); } else { lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - 2 * log(a); } + double ans0 = 0; + if (FunTypeEnum != FunType::Density) { + double var_a = (FunTypeEnum == FunType::GradA) ? w : a; + double var_b = (FunTypeEnum == FunType::GradA) ? a : w; + if (sv != 0) { + if (FunTypeEnum == FunType::GradT) { + ans0 = -0.5 + * (square(sv_sqr) * (y + square(a * w)) + + sv_sqr * (1 - 2 * a * v * w) + square(v)) + / square(one_plus_svsqr_y); + } else { + ans0 = (-v * var_a + sv_sqr * square(var_a) * var_b) + / one_plus_svsqr_y; + } + } else { + ans0 = (FunTypeEnum == FunType::GradT) ? -0.5 * square(v) : -v * var_a; + } + } double es = (err - lg1); if (FunTypeEnum == FunType::GradT) { es += 2.0 * log(a); } + double y_asq = y / square(a); + double K1, u_eps, arg; if (FunTypeEnum == FunType::Density) { K1 = (sqrt(2.0 * y_asq) + w) / 2.0; @@ -40,96 +183,64 @@ inline auto wiener5_helper(const double& y, const double& a, const double& vn, K1 = (sqrt(3.0 * y_asq) + w) / 2.0; if (FunTypeEnum == FunType::GradW) { u_eps - = fmin(-1.0, 2.0 * (err - lg1) + LOG_TWO + LOG_PI + 2.0 * log(y_asq)); + = fmin(-1.0, 2.0 * es + LOG_TWO + LOG_PI + 2.0 * log(y_asq)); } else { - u_eps = fmin( - -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(y_asq) + 2.0 * es) / 3.0); + u_eps = fmin(-1.0, + (log(8.0 / 27.0) + LOG_PI + 4.0 * log(y_asq) + 2.0 * es) + / 3.0); } arg = -3.0 * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); } double K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; - double kss = ceil(fmax(K1, K2)); + size_t kss = static_cast(ceil(fmax(K1, K2))); - // calculate the number of terms needed for large t - double el = es; static const double PISQ = square(pi()); // pi*pi if (FunTypeEnum == FunType::Density) { K1 = 1.0 / (pi() * sqrt(y_asq)); - double two_log_piy = -2.0 * (log(pi() * y_asq) + el); + double two_log_piy = -2.0 * (log(pi() * y_asq) + es); K2 = (two_log_piy >= 0) ? sqrt(two_log_piy / (PISQ * y_asq)) : 0.0; } else if (FunTypeEnum == FunType::GradT) { K1 = sqrt(3.0 / y_asq) / pi(); - u_eps = fmin(-1.0, el + log(0.6) + LOG_PI + 2.0 * log(y_asq)); + u_eps = fmin(-1.0, es + log(0.6) + LOG_PI + 2.0 * log(y_asq)); arg = -2.0 / PISQ / y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); K2 = (arg > 0) ? sqrt(arg) : K1; } else if (FunTypeEnum == FunType::GradW) { K1 = sqrt(2.0 / y_asq) / pi(); - static const double TWO_LOG_PI = 2.0 * LOG_PI; u_eps = fmin( - -1.0, log(4.0 / 9.0) + TWO_LOG_PI + 3.0 * log(y_asq) + 2.0 * (err - lg1)); + -1.0, log(4.0 / 9.0) + 2.0 * LOG_PI + 3.0 * log(y_asq) + 2.0 * es); arg = -(u_eps - sqrt(-2.0 * u_eps - 2.0)); K2 = (arg > 0) ? 1.0 / pi() * sqrt(arg / y_asq) : K1; } - double kll = ceil(fmax(K1, K2)); - return std::make_tuple(kss, kll, lg1); + size_t kll = static_cast(ceil(fmax(K1, K2))); + + double erg; + int newsign; + if (2 * kss <= kll) { + std::forward_as_tuple(erg, newsign) + = calc_erg_kss(y, a, vn, wn, kss); + return kss_functor(erg, newsign, lg1, ans0); + } else { + std::forward_as_tuple(erg, newsign) + = calc_erg_kll(y, a, vn, wn, kll); + return kll_functor(erg, newsign, lg1, ans0); + } } // calculate density in log inline double dwiener5(const double& y, const double& a, const double& vn, const double& wn, const double& sv, const double& err) { - double kll, kss, ans, v, w; - w = 1.0 - wn; - v = -vn; - double y_asq = y / square(a); - ans = 0.0; - - // calculate the number of terms needed for short t - double lg1; - - std::forward_as_tuple(kss, kll, lg1) = wiener5_helper(y, a, vn, wn, sv, err); - - // if small t is better - if (2 * kss <= kll) { - double fplus = NEGATIVE_INFTY; - double fminus = NEGATIVE_INFTY; - double twoy = 2.0 * y_asq; - if (static_cast(kss) > 0) { - for (size_t k = static_cast(kss); k >= 1; k--) { - double w_plus_2k = w + 2.0 * k; - double w_minus_2k = w - 2.0 * k; - - fplus = log_sum_exp(log(w_plus_2k) - square(w_plus_2k) / twoy, fplus); - fminus - = log_sum_exp(log(-w_minus_2k) - square(w_minus_2k) / twoy, fminus); - } - } - fplus = log_sum_exp(log(w) - square(w) / twoy, fplus); - ans = lg1 - + (-0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log(y_asq) - + log_diff_exp(fplus, fminus)); - // if large t is better - } else { - double fplus = NEGATIVE_INFTY; - double fminus = NEGATIVE_INFTY; - double halfy = y_asq / 2.0; - for (size_t k = static_cast(kll); k >= 1; k--) { - double pi_k = k * pi(); - double check = sin(pi_k * w); - if (check > 0) { - fplus = log_sum_exp(log(k) - square(pi_k) * halfy + log(check), fplus); - } else { - fminus - = log_sum_exp(log(k) - square(pi_k) * halfy + log(-check), fminus); - } - } - if (fplus < fminus) { - ans = NEGATIVE_INFTY; - } else { - ans = lg1 + log_diff_exp(fplus, fminus) + LOG_PI; - } - } - return ans; + const auto& kss_functor = [&](double erg, int newsign, + double lg1, double ans0) { + return lg1 - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log(y / square(a)) + erg; + }; + const auto& kll_functor = [&](double erg, int newsign, + double lg1, double ans0) { + return lg1 + erg + LOG_PI; + }; + + return wiener5_helper(y, a, vn, wn, sv, err, + kss_functor, kll_functor); } //----------------------------------------------- @@ -139,85 +250,25 @@ inline double dwiener5(const double& y, const double& a, const double& vn, inline double dtdwiener5(const double& y, const double& a, const double& vn, const double& wn, const double& sv, const double& err) { - double kll, kss, ans, v, w; - w = 1.0 - wn; - v = -vn; - - // prepare some variables - double y_asq = y / square(a); - double la = 2.0 * log(a); - double ans0, lg1; - if (sv != 0) { - double sv_sqr = square(sv); - double one_plus_svsqr_y = (1 + sv_sqr * y); - ans0 = -0.5 - * (square(sv_sqr) * (y + square(a * w)) - + sv_sqr * (1 - 2 * a * v * w) + square(v)) - / square(one_plus_svsqr_y); - } else { - ans0 = -0.5 * square(v); - } - - double erg; - double newsign = 1; - double fplus = NEGATIVE_INFTY; - double fminus = NEGATIVE_INFTY; - - std::forward_as_tuple(kss, kll, lg1) = wiener5_helper(y, a, vn, wn, sv, err); - double factor = lg1 - la; - double ld = dwiener5(y, a, vn, wn, sv, - err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); - - // if small t is better - if (2 * kss <= kll) { - // calculate terms of the sum for small t - double twoy = 2.0 * y_asq; - if (static_cast(kss) > 0) { - for (size_t k = static_cast(kss); k >= 1; k--) { - double w_plus_2k = w + 2.0 * k; - double w_minus_2k = w - 2.0 * k; - fplus = log_sum_exp(3.0 * log(w_plus_2k) - w_plus_2k * w_plus_2k / twoy, - fplus); - fminus = log_sum_exp( - 3.0 * log(-w_minus_2k) - w_minus_2k * w_minus_2k / twoy, fminus); - } - } - fplus = log_sum_exp(3.0 * log(w) - w * w / twoy, fplus); - if (fplus < fminus) { - newsign = -1; - erg = log_diff_exp(fminus, fplus); - } else { - erg = log_diff_exp(fplus, fminus); - } - ans = ans0 - 1.5 / y - + newsign - * exp(factor - 1.5 * LOG_TWO - LOG_SQRT_PI - 3.5 * log(y_asq) + const auto& kss_functor = [&](double erg, int newsign, + double lg1, double ans0) { + double ld = dwiener5(y, a, vn, wn, sv, + err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); + return ans0 - 1.5 / y + newsign + * exp(lg1 - 2.0 * log(a) - 1.5 * LOG_TWO - LOG_SQRT_PI + - 3.5 * log(y / square(a)) + erg - ld); - // if large t is better - } else { - // calculate terms of the sum for large t - double halfy = y_asq / 2.0; - for (size_t k = static_cast(kll); k >= 1; k--) { - double pi_k = pi() * k; - double zwi = sin(pi_k * w); - if (zwi > 0) { - fplus - = log_sum_exp(3.0 * log(k) - pi_k * pi_k * halfy + log(zwi), fplus); - } - if (zwi < 0) { - fminus = log_sum_exp(3.0 * log(k) - pi_k * pi_k * halfy + log(-zwi), - fminus); - } - } - if (fplus < fminus) { - erg = log_diff_exp(fminus, fplus); - newsign = -1; - } else { - erg = log_diff_exp(fplus, fminus); - } - ans = ans0 - newsign * exp(factor + 3.0 * LOG_PI - LOG_TWO + erg - ld); - } - return ans; + }; + const auto& kll_functor = [&](double erg, int newsign, + double lg1, double ans0) { + double ld = dwiener5(y, a, vn, wn, sv, + err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); + return ans0 - newsign * exp(lg1 - 2.0 * log(a) + 3.0 * LOG_PI + - LOG_TWO + erg - ld); + }; + + return wiener5_helper(y, a, vn, wn, sv, err, + kss_functor, kll_functor); } //----------------------------------------------- @@ -227,91 +278,34 @@ inline double dtdwiener5(const double& y, const double& a, const double& vn, inline double dadwiener5(const double& y, const double& a, const double& vn, const double& wn, const double& sv, const double& err, const int& normal_or_log) { - double kll, kss, ans, v, w; - double la = log(a); double ly = log(y); - w = 1.0 - wn; - v = -vn; - // prepare some variables - double y_asq = y / square(a); - double ans0, lg1; - if (sv != 0) { - double sv_sqr = square(sv); - double one_plus_svsqr_y = (1 + sv_sqr * y); - ans0 = (-v * w + sv_sqr * square(w) * a) / one_plus_svsqr_y; - } else { - ans0 = -v * w; - } - - double erg; - double newsign = 1; - double fplus = NEGATIVE_INFTY; - double fminus = NEGATIVE_INFTY; - - double lg2; - bool small_t; - std::forward_as_tuple(kss, kll, lg1) = wiener5_helper(y, a, vn, wn, sv, err); - double factor = lg1 - 3 * la; - double ld - = dwiener5(y, a, vn, wn, sv, - err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); - - // if small t is better - if (2 * kss <= kll) { - // calculate terms of the sum for short t - double twoy = 2.0 * y_asq; - if (static_cast(kss) > 0) { - for (size_t k = static_cast(kss); k >= 1; k--) { - double w_plus_2k = w + 2.0 * k; - double w_minus_2k = w - 2.0 * k; - fplus = log_sum_exp(3.0 * log(w_plus_2k) - w_plus_2k * w_plus_2k / twoy, - fplus); - fminus = log_sum_exp( - 3.0 * log(-w_minus_2k) - w_minus_2k * w_minus_2k / twoy, fminus); - } - } - fplus = log_sum_exp(3.0 * log(w) - w * w / twoy, fplus); - if (fplus < fminus) { - newsign = -1; - erg = log_diff_exp(fminus, fplus); - } else { - erg = log_diff_exp(fplus, fminus); - } - ans = ans0 + 1.0 / a + const auto& kss_functor = [&](double erg, int newsign, + double lg1, double ans0) { + double factor = lg1 - 3 * la; + double ld + = dwiener5(y, a, vn, wn, sv, + err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); + double ans = ans0 + 1.0 / a - newsign * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * ly + 4.0 * la + lg1 + erg - ld); - // if large t is better - } else { - // calculate terms of the sum for large t - double halfy = y_asq / 2.0; - for (size_t k = static_cast(kll); k >= 1; k--) { - double pi_k = pi() * k; - double zwi = sin(pi_k * w); - if (zwi > 0) { - fplus - = log_sum_exp(3.0 * log(k) - pi_k * pi_k * halfy + log(zwi), fplus); - } - if (zwi < 0) { - fminus = log_sum_exp(3.0 * log(k) - pi_k * pi_k * halfy + log(-zwi), - fminus); - } - } - if (fplus > fminus) { - erg = log_diff_exp(fplus, fminus); - } else { - erg = log_diff_exp(fminus, fplus); - newsign = -1; - } - ans = ans0 - 2.0 / a + newsign * exp(ly + factor + 3.0 * LOG_PI + erg - ld); - } - if (normal_or_log == 1) { - return ans * exp(ld); // derivative of f for hcubature - } else { - return ans; // derivative of log(f) - } + return (normal_or_log == 1) ? ans * exp(ld) : ans; + }; + const auto& kll_functor = [&](double erg, int newsign, + double lg1, double ans0) { + double factor = lg1 - 3 * la; + double ld + = dwiener5(y, a, vn, wn, sv, + err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); + double ans = ans0 - 2.0 / a + + newsign * exp(ly + factor + 3.0 * LOG_PI + erg - ld); + return (normal_or_log == 1) ? ans * exp(ld) : ans; + }; + + return wiener5_helper(y, a, vn, wn, sv, err, + kss_functor, kll_functor); } //----------------------------------------------- @@ -320,12 +314,9 @@ inline double dadwiener5(const double& y, const double& a, const double& vn, // d/dv(log(f))=d/dv f'/f; ans*exp(ld)=f' on normal scale) inline double dvdwiener5(const double& y, const double& a, const double& vn, const double& wn, const double& sv) { - double ans; + double ans = (a * (1 - wn) - vn * y); if (sv != 0) { - ans = 1 + square(sv) * y; - ans = (a * (1 - wn) - vn * y) / ans; - } else { - ans = (a * (1 - wn) - vn * y); + ans /= 1 + square(sv) * y; } return ans; } @@ -337,100 +328,26 @@ inline double dvdwiener5(const double& y, const double& a, const double& vn, inline double dwdwiener5(const double& y, const double& a, const double& vn, const double& wn, const double& sv, const double& err, const int& normal_or_log) { - double kll, kss, ans, v, w; - double sign = -1; - w = 1.0 - wn; - v = -vn; - - // prepare some variables - double y_asq = y / square(a); - double ans0, lg1; - if (sv != 0) { - double sv_sqr = square(sv); - double one_plus_svsqr_y = (1 + sv_sqr * y); - ans0 = (-v * a + sv_sqr * square(a) * w) / one_plus_svsqr_y; - } else { - ans0 = -v * a; - } - - - double erg; - double newsign = 1; - double fplus = NEGATIVE_INFTY; - double fminus = NEGATIVE_INFTY; - - std::forward_as_tuple(kss, kll, lg1) = wiener5_helper(y, a, vn, wn, sv, err); - double ld = dwiener5(y, a, vn, wn, sv, err - log(fabs(ans0))); - double ls = -lg1 + ld; - double ll = -lg1 + ld; - - // if small t is better - if (2 * kss <= kll) { - // calculate terms of the sum for short t - double twoy = 2.0 * y_asq; - for (size_t k = static_cast(kss); k >= 1; k--) { - double sqrt_w_plus_2k = square(w + 2 * k); - double sqrt_w_minus_2k = square(w - 2 * k); - double wp2k_minusy = sqrt_w_plus_2k - y_asq; - double wm2k_minusy = sqrt_w_minus_2k - y_asq; - if (wp2k_minusy > 0) { - fplus = log_sum_exp(log(wp2k_minusy) - sqrt_w_plus_2k / twoy, fplus); - } else if (wp2k_minusy < 0) { - fminus - = log_sum_exp(log(-(wp2k_minusy)) - sqrt_w_plus_2k / twoy, fminus); - } - if (wm2k_minusy > 0) { - fplus = log_sum_exp(log(wm2k_minusy) - sqrt_w_minus_2k / twoy, fplus); - } else if (wm2k_minusy < 0) { - fminus - = log_sum_exp(log(-(wm2k_minusy)) - sqrt_w_minus_2k / twoy, fminus); - } - } - double sqr_w = square(w); - double sqrt_w_plus_2k = sqr_w - y_asq; - if (sqrt_w_plus_2k > 0) { - fplus = log_sum_exp(log(sqrt_w_plus_2k) - sqr_w / twoy, fplus); - } else if (sqrt_w_plus_2k < 0) { - fminus = log_sum_exp(log(-(sqrt_w_plus_2k)) - sqr_w / twoy, fminus); - } - if (fplus < fminus) { - newsign = -1; - erg = log_diff_exp(fminus, fplus); - } else { - erg = log_diff_exp(fplus, fminus); - } - ans = ans0 + const auto& kss_functor = [&](double erg, int newsign, + double lg1, double ans0) { + double ld = dwiener5(y, a, vn, wn, sv, err - log(fabs(ans0))); + double ls = -lg1 + ld; + double ans = ans0 - newsign - * exp(erg - ls - 2.5 * log(y_asq) - 0.5 * LOG_TWO + * exp(erg - ls - 2.5 * log(y / square(a)) - 0.5 * LOG_TWO - 0.5 * LOG_PI); - // if large t is better - } else { - // calculate terms of the sum for large t - double halfy = y_asq / 2.0; - for (size_t k = static_cast(kll); k >= 1; k--) { - double pi_k = pi() * k; - double x = cos(pi_k * w); - if (x > 0) { - fplus - = log_sum_exp(2.0 * log(k) - square(pi_k) * halfy + log(x), fplus); - } else if (x < 0) { - fminus = log_sum_exp(2.0 * log(k) - square(pi_k) * halfy + log(-x), - fminus); - } - } - if (fplus < fminus) { - erg = log_diff_exp(fminus, fplus); - newsign = -1; - } else { - erg = log_diff_exp(fplus, fminus); - } - ans = ans0 + newsign * exp(erg - ll + 2 * LOG_PI); - } - if (normal_or_log == 1) { - return ans * sign * exp(ld); // derivative of f for hcubature - } else { - return ans * sign; // derivative of log(f) - } + return (normal_or_log == 1) ? -ans * exp(ld) : -ans; + }; + const auto& kll_functor = [&](double erg, int newsign, + double lg1, double ans0) { + double ld = dwiener5(y, a, vn, wn, sv, err - log(fabs(ans0))); + double ll = -lg1 + ld; + double ans = ans0 + newsign * exp(erg - ll + 2 * LOG_PI); + return (normal_or_log == 1) ? -ans * exp(ld) : -ans; + }; + + return wiener5_helper(y, a, vn, wn, sv, err, + kss_functor, kll_functor); } //----------------------------------------------- @@ -556,52 +473,38 @@ inline return_type_t wiener5_lpdf( const double v_val = v_vec.val(i); const double sv_val = sv_vec.val(i); - dens = internal::dwiener5(y_val - t0_val, a_val, v_val, w_val, sv_val, - labstol_wiener5); - if (labstol_wiener5 > fabs(dens) + lerror_bound_dens - LOG_TWO) { - dens = internal::dwiener5(y_val - t0_val, a_val, v_val, w_val, sv_val, - fabs(dens) + lerror_bound_dens - LOG_TWO); - } + const auto params = std::make_tuple(y_val - t0_val, a_val, v_val, w_val, + sv_val, labstol_wiener5); + + dens = internal::estimate_with_err_check<5>(internal::dwiener5, + lerror_bound_dens - LOG_TWO, + params, true); ld += dens; // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 - double deriv_y = internal::dtdwiener5(y_val - t0_val, a_val, v_val, w_val, - sv_val, labstol_wiener5); - if (labstol_wiener5 > log(fabs(deriv_y)) + dens + lerror_bound - LOG_TWO) { - deriv_y = internal::dtdwiener5( - y_val - t0_val, a_val, v_val, w_val, sv_val, - log(fabs(deriv_y)) + dens + lerror_bound - LOG_FOUR); - } + double deriv_y = internal::estimate_with_err_check<5>(internal::dtdwiener5, + dens + lerror_bound - LOG_TWO, + params); // computation of derivatives and precision checks if (!is_constant_all::value) { ops_partials.edge1_.partials_[i] = deriv_y; } if (!is_constant_all::value) { - double deriv_a = internal::dadwiener5(y_val - t0_val, a_val, v_val, w_val, - sv_val, labstol_wiener5, 0); - if (labstol_wiener5 - > log(fabs(deriv_a)) + dens + lerror_bound - LOG_TWO) { - deriv_a = internal::dadwiener5( - y_val - t0_val, a_val, v_val, w_val, sv_val, - log(fabs(deriv_a)) + dens + lerror_bound - LOG_FOUR, 0); - } - ops_partials.edge2_.partials_[i] = deriv_a; + ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check<5>( + internal::dadwiener5, + dens + lerror_bound - LOG_FOUR, + std::tuple_cat(params, std::make_tuple(0))); } if (!is_constant_all::value) { ops_partials.edge3_.partials_[i] = -deriv_y; } if (!is_constant_all::value) { - double deriv_w = internal::dwdwiener5(y_val - t0_val, a_val, v_val, w_val, - sv_val, labstol_wiener5, 0); - if (labstol_wiener5 - > log(fabs(deriv_w)) + dens + lerror_bound - LOG_TWO) { - deriv_w = internal::dwdwiener5( - y_val - t0_val, a_val, v_val, w_val, sv_val, - log(fabs(deriv_w)) + dens + lerror_bound - LOG_FOUR, 0); - } - ops_partials.edge4_.partials_[i] = deriv_w; + ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check<5>( + internal::dwdwiener5, + dens + lerror_bound - LOG_FOUR, + std::tuple_cat(params, std::make_tuple(0))); } if (!is_constant_all::value) { ops_partials.edge5_.partials_[i] diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index 0e2f2d321ed..90ff73e2679 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -116,27 +116,6 @@ inline double dtdwiener5_for_7(const double& y, const double& a, } //----------------------------------------------- -template -inline void assign_err(std::tuple& args_tuple, double err) { - std::get<8>(args_tuple) = err; -} -inline void assign_err(double arg, double err) { arg = err; } - -template -double estimate_with_err_check(const F& functor, double err, - ArgsTupleT&& args_tuple) { - double result = math::apply([&](auto&&... args) { return functor(args...); }, - args_tuple); - double lfabs_result = log(fabs(result)); - if (lfabs_result < err) { - ArgsTupleT err_args_tuple = args_tuple; - assign_err(std::get(err_args_tuple), err + lfabs_result); - result = math::apply([&](auto&&... args) { return functor(args...); }, - err_args_tuple); - } - return result; -} - template auto wiener7_integrand(const F& integrand_fun, double labstol_wiener5, double lerr_bound, TArgs&&... args) { From ef8bf7cc89763d35696ebd455e6ec796dbc59d19 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 7 May 2023 08:59:59 -0400 Subject: [PATCH 036/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 188 +++++++++++++-------------- 1 file changed, 89 insertions(+), 99 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 6e9830b0f76..8d80d3f20bb 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -40,7 +40,7 @@ inline auto erg_sign(double fminus, double fplus) { template inline auto calc_erg_kss(const double& y, const double& a, const double& vn, - const double& wn, size_t kss) { + const double& wn, size_t kss) { double w = 1.0 - wn; double v = -vn; double y_asq = y / square(a); @@ -58,9 +58,8 @@ inline auto calc_erg_kss(const double& y, const double& a, const double& vn, fplus = log_sum_exp(mult * log(w_plus_2k) - square(w_plus_2k) / twoy, fplus); - fminus - = log_sum_exp(mult * log(-w_minus_2k) - square(w_minus_2k) / twoy, - fminus); + fminus = log_sum_exp( + mult * log(-w_minus_2k) - square(w_minus_2k) / twoy, fminus); } } fplus = log_sum_exp(mult * log(w) - square(w) / twoy, fplus); @@ -96,7 +95,7 @@ inline auto calc_erg_kss(const double& y, const double& a, const double& vn, template inline auto calc_erg_kll(const double& y, const double& a, const double& vn, - const double& wn, size_t kll) { + const double& wn, size_t kll) { double w = 1.0 - wn; double v = -vn; double y_asq = y / square(a); @@ -118,15 +117,14 @@ inline auto calc_erg_kll(const double& y, const double& a, const double& vn, double halfy = y_asq / 2.0; for (size_t k = kll; k >= 1; k--) { double pi_k = k * pi(); - double check = (FunTypeEnum == FunType::GradW) ? cos(pi_k * w) - : sin(pi_k * w); + double check + = (FunTypeEnum == FunType::GradW) ? cos(pi_k * w) : sin(pi_k * w); if (check > 0) { fplus = log_sum_exp(mult * log(k) - square(pi_k) * halfy + log(check), fplus); } else { - fminus - = log_sum_exp(mult * log(k) - square(pi_k) * halfy + log(-check), - fminus); + fminus = log_sum_exp(mult * log(k) - square(pi_k) * halfy + log(-check), + fminus); } } return erg_sign(fminus, fplus); @@ -134,9 +132,9 @@ inline auto calc_erg_kll(const double& y, const double& a, const double& vn, template inline auto wiener5_helper(const double& y, const double& a, const double& vn, - const double& wn, const double& sv, - const double& err, const KSSFuncType& kss_functor, - const KLLFuncType& kll_functor) { + const double& wn, const double& sv, + const double& err, const KSSFuncType& kss_functor, + const KLLFuncType& kll_functor) { double w = 1.0 - wn; double v = -vn; double sv_sqr = square(sv); @@ -145,7 +143,7 @@ inline auto wiener5_helper(const double& y, const double& a, const double& vn, if (sv != 0) { lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 / one_plus_svsqr_y - - 2 * log(a) - 0.5 * log(one_plus_svsqr_y); + - 2 * log(a) - 0.5 * log(one_plus_svsqr_y); } else { lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - 2 * log(a); } @@ -156,12 +154,11 @@ inline auto wiener5_helper(const double& y, const double& a, const double& vn, if (sv != 0) { if (FunTypeEnum == FunType::GradT) { ans0 = -0.5 - * (square(sv_sqr) * (y + square(a * w)) + * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - 2 * a * v * w) + square(v)) - / square(one_plus_svsqr_y); + / square(one_plus_svsqr_y); } else { - ans0 = (-v * var_a + sv_sqr * square(var_a) * var_b) - / one_plus_svsqr_y; + ans0 = (-v * var_a + sv_sqr * square(var_a) * var_b) / one_plus_svsqr_y; } } else { ans0 = (FunTypeEnum == FunType::GradT) ? -0.5 * square(v) : -v * var_a; @@ -182,12 +179,10 @@ inline auto wiener5_helper(const double& y, const double& a, const double& vn, } else { K1 = (sqrt(3.0 * y_asq) + w) / 2.0; if (FunTypeEnum == FunType::GradW) { - u_eps - = fmin(-1.0, 2.0 * es + LOG_TWO + LOG_PI + 2.0 * log(y_asq)); + u_eps = fmin(-1.0, 2.0 * es + LOG_TWO + LOG_PI + 2.0 * log(y_asq)); } else { - u_eps = fmin(-1.0, - (log(8.0 / 27.0) + LOG_PI + 4.0 * log(y_asq) + 2.0 * es) - / 3.0); + u_eps = fmin( + -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(y_asq) + 2.0 * es) / 3.0); } arg = -3.0 * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); } @@ -207,22 +202,22 @@ inline auto wiener5_helper(const double& y, const double& a, const double& vn, K2 = (arg > 0) ? sqrt(arg) : K1; } else if (FunTypeEnum == FunType::GradW) { K1 = sqrt(2.0 / y_asq) / pi(); - u_eps = fmin( - -1.0, log(4.0 / 9.0) + 2.0 * LOG_PI + 3.0 * log(y_asq) + 2.0 * es); + u_eps = fmin(-1.0, + log(4.0 / 9.0) + 2.0 * LOG_PI + 3.0 * log(y_asq) + 2.0 * es); arg = -(u_eps - sqrt(-2.0 * u_eps - 2.0)); K2 = (arg > 0) ? 1.0 / pi() * sqrt(arg / y_asq) : K1; } - size_t kll = static_cast(ceil(fmax(K1, K2))); + size_t kll = static_cast(ceil(fmax(K1, K2))); double erg; int newsign; if (2 * kss <= kll) { std::forward_as_tuple(erg, newsign) - = calc_erg_kss(y, a, vn, wn, kss); + = calc_erg_kss(y, a, vn, wn, kss); return kss_functor(erg, newsign, lg1, ans0); } else { std::forward_as_tuple(erg, newsign) - = calc_erg_kll(y, a, vn, wn, kll); + = calc_erg_kll(y, a, vn, wn, kll); return kll_functor(erg, newsign, lg1, ans0); } } @@ -230,17 +225,15 @@ inline auto wiener5_helper(const double& y, const double& a, const double& vn, // calculate density in log inline double dwiener5(const double& y, const double& a, const double& vn, const double& wn, const double& sv, const double& err) { - const auto& kss_functor = [&](double erg, int newsign, - double lg1, double ans0) { + const auto& kss_functor = [&](double erg, int newsign, double lg1, + double ans0) { return lg1 - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log(y / square(a)) + erg; }; - const auto& kll_functor = [&](double erg, int newsign, - double lg1, double ans0) { - return lg1 + erg + LOG_PI; - }; + const auto& kll_functor = [&](double erg, int newsign, double lg1, + double ans0) { return lg1 + erg + LOG_PI; }; - return wiener5_helper(y, a, vn, wn, sv, err, - kss_functor, kll_functor); + return wiener5_helper(y, a, vn, wn, sv, err, kss_functor, + kll_functor); } //----------------------------------------------- @@ -250,25 +243,26 @@ inline double dwiener5(const double& y, const double& a, const double& vn, inline double dtdwiener5(const double& y, const double& a, const double& vn, const double& wn, const double& sv, const double& err) { - const auto& kss_functor = [&](double erg, int newsign, - double lg1, double ans0) { + const auto& kss_functor = [&](double erg, int newsign, double lg1, + double ans0) { double ld = dwiener5(y, a, vn, wn, sv, - err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); - return ans0 - 1.5 / y + newsign - * exp(lg1 - 2.0 * log(a) - 1.5 * LOG_TWO - LOG_SQRT_PI - - 3.5 * log(y / square(a)) - + erg - ld); + err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); + return ans0 - 1.5 / y + + newsign + * exp(lg1 - 2.0 * log(a) - 1.5 * LOG_TWO - LOG_SQRT_PI + - 3.5 * log(y / square(a)) + erg - ld); }; - const auto& kll_functor = [&](double erg, int newsign, - double lg1, double ans0) { + const auto& kll_functor = [&](double erg, int newsign, double lg1, + double ans0) { double ld = dwiener5(y, a, vn, wn, sv, - err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); - return ans0 - newsign * exp(lg1 - 2.0 * log(a) + 3.0 * LOG_PI - - LOG_TWO + erg - ld); + err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); + return ans0 + - newsign + * exp(lg1 - 2.0 * log(a) + 3.0 * LOG_PI - LOG_TWO + erg - ld); }; - return wiener5_helper(y, a, vn, wn, sv, err, - kss_functor, kll_functor); + return wiener5_helper(y, a, vn, wn, sv, err, kss_functor, + kll_functor); } //----------------------------------------------- @@ -281,31 +275,31 @@ inline double dadwiener5(const double& y, const double& a, const double& vn, double la = log(a); double ly = log(y); - const auto& kss_functor = [&](double erg, int newsign, - double lg1, double ans0) { - double factor = lg1 - 3 * la; - double ld - = dwiener5(y, a, vn, wn, sv, - err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); - double ans = ans0 + 1.0 / a - - newsign - * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * ly + 4.0 * la + lg1 - + erg - ld); - return (normal_or_log == 1) ? ans * exp(ld) : ans; - }; - const auto& kll_functor = [&](double erg, int newsign, - double lg1, double ans0) { + const auto& kss_functor + = [&](double erg, int newsign, double lg1, double ans0) { + double factor = lg1 - 3 * la; + double ld = dwiener5( + y, a, vn, wn, sv, + err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); + double ans = ans0 + 1.0 / a + - newsign + * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * ly + + 4.0 * la + lg1 + erg - ld); + return (normal_or_log == 1) ? ans * exp(ld) : ans; + }; + const auto& kll_functor = [&](double erg, int newsign, double lg1, + double ans0) { double factor = lg1 - 3 * la; double ld = dwiener5(y, a, vn, wn, sv, - err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); - double ans = ans0 - 2.0 / a - + newsign * exp(ly + factor + 3.0 * LOG_PI + erg - ld); + err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); + double ans + = ans0 - 2.0 / a + newsign * exp(ly + factor + 3.0 * LOG_PI + erg - ld); return (normal_or_log == 1) ? ans * exp(ld) : ans; }; - return wiener5_helper(y, a, vn, wn, sv, err, - kss_functor, kll_functor); + return wiener5_helper(y, a, vn, wn, sv, err, kss_functor, + kll_functor); } //----------------------------------------------- @@ -328,26 +322,26 @@ inline double dvdwiener5(const double& y, const double& a, const double& vn, inline double dwdwiener5(const double& y, const double& a, const double& vn, const double& wn, const double& sv, const double& err, const int& normal_or_log) { - const auto& kss_functor = [&](double erg, int newsign, - double lg1, double ans0) { - double ld = dwiener5(y, a, vn, wn, sv, err - log(fabs(ans0))); - double ls = -lg1 + ld; - double ans = ans0 - - newsign - * exp(erg - ls - 2.5 * log(y / square(a)) - 0.5 * LOG_TWO - - 0.5 * LOG_PI); - return (normal_or_log == 1) ? -ans * exp(ld) : -ans; - }; - const auto& kll_functor = [&](double erg, int newsign, - double lg1, double ans0) { - double ld = dwiener5(y, a, vn, wn, sv, err - log(fabs(ans0))); - double ll = -lg1 + ld; - double ans = ans0 + newsign * exp(erg - ll + 2 * LOG_PI); - return (normal_or_log == 1) ? -ans * exp(ld) : -ans; - }; - - return wiener5_helper(y, a, vn, wn, sv, err, - kss_functor, kll_functor); + const auto& kss_functor + = [&](double erg, int newsign, double lg1, double ans0) { + double ld = dwiener5(y, a, vn, wn, sv, err - log(fabs(ans0))); + double ls = -lg1 + ld; + double ans = ans0 + - newsign + * exp(erg - ls - 2.5 * log(y / square(a)) + - 0.5 * LOG_TWO - 0.5 * LOG_PI); + return (normal_or_log == 1) ? -ans * exp(ld) : -ans; + }; + const auto& kll_functor + = [&](double erg, int newsign, double lg1, double ans0) { + double ld = dwiener5(y, a, vn, wn, sv, err - log(fabs(ans0))); + double ll = -lg1 + ld; + double ans = ans0 + newsign * exp(erg - ll + 2 * LOG_PI); + return (normal_or_log == 1) ? -ans * exp(ld) : -ans; + }; + + return wiener5_helper(y, a, vn, wn, sv, err, kss_functor, + kll_functor); } //----------------------------------------------- @@ -476,16 +470,14 @@ inline return_type_t wiener5_lpdf( const auto params = std::make_tuple(y_val - t0_val, a_val, v_val, w_val, sv_val, labstol_wiener5); - dens = internal::estimate_with_err_check<5>(internal::dwiener5, - lerror_bound_dens - LOG_TWO, - params, true); + dens = internal::estimate_with_err_check<5>( + internal::dwiener5, lerror_bound_dens - LOG_TWO, params, true); ld += dens; // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 - double deriv_y = internal::estimate_with_err_check<5>(internal::dtdwiener5, - dens + lerror_bound - LOG_TWO, - params); + double deriv_y = internal::estimate_with_err_check<5>( + internal::dtdwiener5, dens + lerror_bound - LOG_TWO, params); // computation of derivatives and precision checks if (!is_constant_all::value) { @@ -493,8 +485,7 @@ inline return_type_t wiener5_lpdf( } if (!is_constant_all::value) { ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check<5>( - internal::dadwiener5, - dens + lerror_bound - LOG_FOUR, + internal::dadwiener5, dens + lerror_bound - LOG_FOUR, std::tuple_cat(params, std::make_tuple(0))); } if (!is_constant_all::value) { @@ -502,8 +493,7 @@ inline return_type_t wiener5_lpdf( } if (!is_constant_all::value) { ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check<5>( - internal::dwdwiener5, - dens + lerror_bound - LOG_FOUR, + internal::dwdwiener5, dens + lerror_bound - LOG_FOUR, std::tuple_cat(params, std::make_tuple(0))); } if (!is_constant_all::value) { From 0e4a3116028ccad26c81ab9cadca2e6d9c29ad93 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sun, 7 May 2023 20:18:18 +0300 Subject: [PATCH 037/179] Consolidate wiener5 functions --- stan/math/prim/prob/wiener5_lpdf.hpp | 172 +++++++++++---------------- 1 file changed, 69 insertions(+), 103 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 8d80d3f20bb..dc333c8284f 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -31,105 +31,6 @@ double estimate_with_err_check(const F& functor, double err, enum class FunType { Density, GradT, GradA, GradV, GradW, GradSV }; -inline auto erg_sign(double fminus, double fplus) { - double erg = (fplus < fminus) ? log_diff_exp(fminus, fplus) - : log_diff_exp(fplus, fminus); - int newsign = (fplus < fminus) ? -1 : 1; - return std::make_tuple(erg, newsign); -} - -template -inline auto calc_erg_kss(const double& y, const double& a, const double& vn, - const double& wn, size_t kss) { - double w = 1.0 - wn; - double v = -vn; - double y_asq = y / square(a); - - double fplus = NEGATIVE_INFTY; - double fminus = NEGATIVE_INFTY; - double twoy = 2.0 * y_asq; - - if (FunTypeEnum != FunType::GradW) { - double mult = (FunTypeEnum == FunType::Density) ? 1 : 3; - if (kss > 0) { - for (size_t k = kss; k >= 1; k--) { - double w_plus_2k = w + 2.0 * k; - double w_minus_2k = w - 2.0 * k; - - fplus = log_sum_exp(mult * log(w_plus_2k) - square(w_plus_2k) / twoy, - fplus); - fminus = log_sum_exp( - mult * log(-w_minus_2k) - square(w_minus_2k) / twoy, fminus); - } - } - fplus = log_sum_exp(mult * log(w) - square(w) / twoy, fplus); - } else { - for (size_t k = kss; k >= 1; k--) { - double sqrt_w_plus_2k = square(w + 2 * k); - double sqrt_w_minus_2k = square(w - 2 * k); - double wp2k_minusy = sqrt_w_plus_2k - y_asq; - double wm2k_minusy = sqrt_w_minus_2k - y_asq; - if (wp2k_minusy > 0) { - fplus = log_sum_exp(log(wp2k_minusy) - sqrt_w_plus_2k / twoy, fplus); - } else if (wp2k_minusy < 0) { - fminus - = log_sum_exp(log(-(wp2k_minusy)) - sqrt_w_plus_2k / twoy, fminus); - } - if (wm2k_minusy > 0) { - fplus = log_sum_exp(log(wm2k_minusy) - sqrt_w_minus_2k / twoy, fplus); - } else if (wm2k_minusy < 0) { - fminus - = log_sum_exp(log(-(wm2k_minusy)) - sqrt_w_minus_2k / twoy, fminus); - } - } - double sqr_w = square(w); - double sqrt_w_plus_2k = sqr_w - y_asq; - if (sqrt_w_plus_2k > 0) { - fplus = log_sum_exp(log(sqrt_w_plus_2k) - sqr_w / twoy, fplus); - } else if (sqrt_w_plus_2k < 0) { - fminus = log_sum_exp(log(-(sqrt_w_plus_2k)) - sqr_w / twoy, fminus); - } - } - return erg_sign(fminus, fplus); -} - -template -inline auto calc_erg_kll(const double& y, const double& a, const double& vn, - const double& wn, size_t kll) { - double w = 1.0 - wn; - double v = -vn; - double y_asq = y / square(a); - - double fplus = NEGATIVE_INFTY; - double fminus = NEGATIVE_INFTY; - double twoy = 2.0 * y_asq; - double erg; - int newsign = 1; - - double mult; - if (FunTypeEnum == FunType::Density) { - mult = 1; - } else if (FunTypeEnum == FunType::GradW) { - mult = 2; - } else { - mult = 3; - } - double halfy = y_asq / 2.0; - for (size_t k = kll; k >= 1; k--) { - double pi_k = k * pi(); - double check - = (FunTypeEnum == FunType::GradW) ? cos(pi_k * w) : sin(pi_k * w); - if (check > 0) { - fplus = log_sum_exp(mult * log(k) - square(pi_k) * halfy + log(check), - fplus); - } else { - fminus = log_sum_exp(mult * log(k) - square(pi_k) * halfy + log(-check), - fminus); - } - } - return erg_sign(fminus, fplus); -} - template inline auto wiener5_helper(const double& y, const double& a, const double& vn, const double& wn, const double& sv, @@ -211,13 +112,78 @@ inline auto wiener5_helper(const double& y, const double& a, const double& vn, double erg; int newsign; + double fplus = NEGATIVE_INFTY; + double fminus = NEGATIVE_INFTY; + double twoy = 2.0 * y_asq; if (2 * kss <= kll) { - std::forward_as_tuple(erg, newsign) - = calc_erg_kss(y, a, vn, wn, kss); + double mult = (FunTypeEnum == FunType::Density) ? 1 : 3; + double offset = (FunTypeEnum == FunType::GradW) ? y_asq : 0; + double sqrt_offset = sqrt(offset); + if (kss > 0) { + for (size_t k = kss; k >= 1; k--) { + double wp2k = w + 2.0 * k; + double wm2k = w - 2.0 * k; + + if (wp2k > sqrt_offset) { + fplus = log_sum_exp( + mult * log(wp2k - offset) - (square(wp2k) - offset) + / twoy, + fplus); + } else { + fminus = log_sum_exp( + mult * log(-(wp2k - offset)) - (square(wp2k) - offset) + / twoy, + fminus); + } + + if (wm2k > sqrt_offset) { + fplus = log_sum_exp( + mult * log(wm2k - offset) - (square(wm2k) - offset) + / twoy, + fplus); + } else { + fminus = log_sum_exp( + mult * log(-(wm2k - offset)) - (square(wm2k) - offset) + / twoy, + fminus); + } + } + } + if (w > sqrt_offset) { + fplus = log_sum_exp(mult * log(w - offset) - square(w) / twoy, fplus); + } else { + fminus = log_sum_exp(mult * log(-(w - offset)) - square(w) / twoy, + fminus); + } + erg = (fplus < fminus) ? log_diff_exp(fminus, fplus) + : log_diff_exp(fplus, fminus); + newsign = (fplus < fminus) ? -1 : 1; return kss_functor(erg, newsign, lg1, ans0); } else { - std::forward_as_tuple(erg, newsign) - = calc_erg_kll(y, a, vn, wn, kll); + double mult; + if (FunTypeEnum == FunType::Density) { + mult = 1; + } else if (FunTypeEnum == FunType::GradW) { + mult = 2; + } else { + mult = 3; + } + double halfy = y_asq / 2.0; + for (size_t k = kll; k >= 1; k--) { + double pi_k = k * pi(); + double check + = (FunTypeEnum == FunType::GradW) ? cos(pi_k * w) : sin(pi_k * w); + if (check > 0) { + fplus = log_sum_exp(mult * log(k) - square(pi_k) * halfy + log(check), + fplus); + } else { + fminus = log_sum_exp(mult * log(k) - square(pi_k) * halfy + log(-check), + fminus); + } + } + erg = (fplus < fminus) ? log_diff_exp(fminus, fplus) + : log_diff_exp(fplus, fminus); + newsign = (fplus < fminus) ? -1 : 1; return kll_functor(erg, newsign, lg1, ans0); } } From cefd7c7c63a7f1a90ee3fbf831efdd86a1397f7e Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 7 May 2023 13:19:01 -0400 Subject: [PATCH 038/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 30 ++++++++++++---------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index dc333c8284f..9a8262f486c 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -126,37 +126,33 @@ inline auto wiener5_helper(const double& y, const double& a, const double& vn, if (wp2k > sqrt_offset) { fplus = log_sum_exp( - mult * log(wp2k - offset) - (square(wp2k) - offset) - / twoy, - fplus); + mult * log(wp2k - offset) - (square(wp2k) - offset) / twoy, + fplus); } else { fminus = log_sum_exp( - mult * log(-(wp2k - offset)) - (square(wp2k) - offset) - / twoy, - fminus); + mult * log(-(wp2k - offset)) - (square(wp2k) - offset) / twoy, + fminus); } if (wm2k > sqrt_offset) { fplus = log_sum_exp( - mult * log(wm2k - offset) - (square(wm2k) - offset) - / twoy, - fplus); + mult * log(wm2k - offset) - (square(wm2k) - offset) / twoy, + fplus); } else { fminus = log_sum_exp( - mult * log(-(wm2k - offset)) - (square(wm2k) - offset) - / twoy, - fminus); + mult * log(-(wm2k - offset)) - (square(wm2k) - offset) / twoy, + fminus); } } } if (w > sqrt_offset) { fplus = log_sum_exp(mult * log(w - offset) - square(w) / twoy, fplus); } else { - fminus = log_sum_exp(mult * log(-(w - offset)) - square(w) / twoy, - fminus); + fminus + = log_sum_exp(mult * log(-(w - offset)) - square(w) / twoy, fminus); } erg = (fplus < fminus) ? log_diff_exp(fminus, fplus) - : log_diff_exp(fplus, fminus); + : log_diff_exp(fplus, fminus); newsign = (fplus < fminus) ? -1 : 1; return kss_functor(erg, newsign, lg1, ans0); } else { @@ -178,11 +174,11 @@ inline auto wiener5_helper(const double& y, const double& a, const double& vn, fplus); } else { fminus = log_sum_exp(mult * log(k) - square(pi_k) * halfy + log(-check), - fminus); + fminus); } } erg = (fplus < fminus) ? log_diff_exp(fminus, fplus) - : log_diff_exp(fplus, fminus); + : log_diff_exp(fplus, fminus); newsign = (fplus < fminus) ? -1 : 1; return kll_functor(erg, newsign, lg1, ans0); } From 550aa89f4f511d2cae2efbb34282ed1703ba7e50 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sun, 7 May 2023 20:38:30 +0300 Subject: [PATCH 039/179] Consolidate wiener7 deriv --- stan/math/prim/prob/wiener5_lpdf.hpp | 17 +++-- stan/math/prim/prob/wiener7_lpdf.hpp | 109 +-------------------------- 2 files changed, 11 insertions(+), 115 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 9a8262f486c..fdf637c2f9c 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -186,7 +186,8 @@ inline auto wiener5_helper(const double& y, const double& a, const double& vn, // calculate density in log inline double dwiener5(const double& y, const double& a, const double& vn, - const double& wn, const double& sv, const double& err) { + const double& wn, const double& sv, const double& err, + int normal_or_log = 0) { const auto& kss_functor = [&](double erg, int newsign, double lg1, double ans0) { return lg1 - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log(y / square(a)) + erg; @@ -204,23 +205,25 @@ inline double dwiener5(const double& y, const double& a, const double& vn, // d/dt(log(f))=d/dt f'/f; ans*exp(ld)=f' on normal scale) inline double dtdwiener5(const double& y, const double& a, const double& vn, const double& wn, const double& sv, - const double& err) { + const double& err, int normal_or_log = 0) { const auto& kss_functor = [&](double erg, int newsign, double lg1, double ans0) { double ld = dwiener5(y, a, vn, wn, sv, err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); - return ans0 - 1.5 / y + double ans = ans0 - 1.5 / y + newsign * exp(lg1 - 2.0 * log(a) - 1.5 * LOG_TWO - LOG_SQRT_PI - 3.5 * log(y / square(a)) + erg - ld); + return (normal_or_log == 1) ? ans * exp(ld) : ans; }; const auto& kll_functor = [&](double erg, int newsign, double lg1, double ans0) { double ld = dwiener5(y, a, vn, wn, sv, err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); - return ans0 + double ans = ans0 - newsign * exp(lg1 - 2.0 * log(a) + 3.0 * LOG_PI - LOG_TWO + erg - ld); + return (normal_or_log == 1) ? ans * exp(ld) : ans; }; return wiener5_helper(y, a, vn, wn, sv, err, kss_functor, @@ -430,7 +433,7 @@ inline return_type_t wiener5_lpdf( const double sv_val = sv_vec.val(i); const auto params = std::make_tuple(y_val - t0_val, a_val, v_val, w_val, - sv_val, labstol_wiener5); + sv_val, labstol_wiener5, 0); dens = internal::estimate_with_err_check<5>( internal::dwiener5, lerror_bound_dens - LOG_TWO, params, true); @@ -448,7 +451,7 @@ inline return_type_t wiener5_lpdf( if (!is_constant_all::value) { ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check<5>( internal::dadwiener5, dens + lerror_bound - LOG_FOUR, - std::tuple_cat(params, std::make_tuple(0))); + params); } if (!is_constant_all::value) { ops_partials.edge3_.partials_[i] = -deriv_y; @@ -456,7 +459,7 @@ inline return_type_t wiener5_lpdf( if (!is_constant_all::value) { ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check<5>( internal::dwdwiener5, dens + lerror_bound - LOG_FOUR, - std::tuple_cat(params, std::make_tuple(0))); + params); } if (!is_constant_all::value) { ops_partials.edge5_.partials_[i] diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index 90ff73e2679..c4735969351 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -9,113 +9,6 @@ namespace stan { namespace math { namespace internal { -// calculate derivative of density of wiener5 with respect to y (version for -// wiener7) -inline double dtdwiener5_for_7(const double& y, const double& a, - const double& v, const double& w, - const double& sv, const double& err) { - double kll, kss, ans; - - // prepare some variables - double y_asq = y / square(a); - double la = 2.0 * log(a); - double ans0, lg1; - if (sv != 0) { - double sv_sqr = square(sv); - double one_plus_svsqr_y = (1 + sv_sqr * y); - ans0 = -0.5 - * (square(sv_sqr) * (y + square(a * w)) - + sv_sqr * (1 - 2 * a * v * w) + square(v)) - / square(one_plus_svsqr_y); - lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 - / one_plus_svsqr_y - - la - 0.5 * log(one_plus_svsqr_y); - } else { - ans0 = -0.5 * square(v); - lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - la; - } - double factor = lg1 - la; - double ld = dwiener5(y, a, -v, 1 - w, sv, - err - log(max(fabs(ans0), fabs(ans0 - 1.5 / y)))); - - // calculate the number of terms kss needed for small y - double es = err - lg1; - es = es + la; - double K1 = (sqrt(3.0 * y_asq) + w) / 2.0; - double u_eps = fmin( - -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(y_asq) + 2.0 * es) / 3.0); - double arg = -3.0 * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - double K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; - kss = ceil(fmax(K1, K2)); - - // calculate number of terms kll needed for large y - double el = err - lg1; - el = el + la; - K1 = sqrt(3.0 / y_asq) / pi(); - u_eps = fmin(-1.0, el + log(0.6) + LOG_PI + 2.0 * log(y_asq)); - static const double PISQ = square(pi()); // pi*pi - arg = -2.0 / PISQ / y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - double kl = (arg > 0) ? sqrt(arg) : K1; - kll = ceil(fmax(kl, K1)); - - double erg; - double newsign = 1; - double fplus = NEGATIVE_INFTY; - double fminus = NEGATIVE_INFTY; - - // if small y is better - if (2 * kss < kll) { - // calculate terms of the sum for small y - double twot = 2.0 * y_asq; - if (static_cast(kss) > 0) { - for (size_t k = static_cast(kss); k >= 1; k--) { - double w_plus_2k = w + 2.0 * k; - double w_minus_2k = w - 2.0 * k; - fplus = log_sum_exp(3.0 * log(w_plus_2k) - w_plus_2k * w_plus_2k / twot, - fplus); - fminus = log_sum_exp( - 3.0 * log(-w_minus_2k) - w_minus_2k * w_minus_2k / twot, fminus); - } - } - fplus = log_sum_exp(3.0 * log(w) - w * w / twot, fplus); - if (fplus < fminus) { - newsign = -1; - erg = log_diff_exp(fminus, fplus); - } else { - erg = log_diff_exp(fplus, fminus); - } - ans = ans0 - 1.5 / y - + newsign - * exp(factor - 1.5 * LOG_TWO - LOG_SQRT_PI - 3.5 * log(y_asq) - + erg - ld); - // if large y is better - } else { - // calculate terms of the sum for large y - double halfy = y_asq / 2.0; - for (size_t k = static_cast(kll); k >= 1; k--) { - double pi_k = pi() * k; - double zwi = sin(pi_k * w); - if (zwi > 0) { - fplus - = log_sum_exp(3.0 * log(k) - pi_k * pi_k * halfy + log(zwi), fplus); - } - if (zwi < 0) { - fminus = log_sum_exp(3.0 * log(k) - pi_k * pi_k * halfy + log(-zwi), - fminus); - } - } - if (fplus < fminus) { - erg = log_diff_exp(fminus, fplus); - newsign = -1; - } else { - erg = log_diff_exp(fplus, fminus); - } - ans = ans0 - newsign * exp(factor + 3.0 * LOG_PI - LOG_TWO + erg - ld); - } - return ans * exp(ld); -} -//----------------------------------------------- - template auto wiener7_integrand(const F& integrand_fun, double labstol_wiener5, double lerr_bound, TArgs&&... args) { @@ -152,7 +45,7 @@ inline double wiener7_impl(double t0_, double omega, double y, double a, result = exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); break; case FunType::GradT: - result = dtdwiener5_for_7(y - t0_, a, -v, 1 - omega, sv, lerr); + result = dtdwiener5(y - t0_, a, v, omega, sv, lerr, 1); break; case FunType::GradA: result = dadwiener5(y - t0_, a, v, omega, sv, lerr, 1); From 002f3cdaf31427aa2fb8f0a8d4ca4b087876830a Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 7 May 2023 13:39:41 -0400 Subject: [PATCH 040/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index fdf637c2f9c..40ce27611f9 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -204,25 +204,26 @@ inline double dwiener5(const double& y, const double& a, const double& vn, // calculate derivative of density with respect to t (in log, ans = // d/dt(log(f))=d/dt f'/f; ans*exp(ld)=f' on normal scale) inline double dtdwiener5(const double& y, const double& a, const double& vn, - const double& wn, const double& sv, - const double& err, int normal_or_log = 0) { + const double& wn, const double& sv, const double& err, + int normal_or_log = 0) { const auto& kss_functor = [&](double erg, int newsign, double lg1, double ans0) { double ld = dwiener5(y, a, vn, wn, sv, err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); double ans = ans0 - 1.5 / y - + newsign - * exp(lg1 - 2.0 * log(a) - 1.5 * LOG_TWO - LOG_SQRT_PI - - 3.5 * log(y / square(a)) + erg - ld); + + newsign + * exp(lg1 - 2.0 * log(a) - 1.5 * LOG_TWO - LOG_SQRT_PI + - 3.5 * log(y / square(a)) + erg - ld); return (normal_or_log == 1) ? ans * exp(ld) : ans; }; const auto& kll_functor = [&](double erg, int newsign, double lg1, double ans0) { double ld = dwiener5(y, a, vn, wn, sv, err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); - double ans = ans0 - - newsign - * exp(lg1 - 2.0 * log(a) + 3.0 * LOG_PI - LOG_TWO + erg - ld); + double ans + = ans0 + - newsign + * exp(lg1 - 2.0 * log(a) + 3.0 * LOG_PI - LOG_TWO + erg - ld); return (normal_or_log == 1) ? ans * exp(ld) : ans; }; @@ -450,16 +451,14 @@ inline return_type_t wiener5_lpdf( } if (!is_constant_all::value) { ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check<5>( - internal::dadwiener5, dens + lerror_bound - LOG_FOUR, - params); + internal::dadwiener5, dens + lerror_bound - LOG_FOUR, params); } if (!is_constant_all::value) { ops_partials.edge3_.partials_[i] = -deriv_y; } if (!is_constant_all::value) { ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check<5>( - internal::dwdwiener5, dens + lerror_bound - LOG_FOUR, - params); + internal::dwdwiener5, dens + lerror_bound - LOG_FOUR, params); } if (!is_constant_all::value) { ops_partials.edge5_.partials_[i] From 15c4b4a35884d253c5354ca4da7d6f6662b8aab6 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sun, 7 May 2023 21:18:42 +0300 Subject: [PATCH 041/179] Further consolidate functions --- stan/math/prim/prob/wiener5_lpdf.hpp | 266 +++++++++++---------------- stan/math/prim/prob/wiener7_lpdf.hpp | 26 ++- 2 files changed, 127 insertions(+), 165 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 40ce27611f9..01e65b91fb9 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -31,15 +31,30 @@ double estimate_with_err_check(const F& functor, double err, enum class FunType { Density, GradT, GradA, GradV, GradW, GradSV }; -template -inline auto wiener5_helper(const double& y, const double& a, const double& vn, +template +inline double wiener5_helper(const double& y, const double& a, const double& vn, const double& wn, const double& sv, - const double& err, const KSSFuncType& kss_functor, - const KLLFuncType& kll_functor) { + const double& err = log(1e-12), + int normal_or_log = 0) { + if (FunTypeEnum == FunType::GradV) { + double ans = (a * (1 - wn) - vn * y); + if (sv != 0) { + ans /= 1 + square(sv) * y; + } + return ans; + } double w = 1.0 - wn; double v = -vn; double sv_sqr = square(sv); double one_plus_svsqr_y = 1 + sv_sqr * y; + + if (FunTypeEnum == FunType::GradSV) { + double t1 = -y / one_plus_svsqr_y; + double t2 = (square(a * w) + 2 * a * v * w * y + square(v * y)) + / square(one_plus_svsqr_y); + return sv * (t1 + t2); + } + double lg1; if (sv != 0) { lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 @@ -115,6 +130,10 @@ inline auto wiener5_helper(const double& y, const double& a, const double& vn, double fplus = NEGATIVE_INFTY; double fminus = NEGATIVE_INFTY; double twoy = 2.0 * y_asq; + double result; + double ld; + double ans; + double la, ly, factor, ls; if (2 * kss <= kll) { double mult = (FunTypeEnum == FunType::Density) ? 1 : 3; double offset = (FunTypeEnum == FunType::GradW) ? y_asq : 0; @@ -154,7 +173,48 @@ inline auto wiener5_helper(const double& y, const double& a, const double& vn, erg = (fplus < fminus) ? log_diff_exp(fminus, fplus) : log_diff_exp(fplus, fminus); newsign = (fplus < fminus) ? -1 : 1; - return kss_functor(erg, newsign, lg1, ans0); + switch (FunTypeEnum) { + case FunType::Density: + result = lg1 - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log(y / square(a)) + + erg; + break; + case FunType::GradT: + ld = wiener5_helper(y, a, vn, wn, sv, + err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); + ans = ans0 - 1.5 / y + + newsign + * exp(lg1 - 2.0 * log(a) - 1.5 * LOG_TWO - LOG_SQRT_PI + - 3.5 * log(y / square(a)) + erg - ld); + result = (normal_or_log == 1) ? ans * exp(ld) : ans; + break; + case FunType::GradA: + la = log(a); + ly = log(y); + factor = lg1 - 3 * la; + ld = wiener5_helper( + y, a, vn, wn, sv, + err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); + ans = ans0 + 1.0 / a + - newsign + * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * ly + + 4.0 * la + lg1 + erg - ld); + result = (normal_or_log == 1) ? ans * exp(ld) : ans; + break; + case FunType::GradW: + ld = wiener5_helper(y, a, vn, wn, sv, + err - log(fabs(ans0))); + ls = -lg1 + ld; + ans = ans0 + - newsign + * exp(erg - ls - 2.5 * log(y / square(a)) + - 0.5 * LOG_TWO - 0.5 * LOG_PI); + result = (normal_or_log == 1) ? -ans * exp(ld) : -ans; + break; + case FunType::GradV: + break; + case FunType::GradSV: + break; + } } else { double mult; if (FunTypeEnum == FunType::Density) { @@ -180,153 +240,43 @@ inline auto wiener5_helper(const double& y, const double& a, const double& vn, erg = (fplus < fminus) ? log_diff_exp(fminus, fplus) : log_diff_exp(fplus, fminus); newsign = (fplus < fminus) ? -1 : 1; - return kll_functor(erg, newsign, lg1, ans0); - } -} - -// calculate density in log -inline double dwiener5(const double& y, const double& a, const double& vn, - const double& wn, const double& sv, const double& err, - int normal_or_log = 0) { - const auto& kss_functor = [&](double erg, int newsign, double lg1, - double ans0) { - return lg1 - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log(y / square(a)) + erg; - }; - const auto& kll_functor = [&](double erg, int newsign, double lg1, - double ans0) { return lg1 + erg + LOG_PI; }; - - return wiener5_helper(y, a, vn, wn, sv, err, kss_functor, - kll_functor); -} -//----------------------------------------------- - -// d/dt DENSITY -// calculate derivative of density with respect to t (in log, ans = -// d/dt(log(f))=d/dt f'/f; ans*exp(ld)=f' on normal scale) -inline double dtdwiener5(const double& y, const double& a, const double& vn, - const double& wn, const double& sv, const double& err, - int normal_or_log = 0) { - const auto& kss_functor = [&](double erg, int newsign, double lg1, - double ans0) { - double ld = dwiener5(y, a, vn, wn, sv, - err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); - double ans = ans0 - 1.5 / y - + newsign - * exp(lg1 - 2.0 * log(a) - 1.5 * LOG_TWO - LOG_SQRT_PI - - 3.5 * log(y / square(a)) + erg - ld); - return (normal_or_log == 1) ? ans * exp(ld) : ans; - }; - const auto& kll_functor = [&](double erg, int newsign, double lg1, - double ans0) { - double ld = dwiener5(y, a, vn, wn, sv, - err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); - double ans - = ans0 - - newsign + switch (FunTypeEnum) { + case FunType::Density: + result = lg1 + erg + LOG_PI; + break; + case FunType::GradT: + ld = wiener5_helper(y, a, vn, wn, sv, + err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); + ans = ans0 - newsign * exp(lg1 - 2.0 * log(a) + 3.0 * LOG_PI - LOG_TWO + erg - ld); - return (normal_or_log == 1) ? ans * exp(ld) : ans; - }; - - return wiener5_helper(y, a, vn, wn, sv, err, kss_functor, - kll_functor); -} -//----------------------------------------------- - -// d/da DENSITY -// calculate derivative of density with respect to a (in log, ans = -// d/da(log(f))=d/da f'/f; ans*exp(ld)=f' on normal scale) -inline double dadwiener5(const double& y, const double& a, const double& vn, - const double& wn, const double& sv, const double& err, - const int& normal_or_log) { - double la = log(a); - double ly = log(y); - - const auto& kss_functor - = [&](double erg, int newsign, double lg1, double ans0) { - double factor = lg1 - 3 * la; - double ld = dwiener5( - y, a, vn, wn, sv, - err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); - double ans = ans0 + 1.0 / a - - newsign - * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * ly - + 4.0 * la + lg1 + erg - ld); - return (normal_or_log == 1) ? ans * exp(ld) : ans; - }; - const auto& kll_functor = [&](double erg, int newsign, double lg1, - double ans0) { - double factor = lg1 - 3 * la; - double ld - = dwiener5(y, a, vn, wn, sv, - err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); - double ans - = ans0 - 2.0 / a + newsign * exp(ly + factor + 3.0 * LOG_PI + erg - ld); - return (normal_or_log == 1) ? ans * exp(ld) : ans; - }; - - return wiener5_helper(y, a, vn, wn, sv, err, kss_functor, - kll_functor); -} -//----------------------------------------------- - -// d/dv DENSITY -// calculate derivative of density with respect to v (in log, ans = -// d/dv(log(f))=d/dv f'/f; ans*exp(ld)=f' on normal scale) -inline double dvdwiener5(const double& y, const double& a, const double& vn, - const double& wn, const double& sv) { - double ans = (a * (1 - wn) - vn * y); - if (sv != 0) { - ans /= 1 + square(sv) * y; + result = (normal_or_log == 1) ? ans * exp(ld) : ans; + break; + case FunType::GradA: + la = log(a); + ly = log(y); + factor = lg1 - 3 * la; + ld = wiener5_helper( + y, a, vn, wn, sv, + err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); + ans = ans0 - 2.0 / a + + newsign * exp(ly + factor + 3.0 * LOG_PI + erg - ld); + result = (normal_or_log == 1) ? ans * exp(ld) : ans; + break; + case FunType::GradW: + ld = wiener5_helper(y, a, vn, wn, sv, + err - log(fabs(ans0))); + ls = -lg1 + ld; + ans = ans0 + newsign * exp(erg - ls + 2 * LOG_PI); + result = (normal_or_log == 1) ? -ans * exp(ld) : -ans; + break; + case FunType::GradV: + break; + case FunType::GradSV: + break; + } } - return ans; -} -//----------------------------------------------- - -// d/dw DENSITY -// calculate derivative of density with respect to w (in log, ans = -// d/dw(log(f))=d/dw f'/f; ans*exp(ld)=f' on normal scale) -inline double dwdwiener5(const double& y, const double& a, const double& vn, - const double& wn, const double& sv, const double& err, - const int& normal_or_log) { - const auto& kss_functor - = [&](double erg, int newsign, double lg1, double ans0) { - double ld = dwiener5(y, a, vn, wn, sv, err - log(fabs(ans0))); - double ls = -lg1 + ld; - double ans = ans0 - - newsign - * exp(erg - ls - 2.5 * log(y / square(a)) - - 0.5 * LOG_TWO - 0.5 * LOG_PI); - return (normal_or_log == 1) ? -ans * exp(ld) : -ans; - }; - const auto& kll_functor - = [&](double erg, int newsign, double lg1, double ans0) { - double ld = dwiener5(y, a, vn, wn, sv, err - log(fabs(ans0))); - double ll = -lg1 + ld; - double ans = ans0 + newsign * exp(erg - ll + 2 * LOG_PI); - return (normal_or_log == 1) ? -ans * exp(ld) : -ans; - }; - - return wiener5_helper(y, a, vn, wn, sv, err, kss_functor, - kll_functor); -} -//----------------------------------------------- - -// d/dsv DENSITY -// calculate derivative of density with respect to sv (in log, ans = -// d/dsv(log(f))=d/dsv f'/f; ans*exp(ld)=f' on normal scale) -inline double dsvdwiener5(const double& y, const double& a, const double& vn, - const double& wn, const double& sv) { - double v, w; - v = -vn; - w = 1 - wn; - double one_sqrsv_y = 1 + square(sv) * y; - double t1 = -y / one_sqrsv_y; - double t2 = (square(a * w) + 2 * a * v * w * y + square(v * y)) - / square(one_sqrsv_y); - return sv * (t1 + t2); + return result; } -//----------------------------------------------- - } // namespace internal template wiener5_lpdf( sv_val, labstol_wiener5, 0); dens = internal::estimate_with_err_check<5>( - internal::dwiener5, lerror_bound_dens - LOG_TWO, params, true); + internal::wiener5_helper, + lerror_bound_dens - LOG_TWO, params, true); ld += dens; // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 double deriv_y = internal::estimate_with_err_check<5>( - internal::dtdwiener5, dens + lerror_bound - LOG_TWO, params); + internal::wiener5_helper, + dens + lerror_bound - LOG_TWO, params); // computation of derivatives and precision checks if (!is_constant_all::value) { @@ -451,22 +403,26 @@ inline return_type_t wiener5_lpdf( } if (!is_constant_all::value) { ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check<5>( - internal::dadwiener5, dens + lerror_bound - LOG_FOUR, params); + internal::wiener5_helper, + dens + lerror_bound - LOG_FOUR, params); } if (!is_constant_all::value) { ops_partials.edge3_.partials_[i] = -deriv_y; } if (!is_constant_all::value) { ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check<5>( - internal::dwdwiener5, dens + lerror_bound - LOG_FOUR, params); + internal::wiener5_helper, + dens + lerror_bound - LOG_FOUR, params); } if (!is_constant_all::value) { ops_partials.edge5_.partials_[i] - = internal::dvdwiener5(y_val - t0_val, a_val, v_val, w_val, sv_val); + = internal::wiener5_helper( + y_val - t0_val, a_val, v_val, w_val, sv_val); } if (!is_constant_all::value) { ops_partials.edge6_.partials_[i] - = internal::dsvdwiener5(y_val - t0_val, a_val, v_val, w_val, sv_val); + = internal::wiener5_helper( + y_val - t0_val, a_val, v_val, w_val, sv_val); } } // end for loop return ops_partials.build(ld); diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index c4735969351..0a20b48dc50 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -42,24 +42,28 @@ inline double wiener7_impl(double t0_, double omega, double y, double a, double result; switch (FunTypeEnum) { case FunType::Density: - result = exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); + result + = exp(wiener5_helper(y - t0_, a, v, omega, sv, lerr)); break; case FunType::GradT: - result = dtdwiener5(y - t0_, a, v, omega, sv, lerr, 1); + result + = wiener5_helper(y - t0_, a, v, omega, sv, lerr, 1); break; case FunType::GradA: - result = dadwiener5(y - t0_, a, v, omega, sv, lerr, 1); + result + = wiener5_helper(y - t0_, a, v, omega, sv, lerr, 1); break; case FunType::GradW: - result = dwdwiener5(y - t0_, a, v, omega, sv, lerr, 1); + result + = wiener5_helper(y - t0_, a, v, omega, sv, lerr, 1); break; case FunType::GradV: - result = dvdwiener5(y - t0_, a, v, omega, sv) - * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); + result = wiener5_helper(y - t0_, a, v, omega, sv) + * exp(wiener5_helper(y - t0_, a, v, omega, sv, lerr)); break; case FunType::GradSV: - result = dsvdwiener5(y - t0_, a, v, omega, sv) - * exp(dwiener5(y - t0_, a, v, omega, sv, lerr)); + result = wiener5_helper(y - t0_, a, v, omega, sv) + * exp(wiener5_helper(y - t0_, a, v, omega, sv, lerr)); break; } return result; @@ -69,8 +73,10 @@ inline double int_dswddiff(double t0_, double omega, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double lerr, double w_lower, double w_upper, double sw_mean) { - double fl = exp(internal::dwiener5(y - t0_, a, v, w_lower, sv, lerr)); - double fu = exp(internal::dwiener5(y - t0_, a, v, w_upper, sv, lerr)); + double fl + = exp(wiener5_helper(y - t0_, a, v, w_lower, sv, lerr)); + double fu + = exp(wiener5_helper(y - t0_, a, v, w_upper, sv, lerr)); return 0.5 * (fl + fu) / sw_mean; } } // namespace internal From e5e58d75afcd451579f1f531dfb84ad29131ff37 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 7 May 2023 14:19:57 -0400 Subject: [PATCH 042/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 40 +++++++++++++++------------- stan/math/prim/prob/wiener7_lpdf.hpp | 20 +++++++------- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 01e65b91fb9..abd05378bee 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -33,9 +33,9 @@ enum class FunType { Density, GradT, GradA, GradV, GradW, GradSV }; template inline double wiener5_helper(const double& y, const double& a, const double& vn, - const double& wn, const double& sv, - const double& err = log(1e-12), - int normal_or_log = 0) { + const double& wn, const double& sv, + const double& err = log(1e-12), + int normal_or_log = 0) { if (FunTypeEnum == FunType::GradV) { double ans = (a * (1 - wn) - vn * y); if (sv != 0) { @@ -176,15 +176,15 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, switch (FunTypeEnum) { case FunType::Density: result = lg1 - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log(y / square(a)) - + erg; + + erg; break; case FunType::GradT: - ld = wiener5_helper(y, a, vn, wn, sv, - err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); + ld = wiener5_helper( + y, a, vn, wn, sv, err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); ans = ans0 - 1.5 / y - + newsign - * exp(lg1 - 2.0 * log(a) - 1.5 * LOG_TWO - LOG_SQRT_PI - - 3.5 * log(y / square(a)) + erg - ld); + + newsign + * exp(lg1 - 2.0 * log(a) - 1.5 * LOG_TWO - LOG_SQRT_PI + - 3.5 * log(y / square(a)) + erg - ld); result = (normal_or_log == 1) ? ans * exp(ld) : ans; break; case FunType::GradA: @@ -195,9 +195,9 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, y, a, vn, wn, sv, err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); ans = ans0 + 1.0 / a - - newsign - * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * ly - + 4.0 * la + lg1 + erg - ld); + - newsign + * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * ly + 4.0 * la + + lg1 + erg - ld); result = (normal_or_log == 1) ? ans * exp(ld) : ans; break; case FunType::GradW: @@ -205,9 +205,9 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, err - log(fabs(ans0))); ls = -lg1 + ld; ans = ans0 - - newsign - * exp(erg - ls - 2.5 * log(y / square(a)) - - 0.5 * LOG_TWO - 0.5 * LOG_PI); + - newsign + * exp(erg - ls - 2.5 * log(y / square(a)) - 0.5 * LOG_TWO + - 0.5 * LOG_PI); result = (normal_or_log == 1) ? -ans * exp(ld) : -ans; break; case FunType::GradV: @@ -245,10 +245,12 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, result = lg1 + erg + LOG_PI; break; case FunType::GradT: - ld = wiener5_helper(y, a, vn, wn, sv, - err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); - ans = ans0 - newsign - * exp(lg1 - 2.0 * log(a) + 3.0 * LOG_PI - LOG_TWO + erg - ld); + ld = wiener5_helper( + y, a, vn, wn, sv, err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); + ans = ans0 + - newsign + * exp(lg1 - 2.0 * log(a) + 3.0 * LOG_PI - LOG_TWO + erg + - ld); result = (normal_or_log == 1) ? ans * exp(ld) : ans; break; case FunType::GradA: diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index 0a20b48dc50..1becb0b8259 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -42,28 +42,30 @@ inline double wiener7_impl(double t0_, double omega, double y, double a, double result; switch (FunTypeEnum) { case FunType::Density: - result - = exp(wiener5_helper(y - t0_, a, v, omega, sv, lerr)); + result = exp( + wiener5_helper(y - t0_, a, v, omega, sv, lerr)); break; case FunType::GradT: result - = wiener5_helper(y - t0_, a, v, omega, sv, lerr, 1); + = wiener5_helper(y - t0_, a, v, omega, sv, lerr, 1); break; case FunType::GradA: result - = wiener5_helper(y - t0_, a, v, omega, sv, lerr, 1); + = wiener5_helper(y - t0_, a, v, omega, sv, lerr, 1); break; case FunType::GradW: result - = wiener5_helper(y - t0_, a, v, omega, sv, lerr, 1); + = wiener5_helper(y - t0_, a, v, omega, sv, lerr, 1); break; case FunType::GradV: result = wiener5_helper(y - t0_, a, v, omega, sv) - * exp(wiener5_helper(y - t0_, a, v, omega, sv, lerr)); + * exp(wiener5_helper(y - t0_, a, v, omega, sv, + lerr)); break; case FunType::GradSV: result = wiener5_helper(y - t0_, a, v, omega, sv) - * exp(wiener5_helper(y - t0_, a, v, omega, sv, lerr)); + * exp(wiener5_helper(y - t0_, a, v, omega, sv, + lerr)); break; } return result; @@ -74,9 +76,9 @@ inline double int_dswddiff(double t0_, double omega, double y, double a, double st0, double lerr, double w_lower, double w_upper, double sw_mean) { double fl - = exp(wiener5_helper(y - t0_, a, v, w_lower, sv, lerr)); + = exp(wiener5_helper(y - t0_, a, v, w_lower, sv, lerr)); double fu - = exp(wiener5_helper(y - t0_, a, v, w_upper, sv, lerr)); + = exp(wiener5_helper(y - t0_, a, v, w_upper, sv, lerr)); return 0.5 * (fl + fu) / sw_mean; } } // namespace internal From d0598d2d041df5e4009e1d094fe89cfc0db6315a Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 8 May 2023 00:34:58 +0300 Subject: [PATCH 043/179] Simplify wiener5 --- stan/math/prim/prob/wiener5_lpdf.hpp | 249 ++++++++++----------------- 1 file changed, 89 insertions(+), 160 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index abd05378bee..3e60b32dba4 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -47,21 +47,23 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, double v = -vn; double sv_sqr = square(sv); double one_plus_svsqr_y = 1 + sv_sqr * y; + double two_avw = 2 * a * v * w; + double two_log_a = 2 * log(a); if (FunTypeEnum == FunType::GradSV) { double t1 = -y / one_plus_svsqr_y; - double t2 = (square(a * w) + 2 * a * v * w * y + square(v * y)) + double t2 = (square(a * w) + two_avw * y + square(v * y)) / square(one_plus_svsqr_y); return sv * (t1 + t2); } double lg1; if (sv != 0) { - lg1 = (sv_sqr * square(a * w) - 2 * a * v * w - square(v) * y) / 2.0 + lg1 = (sv_sqr * square(a * w) - two_avw - square(v) * y) / 2.0 / one_plus_svsqr_y - - 2 * log(a) - 0.5 * log(one_plus_svsqr_y); + - two_log_a - 0.5 * log(one_plus_svsqr_y); } else { - lg1 = (-2 * a * v * w - square(v) * y) / 2.0 - 2 * log(a); + lg1 = (-two_avw - square(v) * y) / 2.0 - two_log_a; } double ans0 = 0; if (FunTypeEnum != FunType::Density) { @@ -71,7 +73,7 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, if (FunTypeEnum == FunType::GradT) { ans0 = -0.5 * (square(sv_sqr) * (y + square(a * w)) - + sv_sqr * (1 - 2 * a * v * w) + square(v)) + + sv_sqr * (1 - two_avw) + square(v)) / square(one_plus_svsqr_y); } else { ans0 = (-v * var_a + sv_sqr * square(var_a) * var_b) / one_plus_svsqr_y; @@ -81,27 +83,22 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, } } - double es = (err - lg1); - if (FunTypeEnum == FunType::GradT) { - es += 2.0 * log(a); - } + double es = (err - lg1) + (FunTypeEnum == FunType::GradT) * two_log_a; + double two_es = 2.0 * es; double y_asq = y / square(a); + double log_y_asq = log(y) - two_log_a; double K1, u_eps, arg; - if (FunTypeEnum == FunType::Density) { - K1 = (sqrt(2.0 * y_asq) + w) / 2.0; - u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log(y_asq) + 2.0 * (es)); - arg = -y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + double K1_mult = (FunTypeEnum == FunType::Density) ? 2 : 3; + K1 = (sqrt(K1_mult * y_asq) + w) / 2.0; + if (FunTypeEnum == FunType::Density || FunTypeEnum == FunType::GradW) { + u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log_y_asq + two_es); } else { - K1 = (sqrt(3.0 * y_asq) + w) / 2.0; - if (FunTypeEnum == FunType::GradW) { - u_eps = fmin(-1.0, 2.0 * es + LOG_TWO + LOG_PI + 2.0 * log(y_asq)); - } else { - u_eps = fmin( - -1.0, (log(8.0 / 27.0) + LOG_PI + 4.0 * log(y_asq) + 2.0 * es) / 3.0); - } - arg = -3.0 * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + u_eps + = fmin(-3.0, (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_es)); } + double arg_mult = (FunTypeEnum == FunType::Density) ? 1 : 3; + arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); double K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; size_t kss = static_cast(ceil(fmax(K1, K2))); @@ -109,111 +106,74 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, static const double PISQ = square(pi()); // pi*pi if (FunTypeEnum == FunType::Density) { K1 = 1.0 / (pi() * sqrt(y_asq)); - double two_log_piy = -2.0 * (log(pi() * y_asq) + es); + double two_log_piy = -2.0 * (LOG_PI + log_y_asq + es); K2 = (two_log_piy >= 0) ? sqrt(two_log_piy / (PISQ * y_asq)) : 0.0; - } else if (FunTypeEnum == FunType::GradT) { - K1 = sqrt(3.0 / y_asq) / pi(); - u_eps = fmin(-1.0, es + log(0.6) + LOG_PI + 2.0 * log(y_asq)); - arg = -2.0 / PISQ / y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - K2 = (arg > 0) ? sqrt(arg) : K1; - } else if (FunTypeEnum == FunType::GradW) { - K1 = sqrt(2.0 / y_asq) / pi(); - u_eps = fmin(-1.0, - log(4.0 / 9.0) + 2.0 * LOG_PI + 3.0 * log(y_asq) + 2.0 * es); - arg = -(u_eps - sqrt(-2.0 * u_eps - 2.0)); - K2 = (arg > 0) ? 1.0 / pi() * sqrt(arg / y_asq) : K1; + } else { + K1_mult = (FunTypeEnum == FunType::GradT) ? 2 : 3; + K1 = sqrt(K1_mult / y_asq) / pi(); + u_eps = (FunTypeEnum == FunType::GradT) + ? fmin(-1, log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es) + : fmin(-1, log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + + two_es); + arg_mult = (FunTypeEnum == FunType::GradT) ? (2.0 / PISQ / y_asq) : 1; + arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + K2 = (FunTypeEnum == FunType::GradT) + ? (arg > 0) ? sqrt(arg) : K1 + : (arg > 0) ? sqrt(arg / y_asq) / pi() : K1; } + size_t kll = static_cast(ceil(fmax(K1, K2))); - double erg; - int newsign; - double fplus = NEGATIVE_INFTY; - double fminus = NEGATIVE_INFTY; - double twoy = 2.0 * y_asq; - double result; - double ld; + double ld = 0; + double ld_err; + if (FunTypeEnum != FunType::Density) { + if (FunTypeEnum == FunType::GradT) { + ld_err = log(max(fabs(ans0 - 1.5 / y), fabs(ans0))); + } else if (FunTypeEnum == FunType::GradA) { + ld_err = log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a))); + } else if (FunTypeEnum == FunType::GradW) { + ld_err = log(fabs(ans0)); + } + ld = wiener5_helper(y, a, vn, wn, sv, err - ld_err); + } + + double erg = NEGATIVE_INFTY; + int newsign = 1; + double scaling = (2 * kss <= kll) ? inv(2.0 * y_asq) : y_asq / 2.0; double ans; - double la, ly, factor, ls; if (2 * kss <= kll) { double mult = (FunTypeEnum == FunType::Density) ? 1 : 3; double offset = (FunTypeEnum == FunType::GradW) ? y_asq : 0; double sqrt_offset = sqrt(offset); - if (kss > 0) { - for (size_t k = kss; k >= 1; k--) { - double wp2k = w + 2.0 * k; - double wm2k = w - 2.0 * k; - - if (wp2k > sqrt_offset) { - fplus = log_sum_exp( - mult * log(wp2k - offset) - (square(wp2k) - offset) / twoy, - fplus); - } else { - fminus = log_sum_exp( - mult * log(-(wp2k - offset)) - (square(wp2k) - offset) / twoy, - fminus); - } - - if (wm2k > sqrt_offset) { - fplus = log_sum_exp( - mult * log(wm2k - offset) - (square(wm2k) - offset) / twoy, - fplus); - } else { - fminus = log_sum_exp( - mult * log(-(wm2k - offset)) - (square(wm2k) - offset) / twoy, - fminus); - } - } - } - if (w > sqrt_offset) { - fplus = log_sum_exp(mult * log(w - offset) - square(w) / twoy, fplus); - } else { - fminus - = log_sum_exp(mult * log(-(w - offset)) - square(w) / twoy, fminus); + for (size_t k = kss; k >= 0; k--) { + double wp2k = w + 2.0 * k; + double wm2k = w - 2.0 * k; + int wp2k_sign = (wp2k > sqrt_offset) ? 1 : -1; + int wm2k_sign = (wm2k > sqrt_offset) ? 1 : -1; + double wp2k_quant = log(wp2k_sign * (wp2k - offset)) + - (square(wp2k) - offset) * scaling; + double wm2k_quant = log(wm2k_sign * (wm2k - offset)) + - (square(wm2k) - offset) * scaling; + std::forward_as_tuple(erg, newsign) + = log_sum_exp_signed(erg, newsign, mult * wp2k_quant, wp2k_sign); + std::forward_as_tuple(erg, newsign) + = log_sum_exp_signed(erg, newsign, mult * wm2k_quant, -1 * wm2k_sign); } - erg = (fplus < fminus) ? log_diff_exp(fminus, fplus) - : log_diff_exp(fplus, fminus); - newsign = (fplus < fminus) ? -1 : 1; - switch (FunTypeEnum) { - case FunType::Density: - result = lg1 - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log(y / square(a)) - + erg; - break; - case FunType::GradT: - ld = wiener5_helper( - y, a, vn, wn, sv, err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); + if (FunTypeEnum == FunType::Density) { + ans = lg1 - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log_y_asq + erg; + } else if (FunTypeEnum == FunType::GradT) { ans = ans0 - 1.5 / y - + newsign - * exp(lg1 - 2.0 * log(a) - 1.5 * LOG_TWO - LOG_SQRT_PI - - 3.5 * log(y / square(a)) + erg - ld); - result = (normal_or_log == 1) ? ans * exp(ld) : ans; - break; - case FunType::GradA: - la = log(a); - ly = log(y); - factor = lg1 - 3 * la; - ld = wiener5_helper( - y, a, vn, wn, sv, - err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); + + newsign + * exp(lg1 - two_log_a - 1.5 * LOG_TWO - LOG_SQRT_PI + - 3.5 * log_y_asq + erg - ld); + } else if (FunTypeEnum == FunType::GradA) { ans = ans0 + 1.0 / a - - newsign - * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * ly + 4.0 * la - + lg1 + erg - ld); - result = (normal_or_log == 1) ? ans * exp(ld) : ans; - break; - case FunType::GradW: - ld = wiener5_helper(y, a, vn, wn, sv, - err - log(fabs(ans0))); - ls = -lg1 + ld; - ans = ans0 - - newsign - * exp(erg - ls - 2.5 * log(y / square(a)) - 0.5 * LOG_TWO - - 0.5 * LOG_PI); - result = (normal_or_log == 1) ? -ans * exp(ld) : -ans; - break; - case FunType::GradV: - break; - case FunType::GradSV: - break; + - newsign + * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * log(y) + + 2.0 * two_log_a + lg1 + erg - ld); + } else if (FunTypeEnum == FunType::GradW) { + ans = -(ans0 - newsign * exp(erg - (ld - lg1) - 2.5 * log_y_asq + - 0.5 * LOG_TWO - 0.5 * LOG_PI)); } } else { double mult; @@ -224,60 +184,29 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, } else { mult = 3; } - double halfy = y_asq / 2.0; for (size_t k = kll; k >= 1; k--) { double pi_k = k * pi(); double check = (FunTypeEnum == FunType::GradW) ? cos(pi_k * w) : sin(pi_k * w); - if (check > 0) { - fplus = log_sum_exp(mult * log(k) - square(pi_k) * halfy + log(check), - fplus); - } else { - fminus = log_sum_exp(mult * log(k) - square(pi_k) * halfy + log(-check), - fminus); - } + int check_sign = sign(check); + double kll_quant = mult * log(k) - square(pi_k) * scaling + + log(fabs(check)); + std::forward_as_tuple(erg, newsign) + = log_sum_exp_signed(erg, newsign, kll_quant, check_sign); } - erg = (fplus < fminus) ? log_diff_exp(fminus, fplus) - : log_diff_exp(fplus, fminus); - newsign = (fplus < fminus) ? -1 : 1; - switch (FunTypeEnum) { - case FunType::Density: - result = lg1 + erg + LOG_PI; - break; - case FunType::GradT: - ld = wiener5_helper( - y, a, vn, wn, sv, err - log(max(fabs(ans0 - 1.5 / y), fabs(ans0)))); - ans = ans0 - - newsign - * exp(lg1 - 2.0 * log(a) + 3.0 * LOG_PI - LOG_TWO + erg - - ld); - result = (normal_or_log == 1) ? ans * exp(ld) : ans; - break; - case FunType::GradA: - la = log(a); - ly = log(y); - factor = lg1 - 3 * la; - ld = wiener5_helper( - y, a, vn, wn, sv, - err - log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a)))); + if (FunTypeEnum == FunType::Density) { + ans = lg1 + erg + LOG_PI; + } else if (FunTypeEnum == FunType::GradT) { + ans = ans0 - newsign + * exp(lg1 - two_log_a + 3.0 * LOG_PI - LOG_TWO + erg - ld); + } else if (FunTypeEnum == FunType::GradA) { ans = ans0 - 2.0 / a - + newsign * exp(ly + factor + 3.0 * LOG_PI + erg - ld); - result = (normal_or_log == 1) ? ans * exp(ld) : ans; - break; - case FunType::GradW: - ld = wiener5_helper(y, a, vn, wn, sv, - err - log(fabs(ans0))); - ls = -lg1 + ld; - ans = ans0 + newsign * exp(erg - ls + 2 * LOG_PI); - result = (normal_or_log == 1) ? -ans * exp(ld) : -ans; - break; - case FunType::GradV: - break; - case FunType::GradSV: - break; + + newsign * exp(log(y) + lg1 - 3 * (log(a) - LOG_PI) + erg - ld); + } else if (FunTypeEnum == FunType::GradW) { + ans = -(ans0 + newsign * exp(erg - (ld - lg1) + 2 * LOG_PI)); } } - return result; + return (normal_or_log == 1) ? ans * exp(ld) : ans; } } // namespace internal From 1c7a50999a906abdea4a8f7931cd726f13df6896 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 7 May 2023 17:36:11 -0400 Subject: [PATCH 044/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 65 +++++++++++++++------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 3e60b32dba4..19371c6772a 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -72,8 +72,8 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, if (sv != 0) { if (FunTypeEnum == FunType::GradT) { ans0 = -0.5 - * (square(sv_sqr) * (y + square(a * w)) - + sv_sqr * (1 - two_avw) + square(v)) + * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - two_avw) + + square(v)) / square(one_plus_svsqr_y); } else { ans0 = (-v * var_a + sv_sqr * square(var_a) * var_b) / one_plus_svsqr_y; @@ -94,8 +94,8 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, if (FunTypeEnum == FunType::Density || FunTypeEnum == FunType::GradW) { u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log_y_asq + two_es); } else { - u_eps - = fmin(-3.0, (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_es)); + u_eps = fmin(-3.0, + (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_es)); } double arg_mult = (FunTypeEnum == FunType::Density) ? 1 : 3; arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); @@ -112,14 +112,14 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, K1_mult = (FunTypeEnum == FunType::GradT) ? 2 : 3; K1 = sqrt(K1_mult / y_asq) / pi(); u_eps = (FunTypeEnum == FunType::GradT) - ? fmin(-1, log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es) - : fmin(-1, log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq - + two_es); + ? fmin(-1, log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es) + : fmin(-1, log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + + two_es); arg_mult = (FunTypeEnum == FunType::GradT) ? (2.0 / PISQ / y_asq) : 1; arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); K2 = (FunTypeEnum == FunType::GradT) - ? (arg > 0) ? sqrt(arg) : K1 - : (arg > 0) ? sqrt(arg / y_asq) / pi() : K1; + ? (arg > 0) ? sqrt(arg) : K1 + : (arg > 0) ? sqrt(arg / y_asq) / pi() : K1; } size_t kll = static_cast(ceil(fmax(K1, K2))); @@ -155,25 +155,27 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, double wm2k_quant = log(wm2k_sign * (wm2k - offset)) - (square(wm2k) - offset) * scaling; std::forward_as_tuple(erg, newsign) - = log_sum_exp_signed(erg, newsign, mult * wp2k_quant, wp2k_sign); + = log_sum_exp_signed(erg, newsign, mult * wp2k_quant, wp2k_sign); std::forward_as_tuple(erg, newsign) - = log_sum_exp_signed(erg, newsign, mult * wm2k_quant, -1 * wm2k_sign); + = log_sum_exp_signed(erg, newsign, mult * wm2k_quant, -1 * wm2k_sign); } if (FunTypeEnum == FunType::Density) { - ans = lg1 - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log_y_asq + erg; + ans = lg1 - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log_y_asq + erg; } else if (FunTypeEnum == FunType::GradT) { - ans = ans0 - 1.5 / y - + newsign - * exp(lg1 - two_log_a - 1.5 * LOG_TWO - LOG_SQRT_PI - - 3.5 * log_y_asq + erg - ld); + ans = ans0 - 1.5 / y + + newsign + * exp(lg1 - two_log_a - 1.5 * LOG_TWO - LOG_SQRT_PI + - 3.5 * log_y_asq + erg - ld); } else if (FunTypeEnum == FunType::GradA) { - ans = ans0 + 1.0 / a - - newsign - * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * log(y) - + 2.0 * two_log_a + lg1 + erg - ld); + ans = ans0 + 1.0 / a + - newsign + * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * log(y) + + 2.0 * two_log_a + lg1 + erg - ld); } else if (FunTypeEnum == FunType::GradW) { - ans = -(ans0 - newsign * exp(erg - (ld - lg1) - 2.5 * log_y_asq - - 0.5 * LOG_TWO - 0.5 * LOG_PI)); + ans = -(ans0 + - newsign + * exp(erg - (ld - lg1) - 2.5 * log_y_asq - 0.5 * LOG_TWO + - 0.5 * LOG_PI)); } } else { double mult; @@ -189,21 +191,22 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, double check = (FunTypeEnum == FunType::GradW) ? cos(pi_k * w) : sin(pi_k * w); int check_sign = sign(check); - double kll_quant = mult * log(k) - square(pi_k) * scaling - + log(fabs(check)); + double kll_quant + = mult * log(k) - square(pi_k) * scaling + log(fabs(check)); std::forward_as_tuple(erg, newsign) - = log_sum_exp_signed(erg, newsign, kll_quant, check_sign); + = log_sum_exp_signed(erg, newsign, kll_quant, check_sign); } if (FunTypeEnum == FunType::Density) { - ans = lg1 + erg + LOG_PI; + ans = lg1 + erg + LOG_PI; } else if (FunTypeEnum == FunType::GradT) { - ans = ans0 - newsign - * exp(lg1 - two_log_a + 3.0 * LOG_PI - LOG_TWO + erg - ld); + ans = ans0 + - newsign + * exp(lg1 - two_log_a + 3.0 * LOG_PI - LOG_TWO + erg - ld); } else if (FunTypeEnum == FunType::GradA) { - ans = ans0 - 2.0 / a - + newsign * exp(log(y) + lg1 - 3 * (log(a) - LOG_PI) + erg - ld); + ans = ans0 - 2.0 / a + + newsign * exp(log(y) + lg1 - 3 * (log(a) - LOG_PI) + erg - ld); } else if (FunTypeEnum == FunType::GradW) { - ans = -(ans0 + newsign * exp(erg - (ld - lg1) + 2 * LOG_PI)); + ans = -(ans0 + newsign * exp(erg - (ld - lg1) + 2 * LOG_PI)); } } return (normal_or_log == 1) ? ans * exp(ld) : ans; From 96ec686d6c4d96a46b4dc7f92cb30cb98dcc6ca2 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 8 May 2023 01:08:17 +0300 Subject: [PATCH 045/179] Additional simplifications --- stan/math/prim/prob/wiener5_lpdf.hpp | 19 +++--------- stan/math/prim/prob/wiener7_lpdf.hpp | 43 ++++++++-------------------- 2 files changed, 16 insertions(+), 46 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 19371c6772a..de750b9d79b 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -178,13 +178,11 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, - 0.5 * LOG_PI)); } } else { - double mult; + double mult = 3; if (FunTypeEnum == FunType::Density) { mult = 1; } else if (FunTypeEnum == FunType::GradW) { mult = 2; - } else { - mult = 3; } for (size_t k = kll; k >= 1; k--) { double pi_k = k * pi(); @@ -286,24 +284,15 @@ inline return_type_t wiener5_lpdf( return 0; } - double error_bound_dens = 1e-6; // precision for density - double lerror_bound_dens = log(error_bound_dens); - double error_bound = prec; // precision for - // derivatives (controllable by user) - double lerror_bound = log(error_bound); // log(alpha) - double abstol = 0.0; - double reltol = .9 * error_bound; // eps_rel(Integration) - double abstol_wiener5 = 1e-12; // eps_abs(wiener5) - double labstol_wiener5 = log(abstol_wiener5); - // log(eps_abs(wiener5) - int Meval = 6000; + double lerror_bound_dens = log(1e-6); // precision for density + double lerror_bound = log(prec); // precision for derivatives + double labstol_wiener5 = log(1e-12); // eps_abs(wiener5) double dens = 0.0; double ld = 0.0; operands_and_partials ops_partials(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref); static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; - static constexpr double LOG_POINT1 = -1; // calculate density and partials for (size_t i = 0; i < N; i++) { diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index 1becb0b8259..7df35b6be2a 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -39,36 +39,17 @@ template inline double wiener7_impl(double t0_, double omega, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double lerr) { - double result; - switch (FunTypeEnum) { - case FunType::Density: - result = exp( - wiener5_helper(y - t0_, a, v, omega, sv, lerr)); - break; - case FunType::GradT: - result - = wiener5_helper(y - t0_, a, v, omega, sv, lerr, 1); - break; - case FunType::GradA: - result - = wiener5_helper(y - t0_, a, v, omega, sv, lerr, 1); - break; - case FunType::GradW: - result - = wiener5_helper(y - t0_, a, v, omega, sv, lerr, 1); - break; - case FunType::GradV: - result = wiener5_helper(y - t0_, a, v, omega, sv) - * exp(wiener5_helper(y - t0_, a, v, omega, sv, - lerr)); - break; - case FunType::GradSV: - result = wiener5_helper(y - t0_, a, v, omega, sv) - * exp(wiener5_helper(y - t0_, a, v, omega, sv, - lerr)); - break; + if (FunTypeEnum == FunType::GradT || FunTypeEnum == FunType::GradA + || FunTypeEnum == FunType::GradW) { + return wiener5_helper(y - t0_, a, v, omega, sv, lerr, 1); + } + double dens + = exp(wiener5_helper(y - t0_, a, v, omega, sv, lerr)); + if (FunTypeEnum == FunType::Density) { + return dens; + } else { + return wiener5_helper(y - t0_, a, v, omega, sv) * dens; } - return result; } inline double int_dswddiff(double t0_, double omega, double y, double a, @@ -76,9 +57,9 @@ inline double int_dswddiff(double t0_, double omega, double y, double a, double st0, double lerr, double w_lower, double w_upper, double sw_mean) { double fl - = exp(wiener5_helper(y - t0_, a, v, w_lower, sv, lerr)); + = exp(wiener5_helper(y - t0_, a, v, w_lower, sv, lerr)); double fu - = exp(wiener5_helper(y - t0_, a, v, w_upper, sv, lerr)); + = exp(wiener5_helper(y - t0_, a, v, w_upper, sv, lerr)); return 0.5 * (fl + fu) / sw_mean; } } // namespace internal From 44508550ebd65856cbe08b210a41791de40ecf7f Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 7 May 2023 18:09:34 -0400 Subject: [PATCH 046/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 4 ++-- stan/math/prim/prob/wiener7_lpdf.hpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index de750b9d79b..ba8d60bb768 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -285,8 +285,8 @@ inline return_type_t wiener5_lpdf( } double lerror_bound_dens = log(1e-6); // precision for density - double lerror_bound = log(prec); // precision for derivatives - double labstol_wiener5 = log(1e-12); // eps_abs(wiener5) + double lerror_bound = log(prec); // precision for derivatives + double labstol_wiener5 = log(1e-12); // eps_abs(wiener5) double dens = 0.0; double ld = 0.0; operands_and_partials diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index 7df35b6be2a..b108d765def 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -44,7 +44,7 @@ inline double wiener7_impl(double t0_, double omega, double y, double a, return wiener5_helper(y - t0_, a, v, omega, sv, lerr, 1); } double dens - = exp(wiener5_helper(y - t0_, a, v, omega, sv, lerr)); + = exp(wiener5_helper(y - t0_, a, v, omega, sv, lerr)); if (FunTypeEnum == FunType::Density) { return dens; } else { @@ -57,9 +57,9 @@ inline double int_dswddiff(double t0_, double omega, double y, double a, double st0, double lerr, double w_lower, double w_upper, double sw_mean) { double fl - = exp(wiener5_helper(y - t0_, a, v, w_lower, sv, lerr)); + = exp(wiener5_helper(y - t0_, a, v, w_lower, sv, lerr)); double fu - = exp(wiener5_helper(y - t0_, a, v, w_upper, sv, lerr)); + = exp(wiener5_helper(y - t0_, a, v, w_upper, sv, lerr)); return 0.5 * (fl + fu) / sw_mean; } } // namespace internal From cb09fbe2c2b90b3afdf90113c4c9f902ac1057d3 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 8 May 2023 09:29:54 +0300 Subject: [PATCH 047/179] Fix test, consolidate wiener7 derivs --- stan/math/prim/prob/wiener5_lpdf.hpp | 23 ++++-- stan/math/prim/prob/wiener7_lpdf.hpp | 106 +++++++++++---------------- 2 files changed, 58 insertions(+), 71 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index ba8d60bb768..524f36468f2 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -29,7 +29,7 @@ double estimate_with_err_check(const F& functor, double err, return result; } -enum class FunType { Density, GradT, GradA, GradV, GradW, GradSV }; +enum class FunType { Density, GradT, GradA, GradV, GradW, GradSV, GradSW }; template inline double wiener5_helper(const double& y, const double& a, const double& vn, @@ -41,7 +41,9 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, if (sv != 0) { ans /= 1 + square(sv) * y; } - return ans; + return (normal_or_log == 1) + ? ans * wiener5_helper(y, a, vn, wn, sv, err, 1) + : ans; } double w = 1.0 - wn; double v = -vn; @@ -54,7 +56,11 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, double t1 = -y / one_plus_svsqr_y; double t2 = (square(a * w) + two_avw * y + square(v * y)) / square(one_plus_svsqr_y); - return sv * (t1 + t2); + double ans = sv * (t1 + t2); + + return (normal_or_log == 1) + ? ans * wiener5_helper(y, a, vn, wn, sv, err, 1) + : ans; } double lg1; @@ -125,13 +131,13 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, size_t kll = static_cast(ceil(fmax(K1, K2))); double ld = 0; - double ld_err; + double ld_err = 0; if (FunTypeEnum != FunType::Density) { if (FunTypeEnum == FunType::GradT) { ld_err = log(max(fabs(ans0 - 1.5 / y), fabs(ans0))); } else if (FunTypeEnum == FunType::GradA) { ld_err = log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a))); - } else if (FunTypeEnum == FunType::GradW) { + } else { ld_err = log(fabs(ans0)); } ld = wiener5_helper(y, a, vn, wn, sv, err - ld_err); @@ -145,7 +151,7 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, double mult = (FunTypeEnum == FunType::Density) ? 1 : 3; double offset = (FunTypeEnum == FunType::GradW) ? y_asq : 0; double sqrt_offset = sqrt(offset); - for (size_t k = kss; k >= 0; k--) { + for (size_t k = kss; k >= std::fmax(0, kss - 1e4); k--) { double wp2k = w + 2.0 * k; double wm2k = w - 2.0 * k; int wp2k_sign = (wp2k > sqrt_offset) ? 1 : -1; @@ -184,7 +190,7 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, } else if (FunTypeEnum == FunType::GradW) { mult = 2; } - for (size_t k = kll; k >= 1; k--) { + for (size_t k = kll; k >= std::fmax(1, kll - 1e4); k--) { double pi_k = k * pi(); double check = (FunTypeEnum == FunType::GradW) ? cos(pi_k * w) : sin(pi_k * w); @@ -207,6 +213,9 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, ans = -(ans0 + newsign * exp(erg - (ld - lg1) + 2 * LOG_PI)); } } + if (FunTypeEnum == FunType::Density && normal_or_log == 1) { + return exp(ans); + } return (normal_or_log == 1) ? ans * exp(ld) : ans; } } // namespace internal diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index b108d765def..d84276adf94 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -9,22 +9,40 @@ namespace stan { namespace math { namespace internal { -template -auto wiener7_integrand(const F& integrand_fun, double labstol_wiener5, - double lerr_bound, TArgs&&... args) { +template +inline double wiener7_helper(double t0_, double omega, double y, double a, + double v, double w, double t0, double sv, double sw, + double st0, double lerr) { + double ymt0 = y - t0_; + if (FunTypeEnum == FunType::GradSW) { + double low = w - sw / 2; + low = (0 > low) ? 0 : low; + double high = w + sw / 2; + high = (1 < high) ? 1 : high; + double fl = wiener5_helper(ymt0, a, v, low, sv, lerr, 1); + double fu = wiener5_helper(ymt0, a, v, high, sv, lerr, 1); + return 0.5 * (fl + fu) / sw; + } else { + return wiener5_helper(ymt0, a, v, omega, sv, lerr, 1); + } +} + +template +auto wiener7_integrand(double labstol_wiener5, double lerr_bound, + TArgs&&... args) { const auto& wiener7_integrand_impl = [&](std::vector x, double y, double a, double v, double w, - double t0, double sv, double sw, double st0, double lerr, - auto&&... args_int) { + double t0, double sv, double sw, double st0, double lerr) { scalar_seq_view x_vec(x); - double omega = sw ? w + sw * (x_vec[0] - 0.5) : w; - double t0_ = sw ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); + double sw_val = (FunTypeEnum == FunType::GradSW) ? 0 : sw; + double omega = sw_val ? w + sw_val * (x_vec[0] - 0.5) : w; + double t0_ = sw_val ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); if (y - t0_ <= 0) { return 0.0; } else { - return integrand_fun(t0_, omega, y, a, v, w, t0, sv, sw, st0, lerr, - args_int...); + return wiener7_helper(t0_, omega, y, a, v, w, t0, sv, + sw, st0, lerr); } }; @@ -34,34 +52,6 @@ auto wiener7_integrand(const F& integrand_fun, double labstol_wiener5, }; return estimate_with_err_check<0>(functor, err, std::make_tuple(args...)); } - -template -inline double wiener7_impl(double t0_, double omega, double y, double a, - double v, double w, double t0, double sv, double sw, - double st0, double lerr) { - if (FunTypeEnum == FunType::GradT || FunTypeEnum == FunType::GradA - || FunTypeEnum == FunType::GradW) { - return wiener5_helper(y - t0_, a, v, omega, sv, lerr, 1); - } - double dens - = exp(wiener5_helper(y - t0_, a, v, omega, sv, lerr)); - if (FunTypeEnum == FunType::Density) { - return dens; - } else { - return wiener5_helper(y - t0_, a, v, omega, sv) * dens; - } -} - -inline double int_dswddiff(double t0_, double omega, double y, double a, - double v, double w, double t0, double sv, double sw, - double st0, double lerr, double w_lower, - double w_upper, double sw_mean) { - double fl - = exp(wiener5_helper(y - t0_, a, v, w_lower, sv, lerr)); - double fu - = exp(wiener5_helper(y - t0_, a, v, w_upper, sv, lerr)); - return 0.5 * (fl + fu) / sw_mean; -} } // namespace internal template wiener7_lpdf( xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); } - dens = internal::wiener7_integrand( - internal::wiener7_impl, labstol_wiener5, + dens = internal::wiener7_integrand( + labstol_wiener5, lerror_bound_dens, params, dim, xmin, xmax, Meval, abstol, reltol / 2); double log_dens = log(dens); ld += log_dens; // computation of derivative for t and precision check in order to give // the value as deriv_t to edge1 and as -deriv_t to edge5 - double deriv_t_7 = internal::wiener7_integrand( - internal::wiener7_impl, + double deriv_t_7 = internal::wiener7_integrand( labstol_wiener5, lerror_bound + log_dens, params, dim, xmin, xmax, Meval, abstol, reltol / 2) / dens; @@ -241,8 +230,7 @@ inline return_type_t wiener7_lpdf( } if (!is_constant_all::value) { ops_partials.edge2_.partials_[i] - = internal::wiener7_integrand( - internal::wiener7_impl, + = internal::wiener7_integrand( labstol_wiener5, lerror_bound + log_dens, params, dim, xmin, xmax, Meval, abstol, reltol / 2) / dens; @@ -252,24 +240,21 @@ inline return_type_t wiener7_lpdf( } if (!is_constant_all::value) { ops_partials.edge4_.partials_[i] - = internal::wiener7_integrand( - internal::wiener7_impl, + = internal::wiener7_integrand( labstol_wiener5, lerror_bound + log_dens, params, dim, xmin, xmax, Meval, abstol, reltol / 2) / dens; } if (!is_constant_all::value) { ops_partials.edge5_.partials_[i] - = internal::wiener7_integrand( - internal::wiener7_impl, + = internal::wiener7_integrand( labstol_wiener5, lerror_bound + log_dens, params, dim, xmin, xmax, Meval, abstol, reltol / 2) / dens; } if (!is_constant_all::value) { ops_partials.edge6_.partials_[i] - = internal::wiener7_integrand( - internal::wiener7_impl, + = internal::wiener7_integrand( labstol_wiener5, lerror_bound + log_dens, params, dim, xmin, xmax, Meval, abstol, reltol / 2) / dens; @@ -278,20 +263,14 @@ inline return_type_t wiener7_lpdf( if (sw_val == 0) { ops_partials.edge7_.partials_[i] = 0; } else { - double lower = w_val - sw_val / 2; - double upper = w_val + sw_val / 2; - - const auto& params_sw = std::make_tuple( - y_val, a_val, v_val, w_val, t0_val, sv_val, 0, st0_val, - labstol_wiener5 - LOG_TWO, (0 > lower) ? 0 : lower, - (1 < upper) ? 1 : upper, sw_val); if (st0_val == 0) { deriv = internal::estimate_with_err_check<8>( - internal::int_dswddiff, lerror_bound - LOG_TWO, - std::tuple_cat(std::make_tuple(t0_val, 0), params_sw)); + internal::wiener7_helper, + lerror_bound - LOG_TWO, + std::tuple_cat(std::make_tuple(t0_val, 0), params)); } else { - deriv = internal::wiener7_integrand( - internal::int_dswddiff, labstol_wiener5, lerror_bound, params_sw, + deriv = internal::wiener7_integrand( + labstol_wiener5, lerror_bound, params, 1, xmin, xmax, Meval, abstol, reltol / 2); } ops_partials.edge7_.partials_[i] = deriv / dens - 1 / sw_val; @@ -307,7 +286,7 @@ inline return_type_t wiener7_lpdf( double t0_st0 = t0_val + st0_val; if (sw_val == 0) { f = internal::estimate_with_err_check<8>( - internal::wiener7_impl, + internal::wiener7_helper, lerror_bound + log(st0_val), std::tuple_cat(std::make_tuple(t0_st0, w_val), params)); } else { @@ -315,8 +294,7 @@ inline return_type_t wiener7_lpdf( const auto& params_st = std::make_tuple( y_val, a_val, v_val, w_val, t0_st0, sv_val, sw_val, 0, new_error); - f = internal::wiener7_integrand( - internal::wiener7_impl, + f = internal::wiener7_integrand( labstol_wiener5, lerror_bound, params_st, 1, xmin, xmax, Meval, abstol, reltol / 2); } From c7203da6ac5b85d9aa61d54065af97af4ce5ac19 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 8 May 2023 02:31:20 -0400 Subject: [PATCH 048/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 14 ++++++++------ stan/math/prim/prob/wiener7_lpdf.hpp | 16 ++++++++-------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 524f36468f2..5e230812c69 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -41,9 +41,10 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, if (sv != 0) { ans /= 1 + square(sv) * y; } - return (normal_or_log == 1) - ? ans * wiener5_helper(y, a, vn, wn, sv, err, 1) - : ans; + return (normal_or_log == 1) ? ans + * wiener5_helper( + y, a, vn, wn, sv, err, 1) + : ans; } double w = 1.0 - wn; double v = -vn; @@ -58,9 +59,10 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, / square(one_plus_svsqr_y); double ans = sv * (t1 + t2); - return (normal_or_log == 1) - ? ans * wiener5_helper(y, a, vn, wn, sv, err, 1) - : ans; + return (normal_or_log == 1) ? ans + * wiener5_helper( + y, a, vn, wn, sv, err, 1) + : ans; } double lg1; diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index d84276adf94..8f2aa4f9140 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -11,8 +11,8 @@ namespace internal { template inline double wiener7_helper(double t0_, double omega, double y, double a, - double v, double w, double t0, double sv, double sw, - double st0, double lerr) { + double v, double w, double t0, double sv, + double sw, double st0, double lerr) { double ymt0 = y - t0_; if (FunTypeEnum == FunType::GradSW) { double low = w - sw / 2; @@ -29,7 +29,7 @@ inline double wiener7_helper(double t0_, double omega, double y, double a, template auto wiener7_integrand(double labstol_wiener5, double lerr_bound, - TArgs&&... args) { + TArgs&&... args) { const auto& wiener7_integrand_impl = [&](std::vector x, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double lerr) { @@ -42,7 +42,7 @@ auto wiener7_integrand(double labstol_wiener5, double lerr_bound, return 0.0; } else { return wiener7_helper(t0_, omega, y, a, v, w, t0, sv, - sw, st0, lerr); + sw, st0, lerr); } }; @@ -211,8 +211,8 @@ inline return_type_t wiener7_lpdf( } dens = internal::wiener7_integrand( - labstol_wiener5, - lerror_bound_dens, params, dim, xmin, xmax, Meval, abstol, reltol / 2); + labstol_wiener5, lerror_bound_dens, params, dim, xmin, xmax, Meval, + abstol, reltol / 2); double log_dens = log(dens); ld += log_dens; @@ -270,8 +270,8 @@ inline return_type_t wiener7_lpdf( std::tuple_cat(std::make_tuple(t0_val, 0), params)); } else { deriv = internal::wiener7_integrand( - labstol_wiener5, lerror_bound, params, - 1, xmin, xmax, Meval, abstol, reltol / 2); + labstol_wiener5, lerror_bound, params, 1, xmin, xmax, Meval, + abstol, reltol / 2); } ops_partials.edge7_.partials_[i] = deriv / dens - 1 / sw_val; } From 3f61fe98cf52d633419771d2efea24d20c7b52f8 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 8 May 2023 11:40:17 +0300 Subject: [PATCH 049/179] Simplify rev test --- stan/math/prim/prob/wiener5_lpdf.hpp | 4 +- test/unit/math/rev/prob/wiener_full_test.cpp | 90 -------------------- 2 files changed, 2 insertions(+), 92 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 5e230812c69..f84a9393bed 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -153,7 +153,7 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, double mult = (FunTypeEnum == FunType::Density) ? 1 : 3; double offset = (FunTypeEnum == FunType::GradW) ? y_asq : 0; double sqrt_offset = sqrt(offset); - for (size_t k = kss; k >= std::fmax(0, kss - 1e4); k--) { + for (size_t k = kss; k >= std::fmax(0, kss - 1e3); k--) { double wp2k = w + 2.0 * k; double wm2k = w - 2.0 * k; int wp2k_sign = (wp2k > sqrt_offset) ? 1 : -1; @@ -192,7 +192,7 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, } else if (FunTypeEnum == FunType::GradW) { mult = 2; } - for (size_t k = kll; k >= std::fmax(1, kll - 1e4); k--) { + for (size_t k = kll; k >= std::fmax(1, kll - 1e3); k--) { double pi_k = k * pi(); double check = (FunTypeEnum == FunType::GradW) ? cos(pi_k * w) : sin(pi_k * w); diff --git a/test/unit/math/rev/prob/wiener_full_test.cpp b/test/unit/math/rev/prob/wiener_full_test.cpp index 3097afefefe..45edcda9d8b 100644 --- a/test/unit/math/rev/prob/wiener_full_test.cpp +++ b/test/unit/math/rev/prob/wiener_full_test.cpp @@ -117,93 +117,3 @@ TEST(ProbWienerFull, wiener_full_all_scalar) { check_scalar_types(f_st0, st0[i], result[i], dst0[i]); } } - -TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { - // tests all parameter types individually, with other parameters - // set to double - using stan::math::wiener_full_lpdf; - double err_tol = 2e-6; - - std::vector rt{1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector a{1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector v{1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector w{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; - std::vector t0{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0}; - std::vector sv{0.1, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0}; - std::vector sw{0.1, 0.1, 0, 0.1, 0, 0.1, 0, 0, 0}; - std::vector st0{0.1, 0, 0.1, 0.1, 0, 0, 0.1, 0, 0}; - - std::vector result{-2.426204, -2.710348, -2.422505, - -2.422795, -2.70665, -2.706812, - -2.419095, -2.703112, -3.790072}; - std::vector drt{-5.437337, -5.436798, -5.437332, -5.434799, -5.436791, - -5.434801, -5.434802, -5.434802, -5.434802}; - std::vector da{5.857318, 6.395031, 5.856484, 5.858549, 6.394195, - 6.396512, 5.857722, 6.395684, 8.369604}; - std::vector dv{-0.2428443, -0.2967977, -0.2436664, - -0.2446629, -0.297619, -0.2991696, - -0.2454931, -0.3, -0.5}; - std::vector dw{-0.9891369, -0.9887305, -0.9973428, - -0.9915453, -0.9969335, -0.991674, - -0.9997794, -0.9999097, -0.9999953}; - std::vector dt0{5.437337, 5.436798, 5.437332, 5.434799, 5.436791, - 5.434801, 5.434802, 5.434802, 5.434802}; - std::vector dsv{-0.06793703, -0.07047449, -0.06797882, - 0.0, -0.07050737, 0.0, - 0.0, 0.0, 0.0}; - std::vector dsw{-0.07406705, -0.07407386, 0.0, -0.07410901, 0.0, - -0.07410686, 0.0, 0.0, 0.0}; - std::vector dst0{2.963915, 0.0, 2.963912, 2.962338, 0.0, - 0.0, 2.96234, 0.0, 0.0}; - - for (int i = 0; i < result.size(); i++) { - // rt - auto f_rt = [=](auto value) { - return wiener_full_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], - st0[i], 1e-6); - }; - check_scalar_types(f_rt, rt[i], result[i], drt[i]); - // a - auto f_a = [=](auto value) { - return wiener_full_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], - st0[i], 1e-6); - }; - check_scalar_types(f_a, a[i], result[i], da[i]); - // v - auto f_v = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], - st0[i], 1e-6); - }; - check_scalar_types(f_v, v[i], result[i], dv[i]); - // w - auto f_w = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], - st0[i], 1e-6); - }; - check_scalar_types(f_w, w[i], result[i], dw[i]); - // t0 - auto f_t0 = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], - st0[i], 1e-6); - }; - check_scalar_types(f_t0, t0[i], result[i], dt0[i]); - // sv - auto f_sv = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], - st0[i], 1e-6); - }; - check_scalar_types(f_sv, sv[i], result[i], dsv[i]); - // sw - auto f_sw = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, - st0[i], 1e-6); - }; - check_scalar_types(f_sw, sw[i], result[i], dsw[i]); - // st0 - auto f_st0 = [=](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], - value, 1e-6); - }; - check_scalar_types(f_st0, st0[i], result[i], dst0[i]); - } -} From 23cea7424dc6e08a2b38a10e87b2e4b6a35dd5fe Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 10 May 2023 16:12:52 +0300 Subject: [PATCH 050/179] Update doc --- stan/math/prim/prob/wiener5_lpdf.hpp | 428 +++++++++++-------- stan/math/prim/prob/wiener7_lpdf.hpp | 96 ++++- test/unit/math/rev/prob/wiener_full_test.cpp | 90 ++++ 3 files changed, 413 insertions(+), 201 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index f84a9393bed..23eff6ff2ed 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -7,221 +7,277 @@ namespace stan { namespace math { namespace internal { -template -inline void assign_err(std::tuple& args_tuple, double err) { - std::get<8>(args_tuple) = err; -} -inline void assign_err(double arg, double err) { arg = err; } - -template -double estimate_with_err_check(const F& functor, double err, - ArgsTupleT&& args_tuple, - bool log_result = true) { - double result = math::apply([&](auto&&... args) { return functor(args...); }, - args_tuple); - double lfabs_result = log_result ? log(fabs(result)) : fabs(result); - if (lfabs_result < err) { - ArgsTupleT err_args_tuple = args_tuple; - assign_err(std::get(err_args_tuple), err + lfabs_result); - result = math::apply([&](auto&&... args) { return functor(args...); }, - err_args_tuple); - } - return result; -} - enum class FunType { Density, GradT, GradA, GradV, GradW, GradSV, GradSW }; +/** + * Implementation function for calculating the density or gradient w.r.t. a + * specified parameter of the 5-parameter Wiener distribution + * + * @tparam FunTypeEnum An enum value indicating the quantity required + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param vn The drift rate + * @param wn The relative starting point + * @param sv The inter-trial variability of the drift rate + * @param err The error tolerance for estimation + * @param use_log Whether to return calculation w.r.t. the log value + * +*/ template inline double wiener5_helper(const double& y, const double& a, const double& vn, const double& wn, const double& sv, const double& err = log(1e-12), - int normal_or_log = 0) { - if (FunTypeEnum == FunType::GradV) { - double ans = (a * (1 - wn) - vn * y); - if (sv != 0) { - ans /= 1 + square(sv) * y; - } - return (normal_or_log == 1) ? ans - * wiener5_helper( - y, a, vn, wn, sv, err, 1) - : ans; - } + bool use_log = false) { double w = 1.0 - wn; double v = -vn; double sv_sqr = square(sv); double one_plus_svsqr_y = 1 + sv_sqr * y; double two_avw = 2 * a * v * w; double two_log_a = 2 * log(a); + double ans; + double ld = 0; - if (FunTypeEnum == FunType::GradSV) { - double t1 = -y / one_plus_svsqr_y; - double t2 = (square(a * w) + two_avw * y + square(v * y)) - / square(one_plus_svsqr_y); - double ans = sv * (t1 + t2); - - return (normal_or_log == 1) ? ans - * wiener5_helper( - y, a, vn, wn, sv, err, 1) - : ans; - } - - double lg1; - if (sv != 0) { - lg1 = (sv_sqr * square(a * w) - two_avw - square(v) * y) / 2.0 - / one_plus_svsqr_y - - two_log_a - 0.5 * log(one_plus_svsqr_y); + if (FunTypeEnum == FunType::GradSV || FunTypeEnum == FunType::GradV) { + ld = wiener5_helper(y, a, vn, wn, sv, err); + if (FunTypeEnum == FunType::GradV) { + ans = (a * (1 - wn) - vn * y); + if (sv != 0) { + ans /= 1 + sv_sqr * y; + } + } else { + double t1 = -y / one_plus_svsqr_y; + double t2 = (square(a * w) + two_avw * y + square(v * y)) + / square(one_plus_svsqr_y); + ans = sv * (t1 + t2); + } } else { - lg1 = (-two_avw - square(v) * y) / 2.0 - two_log_a; - } - double ans0 = 0; - if (FunTypeEnum != FunType::Density) { - double var_a = (FunTypeEnum == FunType::GradA) ? w : a; - double var_b = (FunTypeEnum == FunType::GradA) ? a : w; + double lg1; if (sv != 0) { - if (FunTypeEnum == FunType::GradT) { - ans0 = -0.5 - * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - two_avw) - + square(v)) - / square(one_plus_svsqr_y); + lg1 = (sv_sqr * square(a * w) - two_avw - square(v) * y) / 2.0 + / one_plus_svsqr_y + - two_log_a - 0.5 * log(one_plus_svsqr_y); + } else { + lg1 = (-two_avw - square(v) * y) / 2.0 - two_log_a; + } + double ans0 = 0; + if (FunTypeEnum != FunType::Density) { + double var_a = (FunTypeEnum == FunType::GradA) ? w : a; + double var_b = (FunTypeEnum == FunType::GradA) ? a : w; + if (sv != 0) { + if (FunTypeEnum == FunType::GradT) { + ans0 = -0.5 + * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - two_avw) + + square(v)) + / square(one_plus_svsqr_y); + } else { + ans0 = (-v * var_a + sv_sqr * square(var_a) * var_b) + / one_plus_svsqr_y; + } } else { - ans0 = (-v * var_a + sv_sqr * square(var_a) * var_b) / one_plus_svsqr_y; + ans0 = (FunTypeEnum == FunType::GradT) ? -0.5 * square(v) : -v * var_a; } - } else { - ans0 = (FunTypeEnum == FunType::GradT) ? -0.5 * square(v) : -v * var_a; } - } - double es = (err - lg1) + (FunTypeEnum == FunType::GradT) * two_log_a; - double two_es = 2.0 * es; - double y_asq = y / square(a); - double log_y_asq = log(y) - two_log_a; + double es = (err - lg1) + (FunTypeEnum == FunType::GradT) * two_log_a; + double two_es = 2.0 * es; + double y_asq = y / square(a); + double log_y_asq = log(y) - two_log_a; - double K1, u_eps, arg; - double K1_mult = (FunTypeEnum == FunType::Density) ? 2 : 3; - K1 = (sqrt(K1_mult * y_asq) + w) / 2.0; - if (FunTypeEnum == FunType::Density || FunTypeEnum == FunType::GradW) { - u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log_y_asq + two_es); - } else { - u_eps = fmin(-3.0, - (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_es)); - } - double arg_mult = (FunTypeEnum == FunType::Density) ? 1 : 3; - arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - - double K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; - size_t kss = static_cast(ceil(fmax(K1, K2))); - - static const double PISQ = square(pi()); // pi*pi - if (FunTypeEnum == FunType::Density) { - K1 = 1.0 / (pi() * sqrt(y_asq)); - double two_log_piy = -2.0 * (LOG_PI + log_y_asq + es); - K2 = (two_log_piy >= 0) ? sqrt(two_log_piy / (PISQ * y_asq)) : 0.0; - } else { - K1_mult = (FunTypeEnum == FunType::GradT) ? 2 : 3; - K1 = sqrt(K1_mult / y_asq) / pi(); - u_eps = (FunTypeEnum == FunType::GradT) - ? fmin(-1, log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es) - : fmin(-1, log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq - + two_es); - arg_mult = (FunTypeEnum == FunType::GradT) ? (2.0 / PISQ / y_asq) : 1; - arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - K2 = (FunTypeEnum == FunType::GradT) - ? (arg > 0) ? sqrt(arg) : K1 - : (arg > 0) ? sqrt(arg / y_asq) / pi() : K1; - } + double K1, u_eps, arg; + double K1_mult = (FunTypeEnum == FunType::Density) ? 2 : 3; + K1 = (sqrt(K1_mult * y_asq) + w) / 2.0; + if (FunTypeEnum == FunType::Density || FunTypeEnum == FunType::GradW) { + u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log_y_asq + two_es); + } else { + u_eps = fmin(-3.0, + (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_es)); + } + double arg_mult = (FunTypeEnum == FunType::Density) ? 1 : 3; + arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - size_t kll = static_cast(ceil(fmax(K1, K2))); + double K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; + size_t kss = static_cast(ceil(fmax(K1, K2))); - double ld = 0; - double ld_err = 0; - if (FunTypeEnum != FunType::Density) { - if (FunTypeEnum == FunType::GradT) { - ld_err = log(max(fabs(ans0 - 1.5 / y), fabs(ans0))); - } else if (FunTypeEnum == FunType::GradA) { - ld_err = log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a))); + static const double PISQ = square(pi()); // pi*pi + if (FunTypeEnum == FunType::Density) { + K1 = 1.0 / (pi() * sqrt(y_asq)); + double two_log_piy = -2.0 * (LOG_PI + log_y_asq + es); + K2 = (two_log_piy >= 0) ? sqrt(two_log_piy / (PISQ * y_asq)) : 0.0; } else { - ld_err = log(fabs(ans0)); + K1_mult = (FunTypeEnum == FunType::GradT) ? 2 : 3; + K1 = sqrt(K1_mult / y_asq) / pi(); + double u_eps_arg = (FunTypeEnum == FunType::GradT) + ? log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es + : log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + + two_es; + u_eps = fmin(-1, u_eps_arg); + arg_mult = (FunTypeEnum == FunType::GradT) ? (2.0 / PISQ / y_asq) : 1; + arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + K2 = (FunTypeEnum == FunType::GradT) + ? (arg > 0) ? sqrt(arg) : K1 + : (arg > 0) ? sqrt(arg / y_asq) / pi() : K1; } - ld = wiener5_helper(y, a, vn, wn, sv, err - ld_err); - } - double erg = NEGATIVE_INFTY; - int newsign = 1; - double scaling = (2 * kss <= kll) ? inv(2.0 * y_asq) : y_asq / 2.0; - double ans; - if (2 * kss <= kll) { - double mult = (FunTypeEnum == FunType::Density) ? 1 : 3; - double offset = (FunTypeEnum == FunType::GradW) ? y_asq : 0; - double sqrt_offset = sqrt(offset); - for (size_t k = kss; k >= std::fmax(0, kss - 1e3); k--) { - double wp2k = w + 2.0 * k; - double wm2k = w - 2.0 * k; - int wp2k_sign = (wp2k > sqrt_offset) ? 1 : -1; - int wm2k_sign = (wm2k > sqrt_offset) ? 1 : -1; - double wp2k_quant = log(wp2k_sign * (wp2k - offset)) - - (square(wp2k) - offset) * scaling; - double wm2k_quant = log(wm2k_sign * (wm2k - offset)) - - (square(wm2k) - offset) * scaling; - std::forward_as_tuple(erg, newsign) - = log_sum_exp_signed(erg, newsign, mult * wp2k_quant, wp2k_sign); - std::forward_as_tuple(erg, newsign) - = log_sum_exp_signed(erg, newsign, mult * wm2k_quant, -1 * wm2k_sign); + size_t kll = static_cast(ceil(fmax(K1, K2))); + + double ld_err = 0; + if (FunTypeEnum != FunType::Density) { + if (FunTypeEnum == FunType::GradT) { + ld_err = log(max(fabs(ans0 - 1.5 / y), fabs(ans0))); + } else if (FunTypeEnum == FunType::GradA) { + ld_err = log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a))); + } else { + ld_err = log(fabs(ans0)); + } + ld = wiener5_helper(y, a, vn, wn, sv, err - ld_err); } - if (FunTypeEnum == FunType::Density) { - ans = lg1 - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log_y_asq + erg; - } else if (FunTypeEnum == FunType::GradT) { - ans = ans0 - 1.5 / y - + newsign - * exp(lg1 - two_log_a - 1.5 * LOG_TWO - LOG_SQRT_PI - - 3.5 * log_y_asq + erg - ld); - } else if (FunTypeEnum == FunType::GradA) { - ans = ans0 + 1.0 / a - - newsign - * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * log(y) - + 2.0 * two_log_a + lg1 + erg - ld); - } else if (FunTypeEnum == FunType::GradW) { - ans = -(ans0 + + double erg = NEGATIVE_INFTY; + int newsign = 1; + double scaling = (2 * kss <= kll) ? inv(2.0 * y_asq) : y_asq / 2.0; + if (2 * kss <= kll) { + double mult = (FunTypeEnum == FunType::Density) ? 1 : 3; + double offset = (FunTypeEnum == FunType::GradW) ? y_asq : 0; + double sqrt_offset = sqrt(offset); + for (size_t k = kss; k >= std::fmax(0, kss - 1e3); k--) { + double wp2k = w + 2.0 * k; + double wm2k = w - 2.0 * k; + int wp2k_sign = (wp2k > sqrt_offset) ? 1 : -1; + int wm2k_sign = (wm2k > sqrt_offset) ? 1 : -1; + double wp2k_quant = log(wp2k_sign * (wp2k - offset)) + - (square(wp2k) - offset) * scaling; + double wm2k_quant = log(wm2k_sign * (wm2k - offset)) + - (square(wm2k) - offset) * scaling; + std::forward_as_tuple(erg, newsign) + = log_sum_exp_signed(erg, newsign, mult * wp2k_quant, wp2k_sign); + std::forward_as_tuple(erg, newsign) + = log_sum_exp_signed(erg, newsign, + mult * wm2k_quant, -1 * wm2k_sign); + } + if (FunTypeEnum == FunType::Density) { + ans = lg1 - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log_y_asq + erg; + } else if (FunTypeEnum == FunType::GradT) { + ans = ans0 - 1.5 / y + + newsign + * exp(lg1 - two_log_a - 1.5 * LOG_TWO - LOG_SQRT_PI + - 3.5 * log_y_asq + erg - ld); + } else if (FunTypeEnum == FunType::GradA) { + ans = ans0 + 1.0 / a - newsign - * exp(erg - (ld - lg1) - 2.5 * log_y_asq - 0.5 * LOG_TWO - - 0.5 * LOG_PI)); - } - } else { - double mult = 3; - if (FunTypeEnum == FunType::Density) { - mult = 1; - } else if (FunTypeEnum == FunType::GradW) { - mult = 2; - } - for (size_t k = kll; k >= std::fmax(1, kll - 1e3); k--) { - double pi_k = k * pi(); - double check - = (FunTypeEnum == FunType::GradW) ? cos(pi_k * w) : sin(pi_k * w); - int check_sign = sign(check); - double kll_quant - = mult * log(k) - square(pi_k) * scaling + log(fabs(check)); - std::forward_as_tuple(erg, newsign) - = log_sum_exp_signed(erg, newsign, kll_quant, check_sign); - } - if (FunTypeEnum == FunType::Density) { - ans = lg1 + erg + LOG_PI; - } else if (FunTypeEnum == FunType::GradT) { - ans = ans0 - - newsign - * exp(lg1 - two_log_a + 3.0 * LOG_PI - LOG_TWO + erg - ld); - } else if (FunTypeEnum == FunType::GradA) { - ans = ans0 - 2.0 / a - + newsign * exp(log(y) + lg1 - 3 * (log(a) - LOG_PI) + erg - ld); - } else if (FunTypeEnum == FunType::GradW) { - ans = -(ans0 + newsign * exp(erg - (ld - lg1) + 2 * LOG_PI)); + * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * log(y) + + 2.0 * two_log_a + lg1 + erg - ld); + } else if (FunTypeEnum == FunType::GradW) { + ans = -(ans0 + - newsign + * exp(erg - (ld - lg1) - 2.5 * log_y_asq - 0.5 * LOG_TWO + - 0.5 * LOG_PI)); + } + } else { + double mult = 3; + if (FunTypeEnum == FunType::Density) { + mult = 1; + } else if (FunTypeEnum == FunType::GradW) { + mult = 2; + } + for (size_t k = kll; k >= std::fmax(1, kll - 1e3); k--) { + double pi_k = k * pi(); + double check + = (FunTypeEnum == FunType::GradW) ? cos(pi_k * w) : sin(pi_k * w); + int check_sign = sign(check); + double kll_quant + = mult * log(k) - square(pi_k) * scaling + log(fabs(check)); + std::forward_as_tuple(erg, newsign) + = log_sum_exp_signed(erg, newsign, kll_quant, check_sign); + } + if (FunTypeEnum == FunType::Density) { + ans = lg1 + erg + LOG_PI; + } else if (FunTypeEnum == FunType::GradT) { + ans = ans0 + - newsign + * exp(lg1 - two_log_a + 3.0 * LOG_PI - LOG_TWO + erg - ld); + } else if (FunTypeEnum == FunType::GradA) { + ans = ans0 - 2.0 / a + + newsign * exp(log(y) + lg1 - 3 * (log(a) - LOG_PI) + erg - ld); + } else if (FunTypeEnum == FunType::GradW) { + ans = -(ans0 + newsign * exp(erg - (ld - lg1) + 2 * LOG_PI)); + } } } - if (FunTypeEnum == FunType::Density && normal_or_log == 1) { + if (FunTypeEnum == FunType::Density && use_log) { return exp(ans); } - return (normal_or_log == 1) ? ans * exp(ld) : ans; + return use_log ? ans * exp(ld) : ans; +} + +/** + * Utility function for replacing a value with a specified error value +*/ +template +inline void assign_err(double arg, double err) { arg = err; } + +/** + * Utility function for replacing a value with a specified error value, + * overload for use when the value is stored within a tuple. +*/ +template +inline void assign_err(std::tuple& args_tuple, double err) { + std::get(args_tuple) = err; +} + +/** + * Utility function for estimating a function with a given set of arguments, + * checking the result against a provided error tolerance, and re-estimating + * the function with the increased error if it fails. + * + * @tparam ErrIndex Position of the error argument in the provided arguments + * @tparam NestedIndex Nested position if the error argument is within a tuple + * @tparam F Type of functor + * @tparam ArgsTupleT Type of tuple of arguments for functor + * + * @param functor Function to apply + * @param err Error value to check against + * @param args_tuple Tuple of arguments to pass to functor + * @param log_result Whether the function result is already on the log-scale +*/ +template +double estimate_with_err_check(const F& functor, double err, + ArgsTupleT&& args_tuple, + bool log_result = true) { + double result = math::apply([&](auto&&... args) { return functor(args...); }, + args_tuple); + double lfabs_result = log_result ? log(fabs(result)) : fabs(result); + if (lfabs_result < err) { + ArgsTupleT err_args_tuple = args_tuple; + assign_err(std::get(err_args_tuple), + err + lfabs_result); + result = math::apply([&](auto&&... args) { return functor(args...); }, + err_args_tuple); + } + return result; } } // namespace internal +/** + * Log-density function for the 5-parameter Wiener density. + * See 'wiener_full_lpdf' for more comprehensive documentation + * + * @tparam T_y type of scalar + * @tparam T_a type of boundary + * @tparam T_t0 type of non-decision time + * @tparam T_w type of relative starting point + * @tparam T_v type of drift rate + * @tparam T_sv type of inter-trial variability of drift rate + * + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param t0 The non-decision time + * @param w The relative starting point + * @param v The drift rate + * @param sv The inter-trial variability of the drift rate + * @return The log of the Wiener first passage time density with + * the specified arguments for upper boundary responses +*/ template inline return_type_t wiener5_lpdf( @@ -318,18 +374,20 @@ inline return_type_t wiener5_lpdf( const double sv_val = sv_vec.val(i); const auto params = std::make_tuple(y_val - t0_val, a_val, v_val, w_val, - sv_val, labstol_wiener5, 0); + sv_val, labstol_wiener5, false); dens = internal::estimate_with_err_check<5>( internal::wiener5_helper, lerror_bound_dens - LOG_TWO, params, true); ld += dens; + double new_est_err = dens + lerror_bound - LOG_FOUR; + // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 double deriv_y = internal::estimate_with_err_check<5>( internal::wiener5_helper, - dens + lerror_bound - LOG_TWO, params); + new_est_err, params); // computation of derivatives and precision checks if (!is_constant_all::value) { @@ -338,7 +396,7 @@ inline return_type_t wiener5_lpdf( if (!is_constant_all::value) { ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check<5>( internal::wiener5_helper, - dens + lerror_bound - LOG_FOUR, params); + new_est_err, params); } if (!is_constant_all::value) { ops_partials.edge3_.partials_[i] = -deriv_y; @@ -346,7 +404,7 @@ inline return_type_t wiener5_lpdf( if (!is_constant_all::value) { ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check<5>( internal::wiener5_helper, - dens + lerror_bound - LOG_FOUR, params); + new_est_err, params); } if (!is_constant_all::value) { ops_partials.edge5_.partials_[i] diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index 8f2aa4f9140..020da744e6e 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -9,6 +9,26 @@ namespace stan { namespace math { namespace internal { +/** + * Implementation function for delegating computation to the correct density + * or derivative function. For all gradients except the sw parameter, the + * respective wiener5 function is called. + * + * @tparam FunTypeEnum An enum value indicating the function required + * @param t0_ See wiener7_integrand function for definition + * @param omega See wiener7_integrand function for definition + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param v The drift rate + * @param w The relative starting point + * @param t0 The non-decision time + * @param sv The inter-trial variability of the drift rate + * @param sw The inter-trial variability of the relative starting point + * @param st0 The inter-trial variability of the non-decision time + * @param lerr Error tolerance + * + * @return Log-density or gradient for wiener7_lpdf +*/ template inline double wiener7_helper(double t0_, double omega, double y, double a, double v, double w, double t0, double sv, @@ -19,17 +39,29 @@ inline double wiener7_helper(double t0_, double omega, double y, double a, low = (0 > low) ? 0 : low; double high = w + sw / 2; high = (1 < high) ? 1 : high; - double fl = wiener5_helper(ymt0, a, v, low, sv, lerr, 1); - double fu = wiener5_helper(ymt0, a, v, high, sv, lerr, 1); + double fl + = wiener5_helper(ymt0, a, v, low, sv, lerr, true); + double fu + = wiener5_helper(ymt0, a, v, high, sv, lerr, true); return 0.5 * (fl + fu) / sw; } else { - return wiener5_helper(ymt0, a, v, omega, sv, lerr, 1); + return wiener5_helper(ymt0, a, v, omega, sv, lerr, true); } } +/** + * Implementation function for preparing arguments and functor to be passed + * to the hcubature() function for calculating wiener7 parameters via + * integration + * + * @tparam FunTypeEnum An enum value indicating the function required + * @tparam Targs... Types of arguments in parameter pack + * @param hcubature_err Error tolerance for calculation + * @param args Additional arguments to be passed to the hcubature function + * @return Wiener7 density or gradient calculated by integration +*/ template -auto wiener7_integrand(double labstol_wiener5, double lerr_bound, - TArgs&&... args) { +auto wiener7_integrand(double hcubature_err, TArgs&&... args) { const auto& wiener7_integrand_impl = [&](std::vector x, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double lerr) { @@ -45,15 +77,43 @@ auto wiener7_integrand(double labstol_wiener5, double lerr_bound, sw, st0, lerr); } }; - - double err = labstol_wiener5 - lerr_bound + LOG_TWO + 1; const auto& functor = [&](auto&&... int_args) { return hcubature(wiener7_integrand_impl, int_args...); }; - return estimate_with_err_check<0>(functor, err, std::make_tuple(args...)); + return estimate_with_err_check<0, 8>(functor, hcubature_err, + std::make_tuple(args...)); } } // namespace internal + +/** + * Log-density function for the 7-parameter Wiener density. + * See 'wiener_full_lpdf' for more comprehensive documentation + * + * @tparam T_y type of scalar + * @tparam T_a type of boundary + * @tparam T_t0 type of non-decision time + * @tparam T_w type of relative starting point + * @tparam T_v type of drift rate + * @tparam T_sv type of inter-trial variability of drift rate + * @tparam T_sw type of inter-trial variability of relative starting point + * @tparam T_st0 type of inter-trial variability of non-decision time + * + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param t0 The non-decision time + * @param w The relative starting point + * @param v The drift rate + * @param sv The inter-trial variability of the drift rate + * @param sw The inter-trial variability of the relative starting point + * @param st0 The inter-trial variability of the non-decision time + * @return The log of the Wiener first passage time density with + * the specified arguments for upper boundary responses + * @throw std::domain_error if non-decision time \c t0 is greater than reaction + time \c y. + * @throw std::domain_error if \c 1-sw/2 is smaller than or equal to \c w. + * @throw std::domain_error if \c sw/2 is larger than or equal to \c w. +*/ template inline return_type_t wiener7_lpdf( @@ -210,16 +270,20 @@ inline return_type_t wiener7_lpdf( xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); } + double hcubature_err = labstol_wiener5 - lerror_bound_dens + LOG_TWO + 1; + dens = internal::wiener7_integrand( - labstol_wiener5, lerror_bound_dens, params, dim, xmin, xmax, Meval, + hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2); double log_dens = log(dens); ld += log_dens; + hcubature_err = labstol_wiener5 - (lerror_bound + log_dens) + LOG_TWO + 1; + // computation of derivative for t and precision check in order to give // the value as deriv_t to edge1 and as -deriv_t to edge5 double deriv_t_7 = internal::wiener7_integrand( - labstol_wiener5, lerror_bound + log_dens, params, + hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2) / dens; @@ -231,7 +295,7 @@ inline return_type_t wiener7_lpdf( if (!is_constant_all::value) { ops_partials.edge2_.partials_[i] = internal::wiener7_integrand( - labstol_wiener5, lerror_bound + log_dens, params, dim, xmin, + hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2) / dens; } @@ -241,21 +305,21 @@ inline return_type_t wiener7_lpdf( if (!is_constant_all::value) { ops_partials.edge4_.partials_[i] = internal::wiener7_integrand( - labstol_wiener5, lerror_bound + log_dens, params, dim, xmin, + hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2) / dens; } if (!is_constant_all::value) { ops_partials.edge5_.partials_[i] = internal::wiener7_integrand( - labstol_wiener5, lerror_bound + log_dens, params, dim, xmin, + hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2) / dens; } if (!is_constant_all::value) { ops_partials.edge6_.partials_[i] = internal::wiener7_integrand( - labstol_wiener5, lerror_bound + log_dens, params, dim, xmin, + hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2) / dens; } @@ -270,7 +334,7 @@ inline return_type_t wiener7_lpdf( std::tuple_cat(std::make_tuple(t0_val, 0), params)); } else { deriv = internal::wiener7_integrand( - labstol_wiener5, lerror_bound, params, 1, xmin, xmax, Meval, + hcubature_err, params, 1, xmin, xmax, Meval, abstol, reltol / 2); } ops_partials.edge7_.partials_[i] = deriv / dens - 1 / sw_val; @@ -295,7 +359,7 @@ inline return_type_t wiener7_lpdf( const auto& params_st = std::make_tuple( y_val, a_val, v_val, w_val, t0_st0, sv_val, sw_val, 0, new_error); f = internal::wiener7_integrand( - labstol_wiener5, lerror_bound, params_st, 1, xmin, xmax, Meval, + hcubature_err, params_st, 1, xmin, xmax, Meval, abstol, reltol / 2); } ops_partials.edge8_.partials_[i] = -1 / st0_val + f / st0_val / dens; diff --git a/test/unit/math/rev/prob/wiener_full_test.cpp b/test/unit/math/rev/prob/wiener_full_test.cpp index 45edcda9d8b..3097afefefe 100644 --- a/test/unit/math/rev/prob/wiener_full_test.cpp +++ b/test/unit/math/rev/prob/wiener_full_test.cpp @@ -117,3 +117,93 @@ TEST(ProbWienerFull, wiener_full_all_scalar) { check_scalar_types(f_st0, st0[i], result[i], dst0[i]); } } + +TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { + // tests all parameter types individually, with other parameters + // set to double + using stan::math::wiener_full_lpdf; + double err_tol = 2e-6; + + std::vector rt{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector a{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector v{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector w{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; + std::vector t0{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0}; + std::vector sv{0.1, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0}; + std::vector sw{0.1, 0.1, 0, 0.1, 0, 0.1, 0, 0, 0}; + std::vector st0{0.1, 0, 0.1, 0.1, 0, 0, 0.1, 0, 0}; + + std::vector result{-2.426204, -2.710348, -2.422505, + -2.422795, -2.70665, -2.706812, + -2.419095, -2.703112, -3.790072}; + std::vector drt{-5.437337, -5.436798, -5.437332, -5.434799, -5.436791, + -5.434801, -5.434802, -5.434802, -5.434802}; + std::vector da{5.857318, 6.395031, 5.856484, 5.858549, 6.394195, + 6.396512, 5.857722, 6.395684, 8.369604}; + std::vector dv{-0.2428443, -0.2967977, -0.2436664, + -0.2446629, -0.297619, -0.2991696, + -0.2454931, -0.3, -0.5}; + std::vector dw{-0.9891369, -0.9887305, -0.9973428, + -0.9915453, -0.9969335, -0.991674, + -0.9997794, -0.9999097, -0.9999953}; + std::vector dt0{5.437337, 5.436798, 5.437332, 5.434799, 5.436791, + 5.434801, 5.434802, 5.434802, 5.434802}; + std::vector dsv{-0.06793703, -0.07047449, -0.06797882, + 0.0, -0.07050737, 0.0, + 0.0, 0.0, 0.0}; + std::vector dsw{-0.07406705, -0.07407386, 0.0, -0.07410901, 0.0, + -0.07410686, 0.0, 0.0, 0.0}; + std::vector dst0{2.963915, 0.0, 2.963912, 2.962338, 0.0, + 0.0, 2.96234, 0.0, 0.0}; + + for (int i = 0; i < result.size(); i++) { + // rt + auto f_rt = [=](auto value) { + return wiener_full_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], + st0[i], 1e-6); + }; + check_scalar_types(f_rt, rt[i], result[i], drt[i]); + // a + auto f_a = [=](auto value) { + return wiener_full_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], + st0[i], 1e-6); + }; + check_scalar_types(f_a, a[i], result[i], da[i]); + // v + auto f_v = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], + st0[i], 1e-6); + }; + check_scalar_types(f_v, v[i], result[i], dv[i]); + // w + auto f_w = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], + st0[i], 1e-6); + }; + check_scalar_types(f_w, w[i], result[i], dw[i]); + // t0 + auto f_t0 = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], + st0[i], 1e-6); + }; + check_scalar_types(f_t0, t0[i], result[i], dt0[i]); + // sv + auto f_sv = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], + st0[i], 1e-6); + }; + check_scalar_types(f_sv, sv[i], result[i], dsv[i]); + // sw + auto f_sw = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, + st0[i], 1e-6); + }; + check_scalar_types(f_sw, sw[i], result[i], dsw[i]); + // st0 + auto f_st0 = [=](auto value) { + return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], + value, 1e-6); + }; + check_scalar_types(f_st0, st0[i], result[i], dst0[i]); + } +} From 3dfa50ff25854955d63409eac81670dfd95ac4a2 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 10 May 2023 09:15:04 -0400 Subject: [PATCH 051/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 53 ++++++++++++++-------------- stan/math/prim/prob/wiener7_lpdf.hpp | 45 +++++++++++------------ 2 files changed, 48 insertions(+), 50 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 23eff6ff2ed..897e0ba9152 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -22,7 +22,7 @@ enum class FunType { Density, GradT, GradA, GradV, GradW, GradSV, GradSW }; * @param err The error tolerance for estimation * @param use_log Whether to return calculation w.r.t. the log value * -*/ + */ template inline double wiener5_helper(const double& y, const double& a, const double& vn, const double& wn, const double& sv, @@ -66,12 +66,12 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, if (sv != 0) { if (FunTypeEnum == FunType::GradT) { ans0 = -0.5 - * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - two_avw) - + square(v)) - / square(one_plus_svsqr_y); + * (square(sv_sqr) * (y + square(a * w)) + + sv_sqr * (1 - two_avw) + square(v)) + / square(one_plus_svsqr_y); } else { ans0 = (-v * var_a + sv_sqr * square(var_a) * var_b) - / one_plus_svsqr_y; + / one_plus_svsqr_y; } } else { ans0 = (FunTypeEnum == FunType::GradT) ? -0.5 * square(v) : -v * var_a; @@ -90,7 +90,7 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log_y_asq + two_es); } else { u_eps = fmin(-3.0, - (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_es)); + (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_es)); } double arg_mult = (FunTypeEnum == FunType::Density) ? 1 : 3; arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); @@ -106,16 +106,16 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, } else { K1_mult = (FunTypeEnum == FunType::GradT) ? 2 : 3; K1 = sqrt(K1_mult / y_asq) / pi(); - double u_eps_arg = (FunTypeEnum == FunType::GradT) - ? log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es - : log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq - + two_es; + double u_eps_arg + = (FunTypeEnum == FunType::GradT) + ? log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es + : log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_es; u_eps = fmin(-1, u_eps_arg); arg_mult = (FunTypeEnum == FunType::GradT) ? (2.0 / PISQ / y_asq) : 1; arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); K2 = (FunTypeEnum == FunType::GradT) - ? (arg > 0) ? sqrt(arg) : K1 - : (arg > 0) ? sqrt(arg / y_asq) / pi() : K1; + ? (arg > 0) ? sqrt(arg) : K1 + : (arg > 0) ? sqrt(arg / y_asq) / pi() : K1; } size_t kll = static_cast(ceil(fmax(K1, K2))); @@ -150,9 +150,8 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, - (square(wm2k) - offset) * scaling; std::forward_as_tuple(erg, newsign) = log_sum_exp_signed(erg, newsign, mult * wp2k_quant, wp2k_sign); - std::forward_as_tuple(erg, newsign) - = log_sum_exp_signed(erg, newsign, - mult * wm2k_quant, -1 * wm2k_sign); + std::forward_as_tuple(erg, newsign) = log_sum_exp_signed( + erg, newsign, mult * wm2k_quant, -1 * wm2k_sign); } if (FunTypeEnum == FunType::Density) { ans = lg1 - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log_y_asq + erg; @@ -211,14 +210,16 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, /** * Utility function for replacing a value with a specified error value -*/ + */ template -inline void assign_err(double arg, double err) { arg = err; } +inline void assign_err(double arg, double err) { + arg = err; +} /** * Utility function for replacing a value with a specified error value, * overload for use when the value is stored within a tuple. -*/ + */ template inline void assign_err(std::tuple& args_tuple, double err) { std::get(args_tuple) = err; @@ -238,7 +239,7 @@ inline void assign_err(std::tuple& args_tuple, double err) { * @param err Error value to check against * @param args_tuple Tuple of arguments to pass to functor * @param log_result Whether the function result is already on the log-scale -*/ + */ template double estimate_with_err_check(const F& functor, double err, @@ -277,7 +278,7 @@ double estimate_with_err_check(const F& functor, double err, * @param sv The inter-trial variability of the drift rate * @return The log of the Wiener first passage time density with * the specified arguments for upper boundary responses -*/ + */ template inline return_type_t wiener5_lpdf( @@ -386,8 +387,8 @@ inline return_type_t wiener5_lpdf( // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 double deriv_y = internal::estimate_with_err_check<5>( - internal::wiener5_helper, - new_est_err, params); + internal::wiener5_helper, new_est_err, + params); // computation of derivatives and precision checks if (!is_constant_all::value) { @@ -395,16 +396,16 @@ inline return_type_t wiener5_lpdf( } if (!is_constant_all::value) { ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check<5>( - internal::wiener5_helper, - new_est_err, params); + internal::wiener5_helper, new_est_err, + params); } if (!is_constant_all::value) { ops_partials.edge3_.partials_[i] = -deriv_y; } if (!is_constant_all::value) { ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check<5>( - internal::wiener5_helper, - new_est_err, params); + internal::wiener5_helper, new_est_err, + params); } if (!is_constant_all::value) { ops_partials.edge5_.partials_[i] diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp index 020da744e6e..70ac917f075 100644 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ b/stan/math/prim/prob/wiener7_lpdf.hpp @@ -28,7 +28,7 @@ namespace internal { * @param lerr Error tolerance * * @return Log-density or gradient for wiener7_lpdf -*/ + */ template inline double wiener7_helper(double t0_, double omega, double y, double a, double v, double w, double t0, double sv, @@ -40,9 +40,9 @@ inline double wiener7_helper(double t0_, double omega, double y, double a, double high = w + sw / 2; high = (1 < high) ? 1 : high; double fl - = wiener5_helper(ymt0, a, v, low, sv, lerr, true); + = wiener5_helper(ymt0, a, v, low, sv, lerr, true); double fu - = wiener5_helper(ymt0, a, v, high, sv, lerr, true); + = wiener5_helper(ymt0, a, v, high, sv, lerr, true); return 0.5 * (fl + fu) / sw; } else { return wiener5_helper(ymt0, a, v, omega, sv, lerr, true); @@ -59,7 +59,7 @@ inline double wiener7_helper(double t0_, double omega, double y, double a, * @param hcubature_err Error tolerance for calculation * @param args Additional arguments to be passed to the hcubature function * @return Wiener7 density or gradient calculated by integration -*/ + */ template auto wiener7_integrand(double hcubature_err, TArgs&&... args) { const auto& wiener7_integrand_impl @@ -81,11 +81,10 @@ auto wiener7_integrand(double hcubature_err, TArgs&&... args) { return hcubature(wiener7_integrand_impl, int_args...); }; return estimate_with_err_check<0, 8>(functor, hcubature_err, - std::make_tuple(args...)); + std::make_tuple(args...)); } } // namespace internal - /** * Log-density function for the 7-parameter Wiener density. * See 'wiener_full_lpdf' for more comprehensive documentation @@ -273,8 +272,7 @@ inline return_type_t wiener7_lpdf( double hcubature_err = labstol_wiener5 - lerror_bound_dens + LOG_TWO + 1; dens = internal::wiener7_integrand( - hcubature_err, params, dim, xmin, xmax, Meval, - abstol, reltol / 2); + hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2); double log_dens = log(dens); ld += log_dens; @@ -282,10 +280,10 @@ inline return_type_t wiener7_lpdf( // computation of derivative for t and precision check in order to give // the value as deriv_t to edge1 and as -deriv_t to edge5 - double deriv_t_7 = internal::wiener7_integrand( - hcubature_err, params, - dim, xmin, xmax, Meval, abstol, reltol / 2) - / dens; + double deriv_t_7 + = internal::wiener7_integrand( + hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2) + / dens; // computation of derivatives and precision checks double deriv; @@ -295,8 +293,8 @@ inline return_type_t wiener7_lpdf( if (!is_constant_all::value) { ops_partials.edge2_.partials_[i] = internal::wiener7_integrand( - hcubature_err, params, dim, xmin, - xmax, Meval, abstol, reltol / 2) + hcubature_err, params, dim, xmin, xmax, Meval, abstol, + reltol / 2) / dens; } if (!is_constant_all::value) { @@ -305,22 +303,22 @@ inline return_type_t wiener7_lpdf( if (!is_constant_all::value) { ops_partials.edge4_.partials_[i] = internal::wiener7_integrand( - hcubature_err, params, dim, xmin, - xmax, Meval, abstol, reltol / 2) + hcubature_err, params, dim, xmin, xmax, Meval, abstol, + reltol / 2) / dens; } if (!is_constant_all::value) { ops_partials.edge5_.partials_[i] = internal::wiener7_integrand( - hcubature_err, params, dim, xmin, - xmax, Meval, abstol, reltol / 2) + hcubature_err, params, dim, xmin, xmax, Meval, abstol, + reltol / 2) / dens; } if (!is_constant_all::value) { ops_partials.edge6_.partials_[i] = internal::wiener7_integrand( - hcubature_err, params, dim, xmin, - xmax, Meval, abstol, reltol / 2) + hcubature_err, params, dim, xmin, xmax, Meval, abstol, + reltol / 2) / dens; } if (!is_constant_all::value) { @@ -334,8 +332,7 @@ inline return_type_t wiener7_lpdf( std::tuple_cat(std::make_tuple(t0_val, 0), params)); } else { deriv = internal::wiener7_integrand( - hcubature_err, params, 1, xmin, xmax, Meval, - abstol, reltol / 2); + hcubature_err, params, 1, xmin, xmax, Meval, abstol, reltol / 2); } ops_partials.edge7_.partials_[i] = deriv / dens - 1 / sw_val; } @@ -359,8 +356,8 @@ inline return_type_t wiener7_lpdf( const auto& params_st = std::make_tuple( y_val, a_val, v_val, w_val, t0_st0, sv_val, sw_val, 0, new_error); f = internal::wiener7_integrand( - hcubature_err, params_st, 1, xmin, xmax, Meval, - abstol, reltol / 2); + hcubature_err, params_st, 1, xmin, xmax, Meval, abstol, + reltol / 2); } ops_partials.edge8_.partials_[i] = -1 / st0_val + f / st0_val / dens; } From 290ef4a304878f5bcfd6395fb8fea27973d0d4fb Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 10 May 2023 16:31:17 +0300 Subject: [PATCH 052/179] Update comp --- stan/math/prim/prob/wiener5_lpdf.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 897e0ba9152..3a729aac5eb 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -135,7 +135,10 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, double erg = NEGATIVE_INFTY; int newsign = 1; double scaling = (2 * kss <= kll) ? inv(2.0 * y_asq) : y_asq / 2.0; - if (2 * kss <= kll) { + + bool kss_comp = (FunTypeEnum == FunType::Density) ? 2 * kss <= kll + : 2 * kss < kll; + if (kss_comp) { double mult = (FunTypeEnum == FunType::Density) ? 1 : 3; double offset = (FunTypeEnum == FunType::GradW) ? y_asq : 0; double sqrt_offset = sqrt(offset); From 777ba44d8fdccfa985232e0ea1263fdf55dbe7ac Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 10 May 2023 09:34:04 -0400 Subject: [PATCH 053/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 3a729aac5eb..fa588b93afb 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -136,8 +136,8 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, int newsign = 1; double scaling = (2 * kss <= kll) ? inv(2.0 * y_asq) : y_asq / 2.0; - bool kss_comp = (FunTypeEnum == FunType::Density) ? 2 * kss <= kll - : 2 * kss < kll; + bool kss_comp + = (FunTypeEnum == FunType::Density) ? 2 * kss <= kll : 2 * kss < kll; if (kss_comp) { double mult = (FunTypeEnum == FunType::Density) ? 1 : 3; double offset = (FunTypeEnum == FunType::GradW) ? y_asq : 0; From 994910399a7cd4d4b1388368cf9f93b1088c6b5f Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 10 May 2023 18:18:34 +0300 Subject: [PATCH 054/179] Fix hang due to zero return --- stan/math/prim/prob/wiener5_lpdf.hpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index fa588b93afb..416f36e3441 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -77,7 +77,6 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, ans0 = (FunTypeEnum == FunType::GradT) ? -0.5 * square(v) : -v * var_a; } } - double es = (err - lg1) + (FunTypeEnum == FunType::GradT) * two_log_a; double two_es = 2.0 * es; double y_asq = y / square(a); @@ -96,7 +95,7 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); double K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; - size_t kss = static_cast(ceil(fmax(K1, K2))); + double kss = ceil(fmax(K1, K2)); static const double PISQ = square(pi()); // pi*pi if (FunTypeEnum == FunType::Density) { @@ -118,7 +117,7 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, : (arg > 0) ? sqrt(arg / y_asq) / pi() : K1; } - size_t kll = static_cast(ceil(fmax(K1, K2))); + double kll = ceil(fmax(K1, K2)); double ld_err = 0; if (FunTypeEnum != FunType::Density) { @@ -137,12 +136,13 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, double scaling = (2 * kss <= kll) ? inv(2.0 * y_asq) : y_asq / 2.0; bool kss_comp - = (FunTypeEnum == FunType::Density) ? 2 * kss <= kll : 2 * kss < kll; + = (FunTypeEnum == FunType::Density) ? (2 * kss <= kll) + : (2 * kss < kll); if (kss_comp) { double mult = (FunTypeEnum == FunType::Density) ? 1 : 3; double offset = (FunTypeEnum == FunType::GradW) ? y_asq : 0; double sqrt_offset = sqrt(offset); - for (size_t k = kss; k >= std::fmax(0, kss - 1e3); k--) { + for (size_t k = static_cast(kss); k >= 0; k--) { double wp2k = w + 2.0 * k; double wm2k = w - 2.0 * k; int wp2k_sign = (wp2k > sqrt_offset) ? 1 : -1; @@ -181,7 +181,7 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, } else if (FunTypeEnum == FunType::GradW) { mult = 2; } - for (size_t k = kll; k >= std::fmax(1, kll - 1e3); k--) { + for (size_t k = static_cast(kll); k >= 1; k--) { double pi_k = k * pi(); double check = (FunTypeEnum == FunType::GradW) ? cos(pi_k * w) : sin(pi_k * w); @@ -252,6 +252,7 @@ double estimate_with_err_check(const F& functor, double err, args_tuple); double lfabs_result = log_result ? log(fabs(result)) : fabs(result); if (lfabs_result < err) { + lfabs_result = std::isinf(lfabs_result) ? 0 : lfabs_result; ArgsTupleT err_args_tuple = args_tuple; assign_err(std::get(err_args_tuple), err + lfabs_result); From 8f1cb4a62a8f5be64d00847e22d5c21284fb7b12 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 10 May 2023 11:20:31 -0400 Subject: [PATCH 055/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 416f36e3441..e9a1b53f5ce 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -135,9 +135,8 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, int newsign = 1; double scaling = (2 * kss <= kll) ? inv(2.0 * y_asq) : y_asq / 2.0; - bool kss_comp - = (FunTypeEnum == FunType::Density) ? (2 * kss <= kll) - : (2 * kss < kll); + bool kss_comp = (FunTypeEnum == FunType::Density) ? (2 * kss <= kll) + : (2 * kss < kll); if (kss_comp) { double mult = (FunTypeEnum == FunType::Density) ? 1 : 3; double offset = (FunTypeEnum == FunType::GradW) ? y_asq : 0; From 783288627a77a4621afc5c9c098f6f7c5ab577c8 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 11 May 2023 12:17:37 +0300 Subject: [PATCH 056/179] wiener7 to wiener_full --- stan/math/prim/prob.hpp | 1 - stan/math/prim/prob/wiener5_lpdf.hpp | 10 +- stan/math/prim/prob/wiener7_lpdf.hpp | 372 ----------------------- stan/math/prim/prob/wiener_full_lpdf.hpp | 351 +++++++++++++++++++-- 4 files changed, 325 insertions(+), 409 deletions(-) delete mode 100644 stan/math/prim/prob/wiener7_lpdf.hpp diff --git a/stan/math/prim/prob.hpp b/stan/math/prim/prob.hpp index 2c6f75cfd0e..72bc47ecd7c 100644 --- a/stan/math/prim/prob.hpp +++ b/stan/math/prim/prob.hpp @@ -367,7 +367,6 @@ #include #include #include -#include #include #include #include diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index e9a1b53f5ce..9fdbecc77e3 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -133,10 +133,10 @@ inline double wiener5_helper(const double& y, const double& a, const double& vn, double erg = NEGATIVE_INFTY; int newsign = 1; - double scaling = (2 * kss <= kll) ? inv(2.0 * y_asq) : y_asq / 2.0; - bool kss_comp = (FunTypeEnum == FunType::Density) ? (2 * kss <= kll) - : (2 * kss < kll); + bool kss_comp + = (FunTypeEnum == FunType::Density) ? 2 * kss <= kll : 2 * kss < kll; + double scaling = kss_comp ? inv(2.0 * y_asq) : y_asq / 2.0; if (kss_comp) { double mult = (FunTypeEnum == FunType::Density) ? 1 : 3; double offset = (FunTypeEnum == FunType::GradW) ? y_asq : 0; @@ -282,8 +282,8 @@ double estimate_with_err_check(const F& functor, double err, * @return The log of the Wiener first passage time density with * the specified arguments for upper boundary responses */ -template +template inline return_type_t wiener5_lpdf( const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, const T_sv& sv, const double& prec) { diff --git a/stan/math/prim/prob/wiener7_lpdf.hpp b/stan/math/prim/prob/wiener7_lpdf.hpp deleted file mode 100644 index 70ac917f075..00000000000 --- a/stan/math/prim/prob/wiener7_lpdf.hpp +++ /dev/null @@ -1,372 +0,0 @@ -#ifndef STAN_MATH_PRIM_PROB_WIENER7_LPDF_HPP -#define STAN_MATH_PRIM_PROB_WIENER7_LPDF_HPP - -#include -#include -#include - -namespace stan { -namespace math { -namespace internal { - -/** - * Implementation function for delegating computation to the correct density - * or derivative function. For all gradients except the sw parameter, the - * respective wiener5 function is called. - * - * @tparam FunTypeEnum An enum value indicating the function required - * @param t0_ See wiener7_integrand function for definition - * @param omega See wiener7_integrand function for definition - * @param y A scalar variable; the reaction time in seconds - * @param a The boundary separation - * @param v The drift rate - * @param w The relative starting point - * @param t0 The non-decision time - * @param sv The inter-trial variability of the drift rate - * @param sw The inter-trial variability of the relative starting point - * @param st0 The inter-trial variability of the non-decision time - * @param lerr Error tolerance - * - * @return Log-density or gradient for wiener7_lpdf - */ -template -inline double wiener7_helper(double t0_, double omega, double y, double a, - double v, double w, double t0, double sv, - double sw, double st0, double lerr) { - double ymt0 = y - t0_; - if (FunTypeEnum == FunType::GradSW) { - double low = w - sw / 2; - low = (0 > low) ? 0 : low; - double high = w + sw / 2; - high = (1 < high) ? 1 : high; - double fl - = wiener5_helper(ymt0, a, v, low, sv, lerr, true); - double fu - = wiener5_helper(ymt0, a, v, high, sv, lerr, true); - return 0.5 * (fl + fu) / sw; - } else { - return wiener5_helper(ymt0, a, v, omega, sv, lerr, true); - } -} - -/** - * Implementation function for preparing arguments and functor to be passed - * to the hcubature() function for calculating wiener7 parameters via - * integration - * - * @tparam FunTypeEnum An enum value indicating the function required - * @tparam Targs... Types of arguments in parameter pack - * @param hcubature_err Error tolerance for calculation - * @param args Additional arguments to be passed to the hcubature function - * @return Wiener7 density or gradient calculated by integration - */ -template -auto wiener7_integrand(double hcubature_err, TArgs&&... args) { - const auto& wiener7_integrand_impl - = [&](std::vector x, double y, double a, double v, double w, - double t0, double sv, double sw, double st0, double lerr) { - scalar_seq_view x_vec(x); - double sw_val = (FunTypeEnum == FunType::GradSW) ? 0 : sw; - double omega = sw_val ? w + sw_val * (x_vec[0] - 0.5) : w; - double t0_ = sw_val ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); - if (y - t0_ <= 0) { - return 0.0; - } else { - return wiener7_helper(t0_, omega, y, a, v, w, t0, sv, - sw, st0, lerr); - } - }; - const auto& functor = [&](auto&&... int_args) { - return hcubature(wiener7_integrand_impl, int_args...); - }; - return estimate_with_err_check<0, 8>(functor, hcubature_err, - std::make_tuple(args...)); -} -} // namespace internal - -/** - * Log-density function for the 7-parameter Wiener density. - * See 'wiener_full_lpdf' for more comprehensive documentation - * - * @tparam T_y type of scalar - * @tparam T_a type of boundary - * @tparam T_t0 type of non-decision time - * @tparam T_w type of relative starting point - * @tparam T_v type of drift rate - * @tparam T_sv type of inter-trial variability of drift rate - * @tparam T_sw type of inter-trial variability of relative starting point - * @tparam T_st0 type of inter-trial variability of non-decision time - * - * @param y A scalar variable; the reaction time in seconds - * @param a The boundary separation - * @param t0 The non-decision time - * @param w The relative starting point - * @param v The drift rate - * @param sv The inter-trial variability of the drift rate - * @param sw The inter-trial variability of the relative starting point - * @param st0 The inter-trial variability of the non-decision time - * @return The log of the Wiener first passage time density with - * the specified arguments for upper boundary responses - * @throw std::domain_error if non-decision time \c t0 is greater than reaction - time \c y. - * @throw std::domain_error if \c 1-sw/2 is smaller than or equal to \c w. - * @throw std::domain_error if \c sw/2 is larger than or equal to \c w. -*/ -template -inline return_type_t wiener7_lpdf( - const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, - const T_sv& sv, const T_sw& sw, const T_st0& st0, const double& prec) { - using T_y_ref = ref_type_t; - using T_a_ref = ref_type_t; - using T_v_ref = ref_type_t; - using T_w_ref = ref_type_t; - using T_t0_ref = ref_type_t; - using T_sv_ref = ref_type_t; - using T_sw_ref = ref_type_t; - using T_st0_ref = ref_type_t; - - const char* function_name = "wiener7_lpdf"; - check_consistent_sizes(function_name, "Random variable", y, - "Boundary separation", a, "Drift rate", v, - "A-priori bias", w, "Nondecision time", t0, - "Inter-trial variability in drift rate", sv, - "Inter-trial variability in A-priori bias", sw, - "Inter-trial variability in Nondecision time", st0); - check_consistent_size(function_name, "Random variable", y, 1); - check_consistent_size(function_name, "Boundary separation", a, 1); - check_consistent_size(function_name, "Drift rate", v, 1); - check_consistent_size(function_name, "A-priori bias", w, 1); - check_consistent_size(function_name, "Nondecision time", t0, 1); - check_consistent_size(function_name, "Inter-trial variability in drift rate", - sv, 1); - check_consistent_size(function_name, - "Inter-trial variability in A-priori bias", sw, 1); - check_consistent_size(function_name, - "Inter-trial variability in Nondecision time", st0, 1); - - T_y_ref y_ref = y; - T_a_ref a_ref = a; - T_v_ref v_ref = v; - T_w_ref w_ref = w; - T_t0_ref t0_ref = t0; - T_sv_ref sv_ref = sv; - T_sw_ref sw_ref = sw; - T_st0_ref st0_ref = st0; - - check_positive_finite(function_name, "Random variable", value_of(y_ref)); - check_positive_finite(function_name, "Boundary separation", value_of(a_ref)); - check_finite(function_name, "Drift rate", value_of(v_ref)); - check_less(function_name, "A-priori bias", value_of(w_ref), 1); - check_greater(function_name, "A-priori bias", value_of(w_ref), 0); - check_nonnegative(function_name, "Nondecision time", value_of(t0_ref)); - check_finite(function_name, "Nondecision time", value_of(t0_ref)); - check_nonnegative(function_name, "Inter-trial variability in drift rate", - value_of(sv_ref)); - check_finite(function_name, "Inter-trial variability in drift rate", - value_of(sv_ref)); - check_bounded(function_name, "Inter-trial variability in A-priori bias", - value_of(sw_ref), 0, 1); - check_nonnegative(function_name, - "Inter-trial variability in Nondecision time", - value_of(st0_ref)); - check_finite(function_name, "Inter-trial variability in Nondecision time", - value_of(st0_ref)); - - if (size_zero(y, a, v, w, t0) || size_zero(sv, sw, st0)) { - return 0; - } - size_t N = max_size(y, a, v, w, t0, sv, sw, st0); - if (!N) { - return 0; - } - scalar_seq_view y_vec(y_ref); - scalar_seq_view a_vec(a_ref); - scalar_seq_view v_vec(v_ref); - scalar_seq_view w_vec(w_ref); - scalar_seq_view t0_vec(t0_ref); - scalar_seq_view sv_vec(sv_ref); - scalar_seq_view sw_vec(sw_ref); - scalar_seq_view st0_vec(st0_ref); - size_t N_y_t0 = max_size(y, t0, st0); - - for (size_t i = 0; i < N_y_t0; ++i) { - if (y_vec[i] <= t0_vec[i]) { - std::stringstream msg; - msg << ", but must be greater than nondecision time = " << t0_vec[i]; - std::string msg_str(msg.str()); - throw_domain_error(function_name, "Random variable", y_vec[i], " = ", - msg_str.c_str()); - } - } - size_t N_beta_sw = max_size(w, sw); - for (size_t i = 0; i < N_beta_sw; ++i) { - if (w_vec[i] - .5 * sw_vec[i] <= 0) { - std::stringstream msg; - msg << ", but must be smaller than 2*(A-priori bias) = " << 2 * w_vec[i]; - std::string msg_str(msg.str()); - throw_domain_error(function_name, - "Inter-trial variability in A-priori bias", sw_vec[i], - " = ", msg_str.c_str()); - } - if (w_vec[i] + .5 * sw_vec[i] >= 1) { - std::stringstream msg; - msg << ", but must be smaller than 2*(1-A-priori bias) = " - << 2 * (1 - w_vec[i]); - std::string msg_str(msg.str()); - throw_domain_error(function_name, - "Inter-trial variability in A-priori bias", sw_vec[i], - " = ", msg_str.c_str()); - } - } - if (!include_summand::value) { - return 0; - } - - double error_bound_dens = 1e-6; // precision for density - double lerror_bound_dens = log(error_bound_dens); - double error_bound = prec; // precision for - // derivatives (controllable by user) - double lerror_bound = log(error_bound); // log(alpha) - double abstol = 0.0; - double reltol = .9 * error_bound; // eps_rel(Integration) - double abstol_wiener5 = 1e-12; // eps_abs(wiener5) - double labstol_wiener5 = log(abstol_wiener5); - // log(eps_abs(wiener5) - int Meval = 6000; - double dens = 0.0; - double ld = 0.0; - operands_and_partials - ops_partials(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref, sw_ref, st0_ref); - static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; - static constexpr double LOG_POINT1 = -1; - - // calculate density and partials - for (size_t i = 0; i < N; i++) { - const double y_val = y_vec.val(i); - const double a_val = a_vec.val(i); - const double v_val = v_vec.val(i); - const double w_val = w_vec.val(i); - const double t0_val = t0_vec.val(i); - const double sv_val = sv_vec.val(i); - const double sw_val = sw_vec.val(i); - const double st0_val = st0_vec.val(i); - const auto params - = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, - st0_val, labstol_wiener5 - LOG_TWO); - int dim = (sw_val != 0) + (st0_val != 0); - check_positive(function_name, - "(Inter-trial variability in A-priori bias) + " - "(Inter-trial variability in nondecision time)", - dim); - - std::vector xmin(dim, 0); - std::vector xmax(dim, 1); - if (st0_val) { - xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); - } - - double hcubature_err = labstol_wiener5 - lerror_bound_dens + LOG_TWO + 1; - - dens = internal::wiener7_integrand( - hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2); - double log_dens = log(dens); - ld += log_dens; - - hcubature_err = labstol_wiener5 - (lerror_bound + log_dens) + LOG_TWO + 1; - - // computation of derivative for t and precision check in order to give - // the value as deriv_t to edge1 and as -deriv_t to edge5 - double deriv_t_7 - = internal::wiener7_integrand( - hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2) - / dens; - - // computation of derivatives and precision checks - double deriv; - if (!is_constant_all::value) { - ops_partials.edge1_.partials_[i] = deriv_t_7; - } - if (!is_constant_all::value) { - ops_partials.edge2_.partials_[i] - = internal::wiener7_integrand( - hcubature_err, params, dim, xmin, xmax, Meval, abstol, - reltol / 2) - / dens; - } - if (!is_constant_all::value) { - ops_partials.edge3_.partials_[i] = -deriv_t_7; - } - if (!is_constant_all::value) { - ops_partials.edge4_.partials_[i] - = internal::wiener7_integrand( - hcubature_err, params, dim, xmin, xmax, Meval, abstol, - reltol / 2) - / dens; - } - if (!is_constant_all::value) { - ops_partials.edge5_.partials_[i] - = internal::wiener7_integrand( - hcubature_err, params, dim, xmin, xmax, Meval, abstol, - reltol / 2) - / dens; - } - if (!is_constant_all::value) { - ops_partials.edge6_.partials_[i] - = internal::wiener7_integrand( - hcubature_err, params, dim, xmin, xmax, Meval, abstol, - reltol / 2) - / dens; - } - if (!is_constant_all::value) { - if (sw_val == 0) { - ops_partials.edge7_.partials_[i] = 0; - } else { - if (st0_val == 0) { - deriv = internal::estimate_with_err_check<8>( - internal::wiener7_helper, - lerror_bound - LOG_TWO, - std::tuple_cat(std::make_tuple(t0_val, 0), params)); - } else { - deriv = internal::wiener7_integrand( - hcubature_err, params, 1, xmin, xmax, Meval, abstol, reltol / 2); - } - ops_partials.edge7_.partials_[i] = deriv / dens - 1 / sw_val; - } - } - if (!is_constant_all::value) { - double f; - if (st0_val == 0) { - ops_partials.edge8_.partials_[i] = 0; - } else if (y_val - (t0_val + st0_val) <= 0) { - ops_partials.edge8_.partials_[i] = -1 / st0_val; - } else { - double t0_st0 = t0_val + st0_val; - if (sw_val == 0) { - f = internal::estimate_with_err_check<8>( - internal::wiener7_helper, - lerror_bound + log(st0_val), - std::tuple_cat(std::make_tuple(t0_st0, w_val), params)); - } else { - double new_error = labstol_wiener5 - LOG_TWO; - - const auto& params_st = std::make_tuple( - y_val, a_val, v_val, w_val, t0_st0, sv_val, sw_val, 0, new_error); - f = internal::wiener7_integrand( - hcubature_err, params_st, 1, xmin, xmax, Meval, abstol, - reltol / 2); - } - ops_partials.edge8_.partials_[i] = -1 / st0_val + f / st0_val / dens; - } - } - std::vector().swap(xmin); - std::vector().swap(xmax); - } - return ops_partials.build(ld); -} -} // namespace math -} // namespace stan -#endif diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 2561c18bb94..2f5ab2d3728 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -2,11 +2,88 @@ #define STAN_MATH_PRIM_PROB_WIENER_FULL_LPDF_HPP #include +#include #include -#include namespace stan { namespace math { +namespace internal { + +/** + * Implementation function for delegating computation to the correct density + * or derivative function. For all gradients except the sw parameter, the + * respective wiener5 function is called. + * + * @tparam FunTypeEnum An enum value indicating the function required + * @param t0_ See wiener7_integrand function for definition + * @param omega See wiener7_integrand function for definition + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param v The drift rate + * @param w The relative starting point + * @param t0 The non-decision time + * @param sv The inter-trial variability of the drift rate + * @param sw The inter-trial variability of the relative starting point + * @param st0 The inter-trial variability of the non-decision time + * @param lerr Error tolerance + * + * @return Log-density or gradient for wiener7_lpdf + */ +template +inline double wiener7_helper(double t0_, double omega, double y, double a, + double v, double w, double t0, double sv, + double sw, double st0, double lerr) { + double ymt0 = y - t0_; + if (FunTypeEnum == FunType::GradSW) { + double low = w - sw / 2; + low = (0 > low) ? 0 : low; + double high = w + sw / 2; + high = (1 < high) ? 1 : high; + double fl + = wiener5_helper(ymt0, a, v, low, sv, lerr, true); + double fu + = wiener5_helper(ymt0, a, v, high, sv, lerr, true); + return 0.5 * (fl + fu) / sw; + } else { + return wiener5_helper(ymt0, a, v, omega, sv, lerr, true); + } +} + +/** + * Implementation function for preparing arguments and functor to be passed + * to the hcubature() function for calculating wiener7 parameters via + * integration + * + * @tparam FunTypeEnum An enum value indicating the function required + * @tparam Targs... Types of arguments in parameter pack + * @param hcubature_err Error tolerance for calculation + * @param args Additional arguments to be passed to the hcubature function + * @return Wiener7 density or gradient calculated by integration + */ +template +auto wiener7_integrand(double hcubature_err, TArgs&&... args) { + const auto& wiener7_integrand_impl + = [&](std::vector x, double y, double a, double v, double w, + double t0, double sv, double sw, double st0, double lerr) { + scalar_seq_view x_vec(x); + double sw_val = (FunTypeEnum == FunType::GradSW) ? 0 : sw; + double omega = sw_val ? w + sw_val * (x_vec[0] - 0.5) : w; + double t0_ = sw_val ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); + if (y - t0_ <= 0) { + return 0.0; + } else { + return wiener7_helper(t0_, omega, y, a, v, w, t0, sv, + sw, st0, lerr); + } + }; + const auto& functor = [&](auto&&... int_args) { + return hcubature(wiener7_integrand_impl, int_args...); + }; + return estimate_with_err_check<0, 8>(functor, hcubature_err, + std::make_tuple(args...)); +} +} // namespace internal /** \ingroup prob_dists * The log of the first passage time density function for a (Wiener) @@ -120,10 +197,9 @@ namespace math { target += wiener_full_lpdf(y, a, 0, w, v, sv, sw, 0) @endcode * - * To also control the precision in the estimation of the partial derivatives, - * call the function \c wiener_full_prec_lpdf(), analogously: + * To also control the precision in the estimation of the partial derivatives: @code - target += wiener_full__prec_lpdf(y, a, t0, w, v, sv, sw, st0, precision); + target += wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0, precision); @endcode * * @@ -149,55 +225,268 @@ namespace math { * *Journal of Mathematical Psychology, 53*(4), 222–230. * https://doi.org/10.1016/j.jmp.2009.02.003 */ - -template -inline return_type_t -wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, - const T_v& v, const T_sv& sv, const T_sw& sw, const T_st0& st0, - double precision = 1e-4) { - const char* function_name = "wiener_full_lpdf"; +template > +inline ReturnT wiener_full_lpdf( + const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, + const T_sv& sv, const T_sw& sw, const T_st0& st0, double prec = 1e-4) { + using T_y_ref = ref_type_t; + using T_a_ref = ref_type_t; + using T_v_ref = ref_type_t; + using T_w_ref = ref_type_t; + using T_t0_ref = ref_type_t; + using T_sv_ref = ref_type_t; using T_sw_ref = ref_type_t; using T_st0_ref = ref_type_t; + const char* function_name = "wiener_full_lpdf"; + check_consistent_sizes(function_name, "Random variable", y, + "Boundary separation", a, "Drift rate", v, + "A-priori bias", w, "Nondecision time", t0, + "Inter-trial variability in drift rate", sv, + "Inter-trial variability in A-priori bias", sw, + "Inter-trial variability in Nondecision time", st0); + check_consistent_size(function_name, "Random variable", y, 1); + check_consistent_size(function_name, "Boundary separation", a, 1); + check_consistent_size(function_name, "Drift rate", v, 1); + check_consistent_size(function_name, "A-priori bias", w, 1); + check_consistent_size(function_name, "Nondecision time", t0, 1); + check_consistent_size(function_name, "Inter-trial variability in drift rate", + sv, 1); check_consistent_size(function_name, "Inter-trial variability in A-priori bias", sw, 1); check_consistent_size(function_name, "Inter-trial variability in Nondecision time", st0, 1); + T_y_ref y_ref = y; + T_a_ref a_ref = a; + T_v_ref v_ref = v; + T_w_ref w_ref = w; + T_t0_ref t0_ref = t0; + T_sv_ref sv_ref = sv; T_sw_ref sw_ref = sw; T_st0_ref st0_ref = st0; - size_t N = max_size(y, a, t0, w, v, sv, sw, st0); + check_positive_finite(function_name, "Random variable", value_of(y_ref)); + check_positive_finite(function_name, "Boundary separation", value_of(a_ref)); + check_finite(function_name, "Drift rate", value_of(v_ref)); + check_less(function_name, "A-priori bias", value_of(w_ref), 1); + check_greater(function_name, "A-priori bias", value_of(w_ref), 0); + check_nonnegative(function_name, "Nondecision time", value_of(t0_ref)); + check_finite(function_name, "Nondecision time", value_of(t0_ref)); + check_nonnegative(function_name, "Inter-trial variability in drift rate", + value_of(sv_ref)); + check_finite(function_name, "Inter-trial variability in drift rate", + value_of(sv_ref)); + check_bounded(function_name, "Inter-trial variability in A-priori bias", + value_of(sw_ref), 0, 1); + check_nonnegative(function_name, + "Inter-trial variability in Nondecision time", + value_of(st0_ref)); + check_finite(function_name, "Inter-trial variability in Nondecision time", + value_of(st0_ref)); + + if (size_zero(y, a, v, w, t0) || size_zero(sv, sw, st0)) { + return 0; + } + size_t N = max_size(y, a, v, w, t0, sv, sw, st0); if (!N) { return 0; } - + scalar_seq_view y_vec(y_ref); + scalar_seq_view a_vec(a_ref); + scalar_seq_view v_vec(v_ref); + scalar_seq_view w_vec(w_ref); + scalar_seq_view t0_vec(t0_ref); + scalar_seq_view sv_vec(sv_ref); scalar_seq_view sw_vec(sw_ref); scalar_seq_view st0_vec(st0_ref); + size_t N_y_t0 = max_size(y, t0, st0); + + for (size_t i = 0; i < N_y_t0; ++i) { + if (y_vec[i] <= t0_vec[i]) { + std::stringstream msg; + msg << ", but must be greater than nondecision time = " << t0_vec[i]; + std::string msg_str(msg.str()); + throw_domain_error(function_name, "Random variable", y_vec[i], " = ", + msg_str.c_str()); + } + } + size_t N_beta_sw = max_size(w, sw); + for (size_t i = 0; i < N_beta_sw; ++i) { + if (w_vec[i] - .5 * sw_vec[i] <= 0) { + std::stringstream msg; + msg << ", but must be smaller than 2*(A-priori bias) = " << 2 * w_vec[i]; + std::string msg_str(msg.str()); + throw_domain_error(function_name, + "Inter-trial variability in A-priori bias", sw_vec[i], + " = ", msg_str.c_str()); + } + if (w_vec[i] + .5 * sw_vec[i] >= 1) { + std::stringstream msg; + msg << ", but must be smaller than 2*(1-A-priori bias) = " + << 2 * (1 - w_vec[i]); + std::string msg_str(msg.str()); + throw_domain_error(function_name, + "Inter-trial variability in A-priori bias", sw_vec[i], + " = ", msg_str.c_str()); + } + } + if (!include_summand::value) { + return 0; + } + + double error_bound_dens = 1e-6; // precision for density + double lerror_bound_dens = log(error_bound_dens); + double error_bound = prec; // precision for + // derivatives (controllable by user) + double lerror_bound = log(error_bound); // log(alpha) + double abstol = 0.0; + double reltol = .9 * error_bound; // eps_rel(Integration) + double abstol_wiener5 = 1e-12; // eps_abs(wiener5) + double labstol_wiener5 = log(abstol_wiener5); + // log(eps_abs(wiener5) + int Meval = 6000; + double dens = 0.0; + double ld = 0.0; + operands_and_partials + ops_partials(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref, sw_ref, st0_ref); + static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; + static constexpr double LOG_POINT1 = -1; + ReturnT result = 0; // calculate density and partials for (size_t i = 0; i < N; i++) { - // Calculate 4-parameter model without inter-trial variabilities (if - // sv_vec[i] == 0) or 5-parameter model with inter-trial variability in - // drift rate (if sv_vec[i] != 0) if (sw_vec[i] == 0 && st0_vec[i] == 0) { - return wiener5_lpdf(y, a, t0, w, v, sv, precision); - // Calculate 6-, or 7-parameter model - } else { - return wiener7_lpdf(y, a, t0, w, v, sv, sw, st0, precision); + result += wiener5_lpdf(y_vec[i], a_vec[i], t0_vec[i], w_vec[i], + v_vec[i], sv_vec[i], prec); + continue; } - } - return 0; -} + const double y_val = y_vec.val(i); + const double a_val = a_vec.val(i); + const double v_val = v_vec.val(i); + const double w_val = w_vec.val(i); + const double t0_val = t0_vec.val(i); + const double sv_val = sv_vec.val(i); + const double sw_val = sw_vec.val(i); + const double st0_val = st0_vec.val(i); + const auto params + = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, + st0_val, labstol_wiener5 - LOG_TWO); + int dim = (sw_val != 0) + (st0_val != 0); + check_positive(function_name, + "(Inter-trial variability in A-priori bias) + " + "(Inter-trial variability in nondecision time)", + dim); + + std::vector xmin(dim, 0); + std::vector xmax(dim, 1); + if (st0_val) { + xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); + } + + double hcubature_err = labstol_wiener5 - lerror_bound_dens + LOG_TWO + 1; -template -inline return_type_t -wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, - const T_v& v, const T_sv& sv, const T_sw& sw, const T_st0& st0, - double precision = 1e-4) { - return wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0, precision); + dens = internal::wiener7_integrand( + hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2); + double log_dens = log(dens); + ld += log_dens; + + hcubature_err = labstol_wiener5 - (lerror_bound + log_dens) + LOG_TWO + 1; + + // computation of derivative for t and precision check in order to give + // the value as deriv_t to edge1 and as -deriv_t to edge5 + double deriv_t_7 + = internal::wiener7_integrand( + hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2) + / dens; + + // computation of derivatives and precision checks + double deriv; + if (!is_constant_all::value) { + ops_partials.edge1_.partials_[i] = deriv_t_7; + } + if (!is_constant_all::value) { + ops_partials.edge2_.partials_[i] + = internal::wiener7_integrand( + hcubature_err, params, dim, xmin, xmax, Meval, abstol, + reltol / 2) + / dens; + } + if (!is_constant_all::value) { + ops_partials.edge3_.partials_[i] = -deriv_t_7; + } + if (!is_constant_all::value) { + ops_partials.edge4_.partials_[i] + = internal::wiener7_integrand( + hcubature_err, params, dim, xmin, xmax, Meval, abstol, + reltol / 2) + / dens; + } + if (!is_constant_all::value) { + ops_partials.edge5_.partials_[i] + = internal::wiener7_integrand( + hcubature_err, params, dim, xmin, xmax, Meval, abstol, + reltol / 2) + / dens; + } + if (!is_constant_all::value) { + ops_partials.edge6_.partials_[i] + = internal::wiener7_integrand( + hcubature_err, params, dim, xmin, xmax, Meval, abstol, + reltol / 2) + / dens; + } + if (!is_constant_all::value) { + if (sw_val == 0) { + ops_partials.edge7_.partials_[i] = 0; + } else { + if (st0_val == 0) { + deriv = internal::estimate_with_err_check<8>( + internal::wiener7_helper, + lerror_bound - LOG_TWO, + std::tuple_cat(std::make_tuple(t0_val, 0), params)); + } else { + deriv = internal::wiener7_integrand( + hcubature_err, params, 1, xmin, xmax, Meval, abstol, reltol / 2); + } + ops_partials.edge7_.partials_[i] = deriv / dens - 1 / sw_val; + } + } + if (!is_constant_all::value) { + double f; + if (st0_val == 0) { + ops_partials.edge8_.partials_[i] = 0; + } else if (y_val - (t0_val + st0_val) <= 0) { + ops_partials.edge8_.partials_[i] = -1 / st0_val; + } else { + double t0_st0 = t0_val + st0_val; + if (sw_val == 0) { + f = internal::estimate_with_err_check<8>( + internal::wiener7_helper, + lerror_bound + log(st0_val), + std::tuple_cat(std::make_tuple(t0_st0, w_val), params)); + } else { + double new_error = labstol_wiener5 - LOG_TWO; + + const auto& params_st = std::make_tuple( + y_val, a_val, v_val, w_val, t0_st0, sv_val, sw_val, 0, new_error); + f = internal::wiener7_integrand( + hcubature_err, params_st, 1, xmin, xmax, Meval, abstol, + reltol / 2); + } + ops_partials.edge8_.partials_[i] = -1 / st0_val + f / st0_val / dens; + } + } + std::vector().swap(xmin); + std::vector().swap(xmax); + } + return result + ops_partials.build(ld); } } // namespace math } // namespace stan From afd3bb11ddd83ce3d27107a80cf3db38c7bcdd5d Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 11 May 2023 05:20:48 -0400 Subject: [PATCH 057/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener_full_lpdf.hpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 2f5ab2d3728..c763592df97 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -228,11 +228,12 @@ auto wiener7_integrand(double hcubature_err, TArgs&&... args) { template > -inline ReturnT wiener_full_lpdf( - const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, - const T_sv& sv, const T_sw& sw, const T_st0& st0, double prec = 1e-4) { + typename ReturnT + = return_type_t> +inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, + const T_w& w, const T_v& v, const T_sv& sv, + const T_sw& sw, const T_st0& st0, + double prec = 1e-4) { using T_y_ref = ref_type_t; using T_a_ref = ref_type_t; using T_v_ref = ref_type_t; @@ -364,7 +365,7 @@ inline ReturnT wiener_full_lpdf( for (size_t i = 0; i < N; i++) { if (sw_vec[i] == 0 && st0_vec[i] == 0) { result += wiener5_lpdf(y_vec[i], a_vec[i], t0_vec[i], w_vec[i], - v_vec[i], sv_vec[i], prec); + v_vec[i], sv_vec[i], prec); continue; } const double y_val = y_vec.val(i); From 91ba08b25578e613b3238453eebf72863d7fcd85 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 15 May 2023 16:55:42 +0300 Subject: [PATCH 058/179] Refactor to functions --- stan/math/prim/prob/wiener5_lpdf.hpp | 472 ++++++++++++++--------- stan/math/prim/prob/wiener_full_lpdf.hpp | 165 ++++---- 2 files changed, 365 insertions(+), 272 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 9fdbecc77e3..e0f42c296e9 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -7,207 +7,293 @@ namespace stan { namespace math { namespace internal { -enum class FunType { Density, GradT, GradA, GradV, GradW, GradSV, GradSW }; - -/** - * Implementation function for calculating the density or gradient w.r.t. a - * specified parameter of the 5-parameter Wiener distribution - * - * @tparam FunTypeEnum An enum value indicating the quantity required - * @param y A scalar variable; the reaction time in seconds - * @param a The boundary separation - * @param vn The drift rate - * @param wn The relative starting point - * @param sv The inter-trial variability of the drift rate - * @param err The error tolerance for estimation - * @param use_log Whether to return calculation w.r.t. the log value - * - */ -template -inline double wiener5_helper(const double& y, const double& a, const double& vn, - const double& wn, const double& sv, - const double& err = log(1e-12), - bool use_log = false) { +double wiener5_lg1(double y, double a, double vn, double wn, double sv) { double w = 1.0 - wn; double v = -vn; double sv_sqr = square(sv); double one_plus_svsqr_y = 1 + sv_sqr * y; double two_avw = 2 * a * v * w; double two_log_a = 2 * log(a); - double ans; - double ld = 0; - - if (FunTypeEnum == FunType::GradSV || FunTypeEnum == FunType::GradV) { - ld = wiener5_helper(y, a, vn, wn, sv, err); - if (FunTypeEnum == FunType::GradV) { - ans = (a * (1 - wn) - vn * y); - if (sv != 0) { - ans /= 1 + sv_sqr * y; - } - } else { - double t1 = -y / one_plus_svsqr_y; - double t2 = (square(a * w) + two_avw * y + square(v * y)) - / square(one_plus_svsqr_y); - ans = sv * (t1 + t2); - } + if (sv != 0) { + return (sv_sqr * square(a * w) - two_avw - square(v) * y) / 2.0 + / one_plus_svsqr_y + - two_log_a - 0.5 * log(one_plus_svsqr_y); } else { - double lg1; + return (-two_avw - square(v) * y) / 2.0 - two_log_a; + } +} + +template +double wiener5_ans0(double y, double a, double vn, double wn, double sv) { + double w = 1.0 - wn; + double v = -vn; + double sv_sqr = square(sv); + double one_plus_svsqr_y = 1 + sv_sqr * y; + double two_avw = 2 * a * v * w; + + double var_a = GradA ? w : a; + double var_b = GradA ? a : w; + + if (GradT) { if (sv != 0) { - lg1 = (sv_sqr * square(a * w) - two_avw - square(v) * y) / 2.0 - / one_plus_svsqr_y - - two_log_a - 0.5 * log(one_plus_svsqr_y); + return -0.5 + * (square(sv_sqr) * (y + square(a * w)) + + sv_sqr * (1 - two_avw) + square(v)) + / square(one_plus_svsqr_y); } else { - lg1 = (-two_avw - square(v) * y) / 2.0 - two_log_a; + return -0.5 * square(v); } - double ans0 = 0; - if (FunTypeEnum != FunType::Density) { - double var_a = (FunTypeEnum == FunType::GradA) ? w : a; - double var_b = (FunTypeEnum == FunType::GradA) ? a : w; - if (sv != 0) { - if (FunTypeEnum == FunType::GradT) { - ans0 = -0.5 - * (square(sv_sqr) * (y + square(a * w)) - + sv_sqr * (1 - two_avw) + square(v)) - / square(one_plus_svsqr_y); - } else { - ans0 = (-v * var_a + sv_sqr * square(var_a) * var_b) - / one_plus_svsqr_y; - } - } else { - ans0 = (FunTypeEnum == FunType::GradT) ? -0.5 * square(v) : -v * var_a; - } + } + + if (sv != 0) { + return (-v * var_a + sv_sqr * square(var_a) * var_b) + / one_plus_svsqr_y; + } else { + return -v * var_a; + } +} + +template +double wiener5_kss(double y, double a, double wn, double es) { + double two_es = 2.0 * es; + double y_asq = y / square(a); + double two_log_a = 2 * log(a); + double log_y_asq = log(y) - two_log_a; + double w = 1.0 - wn; + + double K1, u_eps, arg; + double K1_mult = Density ? 2 : 3; + K1 = (sqrt(K1_mult * y_asq) + w) / 2.0; + if (Density || GradW) { + u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log_y_asq + two_es); + } else { + u_eps = fmin(-3.0, + (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_es)); + } + double arg_mult = Density ? 1 : 3; + arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + + double K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; + return ceil(fmax(K1, K2)); +} + +template +double wiener5_kll(double y, double a, double wn, double es) { + double two_es = 2.0 * es; + double y_asq = y / square(a); + double two_log_a = 2 * log(a); + double log_y_asq = log(y) - two_log_a; + double w = 1.0 - wn; + + double K1, K2, u_eps, arg; + double K1_mult = GradT ? 2 : 3; + static const double PISQ = square(pi()); // pi*pi + + if (Density) { + K1 = 1.0 / (pi() * sqrt(y_asq)); + double two_log_piy = -2.0 * (LOG_PI + log_y_asq + es); + K2 = (two_log_piy >= 0) ? sqrt(two_log_piy / (PISQ * y_asq)) : 0.0; + } else { + K1 = sqrt(K1_mult / y_asq) / pi(); + double u_eps_arg + = GradT + ? log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es + : log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_es; + u_eps = fmin(-1, u_eps_arg); + double arg_mult = GradT ? (2.0 / PISQ / y_asq) : 1; + arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + K2 = GradT ? (arg > 0) ? sqrt(arg) : K1 + : (arg > 0) ? sqrt(arg / y_asq) / pi() : K1; + } + + return ceil(fmax(K1, K2)); +} + +template +std::tuple wiener5_ergsign(double y, double a, double wn, + size_t kss, size_t kll) { + double y_asq = y / square(a); + double w = 1.0 - wn; + bool small_kss = Density ? (2 * kss <= kll) : (2 * kss < kll); + double scaling = small_kss ? inv(2.0 * y_asq) : y_asq / 2.0; + + double erg = NEGATIVE_INFTY; + int newsign = 1; + + if (small_kss) { + double mult = Density ? 1 : 3; + double offset = GradW ? y_asq : 0; + double sqrt_offset = sqrt(offset); + for (size_t k = kss; k >= 0; k--) { + double wp2k = w + 2.0 * k; + double wm2k = w - 2.0 * k; + int wp2k_sign = (wp2k > sqrt_offset) ? 1 : -1; + int wm2k_sign = (wm2k > sqrt_offset) ? 1 : -1; + double wp2k_quant = log(wp2k_sign * (wp2k - offset)) + - (square(wp2k) - offset) * scaling; + double wm2k_quant = log(wm2k_sign * (wm2k - offset)) + - (square(wm2k) - offset) * scaling; + std::forward_as_tuple(erg, newsign) + = log_sum_exp_signed(erg, newsign, mult * wp2k_quant, wp2k_sign); + std::forward_as_tuple(erg, newsign) = log_sum_exp_signed( + erg, newsign, mult * wm2k_quant, -1 * wm2k_sign); } - double es = (err - lg1) + (FunTypeEnum == FunType::GradT) * two_log_a; - double two_es = 2.0 * es; - double y_asq = y / square(a); - double log_y_asq = log(y) - two_log_a; - - double K1, u_eps, arg; - double K1_mult = (FunTypeEnum == FunType::Density) ? 2 : 3; - K1 = (sqrt(K1_mult * y_asq) + w) / 2.0; - if (FunTypeEnum == FunType::Density || FunTypeEnum == FunType::GradW) { - u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log_y_asq + two_es); - } else { - u_eps = fmin(-3.0, - (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_es)); + } else { + double mult = 3; + if (Density) { + mult = 1; + } else if (GradW) { + mult = 2; + } + for (size_t k = kll; k >= 1; k--) { + double pi_k = k * pi(); + double check + = (GradW) ? cos(pi_k * w) : sin(pi_k * w); + int check_sign = sign(check); + double kll_quant + = mult * log(k) - square(pi_k) * scaling + log(fabs(check)); + std::forward_as_tuple(erg, newsign) + = log_sum_exp_signed(erg, newsign, kll_quant, check_sign); } - double arg_mult = (FunTypeEnum == FunType::Density) ? 1 : 3; - arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + } + return std::make_tuple(erg, newsign); +} - double K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; - double kss = ceil(fmax(K1, K2)); +template +double wiener5_density(double y, double a, double vn, double wn, + double sv, double err = log(1e-12)) { + double lg1 = wiener5_lg1(y, a, vn, wn, sv); + double es = (err - lg1); + double kss = wiener5_kss(y, a, wn, es); + double kll = wiener5_kll(y, a, wn, es); - static const double PISQ = square(pi()); // pi*pi - if (FunTypeEnum == FunType::Density) { - K1 = 1.0 / (pi() * sqrt(y_asq)); - double two_log_piy = -2.0 * (LOG_PI + log_y_asq + es); - K2 = (two_log_piy >= 0) ? sqrt(two_log_piy / (PISQ * y_asq)) : 0.0; - } else { - K1_mult = (FunTypeEnum == FunType::GradT) ? 2 : 3; - K1 = sqrt(K1_mult / y_asq) / pi(); - double u_eps_arg - = (FunTypeEnum == FunType::GradT) - ? log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es - : log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_es; - u_eps = fmin(-1, u_eps_arg); - arg_mult = (FunTypeEnum == FunType::GradT) ? (2.0 / PISQ / y_asq) : 1; - arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - K2 = (FunTypeEnum == FunType::GradT) - ? (arg > 0) ? sqrt(arg) : K1 - : (arg > 0) ? sqrt(arg / y_asq) / pi() : K1; - } + double erg; + int newsign; + double ld; + std::forward_as_tuple(erg, newsign) + = wiener5_ergsign(y, a, wn, kss, kll); + if (2 * kss <= kll) { + ld = lg1 - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * (log(y) - 2 * log(a)) + erg; + } else { + ld = lg1 + erg + LOG_PI; + } - double kll = ceil(fmax(K1, K2)); - - double ld_err = 0; - if (FunTypeEnum != FunType::Density) { - if (FunTypeEnum == FunType::GradT) { - ld_err = log(max(fabs(ans0 - 1.5 / y), fabs(ans0))); - } else if (FunTypeEnum == FunType::GradA) { - ld_err = log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a))); - } else { - ld_err = log(fabs(ans0)); - } - ld = wiener5_helper(y, a, vn, wn, sv, err - ld_err); - } + return WrtLog ? exp(ld) : ld; +} - double erg = NEGATIVE_INFTY; - int newsign = 1; - - bool kss_comp - = (FunTypeEnum == FunType::Density) ? 2 * kss <= kll : 2 * kss < kll; - double scaling = kss_comp ? inv(2.0 * y_asq) : y_asq / 2.0; - if (kss_comp) { - double mult = (FunTypeEnum == FunType::Density) ? 1 : 3; - double offset = (FunTypeEnum == FunType::GradW) ? y_asq : 0; - double sqrt_offset = sqrt(offset); - for (size_t k = static_cast(kss); k >= 0; k--) { - double wp2k = w + 2.0 * k; - double wm2k = w - 2.0 * k; - int wp2k_sign = (wp2k > sqrt_offset) ? 1 : -1; - int wm2k_sign = (wm2k > sqrt_offset) ? 1 : -1; - double wp2k_quant = log(wp2k_sign * (wp2k - offset)) - - (square(wp2k) - offset) * scaling; - double wm2k_quant = log(wm2k_sign * (wm2k - offset)) - - (square(wm2k) - offset) * scaling; - std::forward_as_tuple(erg, newsign) - = log_sum_exp_signed(erg, newsign, mult * wp2k_quant, wp2k_sign); - std::forward_as_tuple(erg, newsign) = log_sum_exp_signed( - erg, newsign, mult * wm2k_quant, -1 * wm2k_sign); - } - if (FunTypeEnum == FunType::Density) { - ans = lg1 - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * log_y_asq + erg; - } else if (FunTypeEnum == FunType::GradT) { - ans = ans0 - 1.5 / y - + newsign - * exp(lg1 - two_log_a - 1.5 * LOG_TWO - LOG_SQRT_PI - - 3.5 * log_y_asq + erg - ld); - } else if (FunTypeEnum == FunType::GradA) { - ans = ans0 + 1.0 / a - - newsign - * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * log(y) - + 2.0 * two_log_a + lg1 + erg - ld); - } else if (FunTypeEnum == FunType::GradW) { - ans = -(ans0 - - newsign - * exp(erg - (ld - lg1) - 2.5 * log_y_asq - 0.5 * LOG_TWO - - 0.5 * LOG_PI)); - } - } else { - double mult = 3; - if (FunTypeEnum == FunType::Density) { - mult = 1; - } else if (FunTypeEnum == FunType::GradW) { - mult = 2; - } - for (size_t k = static_cast(kll); k >= 1; k--) { - double pi_k = k * pi(); - double check - = (FunTypeEnum == FunType::GradW) ? cos(pi_k * w) : sin(pi_k * w); - int check_sign = sign(check); - double kll_quant - = mult * log(k) - square(pi_k) * scaling + log(fabs(check)); - std::forward_as_tuple(erg, newsign) - = log_sum_exp_signed(erg, newsign, kll_quant, check_sign); - } - if (FunTypeEnum == FunType::Density) { - ans = lg1 + erg + LOG_PI; - } else if (FunTypeEnum == FunType::GradT) { - ans = ans0 - - newsign - * exp(lg1 - two_log_a + 3.0 * LOG_PI - LOG_TWO + erg - ld); - } else if (FunTypeEnum == FunType::GradA) { - ans = ans0 - 2.0 / a - + newsign * exp(log(y) + lg1 - 3 * (log(a) - LOG_PI) + erg - ld); - } else if (FunTypeEnum == FunType::GradW) { - ans = -(ans0 + newsign * exp(erg - (ld - lg1) + 2 * LOG_PI)); - } - } +template +double grad_wiener5_t(double y, double a, double vn, double wn, + double sv, double err = log(1e-12)) { + double two_log_a = 2 * log(a); + double log_y_asq = log(y) - two_log_a; + double lg1 = wiener5_lg1(y, a, vn, wn, sv); + double ans0 = wiener5_ans0(y, a, vn, wn, sv); + double es = (err - lg1) + two_log_a; + + double kss = wiener5_kss(y, a, wn, es); + double kll = wiener5_kll(y, a, wn, es); + double erg; + int newsign; + std::forward_as_tuple(erg, newsign) + = wiener5_ergsign(y, a, wn, kss, kll); + + double ld_err = log(max(fabs(ans0 - 1.5 / y), fabs(ans0))); + double ld = wiener5_density(y, a, vn, wn, sv, err - ld_err); + double ans; + if (2 * kss < kll) { + ans = ans0 - 1.5 / y + + newsign + * exp(lg1 - two_log_a - 1.5 * LOG_TWO - LOG_SQRT_PI + - 3.5 * log_y_asq + erg - ld); + } else { + ans = ans0 + - newsign + * exp(lg1 - two_log_a + 3.0 * LOG_PI - LOG_TWO + erg - ld); } - if (FunTypeEnum == FunType::Density && use_log) { - return exp(ans); + return WrtLog ? ans * exp(ld) : ans; +} + +template +double grad_wiener5_a(double y, double a, double vn, double wn, + double sv, double err = log(1e-12)) { + double two_log_a = 2 * log(a); + double log_y_asq = log(y) - two_log_a; + double lg1 = wiener5_lg1(y, a, vn, wn, sv); + double ans0 = wiener5_ans0(y, a, vn, wn, sv); + double es = (err - lg1); + + double kss = wiener5_kss(y, a, wn, es); + double kll = wiener5_kll(y, a, wn, es); + double erg; + int newsign; + std::forward_as_tuple(erg, newsign) + = wiener5_ergsign(y, a, wn, kss, kll); + + double ld_err = log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a))); + double ld = wiener5_density(y, a, vn, wn, sv, err - ld_err); + double ans; + if (2 * kss < kll) { + ans = ans0 + 1.0 / a + - newsign + * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * log(y) + + 2.0 * two_log_a + lg1 + erg - ld); + } else { + ans = ans0 - 2.0 / a + + newsign * exp(log(y) + lg1 - 3 * (log(a) - LOG_PI) + erg - ld); } - return use_log ? ans * exp(ld) : ans; + return WrtLog ? ans * exp(ld) : ans; +} + +template +double grad_wiener5_v(double y, double a, double vn, double wn, + double sv, double err = log(1e-12)) { + double ans = (a * (1 - wn) - vn * y); + if (sv != 0) { + ans /= 1 + square(sv) * y; + } + return WrtLog ? ans * wiener5_density(y, a, vn, wn, sv, err) : ans; +} + +template +double grad_wiener5_w(double y, double a, double vn, double wn, + double sv, double err = log(1e-12)) { + double two_log_a = 2 * log(a); + double log_y_asq = log(y) - two_log_a; + double lg1 = wiener5_lg1(y, a, vn, wn, sv); + double ans0 = wiener5_ans0(y, a, vn, wn, sv); + double es = (err - lg1); + + double kss = wiener5_kss(y, a, wn, es); + double kll = wiener5_kll(y, a, wn, es); + double erg; + int newsign; + std::forward_as_tuple(erg, newsign) + = wiener5_ergsign(y, a, wn, kss, kll); + + double ld = wiener5_density(y, a, vn, wn, sv, err - log(fabs(ans0))); + double ans; + if (2 * kss < kll) { + ans = -(ans0 + - newsign + * exp(erg - (ld - lg1) - 2.5 * log_y_asq - 0.5 * LOG_TWO + - 0.5 * LOG_PI)); + } else { + ans = -(ans0 + newsign * exp(erg - (ld - lg1) + 2 * LOG_PI)); + } + return WrtLog ? ans * exp(ld) : ans; +} + +template +double grad_wiener5_sv(double y, double a, double vn, double wn, + double sv, double err = log(1e-12)) { + double one_plus_svsqr_y = 1 + square(sv) * y; + double w = 1.0 - wn; + double v = -vn; + double t1 = -y / one_plus_svsqr_y; + double t2 = (square(a * w) + 2 * a * v * w * y + square(v * y)) + / square(one_plus_svsqr_y); + double ans = sv * (t1 + t2); + return WrtLog ? ans * wiener5_density(y, a, vn, wn, sv, err) : ans; } /** @@ -378,10 +464,10 @@ inline return_type_t wiener5_lpdf( const double sv_val = sv_vec.val(i); const auto params = std::make_tuple(y_val - t0_val, a_val, v_val, w_val, - sv_val, labstol_wiener5, false); + sv_val, labstol_wiener5); dens = internal::estimate_with_err_check<5>( - internal::wiener5_helper, + [&](auto&&... args) { return internal::wiener5_density(args...); }, lerror_bound_dens - LOG_TWO, params, true); ld += dens; @@ -390,8 +476,8 @@ inline return_type_t wiener5_lpdf( // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 double deriv_y = internal::estimate_with_err_check<5>( - internal::wiener5_helper, new_est_err, - params); + [&](auto&&... args) { return internal::grad_wiener5_t(args...); }, + new_est_err, params); // computation of derivatives and precision checks if (!is_constant_all::value) { @@ -399,25 +485,25 @@ inline return_type_t wiener5_lpdf( } if (!is_constant_all::value) { ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check<5>( - internal::wiener5_helper, new_est_err, - params); + [&](auto&&... args) { return internal::grad_wiener5_a(args...); }, + new_est_err, params); } if (!is_constant_all::value) { ops_partials.edge3_.partials_[i] = -deriv_y; } if (!is_constant_all::value) { ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check<5>( - internal::wiener5_helper, new_est_err, - params); + [&](auto&&... args) { return internal::grad_wiener5_w(args...); }, + new_est_err, params); } if (!is_constant_all::value) { ops_partials.edge5_.partials_[i] - = internal::wiener5_helper( + = internal::grad_wiener5_v( y_val - t0_val, a_val, v_val, w_val, sv_val); } if (!is_constant_all::value) { ops_partials.edge6_.partials_[i] - = internal::wiener5_helper( + = internal::grad_wiener5_sv( y_val - t0_val, a_val, v_val, w_val, sv_val); } } // end for loop diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index c763592df97..b91ae82f761 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -9,44 +9,30 @@ namespace stan { namespace math { namespace internal { -/** - * Implementation function for delegating computation to the correct density - * or derivative function. For all gradients except the sw parameter, the - * respective wiener5 function is called. - * - * @tparam FunTypeEnum An enum value indicating the function required - * @param t0_ See wiener7_integrand function for definition - * @param omega See wiener7_integrand function for definition - * @param y A scalar variable; the reaction time in seconds - * @param a The boundary separation - * @param v The drift rate - * @param w The relative starting point - * @param t0 The non-decision time - * @param sv The inter-trial variability of the drift rate - * @param sw The inter-trial variability of the relative starting point - * @param st0 The inter-trial variability of the non-decision time - * @param lerr Error tolerance - * - * @return Log-density or gradient for wiener7_lpdf - */ -template -inline double wiener7_helper(double t0_, double omega, double y, double a, - double v, double w, double t0, double sv, - double sw, double st0, double lerr) { - double ymt0 = y - t0_; - if (FunTypeEnum == FunType::GradSW) { - double low = w - sw / 2; - low = (0 > low) ? 0 : low; - double high = w + sw / 2; - high = (1 < high) ? 1 : high; - double fl - = wiener5_helper(ymt0, a, v, low, sv, lerr, true); - double fu - = wiener5_helper(ymt0, a, v, high, sv, lerr, true); - return 0.5 * (fl + fu) / sw; - } else { - return wiener5_helper(ymt0, a, v, omega, sv, lerr, true); - } +inline double grad_wiener7_sw(double y, double a, double v, double w, + double sv, double sw, double lerr) { + double low = w - sw / 2; + low = (0 > low) ? 0 : low; + double high = w + sw / 2; + high = (1 < high) ? 1 : high; + + double fl = wiener5_density(y, a, v, low, sv, lerr); + double fu = wiener5_density(y, a, v, high, sv, lerr); + return 0.5 * (fl + fu) / sw; +} + +template * = nullptr> +inline double call_wiener7_function(const F& functor, double y, double a, + double v, double w, double t0, double sv, + double sw, double lerr) { + return functor(y-t0, a, v, w, sv, lerr); +} + +template * = nullptr> +inline double call_wiener7_function(const F& functor, double y, double a, + double v, double w, double t0, + double sv, double sw, double lerr) { + return functor(y-t0, a, v, w, sv, sw, lerr); } /** @@ -60,21 +46,22 @@ inline double wiener7_helper(double t0_, double omega, double y, double a, * @param args Additional arguments to be passed to the hcubature function * @return Wiener7 density or gradient calculated by integration */ -template -auto wiener7_integrand(double hcubature_err, TArgs&&... args) { +template +auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, + double hcubature_err, TArgs&&... args) { const auto& wiener7_integrand_impl = [&](std::vector x, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double lerr) { scalar_seq_view x_vec(x); - double sw_val = (FunTypeEnum == FunType::GradSW) ? 0 : sw; + double sw_val = GradSW ? 0 : sw; double omega = sw_val ? w + sw_val * (x_vec[0] - 0.5) : w; double t0_ = sw_val ? (st0 ? t0 + st0 * x_vec[1] : t0) : (st0 ? t0 + st0 * x_vec[0] : t0); if (y - t0_ <= 0) { return 0.0; } else { - return wiener7_helper(t0_, omega, y, a, v, w, t0, sv, - sw, st0, lerr); + return call_wiener7_function(wiener7_functor, y, a, v, + omega, t0_, sv, sw, lerr); } }; const auto& functor = [&](auto&&... int_args) { @@ -393,7 +380,9 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, double hcubature_err = labstol_wiener5 - lerror_bound_dens + LOG_TWO + 1; - dens = internal::wiener7_integrand( + dens = internal::wiener7_integrate( + [&](auto&&... args) { + return internal::wiener5_density(args...); }, hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2); double log_dens = log(dens); ld += log_dens; @@ -402,10 +391,10 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, // computation of derivative for t and precision check in order to give // the value as deriv_t to edge1 and as -deriv_t to edge5 - double deriv_t_7 - = internal::wiener7_integrand( - hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2) - / dens; + double deriv_t_7 = internal::wiener7_integrate([&](auto&&... args) { + return internal::grad_wiener5_t(args...); + }, hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2) + / dens; // computation of derivatives and precision checks double deriv; @@ -413,48 +402,56 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, ops_partials.edge1_.partials_[i] = deriv_t_7; } if (!is_constant_all::value) { - ops_partials.edge2_.partials_[i] - = internal::wiener7_integrand( - hcubature_err, params, dim, xmin, xmax, Meval, abstol, - reltol / 2) - / dens; + ops_partials.edge2_.partials_[i] = internal::wiener7_integrate( + [&](auto&&... args) { return internal::grad_wiener5_a(args...); }, + hcubature_err, params, dim, xmin, xmax, Meval, abstol, + reltol / 2) + / dens; } if (!is_constant_all::value) { ops_partials.edge3_.partials_[i] = -deriv_t_7; } if (!is_constant_all::value) { - ops_partials.edge4_.partials_[i] - = internal::wiener7_integrand( - hcubature_err, params, dim, xmin, xmax, Meval, abstol, - reltol / 2) - / dens; + ops_partials.edge4_.partials_[i] = internal::wiener7_integrate( + [&](auto&&... args) { return internal::grad_wiener5_w(args...); }, + hcubature_err, params, dim, xmin, xmax, Meval, abstol, + reltol / 2) + / dens; } if (!is_constant_all::value) { - ops_partials.edge5_.partials_[i] - = internal::wiener7_integrand( - hcubature_err, params, dim, xmin, xmax, Meval, abstol, - reltol / 2) - / dens; + ops_partials.edge5_.partials_[i] = internal::wiener7_integrate( + [&](auto&&... args) { return internal::grad_wiener5_v(args...); }, + hcubature_err, params, dim, xmin, xmax, Meval, abstol, + reltol / 2) + / dens; } if (!is_constant_all::value) { - ops_partials.edge6_.partials_[i] - = internal::wiener7_integrand( - hcubature_err, params, dim, xmin, xmax, Meval, abstol, - reltol / 2) - / dens; + ops_partials.edge6_.partials_[i] = internal::wiener7_integrate( + [&](auto&&... args) { + return internal::grad_wiener5_sv(args...); }, + hcubature_err, params, dim, xmin, xmax, Meval, abstol, + reltol / 2) + / dens; } if (!is_constant_all::value) { if (sw_val == 0) { ops_partials.edge7_.partials_[i] = 0; } else { if (st0_val == 0) { - deriv = internal::estimate_with_err_check<8>( - internal::wiener7_helper, + const auto sw_params = std::make_tuple(y_val, a_val, v_val, w_val, + t0_val, sv_val, sw_val, + labstol_wiener5 - LOG_TWO); + deriv = internal::estimate_with_err_check<6>( + [&](auto&&... args) { + return internal::call_wiener7_function( + internal::grad_wiener7_sw, args...); + }, lerror_bound - LOG_TWO, - std::tuple_cat(std::make_tuple(t0_val, 0), params)); + sw_params); } else { - deriv = internal::wiener7_integrand( - hcubature_err, params, 1, xmin, xmax, Meval, abstol, reltol / 2); + deriv = internal::wiener7_integrate( + [&](auto&&... args) { return internal::grad_wiener7_sw(args...); }, + hcubature_err, params, 1, xmin, xmax, Meval, abstol, reltol / 2); } ops_partials.edge7_.partials_[i] = deriv / dens - 1 / sw_val; } @@ -468,16 +465,26 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } else { double t0_st0 = t0_val + st0_val; if (sw_val == 0) { - f = internal::estimate_with_err_check<8>( - internal::wiener7_helper, + const auto st_params + = std::make_tuple(y_val, a_val, v_val, w_val, + t0_st0, sv_val, sw_val, + labstol_wiener5 - LOG_TWO); + f = internal::estimate_with_err_check<5>( + [&](auto&&... args) { + return internal::call_wiener7_function( + internal::wiener5_density, args...); + }, lerror_bound + log(st0_val), - std::tuple_cat(std::make_tuple(t0_st0, w_val), params)); + st_params); } else { double new_error = labstol_wiener5 - LOG_TWO; - const auto& params_st = std::make_tuple( - y_val, a_val, v_val, w_val, t0_st0, sv_val, sw_val, 0, new_error); - f = internal::wiener7_integrand( + const auto& params_st = std::make_tuple(y_val, a_val, v_val, w_val, + t0_st0, sv_val, sw_val, 0, + new_error); + f = internal::wiener7_integrate( + [&](auto&&... args) { + return internal::wiener5_density(args...); }, hcubature_err, params_st, 1, xmin, xmax, Meval, abstol, reltol / 2); } From 3ff14012f823235d961b12414070eccae989e32e Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 15 May 2023 10:15:01 -0400 Subject: [PATCH 059/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 74 +++++++------- stan/math/prim/prob/wiener_full_lpdf.hpp | 118 +++++++++++++---------- 2 files changed, 100 insertions(+), 92 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index e0f42c296e9..5aeeba5a6f6 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -16,8 +16,8 @@ double wiener5_lg1(double y, double a, double vn, double wn, double sv) { double two_log_a = 2 * log(a); if (sv != 0) { return (sv_sqr * square(a * w) - two_avw - square(v) * y) / 2.0 - / one_plus_svsqr_y - - two_log_a - 0.5 * log(one_plus_svsqr_y); + / one_plus_svsqr_y + - two_log_a - 0.5 * log(one_plus_svsqr_y); } else { return (-two_avw - square(v) * y) / 2.0 - two_log_a; } @@ -37,17 +37,16 @@ double wiener5_ans0(double y, double a, double vn, double wn, double sv) { if (GradT) { if (sv != 0) { return -0.5 - * (square(sv_sqr) * (y + square(a * w)) - + sv_sqr * (1 - two_avw) + square(v)) - / square(one_plus_svsqr_y); + * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - two_avw) + + square(v)) + / square(one_plus_svsqr_y); } else { return -0.5 * square(v); } } if (sv != 0) { - return (-v * var_a + sv_sqr * square(var_a) * var_b) - / one_plus_svsqr_y; + return (-v * var_a + sv_sqr * square(var_a) * var_b) / one_plus_svsqr_y; } else { return -v * var_a; } @@ -68,7 +67,7 @@ double wiener5_kss(double y, double a, double wn, double es) { u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log_y_asq + two_es); } else { u_eps = fmin(-3.0, - (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_es)); + (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_es)); } double arg_mult = Density ? 1 : 3; arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); @@ -96,14 +95,13 @@ double wiener5_kll(double y, double a, double wn, double es) { } else { K1 = sqrt(K1_mult / y_asq) / pi(); double u_eps_arg - = GradT - ? log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es - : log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_es; + = GradT ? log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es + : log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_es; u_eps = fmin(-1, u_eps_arg); double arg_mult = GradT ? (2.0 / PISQ / y_asq) : 1; arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); K2 = GradT ? (arg > 0) ? sqrt(arg) : K1 - : (arg > 0) ? sqrt(arg / y_asq) / pi() : K1; + : (arg > 0) ? sqrt(arg / y_asq) / pi() : K1; } return ceil(fmax(K1, K2)); @@ -135,8 +133,8 @@ std::tuple wiener5_ergsign(double y, double a, double wn, - (square(wm2k) - offset) * scaling; std::forward_as_tuple(erg, newsign) = log_sum_exp_signed(erg, newsign, mult * wp2k_quant, wp2k_sign); - std::forward_as_tuple(erg, newsign) = log_sum_exp_signed( - erg, newsign, mult * wm2k_quant, -1 * wm2k_sign); + std::forward_as_tuple(erg, newsign) + = log_sum_exp_signed(erg, newsign, mult * wm2k_quant, -1 * wm2k_sign); } } else { double mult = 3; @@ -147,8 +145,7 @@ std::tuple wiener5_ergsign(double y, double a, double wn, } for (size_t k = kll; k >= 1; k--) { double pi_k = k * pi(); - double check - = (GradW) ? cos(pi_k * w) : sin(pi_k * w); + double check = (GradW) ? cos(pi_k * w) : sin(pi_k * w); int check_sign = sign(check); double kll_quant = mult * log(k) - square(pi_k) * scaling + log(fabs(check)); @@ -160,8 +157,8 @@ std::tuple wiener5_ergsign(double y, double a, double wn, } template -double wiener5_density(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { +double wiener5_density(double y, double a, double vn, double wn, double sv, + double err = log(1e-12)) { double lg1 = wiener5_lg1(y, a, vn, wn, sv); double es = (err - lg1); double kss = wiener5_kss(y, a, wn, es); @@ -171,7 +168,7 @@ double wiener5_density(double y, double a, double vn, double wn, int newsign; double ld; std::forward_as_tuple(erg, newsign) - = wiener5_ergsign(y, a, wn, kss, kll); + = wiener5_ergsign(y, a, wn, kss, kll); if (2 * kss <= kll) { ld = lg1 - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * (log(y) - 2 * log(a)) + erg; } else { @@ -182,8 +179,8 @@ double wiener5_density(double y, double a, double vn, double wn, } template -double grad_wiener5_t(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { +double grad_wiener5_t(double y, double a, double vn, double wn, double sv, + double err = log(1e-12)) { double two_log_a = 2 * log(a); double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); @@ -195,7 +192,7 @@ double grad_wiener5_t(double y, double a, double vn, double wn, double erg; int newsign; std::forward_as_tuple(erg, newsign) - = wiener5_ergsign(y, a, wn, kss, kll); + = wiener5_ergsign(y, a, wn, kss, kll); double ld_err = log(max(fabs(ans0 - 1.5 / y), fabs(ans0))); double ld = wiener5_density(y, a, vn, wn, sv, err - ld_err); @@ -207,15 +204,14 @@ double grad_wiener5_t(double y, double a, double vn, double wn, - 3.5 * log_y_asq + erg - ld); } else { ans = ans0 - - newsign - * exp(lg1 - two_log_a + 3.0 * LOG_PI - LOG_TWO + erg - ld); + - newsign * exp(lg1 - two_log_a + 3.0 * LOG_PI - LOG_TWO + erg - ld); } return WrtLog ? ans * exp(ld) : ans; } template -double grad_wiener5_a(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { +double grad_wiener5_a(double y, double a, double vn, double wn, double sv, + double err = log(1e-12)) { double two_log_a = 2 * log(a); double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); @@ -227,7 +223,7 @@ double grad_wiener5_a(double y, double a, double vn, double wn, double erg; int newsign; std::forward_as_tuple(erg, newsign) - = wiener5_ergsign(y, a, wn, kss, kll); + = wiener5_ergsign(y, a, wn, kss, kll); double ld_err = log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a))); double ld = wiener5_density(y, a, vn, wn, sv, err - ld_err); @@ -245,8 +241,8 @@ double grad_wiener5_a(double y, double a, double vn, double wn, } template -double grad_wiener5_v(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { +double grad_wiener5_v(double y, double a, double vn, double wn, double sv, + double err = log(1e-12)) { double ans = (a * (1 - wn) - vn * y); if (sv != 0) { ans /= 1 + square(sv) * y; @@ -255,8 +251,8 @@ double grad_wiener5_v(double y, double a, double vn, double wn, } template -double grad_wiener5_w(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { +double grad_wiener5_w(double y, double a, double vn, double wn, double sv, + double err = log(1e-12)) { double two_log_a = 2 * log(a); double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); @@ -268,7 +264,7 @@ double grad_wiener5_w(double y, double a, double vn, double wn, double erg; int newsign; std::forward_as_tuple(erg, newsign) - = wiener5_ergsign(y, a, wn, kss, kll); + = wiener5_ergsign(y, a, wn, kss, kll); double ld = wiener5_density(y, a, vn, wn, sv, err - log(fabs(ans0))); double ans; @@ -284,8 +280,8 @@ double grad_wiener5_w(double y, double a, double vn, double wn, } template -double grad_wiener5_sv(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { +double grad_wiener5_sv(double y, double a, double vn, double wn, double sv, + double err = log(1e-12)) { double one_plus_svsqr_y = 1 + square(sv) * y; double w = 1.0 - wn; double v = -vn; @@ -497,14 +493,12 @@ inline return_type_t wiener5_lpdf( new_est_err, params); } if (!is_constant_all::value) { - ops_partials.edge5_.partials_[i] - = internal::grad_wiener5_v( - y_val - t0_val, a_val, v_val, w_val, sv_val); + ops_partials.edge5_.partials_[i] = internal::grad_wiener5_v( + y_val - t0_val, a_val, v_val, w_val, sv_val); } if (!is_constant_all::value) { - ops_partials.edge6_.partials_[i] - = internal::grad_wiener5_sv( - y_val - t0_val, a_val, v_val, w_val, sv_val); + ops_partials.edge6_.partials_[i] = internal::grad_wiener5_sv( + y_val - t0_val, a_val, v_val, w_val, sv_val); } } // end for loop return ops_partials.build(ld); diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index b91ae82f761..c67e7ebdba4 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -9,8 +9,8 @@ namespace stan { namespace math { namespace internal { -inline double grad_wiener7_sw(double y, double a, double v, double w, - double sv, double sw, double lerr) { +inline double grad_wiener7_sw(double y, double a, double v, double w, double sv, + double sw, double lerr) { double low = w - sw / 2; low = (0 > low) ? 0 : low; double high = w + sw / 2; @@ -25,14 +25,14 @@ template * = nullptr> inline double call_wiener7_function(const F& functor, double y, double a, double v, double w, double t0, double sv, double sw, double lerr) { - return functor(y-t0, a, v, w, sv, lerr); + return functor(y - t0, a, v, w, sv, lerr); } template * = nullptr> inline double call_wiener7_function(const F& functor, double y, double a, - double v, double w, double t0, - double sv, double sw, double lerr) { - return functor(y-t0, a, v, w, sv, sw, lerr); + double v, double w, double t0, double sv, + double sw, double lerr) { + return functor(y - t0, a, v, w, sv, sw, lerr); } /** @@ -48,7 +48,7 @@ inline double call_wiener7_function(const F& functor, double y, double a, */ template auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, - double hcubature_err, TArgs&&... args) { + double hcubature_err, TArgs&&... args) { const auto& wiener7_integrand_impl = [&](std::vector x, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double lerr) { @@ -61,7 +61,7 @@ auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, return 0.0; } else { return call_wiener7_function(wiener7_functor, y, a, v, - omega, t0_, sv, sw, lerr); + omega, t0_, sv, sw, lerr); } }; const auto& functor = [&](auto&&... int_args) { @@ -382,7 +382,8 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, dens = internal::wiener7_integrate( [&](auto&&... args) { - return internal::wiener5_density(args...); }, + return internal::wiener5_density(args...); + }, hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2); double log_dens = log(dens); ld += log_dens; @@ -391,10 +392,13 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, // computation of derivative for t and precision check in order to give // the value as deriv_t to edge1 and as -deriv_t to edge5 - double deriv_t_7 = internal::wiener7_integrate([&](auto&&... args) { - return internal::grad_wiener5_t(args...); - }, hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2) - / dens; + double deriv_t_7 + = internal::wiener7_integrate( + [&](auto&&... args) { + return internal::grad_wiener5_t(args...); + }, + hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2) + / dens; // computation of derivatives and precision checks double deriv; @@ -402,56 +406,68 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, ops_partials.edge1_.partials_[i] = deriv_t_7; } if (!is_constant_all::value) { - ops_partials.edge2_.partials_[i] = internal::wiener7_integrate( - [&](auto&&... args) { return internal::grad_wiener5_a(args...); }, - hcubature_err, params, dim, xmin, xmax, Meval, abstol, - reltol / 2) - / dens; + ops_partials.edge2_.partials_[i] + = internal::wiener7_integrate( + [&](auto&&... args) { + return internal::grad_wiener5_a(args...); + }, + hcubature_err, params, dim, xmin, xmax, Meval, abstol, + reltol / 2) + / dens; } if (!is_constant_all::value) { ops_partials.edge3_.partials_[i] = -deriv_t_7; } if (!is_constant_all::value) { - ops_partials.edge4_.partials_[i] = internal::wiener7_integrate( - [&](auto&&... args) { return internal::grad_wiener5_w(args...); }, - hcubature_err, params, dim, xmin, xmax, Meval, abstol, - reltol / 2) - / dens; + ops_partials.edge4_.partials_[i] + = internal::wiener7_integrate( + [&](auto&&... args) { + return internal::grad_wiener5_w(args...); + }, + hcubature_err, params, dim, xmin, xmax, Meval, abstol, + reltol / 2) + / dens; } if (!is_constant_all::value) { - ops_partials.edge5_.partials_[i] = internal::wiener7_integrate( - [&](auto&&... args) { return internal::grad_wiener5_v(args...); }, - hcubature_err, params, dim, xmin, xmax, Meval, abstol, - reltol / 2) - / dens; + ops_partials.edge5_.partials_[i] + = internal::wiener7_integrate( + [&](auto&&... args) { + return internal::grad_wiener5_v(args...); + }, + hcubature_err, params, dim, xmin, xmax, Meval, abstol, + reltol / 2) + / dens; } if (!is_constant_all::value) { - ops_partials.edge6_.partials_[i] = internal::wiener7_integrate( - [&](auto&&... args) { - return internal::grad_wiener5_sv(args...); }, - hcubature_err, params, dim, xmin, xmax, Meval, abstol, - reltol / 2) - / dens; + ops_partials.edge6_.partials_[i] + = internal::wiener7_integrate( + [&](auto&&... args) { + return internal::grad_wiener5_sv(args...); + }, + hcubature_err, params, dim, xmin, xmax, Meval, abstol, + reltol / 2) + / dens; } if (!is_constant_all::value) { if (sw_val == 0) { ops_partials.edge7_.partials_[i] = 0; } else { if (st0_val == 0) { - const auto sw_params = std::make_tuple(y_val, a_val, v_val, w_val, - t0_val, sv_val, sw_val, - labstol_wiener5 - LOG_TWO); + const auto sw_params + = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, + sw_val, labstol_wiener5 - LOG_TWO); deriv = internal::estimate_with_err_check<6>( [&](auto&&... args) { return internal::call_wiener7_function( - internal::grad_wiener7_sw, args...); + internal::grad_wiener7_sw, args...); }, - lerror_bound - LOG_TWO, - sw_params); + lerror_bound - LOG_TWO, sw_params); } else { deriv = internal::wiener7_integrate( - [&](auto&&... args) { return internal::grad_wiener7_sw(args...); }, - hcubature_err, params, 1, xmin, xmax, Meval, abstol, reltol / 2); + [&](auto&&... args) { + return internal::grad_wiener7_sw(args...); + }, + hcubature_err, params, 1, xmin, xmax, Meval, abstol, reltol / 2); } ops_partials.edge7_.partials_[i] = deriv / dens - 1 / sw_val; } @@ -466,25 +482,23 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, double t0_st0 = t0_val + st0_val; if (sw_val == 0) { const auto st_params - = std::make_tuple(y_val, a_val, v_val, w_val, - t0_st0, sv_val, sw_val, - labstol_wiener5 - LOG_TWO); + = std::make_tuple(y_val, a_val, v_val, w_val, t0_st0, sv_val, + sw_val, labstol_wiener5 - LOG_TWO); f = internal::estimate_with_err_check<5>( [&](auto&&... args) { return internal::call_wiener7_function( - internal::wiener5_density, args...); + internal::wiener5_density, args...); }, - lerror_bound + log(st0_val), - st_params); + lerror_bound + log(st0_val), st_params); } else { double new_error = labstol_wiener5 - LOG_TWO; - const auto& params_st = std::make_tuple(y_val, a_val, v_val, w_val, - t0_st0, sv_val, sw_val, 0, - new_error); + const auto& params_st = std::make_tuple( + y_val, a_val, v_val, w_val, t0_st0, sv_val, sw_val, 0, new_error); f = internal::wiener7_integrate( [&](auto&&... args) { - return internal::wiener5_density(args...); }, + return internal::wiener5_density(args...); + }, hcubature_err, params_st, 1, xmin, xmax, Meval, abstol, reltol / 2); } From 4880c6ad29692f02e568db4211d4d3aaeee6978a Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 15 May 2023 17:16:46 +0300 Subject: [PATCH 060/179] Other comments --- stan/math/prim/functor/hcubature.hpp | 68 ++++++++------ stan/math/prim/prob/wiener5_lpdf.hpp | 136 +++++++++++++-------------- 2 files changed, 107 insertions(+), 97 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 1420b0a4040..1854eeea20f 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -68,8 +68,8 @@ static constexpr double gwd7[4] = {1.2948496616886969327061143267787e-01, * @param p number of elements * @param x x-th lexicographically ordered set */ -inline void combination(std::vector& c, const int& dim, const int& p, - const int& x) { +inline void combination(std::vector& c, const int dim, const int p, + const int x) { size_t r, k = 0; for (std::size_t i = 0; i < p - 1; i++) { c[i] = (i != 0) ? c[i - 1] : 0; @@ -96,7 +96,7 @@ inline void combination(std::vector& c, const int& dim, const int& p, * @param dim dimension * @param p vector of vectors */ -inline void combos(const int& k, const double& lambda, const int& dim, +inline void combos(const int k, const double lambda, const int dim, std::vector>& p) { std::vector c(k); const auto choose_dimk = choose(dim, k); @@ -119,8 +119,8 @@ inline void combos(const int& k, const double& lambda, const int& dim, * @param c ordered vector * @param temp helper vector */ -inline void increment(std::vector& index, const int& k, - const double& lambda, const std::vector& c, +inline void increment(std::vector& index, const int k, + const double lambda, const std::vector& c, std::vector& temp) { if (index.size() == 0) { index.push_back(false); @@ -162,7 +162,7 @@ inline void increment(std::vector& index, const int& k, * @param dim dimension * @param p vector of vectors */ -inline void signcombos(const int& k, const double& lambda, const int& dim, +inline void signcombos(const int k, const double lambda, const int dim, std::vector>& p) { std::vector c(k); const auto choose_dimk = choose(dim, k); @@ -191,16 +191,17 @@ inline void signcombos(const int& k, const double& lambda, const int& dim, * @return numeric integral of the integrand and error */ template -std::tuple gauss_kronrod(const F& integrand, const double& a, - const double& b, - ParsTupleT& pars_tuple) { +std::tuple gauss_kronrod(const F& integrand, const double a, + const double b, + const ParsTupleT& pars_tuple) { std::vector c(1, 0); std::vector cp(1, 0); std::vector cm(1, 0); c[0] = 0.5 * (a + b); double delta = 0.5 * (b - a); - double f0 = math::apply([&](auto&&... args) { return integrand(c, args...); }, - pars_tuple); + double f0 = math::apply( + [&integrand, &c](auto&&... args) { return integrand(c, args...); }, + pars_tuple); double I = f0 * wd7[7]; double Idash = f0 * gwd7[3]; @@ -209,9 +210,11 @@ std::tuple gauss_kronrod(const F& integrand, const double& a, cp[0] = c[0] + deltax; cm[0] = c[0] - deltax; double fx = math::apply( - [&](auto&&... args) { return integrand(cp, args...); }, pars_tuple); + [&integrand, &cp](auto&&... args) { return integrand(cp, args...); }, + pars_tuple); double temp = math::apply( - [&](auto&&... args) { return integrand(cm, args...); }, pars_tuple); + [&integrand, &cm](auto&&... args) { return integrand(cm, args...); }, + pars_tuple); fx += temp; I += fx * wd7[i]; if (i % 2 == 1) { @@ -233,7 +236,7 @@ std::tuple gauss_kronrod(const F& integrand, const double& a, * @param w weights for the 5 terms in the GenzMalik rule * @param wd weights for the embedded lower-degree rule */ -inline void make_GenzMalik(const int& dim, +inline void make_GenzMalik(const int dim, std::vector>>& p, std::vector& w, std::vector& wd) { double l4 = std::sqrt(9 * 1.0 / 10); @@ -279,11 +282,11 @@ inline void make_GenzMalik(const int& dim, template std::tuple integrate_GenzMalik( const F& integrand, std::vector>>& p, - std::vector& w, std::vector& wd, const int& dim, + std::vector& w, std::vector& wd, const int dim, const std::vector& a, const std::vector& b, - ParsTupleT& pars_tuple) { + const ParsTupleT& pars_tuple) { std::vector c(dim, 0); - std::vector deltac(dim); + std::vector deltac(dim, 0); for (std::size_t i = 0; i != dim; i++) { c[i] = (a[i] + b[i]) / 2; @@ -301,8 +304,9 @@ std::tuple integrate_GenzMalik( return std::make_tuple(0.0, 0.0, 0); } - double f1 = math::apply([&](auto&&... args) { return integrand(c, args...); }, - pars_tuple); + double f1 = math::apply( + [&integrand, &c](auto&&... args) { return integrand(c, args...); }, + pars_tuple); double f2 = 0.0; double f3 = 0.0; double twelvef1 = 12 * f1; @@ -322,12 +326,14 @@ std::tuple integrate_GenzMalik( cc[j] = c[j] + p2[j]; } double f2i = math::apply( - [&](auto&&... args) { return integrand(cc, args...); }, pars_tuple); + [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, + pars_tuple); for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] - p2[j]; } double temp = math::apply( - [&](auto&&... args) { return integrand(cc, args...); }, pars_tuple); + [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, + pars_tuple); f2i += temp; for (std::size_t j = 0; j != dim; j++) { @@ -337,12 +343,14 @@ std::tuple integrate_GenzMalik( cc[j] = c[j] + p3[j]; } double f3i = math::apply( - [&](auto&&... args) { return integrand(cc, args...); }, pars_tuple); + [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, + pars_tuple); for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] - p3[j]; } - temp = math::apply([&](auto&&... args) { return integrand(cc, args...); }, - pars_tuple); + temp = math::apply( + [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, + pars_tuple); f3i += temp; f2 += f2i; f3 += f3i; @@ -358,7 +366,8 @@ std::tuple integrate_GenzMalik( cc[j] = c[j] + p4[j]; } double temp = math::apply( - [&](auto&&... args) { return integrand(cc, args...); }, pars_tuple); + [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, + pars_tuple); f4 += temp; } double f5 = 0.0; @@ -372,7 +381,8 @@ std::tuple integrate_GenzMalik( cc[j] = c[j] + p5[j]; } double temp = math::apply( - [&](auto&&... args) { return integrand(cc, args...); }, pars_tuple); + [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, + pars_tuple); f5 += temp; } @@ -453,10 +463,10 @@ struct Box { * @throw std::domain_error no errors will be thrown. */ template -double hcubature(const F& integrand, const ParsTuple& pars, const int& dim, +double hcubature(const F& integrand, const ParsTuple& pars, const int dim, const std::vector& a, const std::vector& b, - int& maxEval, const double& reqAbsError, - const double& reqRelError) { + int& maxEval, const double reqAbsError, + const double reqRelError) { if (maxEval <= 0) { maxEval = 1000000; } diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 5aeeba5a6f6..233a2699ad4 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -8,12 +8,12 @@ namespace math { namespace internal { double wiener5_lg1(double y, double a, double vn, double wn, double sv) { - double w = 1.0 - wn; - double v = -vn; - double sv_sqr = square(sv); - double one_plus_svsqr_y = 1 + sv_sqr * y; - double two_avw = 2 * a * v * w; - double two_log_a = 2 * log(a); + const double w = 1.0 - wn; + const double v = -vn; + const double sv_sqr = square(sv); + const double one_plus_svsqr_y = 1 + sv_sqr * y; + const double two_avw = 2 * a * v * w; + const double two_log_a = 2 * log(a); if (sv != 0) { return (sv_sqr * square(a * w) - two_avw - square(v) * y) / 2.0 / one_plus_svsqr_y @@ -25,14 +25,14 @@ double wiener5_lg1(double y, double a, double vn, double wn, double sv) { template double wiener5_ans0(double y, double a, double vn, double wn, double sv) { - double w = 1.0 - wn; - double v = -vn; - double sv_sqr = square(sv); - double one_plus_svsqr_y = 1 + sv_sqr * y; - double two_avw = 2 * a * v * w; + const double w = 1.0 - wn; + const double v = -vn; + const double sv_sqr = square(sv); + const double one_plus_svsqr_y = 1 + sv_sqr * y; + const double two_avw = 2 * a * v * w; - double var_a = GradA ? w : a; - double var_b = GradA ? a : w; + const double var_a = GradA ? w : a; + const double var_b = GradA ? a : w; if (GradT) { if (sv != 0) { @@ -54,15 +54,15 @@ double wiener5_ans0(double y, double a, double vn, double wn, double sv) { template double wiener5_kss(double y, double a, double wn, double es) { - double two_es = 2.0 * es; - double y_asq = y / square(a); - double two_log_a = 2 * log(a); - double log_y_asq = log(y) - two_log_a; - double w = 1.0 - wn; - - double K1, u_eps, arg; - double K1_mult = Density ? 2 : 3; - K1 = (sqrt(K1_mult * y_asq) + w) / 2.0; + const double two_es = 2.0 * es; + const double y_asq = y / square(a); + const double two_log_a = 2 * log(a); + const double log_y_asq = log(y) - two_log_a; + const double w = 1.0 - wn; + + const double K1_mult = Density ? 2 : 3; + double K1 = (sqrt(K1_mult * y_asq) + w) / 2.0; + double u_eps; if (Density || GradW) { u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log_y_asq + two_es); } else { @@ -70,7 +70,7 @@ double wiener5_kss(double y, double a, double wn, double es) { (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_es)); } double arg_mult = Density ? 1 : 3; - arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + double arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); double K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; return ceil(fmax(K1, K2)); @@ -78,28 +78,30 @@ double wiener5_kss(double y, double a, double wn, double es) { template double wiener5_kll(double y, double a, double wn, double es) { - double two_es = 2.0 * es; - double y_asq = y / square(a); - double two_log_a = 2 * log(a); - double log_y_asq = log(y) - two_log_a; - double w = 1.0 - wn; + const double two_es = 2.0 * es; + const double y_asq = y / square(a); + const double two_log_a = 2 * log(a); + const double log_y_asq = log(y) - two_log_a; + const double w = 1.0 - wn; - double K1, K2, u_eps, arg; - double K1_mult = GradT ? 2 : 3; - static const double PISQ = square(pi()); // pi*pi + const double K1_mult = GradT ? 2 : 3; + static constexpr double PI_SQUARED = pi() * pi(); // pi*pi + double K1; + double K2; if (Density) { K1 = 1.0 / (pi() * sqrt(y_asq)); double two_log_piy = -2.0 * (LOG_PI + log_y_asq + es); - K2 = (two_log_piy >= 0) ? sqrt(two_log_piy / (PISQ * y_asq)) : 0.0; + K2 = (two_log_piy >= 0) ? sqrt(two_log_piy / (PI_SQUARED * y_asq)) : 0.0; } else { K1 = sqrt(K1_mult / y_asq) / pi(); double u_eps_arg - = GradT ? log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es - : log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_es; - u_eps = fmin(-1, u_eps_arg); - double arg_mult = GradT ? (2.0 / PISQ / y_asq) : 1; - arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + = GradT + ? log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es + : log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_es; + double u_eps = fmin(-1, u_eps_arg); + double arg_mult = GradT ? (2.0 / PI_SQUARED / y_asq) : 1; + double arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); K2 = GradT ? (arg > 0) ? sqrt(arg) : K1 : (arg > 0) ? sqrt(arg / y_asq) / pi() : K1; } @@ -110,10 +112,10 @@ double wiener5_kll(double y, double a, double wn, double es) { template std::tuple wiener5_ergsign(double y, double a, double wn, size_t kss, size_t kll) { - double y_asq = y / square(a); - double w = 1.0 - wn; - bool small_kss = Density ? (2 * kss <= kll) : (2 * kss < kll); - double scaling = small_kss ? inv(2.0 * y_asq) : y_asq / 2.0; + const double y_asq = y / square(a); + const double w = 1.0 - wn; + const bool small_kss = Density ? (2 * kss <= kll) : (2 * kss < kll); + const double scaling = small_kss ? inv(2.0 * y_asq) : y_asq / 2.0; double erg = NEGATIVE_INFTY; int newsign = 1; @@ -179,10 +181,10 @@ double wiener5_density(double y, double a, double vn, double wn, double sv, } template -double grad_wiener5_t(double y, double a, double vn, double wn, double sv, - double err = log(1e-12)) { - double two_log_a = 2 * log(a); - double log_y_asq = log(y) - two_log_a; +double grad_wiener5_t(double y, double a, double vn, double wn, + double sv, double err = log(1e-12)) { + const double two_log_a = 2 * log(a); + const double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); double ans0 = wiener5_ans0(y, a, vn, wn, sv); double es = (err - lg1) + two_log_a; @@ -210,10 +212,10 @@ double grad_wiener5_t(double y, double a, double vn, double wn, double sv, } template -double grad_wiener5_a(double y, double a, double vn, double wn, double sv, - double err = log(1e-12)) { - double two_log_a = 2 * log(a); - double log_y_asq = log(y) - two_log_a; +double grad_wiener5_a(double y, double a, double vn, double wn, + double sv, double err = log(1e-12)) { + const double two_log_a = 2 * log(a); + const double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); double ans0 = wiener5_ans0(y, a, vn, wn, sv); double es = (err - lg1); @@ -251,10 +253,10 @@ double grad_wiener5_v(double y, double a, double vn, double wn, double sv, } template -double grad_wiener5_w(double y, double a, double vn, double wn, double sv, - double err = log(1e-12)) { - double two_log_a = 2 * log(a); - double log_y_asq = log(y) - two_log_a; +double grad_wiener5_w(double y, double a, double vn, double wn, + double sv, double err = log(1e-12)) { + const double two_log_a = 2 * log(a); + const double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); double ans0 = wiener5_ans0(y, a, vn, wn, sv); double es = (err - lg1); @@ -280,11 +282,11 @@ double grad_wiener5_w(double y, double a, double vn, double wn, double sv, } template -double grad_wiener5_sv(double y, double a, double vn, double wn, double sv, - double err = log(1e-12)) { - double one_plus_svsqr_y = 1 + square(sv) * y; - double w = 1.0 - wn; - double v = -vn; +double grad_wiener5_sv(double y, double a, double vn, double wn, + double sv, double err = log(1e-12)) { + const double one_plus_svsqr_y = 1 + square(sv) * y; + const double w = 1.0 - wn; + const double v = -vn; double t1 = -y / one_plus_svsqr_y; double t2 = (square(a * w) + 2 * a * v * w * y + square(v * y)) / square(one_plus_svsqr_y); @@ -377,6 +379,13 @@ inline return_type_t wiener5_lpdf( using T_sv_ref = ref_type_t; const char* function_name = "wiener5_lpdf"; + if (size_zero(y, a, t0, w, v, sv)) { + return 0; + } + if (!include_summand::value) { + return 0; + } + check_consistent_sizes(function_name, "Random variable", y, "Boundary separation", a, "Drift rate", v, "A-priori bias", w, "Nondecision time", t0, @@ -408,13 +417,8 @@ inline return_type_t wiener5_lpdf( check_finite(function_name, "Inter-trial variability in drift rate", value_of(sv_ref)); - if (size_zero(y, a, t0, w, v) || size_zero(sv)) { - return 0; - } size_t N = max_size(y, a, t0, w, v, sv); - if (!N) { - return 0; - } + scalar_seq_view y_vec(y_ref); scalar_seq_view a_vec(a_ref); scalar_seq_view t0_vec(t0_ref); @@ -433,10 +437,6 @@ inline return_type_t wiener5_lpdf( } } - if (!include_summand::value) { - return 0; - } - double lerror_bound_dens = log(1e-6); // precision for density double lerror_bound = log(prec); // precision for derivatives double labstol_wiener5 = log(1e-12); // eps_abs(wiener5) From 54f50d4c26d7382466dcd465aeb1c7c659a3696c Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 15 May 2023 10:19:11 -0400 Subject: [PATCH 061/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/functor/hcubature.hpp | 12 ++++++------ stan/math/prim/prob/wiener5_lpdf.hpp | 21 ++++++++++----------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 1854eeea20f..3fccc0852c7 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -200,8 +200,8 @@ std::tuple gauss_kronrod(const F& integrand, const double a, c[0] = 0.5 * (a + b); double delta = 0.5 * (b - a); double f0 = math::apply( - [&integrand, &c](auto&&... args) { return integrand(c, args...); }, - pars_tuple); + [&integrand, &c](auto&&... args) { return integrand(c, args...); }, + pars_tuple); double I = f0 * wd7[7]; double Idash = f0 * gwd7[3]; @@ -305,8 +305,8 @@ std::tuple integrate_GenzMalik( } double f1 = math::apply( - [&integrand, &c](auto&&... args) { return integrand(c, args...); }, - pars_tuple); + [&integrand, &c](auto&&... args) { return integrand(c, args...); }, + pars_tuple); double f2 = 0.0; double f3 = 0.0; double twelvef1 = 12 * f1; @@ -349,8 +349,8 @@ std::tuple integrate_GenzMalik( cc[j] = c[j] - p3[j]; } temp = math::apply( - [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, - pars_tuple); + [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, + pars_tuple); f3i += temp; f2 += f2i; f3 += f3i; diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 233a2699ad4..471a76c3e99 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -96,9 +96,8 @@ double wiener5_kll(double y, double a, double wn, double es) { } else { K1 = sqrt(K1_mult / y_asq) / pi(); double u_eps_arg - = GradT - ? log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es - : log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_es; + = GradT ? log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es + : log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_es; double u_eps = fmin(-1, u_eps_arg); double arg_mult = GradT ? (2.0 / PI_SQUARED / y_asq) : 1; double arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); @@ -181,8 +180,8 @@ double wiener5_density(double y, double a, double vn, double wn, double sv, } template -double grad_wiener5_t(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { +double grad_wiener5_t(double y, double a, double vn, double wn, double sv, + double err = log(1e-12)) { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); @@ -212,8 +211,8 @@ double grad_wiener5_t(double y, double a, double vn, double wn, } template -double grad_wiener5_a(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { +double grad_wiener5_a(double y, double a, double vn, double wn, double sv, + double err = log(1e-12)) { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); @@ -253,8 +252,8 @@ double grad_wiener5_v(double y, double a, double vn, double wn, double sv, } template -double grad_wiener5_w(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { +double grad_wiener5_w(double y, double a, double vn, double wn, double sv, + double err = log(1e-12)) { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); @@ -282,8 +281,8 @@ double grad_wiener5_w(double y, double a, double vn, double wn, } template -double grad_wiener5_sv(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { +double grad_wiener5_sv(double y, double a, double vn, double wn, double sv, + double err = log(1e-12)) { const double one_plus_svsqr_y = 1 + square(sv) * y; const double w = 1.0 - wn; const double v = -vn; From a4c1da858cfa47657d9829d065c4b2885f18b4bb Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 24 May 2023 19:09:41 +0300 Subject: [PATCH 062/179] Resolve comments, add function docs --- stan/math/prim/functor/hcubature.hpp | 50 +++--- stan/math/prim/prob/wiener5_lpdf.hpp | 212 +++++++++++++++++++---- stan/math/prim/prob/wiener_full_lpdf.hpp | 56 ++++++ 3 files changed, 264 insertions(+), 54 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 3fccc0852c7..30be009305f 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -97,16 +97,15 @@ inline void combination(std::vector& c, const int dim, const int p, * @param p vector of vectors */ inline void combos(const int k, const double lambda, const int dim, - std::vector>& p) { + Eigen::MatrixXd& p) { std::vector c(k); const auto choose_dimk = choose(dim, k); - for (std::size_t i = 1; i != choose_dimk + 1; i++) { - std::vector temp(dim, 0.0); - combination(c, dim, k, i); - for (std::size_t j = 0; j != k; j++) { - temp[c[j] - 1] = lambda; + p = Eigen::MatrixXd::Zero(dim, choose_dimk); + for (size_t i = 0; i < choose_dimk; i++) { + combination(c, dim, k, i + 1); + for (size_t j = 0; j < k; j++) { + p(c[j] - 1, i) = lambda; } - p.push_back(temp); } } @@ -121,7 +120,7 @@ inline void combos(const int k, const double lambda, const int dim, */ inline void increment(std::vector& index, const int k, const double lambda, const std::vector& c, - std::vector& temp) { + Eigen::VectorXd& temp) { if (index.size() == 0) { index.push_back(false); for (std::size_t j = 0; j != k; j++) { @@ -163,17 +162,21 @@ inline void increment(std::vector& index, const int k, * @param p vector of vectors */ inline void signcombos(const int k, const double lambda, const int dim, - std::vector>& p) { + Eigen::MatrixXd& p) { std::vector c(k); const auto choose_dimk = choose(dim, k); + p.resize(dim, choose_dimk * std::pow(2, k)); + p.setZero(); + int col = 0; for (std::size_t i = 1; i != choose_dimk + 1; i++) { - std::vector temp(dim, 0.0); + Eigen::VectorXd temp = Eigen::VectorXd::Zero(dim); combination(c, dim, k, i); std::vector index; index.clear(); for (std::size_t j = 0; j != std::pow(2, k); j++) { increment(index, k, lambda, c, temp); - p.push_back(temp); + p.col(col) = temp; + col += 1; } } } @@ -237,7 +240,7 @@ std::tuple gauss_kronrod(const F& integrand, const double a, * @param wd weights for the embedded lower-degree rule */ inline void make_GenzMalik(const int dim, - std::vector>>& p, + std::vector& p, std::vector& w, std::vector& wd) { double l4 = std::sqrt(9 * 1.0 / 10); double l2 = std::sqrt(9 * 1.0 / 70); @@ -281,7 +284,7 @@ inline void make_GenzMalik(const int dim, */ template std::tuple integrate_GenzMalik( - const F& integrand, std::vector>>& p, + const F& integrand, std::vector& p, std::vector& w, std::vector& wd, const int dim, const std::vector& a, const std::vector& b, const ParsTupleT& pars_tuple) { @@ -289,6 +292,9 @@ std::tuple integrate_GenzMalik( std::vector deltac(dim, 0); for (std::size_t i = 0; i != dim; i++) { + if (a[i] == b[i]) { + return std::make_tuple(0.0, 0.0, 0); + } c[i] = (a[i] + b[i]) / 2; } @@ -300,10 +306,6 @@ std::tuple integrate_GenzMalik( v *= deltac[i]; } - if (v == 0.0) { - return std::make_tuple(0.0, 0.0, 0); - } - double f1 = math::apply( [&integrand, &c](auto&&... args) { return integrand(c, args...); }, pars_tuple); @@ -319,7 +321,7 @@ std::tuple integrate_GenzMalik( for (std::size_t i = 0; i != dim; i++) { for (std::size_t j = 0; j != dim; j++) { - p2[j] = deltac[j] * p[0][i][j]; + p2[j] = deltac[j] * p[0](j, i); } for (std::size_t j = 0; j != dim; j++) { @@ -337,7 +339,7 @@ std::tuple integrate_GenzMalik( f2i += temp; for (std::size_t j = 0; j != dim; j++) { - p3[j] = deltac[j] * p[1][i][j]; + p3[j] = deltac[j] * p[1](j, i); } for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] + p3[j]; @@ -358,9 +360,9 @@ std::tuple integrate_GenzMalik( } std::vector p4(dim); double f4 = 0.0; - for (std::size_t i = 0; i != p[2].size(); i++) { + for (std::size_t i = 0; i != p[2].cols(); i++) { for (std::size_t j = 0; j != dim; j++) { - p4[j] = deltac[j] * p[2][i][j]; + p4[j] = deltac[j] * p[2](j, i); } for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] + p4[j]; @@ -372,9 +374,9 @@ std::tuple integrate_GenzMalik( } double f5 = 0.0; std::vector p5(dim); - for (std::size_t i = 0; i != p[3].size(); i++) { + for (std::size_t i = 0; i != p[3].cols(); i++) { for (std::size_t j = 0; j != dim; j++) { - p5[j] = deltac[j] * p[3][i][j]; + p5[j] = deltac[j] * p[3](j, i);; } for (std::size_t j = 0; j != dim; j++) { @@ -474,7 +476,7 @@ double hcubature(const F& integrand, const ParsTuple& pars, const int dim, double result, err; int kdivide = 0; - std::vector>> p(4); + std::vector p(4); std::vector w_five(5); std::vector wd_four(4); diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 471a76c3e99..c6070f94ef1 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -6,8 +6,17 @@ namespace stan { namespace math { namespace internal { - -double wiener5_lg1(double y, double a, double vn, double wn, double sv) { +/** + * Calculate the 'lg1' term for a wiener5 density or gradient + * + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param vn The relative starting point + * @param wn The drift rate + * @param sv The inter-trial variability of the drift rate + * @return 'lg1' term +*/ +inline double wiener5_lg1(double y, double a, double vn, double wn, double sv) { const double w = 1.0 - wn; const double v = -vn; const double sv_sqr = square(sv); @@ -23,8 +32,22 @@ double wiener5_lg1(double y, double a, double vn, double wn, double sv) { } } +/** + * Calculate the 'ans0' term for a wiener5 density or gradient + * + * @tparam GradA Whether the calculation is for gradient w.r.t. 'a' + * @tparam GradT Whether the calculation is for gradient w.r.t. 't' + * + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param vn The relative starting point + * @param wn The drift rate + * @param sv The inter-trial variability of the drift rate + * @return 'ans0' term +*/ template -double wiener5_ans0(double y, double a, double vn, double wn, double sv) { +inline double wiener5_ans0(double y, double a, double vn, + double wn, double sv) { const double w = 1.0 - wn; const double v = -vn; const double sv_sqr = square(sv); @@ -52,8 +75,20 @@ double wiener5_ans0(double y, double a, double vn, double wn, double sv) { } } +/** + * Calculate the 'kss' term for a wiener5 density or gradient + * + * @tparam Density Whether the calculation is for the density + * @tparam GradW Whether the calculation is for gradient w.r.t. 'w' + * + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param wn The drift rate + * @param es The error tolerance + * @return 'kss' term +*/ template -double wiener5_kss(double y, double a, double wn, double es) { +inline double wiener5_kss(double y, double a, double wn, double es) { const double two_es = 2.0 * es; const double y_asq = y / square(a); const double two_log_a = 2 * log(a); @@ -76,8 +111,20 @@ double wiener5_kss(double y, double a, double wn, double es) { return ceil(fmax(K1, K2)); } +/** + * Calculate the 'kss' term for a wiener5 density or gradient + * + * @tparam Density Whether the calculation is for the density + * @tparam GradT Whether the calculation is for gradient w.r.t. 't' + * + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param wn The drift rate + * @param es The error tolerance + * @return 'kll' term +*/ template -double wiener5_kll(double y, double a, double wn, double es) { +inline double wiener5_kll(double y, double a, double wn, double es) { const double two_es = 2.0 * es; const double y_asq = y / square(a); const double two_log_a = 2 * log(a); @@ -108,16 +155,31 @@ double wiener5_kll(double y, double a, double wn, double es) { return ceil(fmax(K1, K2)); } +/** + * Calculate the 'erg' term and its sign for a wiener5 density or gradient + * + * @tparam Density Whether the calculation is for the density + * @tparam GradW Whether the calculation is for gradient w.r.t. 'w' + * + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param wn The drift rate + * @param kss The kss term + * @param kll The kll term + * @return 'erg' sum and its sign +*/ template -std::tuple wiener5_ergsign(double y, double a, double wn, - size_t kss, size_t kll) { +inline std::tuple wiener5_ergsign(double y, double a, double wn, + size_t kss, size_t kll) { const double y_asq = y / square(a); const double w = 1.0 - wn; const bool small_kss = Density ? (2 * kss <= kll) : (2 * kss < kll); const double scaling = small_kss ? inv(2.0 * y_asq) : y_asq / 2.0; - double erg = NEGATIVE_INFTY; - int newsign = 1; + double prev_val = NEGATIVE_INFTY; + double current_val = NEGATIVE_INFTY; + int prev_sign = 1; + int current_sign = 1; if (small_kss) { double mult = Density ? 1 : 3; @@ -132,10 +194,15 @@ std::tuple wiener5_ergsign(double y, double a, double wn, - (square(wp2k) - offset) * scaling; double wm2k_quant = log(wm2k_sign * (wm2k - offset)) - (square(wm2k) - offset) * scaling; - std::forward_as_tuple(erg, newsign) - = log_sum_exp_signed(erg, newsign, mult * wp2k_quant, wp2k_sign); - std::forward_as_tuple(erg, newsign) - = log_sum_exp_signed(erg, newsign, mult * wm2k_quant, -1 * wm2k_sign); + double k_term; + int k_sign; + std::forward_as_tuple(k_term, k_sign) + = log_sum_exp_signed(mult * wm2k_quant, -1 * wm2k_sign, + mult * wp2k_quant, wp2k_sign); + std::forward_as_tuple(current_val, current_sign) + = log_sum_exp_signed(k_term, k_sign, prev_val, prev_sign); + prev_val = current_val; + prev_sign = current_sign; } } else { double mult = 3; @@ -150,16 +217,31 @@ std::tuple wiener5_ergsign(double y, double a, double wn, int check_sign = sign(check); double kll_quant = mult * log(k) - square(pi_k) * scaling + log(fabs(check)); - std::forward_as_tuple(erg, newsign) - = log_sum_exp_signed(erg, newsign, kll_quant, check_sign); + std::forward_as_tuple(current_val, current_sign) + = log_sum_exp_signed(prev_val, prev_sign, kll_quant, check_sign); + prev_val = current_val; + prev_sign = current_sign; } } - return std::make_tuple(erg, newsign); + return std::make_tuple(current_val, current_sign); } -template -double wiener5_density(double y, double a, double vn, double wn, double sv, - double err = log(1e-12)) { +/** + * Calculate the wiener5 density + * + * @tparam NaturalScale Whether to return the density on natural or log-scale + * + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param vn The relative starting point + * @param wn The drift rate + * @param sv The inter-trial variability of the drift rate + * @param err The log error tolerance + * @return density +*/ +template +inline double wiener5_density(double y, double a, double vn, double wn, + double sv, double err = log(1e-12)) { double lg1 = wiener5_lg1(y, a, vn, wn, sv); double es = (err - lg1); double kss = wiener5_kss(y, a, wn, es); @@ -176,12 +258,26 @@ double wiener5_density(double y, double a, double vn, double wn, double sv, ld = lg1 + erg + LOG_PI; } - return WrtLog ? exp(ld) : ld; + return NaturalScale ? exp(ld) : ld; } +/** + * Calculate the derivative of the wiener5 density w.r.t. 't' + * + * @tparam WrtLog Whether to return the derivative w.r.t. + * the natural or log-scale density + * + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param vn The relative starting point + * @param wn The drift rate + * @param sv The inter-trial variability of the drift rate + * @param err The log error tolerance + * @return Gradient w.r.t. t +*/ template -double grad_wiener5_t(double y, double a, double vn, double wn, double sv, - double err = log(1e-12)) { +inline double grad_wiener5_t(double y, double a, double vn, double wn, + double sv, double err = log(1e-12)) { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); @@ -210,9 +306,23 @@ double grad_wiener5_t(double y, double a, double vn, double wn, double sv, return WrtLog ? ans * exp(ld) : ans; } +/** + * Calculate the derivative of the wiener5 density w.r.t. 'a' + * + * @tparam WrtLog Whether to return the derivative w.r.t. + * the natural or log-scale density + * + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param vn The relative starting point + * @param wn The drift rate + * @param sv The inter-trial variability of the drift rate + * @param err The log error tolerance + * @return Gradient w.r.t. a +*/ template -double grad_wiener5_a(double y, double a, double vn, double wn, double sv, - double err = log(1e-12)) { +inline double grad_wiener5_a(double y, double a, double vn, double wn, + double sv, double err = log(1e-12)) { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); @@ -241,9 +351,23 @@ double grad_wiener5_a(double y, double a, double vn, double wn, double sv, return WrtLog ? ans * exp(ld) : ans; } +/** + * Calculate the derivative of the wiener5 density w.r.t. 'v' + * + * @tparam WrtLog Whether to return the derivative w.r.t. + * the natural or log-scale density + * + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param vn The relative starting point + * @param wn The drift rate + * @param sv The inter-trial variability of the drift rate + * @param err The log error tolerance + * @return Gradient w.r.t. v +*/ template -double grad_wiener5_v(double y, double a, double vn, double wn, double sv, - double err = log(1e-12)) { +inline double grad_wiener5_v(double y, double a, double vn, double wn, + double sv, double err = log(1e-12)) { double ans = (a * (1 - wn) - vn * y); if (sv != 0) { ans /= 1 + square(sv) * y; @@ -251,9 +375,23 @@ double grad_wiener5_v(double y, double a, double vn, double wn, double sv, return WrtLog ? ans * wiener5_density(y, a, vn, wn, sv, err) : ans; } +/** + * Calculate the derivative of the wiener5 density w.r.t. 'w' + * + * @tparam WrtLog Whether to return the derivative w.r.t. + * the natural or log-scale density + * + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param vn The relative starting point + * @param wn The drift rate + * @param sv The inter-trial variability of the drift rate + * @param err The log error tolerance + * @return Gradient w.r.t. w +*/ template -double grad_wiener5_w(double y, double a, double vn, double wn, double sv, - double err = log(1e-12)) { +inline double grad_wiener5_w(double y, double a, double vn, double wn, + double sv, double err = log(1e-12)) { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); @@ -280,9 +418,23 @@ double grad_wiener5_w(double y, double a, double vn, double wn, double sv, return WrtLog ? ans * exp(ld) : ans; } +/** + * Calculate the derivative of the wiener5 density w.r.t. 'sv' + * + * @tparam WrtLog Whether to return the derivative w.r.t. + * the natural or log-scale density + * + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param vn The relative starting point + * @param wn The drift rate + * @param sv The inter-trial variability of the drift rate + * @param err The log error tolerance + * @return Gradient w.r.t. sv +*/ template -double grad_wiener5_sv(double y, double a, double vn, double wn, double sv, - double err = log(1e-12)) { +inline double grad_wiener5_sv(double y, double a, double vn, double wn, + double sv, double err = log(1e-12)) { const double one_plus_svsqr_y = 1 + square(sv) * y; const double w = 1.0 - wn; const double v = -vn; diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index c67e7ebdba4..421fc0d38ca 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -9,6 +9,18 @@ namespace stan { namespace math { namespace internal { +/** + * Calculate the derivative of the wiener7 density w.r.t. 'sw' + * + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param v The drift rate + * @param w The relative starting point + * @param sv The inter-trial variability of the drift rate + * @param sw The inter-trial variability of the relative starting point + * @param lerr The log error tolerance + * @return Gradient w.r.t. sw +*/ inline double grad_wiener7_sw(double y, double a, double v, double w, double sv, double sw, double lerr) { double low = w - sw / 2; @@ -21,6 +33,28 @@ inline double grad_wiener7_sw(double y, double a, double v, double w, double sv, return 0.5 * (fl + fu) / sw; } +/** + * Helper function for agnostically calling wiener5 functions + * (to be integrated over) or directly calling wiener7 functions, + * accounting for the different number of arguments. + * + * Specialisation for wiener5 functions + * + * @tparam GradSW Whether the wiener7 gradient function is passed + * @tparam F Type of Gradient/density functor + * + * @param functor Gradient/density functor to apply + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param v The drift rate + * @param w The relative starting point + * @param t0 The non-decision time + * @param sv The inter-trial variability of the drift rate + * @param sw The inter-trial variability of the relative starting point + * @param st0 The inter-trial variability of the non-decision time + * @param lerr The log error tolerance + * @return Functor applied to arguments +*/ template * = nullptr> inline double call_wiener7_function(const F& functor, double y, double a, double v, double w, double t0, double sv, @@ -28,6 +62,28 @@ inline double call_wiener7_function(const F& functor, double y, double a, return functor(y - t0, a, v, w, sv, lerr); } +/** + * Helper function for agnostically calling wiener5 functions + * (to be integrated over) or directly calling wiener7 functions, + * accounting for the different number of arguments. + * + * Specialisation for wiener7 functions + * + * @tparam GradSW Whether the wiener7 gradient function is passed + * @tparam F Type of Gradient/density functor + * + * @param functor Gradient/density functor to apply + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param v The drift rate + * @param w The relative starting point + * @param t0 The non-decision time + * @param sv The inter-trial variability of the drift rate + * @param sw The inter-trial variability of the relative starting point + * @param st0 The inter-trial variability of the non-decision time + * @param lerr The log error tolerance + * @return Functor applied to arguments +*/ template * = nullptr> inline double call_wiener7_function(const F& functor, double y, double a, double v, double w, double t0, double sv, From 655cd79eb69709904972cb935ef209f174b87700 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 24 May 2023 12:13:12 -0400 Subject: [PATCH 063/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/functor/hcubature.hpp | 13 ++++--- stan/math/prim/prob/wiener5_lpdf.hpp | 43 ++++++++++++------------ stan/math/prim/prob/wiener_full_lpdf.hpp | 6 ++-- 3 files changed, 30 insertions(+), 32 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index ea05c036c64..ca115f42e36 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -239,8 +239,7 @@ std::tuple gauss_kronrod(const F& integrand, const double a, * @param w weights for the 5 terms in the GenzMalik rule * @param wd weights for the embedded lower-degree rule */ -inline void make_GenzMalik(const int dim, - std::vector& p, +inline void make_GenzMalik(const int dim, std::vector& p, std::vector& w, std::vector& wd) { double l4 = std::sqrt(9 * 1.0 / 10); double l2 = std::sqrt(9 * 1.0 / 70); @@ -284,10 +283,9 @@ inline void make_GenzMalik(const int dim, */ template std::tuple integrate_GenzMalik( - const F& integrand, std::vector& p, - std::vector& w, std::vector& wd, const int dim, - const std::vector& a, const std::vector& b, - const ParsTupleT& pars_tuple) { + const F& integrand, std::vector& p, std::vector& w, + std::vector& wd, const int dim, const std::vector& a, + const std::vector& b, const ParsTupleT& pars_tuple) { std::vector c(dim, 0); std::vector deltac(dim, 0); @@ -376,7 +374,8 @@ std::tuple integrate_GenzMalik( std::vector p5(dim); for (std::size_t i = 0; i != p[3].cols(); i++) { for (std::size_t j = 0; j != dim; j++) { - p5[j] = deltac[j] * p[3](j, i);; + p5[j] = deltac[j] * p[3](j, i); + ; } for (std::size_t j = 0; j != dim; j++) { diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index c6070f94ef1..5c5f20ecf38 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -15,7 +15,7 @@ namespace internal { * @param wn The drift rate * @param sv The inter-trial variability of the drift rate * @return 'lg1' term -*/ + */ inline double wiener5_lg1(double y, double a, double vn, double wn, double sv) { const double w = 1.0 - wn; const double v = -vn; @@ -44,10 +44,10 @@ inline double wiener5_lg1(double y, double a, double vn, double wn, double sv) { * @param wn The drift rate * @param sv The inter-trial variability of the drift rate * @return 'ans0' term -*/ + */ template -inline double wiener5_ans0(double y, double a, double vn, - double wn, double sv) { +inline double wiener5_ans0(double y, double a, double vn, double wn, + double sv) { const double w = 1.0 - wn; const double v = -vn; const double sv_sqr = square(sv); @@ -86,7 +86,7 @@ inline double wiener5_ans0(double y, double a, double vn, * @param wn The drift rate * @param es The error tolerance * @return 'kss' term -*/ + */ template inline double wiener5_kss(double y, double a, double wn, double es) { const double two_es = 2.0 * es; @@ -122,7 +122,7 @@ inline double wiener5_kss(double y, double a, double wn, double es) { * @param wn The drift rate * @param es The error tolerance * @return 'kll' term -*/ + */ template inline double wiener5_kll(double y, double a, double wn, double es) { const double two_es = 2.0 * es; @@ -167,10 +167,10 @@ inline double wiener5_kll(double y, double a, double wn, double es) { * @param kss The kss term * @param kll The kll term * @return 'erg' sum and its sign -*/ + */ template inline std::tuple wiener5_ergsign(double y, double a, double wn, - size_t kss, size_t kll) { + size_t kss, size_t kll) { const double y_asq = y / square(a); const double w = 1.0 - wn; const bool small_kss = Density ? (2 * kss <= kll) : (2 * kss < kll); @@ -196,9 +196,8 @@ inline std::tuple wiener5_ergsign(double y, double a, double wn, - (square(wm2k) - offset) * scaling; double k_term; int k_sign; - std::forward_as_tuple(k_term, k_sign) - = log_sum_exp_signed(mult * wm2k_quant, -1 * wm2k_sign, - mult * wp2k_quant, wp2k_sign); + std::forward_as_tuple(k_term, k_sign) = log_sum_exp_signed( + mult * wm2k_quant, -1 * wm2k_sign, mult * wp2k_quant, wp2k_sign); std::forward_as_tuple(current_val, current_sign) = log_sum_exp_signed(k_term, k_sign, prev_val, prev_sign); prev_val = current_val; @@ -238,7 +237,7 @@ inline std::tuple wiener5_ergsign(double y, double a, double wn, * @param sv The inter-trial variability of the drift rate * @param err The log error tolerance * @return density -*/ + */ template inline double wiener5_density(double y, double a, double vn, double wn, double sv, double err = log(1e-12)) { @@ -274,10 +273,10 @@ inline double wiener5_density(double y, double a, double vn, double wn, * @param sv The inter-trial variability of the drift rate * @param err The log error tolerance * @return Gradient w.r.t. t -*/ + */ template inline double grad_wiener5_t(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { + double sv, double err = log(1e-12)) { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); @@ -319,10 +318,10 @@ inline double grad_wiener5_t(double y, double a, double vn, double wn, * @param sv The inter-trial variability of the drift rate * @param err The log error tolerance * @return Gradient w.r.t. a -*/ + */ template inline double grad_wiener5_a(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { + double sv, double err = log(1e-12)) { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); @@ -364,10 +363,10 @@ inline double grad_wiener5_a(double y, double a, double vn, double wn, * @param sv The inter-trial variability of the drift rate * @param err The log error tolerance * @return Gradient w.r.t. v -*/ + */ template inline double grad_wiener5_v(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { + double sv, double err = log(1e-12)) { double ans = (a * (1 - wn) - vn * y); if (sv != 0) { ans /= 1 + square(sv) * y; @@ -388,10 +387,10 @@ inline double grad_wiener5_v(double y, double a, double vn, double wn, * @param sv The inter-trial variability of the drift rate * @param err The log error tolerance * @return Gradient w.r.t. w -*/ + */ template inline double grad_wiener5_w(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { + double sv, double err = log(1e-12)) { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); @@ -431,10 +430,10 @@ inline double grad_wiener5_w(double y, double a, double vn, double wn, * @param sv The inter-trial variability of the drift rate * @param err The log error tolerance * @return Gradient w.r.t. sv -*/ + */ template inline double grad_wiener5_sv(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { + double sv, double err = log(1e-12)) { const double one_plus_svsqr_y = 1 + square(sv) * y; const double w = 1.0 - wn; const double v = -vn; diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 421fc0d38ca..c8f1451ec6d 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -20,7 +20,7 @@ namespace internal { * @param sw The inter-trial variability of the relative starting point * @param lerr The log error tolerance * @return Gradient w.r.t. sw -*/ + */ inline double grad_wiener7_sw(double y, double a, double v, double w, double sv, double sw, double lerr) { double low = w - sw / 2; @@ -54,7 +54,7 @@ inline double grad_wiener7_sw(double y, double a, double v, double w, double sv, * @param st0 The inter-trial variability of the non-decision time * @param lerr The log error tolerance * @return Functor applied to arguments -*/ + */ template * = nullptr> inline double call_wiener7_function(const F& functor, double y, double a, double v, double w, double t0, double sv, @@ -83,7 +83,7 @@ inline double call_wiener7_function(const F& functor, double y, double a, * @param st0 The inter-trial variability of the non-decision time * @param lerr The log error tolerance * @return Functor applied to arguments -*/ + */ template * = nullptr> inline double call_wiener7_function(const F& functor, double y, double a, double v, double w, double t0, double sv, From 485bd56f5e7d15ba417656febd0e6306320e3567 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 24 May 2023 19:23:28 +0300 Subject: [PATCH 064/179] Doxygen --- stan/math/prim/functor/hcubature.hpp | 9 ++++----- stan/math/prim/prob/wiener5_lpdf.hpp | 1 + stan/math/prim/prob/wiener_full_lpdf.hpp | 6 +++++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index ca115f42e36..f712c954c24 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -186,11 +186,11 @@ inline void signcombos(const int k, const double lambda, const int dim, * for one dimension. * * @tparam F type of the integrand - * @tparam T_pars type of the parameters for the integrand + * @tparam ParsTupleT type of the tuple of parameters for the integrand * @param integrand function to be integrated * @param a lower limit of integration * @param b upper limit of integration - * @param pars parameters for the integrand + * @param pars_tuple Tuple of parameters for the integrand * @return numeric integral of the integrand and error */ template @@ -269,7 +269,7 @@ inline void make_GenzMalik(const int dim, std::vector& p, * for more than one dimensions. * * @tparam F type of the integrand - * @tparam T_pars type of the parameters for the integrand + * @tparam ParsTupleT type of the tuple of parameters for the integrand * @param integrand function to be integrated * @param p * @param w @@ -277,7 +277,7 @@ inline void make_GenzMalik(const int dim, std::vector& p, * @param dim dimension of the multidimensional integral * @param a lower limit of integration * @param b upper limit of integration - * @param pars parameters for the integrand + * @param pars_tuple Tuple of parameters for the integrand * @return numeric integral of the integrand, error, and suggested coordinate to * subdivide next */ @@ -375,7 +375,6 @@ std::tuple integrate_GenzMalik( for (std::size_t i = 0; i != p[3].cols(); i++) { for (std::size_t j = 0; j != dim; j++) { p5[j] = deltac[j] * p[3](j, i); - ; } for (std::size_t j = 0; j != dim; j++) { diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 5c5f20ecf38..4a0ee2df56e 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -513,6 +513,7 @@ double estimate_with_err_check(const F& functor, double err, * @param w The relative starting point * @param v The drift rate * @param sv The inter-trial variability of the drift rate + * @param prec Level of precision in estimation * @return The log of the Wiener first passage time density with * the specified arguments for upper boundary responses */ diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index c8f1451ec6d..219b5887efb 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -96,8 +96,11 @@ inline double call_wiener7_function(const F& functor, double y, double a, * to the hcubature() function for calculating wiener7 parameters via * integration * - * @tparam FunTypeEnum An enum value indicating the function required + * @tparam GradSW Whether the wiener7 gradient function is passed + * @tparam Wiener7FunctorT Type of functor * @tparam Targs... Types of arguments in parameter pack + * + * @param wiener7_functor Gradient/density functor to apply * @param hcubature_err Error tolerance for calculation * @param args Additional arguments to be passed to the hcubature function * @return Wiener7 density or gradient calculated by integration @@ -193,6 +196,7 @@ auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, * @param sv The inter-trial variability of the drift rate * @param sw The inter-trial variability of the relative starting point * @param st0 The inter-trial variability of the non-decision time + * @param prec Level of precision in estimation * @return The log of the Wiener first passage time density with * the specified arguments for upper boundary responses * @throw std::domain_error if non-decision time \c t0 is greater than reaction From 6913848d128b9a142c7c360081445500c91c6b12 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 25 May 2023 13:06:30 +0300 Subject: [PATCH 065/179] Additional comments --- stan/math/prim/functor/hcubature.hpp | 29 ++++++++++++++-------------- stan/math/prim/prob/wiener5_lpdf.hpp | 23 +++++++++++----------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index f712c954c24..5f1a78751d8 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -68,7 +68,7 @@ static constexpr double gwd7[4] = {1.2948496616886969327061143267787e-01, * @param p number of elements * @param x x-th lexicographically ordered set */ -inline void combination(std::vector& c, const int dim, const int p, +inline void combination(Eigen::VectorXi& c, const int dim, const int p, const int x) { size_t r, k = 0; for (std::size_t i = 0; i < p - 1; i++) { @@ -98,13 +98,13 @@ inline void combination(std::vector& c, const int dim, const int p, */ inline void combos(const int k, const double lambda, const int dim, Eigen::MatrixXd& p) { - std::vector c(k); + Eigen::VectorXi c(k); const auto choose_dimk = choose(dim, k); p = Eigen::MatrixXd::Zero(dim, choose_dimk); for (size_t i = 0; i < choose_dimk; i++) { combination(c, dim, k, i + 1); for (size_t j = 0; j < k; j++) { - p(c[j] - 1, i) = lambda; + p.coeffRef(c.coeff(j) - 1, i) = lambda; } } } @@ -116,17 +116,18 @@ inline void combos(const int k, const double lambda, const int dim, * @param k number of components equal to lambda * @param lambda scalar * @param c ordered vector - * @param temp helper vector + * @param inp Input vector to be incremented */ -inline void increment(std::vector& index, const int k, - const double lambda, const std::vector& c, - Eigen::VectorXd& temp) { +inline Eigen::VectorXd increment(std::vector& index, const int k, + const double lambda, const Eigen::VectorXi& c, + const Eigen::VectorXd& inp) { + Eigen::VectorXd temp = inp; if (index.size() == 0) { index.push_back(false); for (std::size_t j = 0; j != k; j++) { temp[c[j] - 1] = lambda; } - return; + return temp; } int first_zero = 0; while ((first_zero < index.size()) && index[first_zero]) { @@ -149,6 +150,7 @@ inline void increment(std::vector& index, const int k, temp[c[i] - 1] *= -1; } } + return temp; } /** @@ -163,20 +165,19 @@ inline void increment(std::vector& index, const int k, */ inline void signcombos(const int k, const double lambda, const int dim, Eigen::MatrixXd& p) { - std::vector c(k); + Eigen::VectorXi c(k); const auto choose_dimk = choose(dim, k); p.resize(dim, choose_dimk * std::pow(2, k)); p.setZero(); - int col = 0; + int current_col = 0; for (std::size_t i = 1; i != choose_dimk + 1; i++) { - Eigen::VectorXd temp = Eigen::VectorXd::Zero(dim); combination(c, dim, k, i); std::vector index; index.clear(); for (std::size_t j = 0; j != std::pow(2, k); j++) { - increment(index, k, lambda, c, temp); - p.col(col) = temp; - col += 1; + size_t prev_col = j == 0 ? current_col : current_col - 1; + p.col(current_col) = increment(index, k, lambda, c, p.col(prev_col)); + current_col += 1; } } } diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 4a0ee2df56e..ff6857149d4 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -16,7 +16,8 @@ namespace internal { * @param sv The inter-trial variability of the drift rate * @return 'lg1' term */ -inline double wiener5_lg1(double y, double a, double vn, double wn, double sv) { +inline double wiener5_lg1(double y, double a, double vn, + double wn, double sv) noexcept { const double w = 1.0 - wn; const double v = -vn; const double sv_sqr = square(sv); @@ -47,7 +48,7 @@ inline double wiener5_lg1(double y, double a, double vn, double wn, double sv) { */ template inline double wiener5_ans0(double y, double a, double vn, double wn, - double sv) { + double sv) noexcept { const double w = 1.0 - wn; const double v = -vn; const double sv_sqr = square(sv); @@ -88,7 +89,7 @@ inline double wiener5_ans0(double y, double a, double vn, double wn, * @return 'kss' term */ template -inline double wiener5_kss(double y, double a, double wn, double es) { +inline double wiener5_kss(double y, double a, double wn, double es) noexcept { const double two_es = 2.0 * es; const double y_asq = y / square(a); const double two_log_a = 2 * log(a); @@ -124,7 +125,7 @@ inline double wiener5_kss(double y, double a, double wn, double es) { * @return 'kll' term */ template -inline double wiener5_kll(double y, double a, double wn, double es) { +inline double wiener5_kll(double y, double a, double wn, double es) noexcept { const double two_es = 2.0 * es; const double y_asq = y / square(a); const double two_log_a = 2 * log(a); @@ -170,7 +171,7 @@ inline double wiener5_kll(double y, double a, double wn, double es) { */ template inline std::tuple wiener5_ergsign(double y, double a, double wn, - size_t kss, size_t kll) { + size_t kss, size_t kll) noexcept { const double y_asq = y / square(a); const double w = 1.0 - wn; const bool small_kss = Density ? (2 * kss <= kll) : (2 * kss < kll); @@ -240,7 +241,7 @@ inline std::tuple wiener5_ergsign(double y, double a, double wn, */ template inline double wiener5_density(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { + double sv, double err = log(1e-12)) noexcept { double lg1 = wiener5_lg1(y, a, vn, wn, sv); double es = (err - lg1); double kss = wiener5_kss(y, a, wn, es); @@ -276,7 +277,7 @@ inline double wiener5_density(double y, double a, double vn, double wn, */ template inline double grad_wiener5_t(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { + double sv, double err = log(1e-12)) noexcept { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); @@ -321,7 +322,7 @@ inline double grad_wiener5_t(double y, double a, double vn, double wn, */ template inline double grad_wiener5_a(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { + double sv, double err = log(1e-12)) noexcept { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); @@ -366,7 +367,7 @@ inline double grad_wiener5_a(double y, double a, double vn, double wn, */ template inline double grad_wiener5_v(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { + double sv, double err = log(1e-12)) noexcept { double ans = (a * (1 - wn) - vn * y); if (sv != 0) { ans /= 1 + square(sv) * y; @@ -390,7 +391,7 @@ inline double grad_wiener5_v(double y, double a, double vn, double wn, */ template inline double grad_wiener5_w(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { + double sv, double err = log(1e-12)) noexcept { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; double lg1 = wiener5_lg1(y, a, vn, wn, sv); @@ -433,7 +434,7 @@ inline double grad_wiener5_w(double y, double a, double vn, double wn, */ template inline double grad_wiener5_sv(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) { + double sv, double err = log(1e-12)) noexcept { const double one_plus_svsqr_y = 1 + square(sv) * y; const double w = 1.0 - wn; const double v = -vn; From 41fbb3bf7e748f224a5a1a13bbd407984f3eac42 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 25 May 2023 06:07:39 -0400 Subject: [PATCH 066/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/functor/hcubature.hpp | 4 ++-- stan/math/prim/prob/wiener5_lpdf.hpp | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 5f1a78751d8..cd8fbe47cc3 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -119,8 +119,8 @@ inline void combos(const int k, const double lambda, const int dim, * @param inp Input vector to be incremented */ inline Eigen::VectorXd increment(std::vector& index, const int k, - const double lambda, const Eigen::VectorXi& c, - const Eigen::VectorXd& inp) { + const double lambda, const Eigen::VectorXi& c, + const Eigen::VectorXd& inp) { Eigen::VectorXd temp = inp; if (index.size() == 0) { index.push_back(false); diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index ff6857149d4..ef725ea2c12 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -16,8 +16,8 @@ namespace internal { * @param sv The inter-trial variability of the drift rate * @return 'lg1' term */ -inline double wiener5_lg1(double y, double a, double vn, - double wn, double sv) noexcept { +inline double wiener5_lg1(double y, double a, double vn, double wn, + double sv) noexcept { const double w = 1.0 - wn; const double v = -vn; const double sv_sqr = square(sv); @@ -171,7 +171,8 @@ inline double wiener5_kll(double y, double a, double wn, double es) noexcept { */ template inline std::tuple wiener5_ergsign(double y, double a, double wn, - size_t kss, size_t kll) noexcept { + size_t kss, + size_t kll) noexcept { const double y_asq = y / square(a); const double w = 1.0 - wn; const bool small_kss = Density ? (2 * kss <= kll) : (2 * kss < kll); From 75b317505324885416104be72792d82f0667e7bc Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Mon, 26 Jun 2023 10:26:20 +0200 Subject: [PATCH 067/179] all values are computed correctly --- stan/math/prim/prob/wiener5_lpdf.hpp | 146 ++++++++++++----------- stan/math/prim/prob/wiener_full_lpdf.hpp | 60 +++++----- 2 files changed, 106 insertions(+), 100 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index ef725ea2c12..11001a5c26b 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -97,7 +97,7 @@ inline double wiener5_kss(double y, double a, double wn, double es) noexcept { const double w = 1.0 - wn; const double K1_mult = Density ? 2 : 3; - double K1 = (sqrt(K1_mult * y_asq) + w) / 2.0; + const double K1 = (sqrt(K1_mult * y_asq) + w) / 2.0; double u_eps; if (Density || GradW) { u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log_y_asq + two_es); @@ -105,10 +105,10 @@ inline double wiener5_kss(double y, double a, double wn, double es) noexcept { u_eps = fmin(-3.0, (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_es)); } - double arg_mult = Density ? 1 : 3; - double arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + const double arg_mult = (Density || GradW) ? 1 : 3; + const double arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - double K2 = (arg > 0) ? 0.5 * (sqrt(arg) - w) : K1; + const double K2 = (arg > 0) ? GradW ? 0.5 * (sqrt(arg) + w) : 0.5 * (sqrt(arg) - w) : K1; return ceil(fmax(K1, K2)); } @@ -124,7 +124,7 @@ inline double wiener5_kss(double y, double a, double wn, double es) noexcept { * @param es The error tolerance * @return 'kll' term */ -template +template inline double wiener5_kll(double y, double a, double wn, double es) noexcept { const double two_es = 2.0 * es; const double y_asq = y / square(a); @@ -132,25 +132,25 @@ inline double wiener5_kll(double y, double a, double wn, double es) noexcept { const double log_y_asq = log(y) - two_log_a; const double w = 1.0 - wn; - const double K1_mult = GradT ? 2 : 3; + const double K1_mult = GradW ? 2 : 3; static constexpr double PI_SQUARED = pi() * pi(); // pi*pi double K1; double K2; if (Density) { K1 = 1.0 / (pi() * sqrt(y_asq)); - double two_log_piy = -2.0 * (LOG_PI + log_y_asq + es); + const double two_log_piy = -2.0 * (LOG_PI + log_y_asq + es); K2 = (two_log_piy >= 0) ? sqrt(two_log_piy / (PI_SQUARED * y_asq)) : 0.0; } else { K1 = sqrt(K1_mult / y_asq) / pi(); - double u_eps_arg - = GradT ? log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es - : log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_es; - double u_eps = fmin(-1, u_eps_arg); - double arg_mult = GradT ? (2.0 / PI_SQUARED / y_asq) : 1; - double arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - K2 = GradT ? (arg > 0) ? sqrt(arg) : K1 - : (arg > 0) ? sqrt(arg / y_asq) / pi() : K1; + const double u_eps_arg + = GradW ? log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_es + : log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es; + const double u_eps = fmin(-1, u_eps_arg); + const double arg_mult = GradW ? 1 : (2.0 / PI_SQUARED / y_asq); + const double arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + K2 = GradW ? (arg > 0) ? sqrt(arg / y_asq) / pi() : K1 + : (arg > 0) ? sqrt(arg) : K1; } return ceil(fmax(K1, K2)); @@ -184,27 +184,38 @@ inline std::tuple wiener5_ergsign(double y, double a, double wn, int current_sign = 1; if (small_kss) { - double mult = Density ? 1 : 3; - double offset = GradW ? y_asq : 0; - double sqrt_offset = sqrt(offset); - for (size_t k = kss; k >= 0; k--) { - double wp2k = w + 2.0 * k; - double wm2k = w - 2.0 * k; - int wp2k_sign = (wp2k > sqrt_offset) ? 1 : -1; - int wm2k_sign = (wm2k > sqrt_offset) ? 1 : -1; - double wp2k_quant = log(wp2k_sign * (wp2k - offset)) - - (square(wp2k) - offset) * scaling; - double wm2k_quant = log(wm2k_sign * (wm2k - offset)) - - (square(wm2k) - offset) * scaling; + const double mult = Density ? 1 : 3; + const double offset = GradW ? y_asq : 0; + const double sqrt_offset = sqrt(offset); + for (size_t k = kss; k >= 1; k--) { + const double wp2k = w + 2.0 * k; + const double wm2k = w - 2.0 * k; + int wp2k_sign = (wp2k > sqrt_offset) ? : 1 - 1; + int wm2k_sign = (wm2k > sqrt_offset) ? 1 : -1; + double wp2k_quant = GradW ? log( fabs((square(wp2k) - offset))) + - square(wp2k) * scaling : + mult * log(wp2k_sign * wp2k) + - square(wp2k) * scaling; + double wm2k_quant = GradW ? log( fabs((square(wm2k) - offset)) ) + - square(wm2k) * scaling : + mult * log(wm2k_sign * wm2k) + - square(wm2k) * scaling; double k_term; int k_sign; std::forward_as_tuple(k_term, k_sign) = log_sum_exp_signed( - mult * wm2k_quant, -1 * wm2k_sign, mult * wp2k_quant, wp2k_sign); + wm2k_quant, -1 * wm2k_sign, wp2k_quant, wp2k_sign); std::forward_as_tuple(current_val, current_sign) = log_sum_exp_signed(k_term, k_sign, prev_val, prev_sign); prev_val = current_val; prev_sign = current_sign; } + double new_val = GradW ? log(fabs(square(w) - offset)) - square(w) * scaling : + mult*log(w)-square(w)*scaling; + int new_val_sign = GradW ? ( w > sqrt_offset ? 1 : -1) + : (new_val > 0 ? 1 : -1); + int factor_sign = GradW ? 1 : -1; + std::forward_as_tuple(current_val, current_sign) + = log_sum_exp_signed(new_val, factor_sign * new_val_sign, current_val, factor_sign * current_sign); } else { double mult = 3; if (Density) { @@ -213,8 +224,8 @@ inline std::tuple wiener5_ergsign(double y, double a, double wn, mult = 2; } for (size_t k = kll; k >= 1; k--) { - double pi_k = k * pi(); - double check = (GradW) ? cos(pi_k * w) : sin(pi_k * w); + const double pi_k = k * pi(); + const double check = (GradW) ? cos(pi_k * w) : sin(pi_k * w); int check_sign = sign(check); double kll_quant = mult * log(k) - square(pi_k) * scaling + log(fabs(check)); @@ -243,10 +254,10 @@ inline std::tuple wiener5_ergsign(double y, double a, double wn, template inline double wiener5_density(double y, double a, double vn, double wn, double sv, double err = log(1e-12)) noexcept { - double lg1 = wiener5_lg1(y, a, vn, wn, sv); - double es = (err - lg1); - double kss = wiener5_kss(y, a, wn, es); - double kll = wiener5_kll(y, a, wn, es); + const double lg1 = wiener5_lg1(y, a, vn, wn, sv); + const double es = (err - lg1); + const double kss = wiener5_kss(y, a, wn, es); + const double kll = wiener5_kll(y, a, wn, es); double erg; int newsign; @@ -281,19 +292,19 @@ inline double grad_wiener5_t(double y, double a, double vn, double wn, double sv, double err = log(1e-12)) noexcept { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; - double lg1 = wiener5_lg1(y, a, vn, wn, sv); - double ans0 = wiener5_ans0(y, a, vn, wn, sv); - double es = (err - lg1) + two_log_a; + const double lg1 = wiener5_lg1(y, a, vn, wn, sv); + const double ans0 = wiener5_ans0(y, a, vn, wn, sv); + const double es = (err - lg1) + two_log_a; - double kss = wiener5_kss(y, a, wn, es); - double kll = wiener5_kll(y, a, wn, es); + const double kss = wiener5_kss(y, a, wn, es); + const double kll = wiener5_kll(y, a, wn, es); double erg; int newsign; std::forward_as_tuple(erg, newsign) = wiener5_ergsign(y, a, wn, kss, kll); - double ld_err = log(max(fabs(ans0 - 1.5 / y), fabs(ans0))); - double ld = wiener5_density(y, a, vn, wn, sv, err - ld_err); + const double ld_err = log(max(fabs(ans0 - 1.5 / y), fabs(ans0))); + const double ld = wiener5_density(y, a, vn, wn, sv, err - ld_err); double ans; if (2 * kss < kll) { ans = ans0 - 1.5 / y @@ -326,19 +337,19 @@ inline double grad_wiener5_a(double y, double a, double vn, double wn, double sv, double err = log(1e-12)) noexcept { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; - double lg1 = wiener5_lg1(y, a, vn, wn, sv); - double ans0 = wiener5_ans0(y, a, vn, wn, sv); - double es = (err - lg1); + const double lg1 = wiener5_lg1(y, a, vn, wn, sv); + const double ans0 = wiener5_ans0(y, a, vn, wn, sv); + const double es = err - lg1 + 3*log(a) - log(y) - LOG_TWO; - double kss = wiener5_kss(y, a, wn, es); - double kll = wiener5_kll(y, a, wn, es); + const double kss = wiener5_kss(y, a, wn, es); + const double kll = wiener5_kll(y, a, wn, es); double erg; int newsign; std::forward_as_tuple(erg, newsign) = wiener5_ergsign(y, a, wn, kss, kll); - double ld_err = log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a))); - double ld = wiener5_density(y, a, vn, wn, sv, err - ld_err); + const double ld_err = log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a))); + const double ld = wiener5_density(y, a, vn, wn, sv, err - ld_err); double ans; if (2 * kss < kll) { ans = ans0 + 1.0 / a @@ -395,18 +406,18 @@ inline double grad_wiener5_w(double y, double a, double vn, double wn, double sv, double err = log(1e-12)) noexcept { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; - double lg1 = wiener5_lg1(y, a, vn, wn, sv); - double ans0 = wiener5_ans0(y, a, vn, wn, sv); - double es = (err - lg1); + const double lg1 = wiener5_lg1(y, a, vn, wn, sv); + const double ans0 = wiener5_ans0(y, a, vn, wn, sv); + const double es = (err - lg1); - double kss = wiener5_kss(y, a, wn, es); - double kll = wiener5_kll(y, a, wn, es); + const double kss = wiener5_kss(y, a, wn, es); + const double kll = wiener5_kll(y, a, wn, es); double erg; int newsign; std::forward_as_tuple(erg, newsign) = wiener5_ergsign(y, a, wn, kss, kll); - double ld = wiener5_density(y, a, vn, wn, sv, err - log(fabs(ans0))); + const double ld = wiener5_density(y, a, vn, wn, sv, err - log(fabs(ans0))); double ans; if (2 * kss < kll) { ans = -(ans0 @@ -439,10 +450,10 @@ inline double grad_wiener5_sv(double y, double a, double vn, double wn, const double one_plus_svsqr_y = 1 + square(sv) * y; const double w = 1.0 - wn; const double v = -vn; - double t1 = -y / one_plus_svsqr_y; - double t2 = (square(a * w) + 2 * a * v * w * y + square(v * y)) + const double t1 = -y / one_plus_svsqr_y; + const double t2 = (square(a * w) + 2 * a * v * w * y + square(v * y)) / square(one_plus_svsqr_y); - double ans = sv * (t1 + t2); + const double ans = sv * (t1 + t2); return WrtLog ? ans * wiener5_density(y, a, vn, wn, sv, err) : ans; } @@ -478,7 +489,7 @@ inline void assign_err(std::tuple& args_tuple, double err) { * @param args_tuple Tuple of arguments to pass to functor * @param log_result Whether the function result is already on the log-scale */ -template double estimate_with_err_check(const F& functor, double err, ArgsTupleT&& args_tuple, @@ -489,8 +500,9 @@ double estimate_with_err_check(const F& functor, double err, if (lfabs_result < err) { lfabs_result = std::isinf(lfabs_result) ? 0 : lfabs_result; ArgsTupleT err_args_tuple = args_tuple; + const double new_error = GradW7 ? err + lfabs_result + LOG_TWO : err + lfabs_result; assign_err(std::get(err_args_tuple), - err + lfabs_result); + new_error); result = math::apply([&](auto&&... args) { return functor(args...); }, err_args_tuple); } @@ -570,7 +582,7 @@ inline return_type_t wiener5_lpdf( check_finite(function_name, "Inter-trial variability in drift rate", value_of(sv_ref)); - size_t N = max_size(y, a, t0, w, v, sv); + const size_t N = max_size(y, a, t0, w, v, sv); scalar_seq_view y_vec(y_ref); scalar_seq_view a_vec(a_ref); @@ -578,7 +590,7 @@ inline return_type_t wiener5_lpdf( scalar_seq_view w_vec(w_ref); scalar_seq_view v_vec(v_ref); scalar_seq_view sv_vec(sv_ref); - size_t N_y_t0 = max_size(y, t0); + const size_t N_y_t0 = max_size(y, t0); for (size_t i = 0; i < N_y_t0; ++i) { if (y_vec[i] <= t0_vec[i]) { @@ -590,9 +602,9 @@ inline return_type_t wiener5_lpdf( } } - double lerror_bound_dens = log(1e-6); // precision for density - double lerror_bound = log(prec); // precision for derivatives - double labstol_wiener5 = log(1e-12); // eps_abs(wiener5) + const double lerror_bound_dens = log(1e-6); // precision for density + const double lerror_bound = log(prec); // precision for derivatives + const double labstol_wiener5 = log(1e-12); // eps_abs(wiener5) double dens = 0.0; double ld = 0.0; operands_and_partials @@ -617,14 +629,14 @@ inline return_type_t wiener5_lpdf( dens = internal::estimate_with_err_check<5>( [&](auto&&... args) { return internal::wiener5_density(args...); }, - lerror_bound_dens - LOG_TWO, params, true); + lerror_bound_dens - LOG_TWO, params, false); ld += dens; - double new_est_err = dens + lerror_bound - LOG_FOUR; + const double new_est_err = dens + lerror_bound - LOG_FOUR; // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 - double deriv_y = internal::estimate_with_err_check<5>( + const double deriv_y = internal::estimate_with_err_check<5>( [&](auto&&... args) { return internal::grad_wiener5_t(args...); }, new_est_err, params); diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 219b5887efb..a53620ad841 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -23,13 +23,13 @@ namespace internal { */ inline double grad_wiener7_sw(double y, double a, double v, double w, double sv, double sw, double lerr) { - double low = w - sw / 2; + double low = w - sw / 2.0; low = (0 > low) ? 0 : low; - double high = w + sw / 2; + double high = w + sw / 2.0; high = (1 < high) ? 1 : high; - double fl = wiener5_density(y, a, v, low, sv, lerr); - double fu = wiener5_density(y, a, v, high, sv, lerr); + const double fl = wiener5_density(y, a, v, low, sv, lerr); + const double fu = wiener5_density(y, a, v, high, sv, lerr); return 0.5 * (fl + fu) / sw; } @@ -105,16 +105,16 @@ inline double call_wiener7_function(const F& functor, double y, double a, * @param args Additional arguments to be passed to the hcubature function * @return Wiener7 density or gradient calculated by integration */ -template +template //added GradW7 auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, double hcubature_err, TArgs&&... args) { const auto& wiener7_integrand_impl = [&](std::vector x, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double lerr) { scalar_seq_view x_vec(x); - double sw_val = GradSW ? 0 : sw; - double omega = sw_val ? w + sw_val * (x_vec[0] - 0.5) : w; - double t0_ = sw_val ? (st0 ? t0 + st0 * x_vec[1] : t0) + const double sw_val = GradSW ? 0 : sw; + const double omega = sw_val ? w + sw_val * (x_vec[0] - 0.5) : w; + const double t0_ = sw_val ? (st0 ? t0 + st0 * x_vec[1] : t0) : (st0 ? t0 + st0 * x_vec[0] : t0); if (y - t0_ <= 0) { return 0.0; @@ -126,7 +126,7 @@ auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, const auto& functor = [&](auto&&... int_args) { return hcubature(wiener7_integrand_impl, int_args...); }; - return estimate_with_err_check<0, 8>(functor, hcubature_err, + return estimate_with_err_check<0, GradW7, 8>(functor, hcubature_err, std::make_tuple(args...)); } } // namespace internal @@ -340,7 +340,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, if (size_zero(y, a, v, w, t0) || size_zero(sv, sw, st0)) { return 0; } - size_t N = max_size(y, a, v, w, t0, sv, sw, st0); + const size_t N = max_size(y, a, v, w, t0, sv, sw, st0); if (!N) { return 0; } @@ -352,7 +352,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, scalar_seq_view sv_vec(sv_ref); scalar_seq_view sw_vec(sw_ref); scalar_seq_view st0_vec(st0_ref); - size_t N_y_t0 = max_size(y, t0, st0); + const size_t N_y_t0 = max_size(y, t0, st0); for (size_t i = 0; i < N_y_t0; ++i) { if (y_vec[i] <= t0_vec[i]) { @@ -388,24 +388,19 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, return 0; } - double error_bound_dens = 1e-6; // precision for density - double lerror_bound_dens = log(error_bound_dens); - double error_bound = prec; // precision for + const double lerror_bound_dens = log(1e-6); // precision for density + const double error_bound = prec; // precision for // derivatives (controllable by user) - double lerror_bound = log(error_bound); // log(alpha) - double abstol = 0.0; - double reltol = .9 * error_bound; // eps_rel(Integration) - double abstol_wiener5 = 1e-12; // eps_abs(wiener5) - double labstol_wiener5 = log(abstol_wiener5); - // log(eps_abs(wiener5) - int Meval = 6000; + const double lerror_bound = log(error_bound); + const double abstol = 0.0; + const double reltol = .9 * error_bound; // eps_rel(Integration) + const double labstol_wiener5 = log(1e-12); + const int Meval = 6000; double dens = 0.0; double ld = 0.0; operands_and_partials ops_partials(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref, sw_ref, st0_ref); - static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; - static constexpr double LOG_POINT1 = -1; ReturnT result = 0; // calculate density and partials @@ -426,7 +421,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const auto params = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, st0_val, labstol_wiener5 - LOG_TWO); - int dim = (sw_val != 0) + (st0_val != 0); + const int dim = (sw_val != 0) + (st0_val != 0); check_positive(function_name, "(Inter-trial variability in A-priori bias) + " "(Inter-trial variability in nondecision time)", @@ -445,14 +440,14 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, return internal::wiener5_density(args...); }, hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2); - double log_dens = log(dens); + const double log_dens = log(dens); ld += log_dens; - hcubature_err = labstol_wiener5 - (lerror_bound + log_dens) + LOG_TWO + 1; + hcubature_err = labstol_wiener5 - lerror_bound + log(fabs(dens)) + LOG_TWO + 1; // computation of derivative for t and precision check in order to give // the value as deriv_t to edge1 and as -deriv_t to edge5 - double deriv_t_7 + const double deriv_t_7 = internal::wiener7_integrate( [&](auto&&... args) { return internal::grad_wiener5_t(args...); @@ -480,7 +475,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } if (!is_constant_all::value) { ops_partials.edge4_.partials_[i] - = internal::wiener7_integrate( + = internal::wiener7_integrate( [&](auto&&... args) { return internal::grad_wiener5_w(args...); }, @@ -516,12 +511,12 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const auto sw_params = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, labstol_wiener5 - LOG_TWO); - deriv = internal::estimate_with_err_check<6>( + deriv = internal::estimate_with_err_check<5>( [&](auto&&... args) { return internal::call_wiener7_function( internal::grad_wiener7_sw, args...); }, - lerror_bound - LOG_TWO, sw_params); + hcubature_err, sw_params); } else { deriv = internal::wiener7_integrate( [&](auto&&... args) { @@ -539,7 +534,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } else if (y_val - (t0_val + st0_val) <= 0) { ops_partials.edge8_.partials_[i] = -1 / st0_val; } else { - double t0_st0 = t0_val + st0_val; + const double t0_st0 = t0_val + st0_val; if (sw_val == 0) { const auto st_params = std::make_tuple(y_val, a_val, v_val, w_val, t0_st0, sv_val, @@ -551,8 +546,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, }, lerror_bound + log(st0_val), st_params); } else { - double new_error = labstol_wiener5 - LOG_TWO; - + const double new_error = labstol_wiener5 - LOG_TWO; const auto& params_st = std::make_tuple( y_val, a_val, v_val, w_val, t0_st0, sv_val, sw_val, 0, new_error); f = internal::wiener7_integrate( From 8a3e678d076a95b17ce5ec8ebeb5fd3cd84c436a Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Mon, 26 Jun 2023 11:24:27 +0200 Subject: [PATCH 068/179] rename variables --- stan/math/prim/prob/wiener5_lpdf.hpp | 442 ++++++++++++----------- stan/math/prim/prob/wiener_full_lpdf.hpp | 156 ++++---- 2 files changed, 325 insertions(+), 273 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 11001a5c26b..02b77478ad0 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -7,19 +7,19 @@ namespace stan { namespace math { namespace internal { /** - * Calculate the 'lg1' term for a wiener5 density or gradient + * Calculate the 'error_term' term for a wiener5 density or gradient * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation - * @param vn The relative starting point - * @param wn The drift rate + * @param v_value The drift rate + * @param w_value The relative starting point * @param sv The inter-trial variability of the drift rate - * @return 'lg1' term + * @return 'error_term' term */ -inline double wiener5_lg1(double y, double a, double vn, double wn, - double sv) noexcept { - const double w = 1.0 - wn; - const double v = -vn; +inline double wiener5_compute_error_term(double y, double a, double v_value, + double w_value, double sv) noexcept { + const double w = 1.0 - w_value; + const double v = -v_value; const double sv_sqr = square(sv); const double one_plus_svsqr_y = 1 + sv_sqr * y; const double two_avw = 2 * a * v * w; @@ -34,23 +34,23 @@ inline double wiener5_lg1(double y, double a, double vn, double wn, } /** - * Calculate the 'ans0' term for a wiener5 density or gradient + * Calculate the 'density_part_one' term for a wiener5 density or gradient * * @tparam GradA Whether the calculation is for gradient w.r.t. 'a' * @tparam GradT Whether the calculation is for gradient w.r.t. 't' * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation - * @param vn The relative starting point - * @param wn The drift rate + * @param v_value The drift rate + * @param w_value The relative starting point * @param sv The inter-trial variability of the drift rate - * @return 'ans0' term + * @return 'density_part_one' term */ template -inline double wiener5_ans0(double y, double a, double vn, double wn, - double sv) noexcept { - const double w = 1.0 - wn; - const double v = -vn; +inline double wiener5_density_part_one(double y, double a, double v_value, + double w_value, double sv) noexcept { + const double w = 1.0 - w_value; + const double v = -v_value; const double sv_sqr = square(sv); const double one_plus_svsqr_y = 1 + sv_sqr * y; const double two_avw = 2 * a * v * w; @@ -77,145 +77,150 @@ inline double wiener5_ans0(double y, double a, double vn, double wn, } /** - * Calculate the 'kss' term for a wiener5 density or gradient + * Calculate the 'n_terms_small_t' term for a wiener5 density or gradient * * @tparam Density Whether the calculation is for the density * @tparam GradW Whether the calculation is for gradient w.r.t. 'w' * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation - * @param wn The drift rate - * @param es The error tolerance - * @return 'kss' term + * @param w_value The relative starting point + * @param error The error tolerance + * @return 'n_terms_small_t' term */ template -inline double wiener5_kss(double y, double a, double wn, double es) noexcept { - const double two_es = 2.0 * es; +inline double wiener5_n_terms_small_t(double y, double a, double w_value, + double error) noexcept { + const double two_error = 2.0 * error; const double y_asq = y / square(a); const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; - const double w = 1.0 - wn; + const double w = 1.0 - w_value; - const double K1_mult = Density ? 2 : 3; - const double K1 = (sqrt(K1_mult * y_asq) + w) / 2.0; + const double n_1_factor = Density ? 2 : 3; + const double n_1 = (sqrt(n_1_factor * y_asq) + w) / 2.0; double u_eps; if (Density || GradW) { - u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log_y_asq + two_es); + u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log_y_asq + two_error); } else { u_eps = fmin(-3.0, - (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_es)); + (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_error)); } const double arg_mult = (Density || GradW) ? 1 : 3; const double arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - const double K2 = (arg > 0) ? GradW ? 0.5 * (sqrt(arg) + w) : 0.5 * (sqrt(arg) - w) : K1; - return ceil(fmax(K1, K2)); + const double n_2 + = (arg > 0) ? GradW ? 0.5 * (sqrt(arg) + w) : 0.5 * (sqrt(arg) - w) : n_1; + return ceil(fmax(n_1, n_2)); } /** - * Calculate the 'kss' term for a wiener5 density or gradient + * Calculate the 'n_terms_small_t' term for a wiener5 density or gradient * * @tparam Density Whether the calculation is for the density * @tparam GradT Whether the calculation is for gradient w.r.t. 't' * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation - * @param wn The drift rate - * @param es The error tolerance - * @return 'kll' term + * @param w_value The relative starting point + * @param error The error tolerance + * @return 'n_terms_large_t' term */ template -inline double wiener5_kll(double y, double a, double wn, double es) noexcept { - const double two_es = 2.0 * es; +inline double wiener5_n_terms_largel_t(double y, double a, double w_value, + double error) noexcept { + const double two_error = 2.0 * error; const double y_asq = y / square(a); const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; - const double w = 1.0 - wn; + const double w = 1.0 - w_value; - const double K1_mult = GradW ? 2 : 3; - static constexpr double PI_SQUARED = pi() * pi(); // pi*pi + const double n_1_factor = GradW ? 2 : 3; + static constexpr double PI_SQUARED = pi() * pi(); - double K1; - double K2; + double n_1; + double n_2; if (Density) { - K1 = 1.0 / (pi() * sqrt(y_asq)); - const double two_log_piy = -2.0 * (LOG_PI + log_y_asq + es); - K2 = (two_log_piy >= 0) ? sqrt(two_log_piy / (PI_SQUARED * y_asq)) : 0.0; + n_1 = 1.0 / (pi() * sqrt(y_asq)); + const double two_log_piy = -2.0 * (LOG_PI + log_y_asq + error); + n_2 = (two_log_piy >= 0) ? sqrt(two_log_piy / (PI_SQUARED * y_asq)) : 0.0; } else { - K1 = sqrt(K1_mult / y_asq) / pi(); + n_1 = sqrt(n_1_factor / y_asq) / pi(); const double u_eps_arg - = GradW ? log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_es - : log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + es; + = GradW + ? log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_error + : log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + error; const double u_eps = fmin(-1, u_eps_arg); - const double arg_mult = GradW ? 1 : (2.0 / PI_SQUARED / y_asq); + const double arg_mult = GradW ? 1 : (2.0 / PI_SQUARED / y_asq); const double arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - K2 = GradW ? (arg > 0) ? sqrt(arg / y_asq) / pi() : K1 - : (arg > 0) ? sqrt(arg) : K1; + n_2 = GradW ? (arg > 0) ? sqrt(arg / y_asq) / pi() : n_1 + : (arg > 0) ? sqrt(arg) : n_1; } - return ceil(fmax(K1, K2)); + return ceil(fmax(n_1, n_2)); } /** - * Calculate the 'erg' term and its sign for a wiener5 density or gradient + * Calculate the 'result' term and its sign for a wiener5 density or gradient * * @tparam Density Whether the calculation is for the density * @tparam GradW Whether the calculation is for gradient w.r.t. 'w' * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation - * @param wn The drift rate - * @param kss The kss term - * @param kll The kll term - * @return 'erg' sum and its sign + * @param w_value The relative starting point + * @param n_terms_small_t The n_terms_small_t term + * @param n_terms_large_t The n_terms_large_t term + * @return 'result' sum and its sign */ template -inline std::tuple wiener5_ergsign(double y, double a, double wn, - size_t kss, - size_t kll) noexcept { +inline std::tuple wiener5_log_sum_exp( + double y, double a, double w_value, size_t n_terms_small_t, + size_t n_terms_large_t) noexcept { const double y_asq = y / square(a); - const double w = 1.0 - wn; - const bool small_kss = Density ? (2 * kss <= kll) : (2 * kss < kll); - const double scaling = small_kss ? inv(2.0 * y_asq) : y_asq / 2.0; + const double w = 1.0 - w_value; + const bool small_n_terms_small_t + = Density ? (2 * n_terms_small_t <= n_terms_large_t) + : (2 * n_terms_small_t < n_terms_large_t); + const double scaling = small_n_terms_small_t ? inv(2.0 * y_asq) : y_asq / 2.0; double prev_val = NEGATIVE_INFTY; double current_val = NEGATIVE_INFTY; int prev_sign = 1; int current_sign = 1; - if (small_kss) { + if (small_n_terms_small_t) { const double mult = Density ? 1 : 3; const double offset = GradW ? y_asq : 0; const double sqrt_offset = sqrt(offset); - for (size_t k = kss; k >= 1; k--) { - const double wp2k = w + 2.0 * k; + for (size_t k = n_terms_small_t; k >= 1; k--) { + const double wp2k = w + 2.0 * k; const double wm2k = w - 2.0 * k; - int wp2k_sign = (wp2k > sqrt_offset) ? : 1 - 1; - int wm2k_sign = (wm2k > sqrt_offset) ? 1 : -1; - double wp2k_quant = GradW ? log( fabs((square(wp2k) - offset))) - - square(wp2k) * scaling : - mult * log(wp2k_sign * wp2k) - - square(wp2k) * scaling; - double wm2k_quant = GradW ? log( fabs((square(wm2k) - offset)) ) - - square(wm2k) * scaling : - mult * log(wm2k_sign * wm2k) - - square(wm2k) * scaling; + int wp2k_sign = (wp2k > sqrt_offset) ?: 1 - 1; + int wm2k_sign = (wm2k > sqrt_offset) ? 1 : -1; + double wp2k_quant + = GradW ? log(fabs((square(wp2k) - offset))) - square(wp2k) * scaling + : mult * log(wp2k_sign * wp2k) - square(wp2k) * scaling; + double wm2k_quant + = GradW ? log(fabs((square(wm2k) - offset))) - square(wm2k) * scaling + : mult * log(wm2k_sign * wm2k) - square(wm2k) * scaling; double k_term; int k_sign; std::forward_as_tuple(k_term, k_sign) = log_sum_exp_signed( - wm2k_quant, -1 * wm2k_sign, wp2k_quant, wp2k_sign); + wm2k_quant, -1 * wm2k_sign, wp2k_quant, wp2k_sign); std::forward_as_tuple(current_val, current_sign) = log_sum_exp_signed(k_term, k_sign, prev_val, prev_sign); prev_val = current_val; prev_sign = current_sign; } - double new_val = GradW ? log(fabs(square(w) - offset)) - square(w) * scaling : - mult*log(w)-square(w)*scaling; - int new_val_sign = GradW ? ( w > sqrt_offset ? 1 : -1) - : (new_val > 0 ? 1 : -1); - int factor_sign = GradW ? 1 : -1; - std::forward_as_tuple(current_val, current_sign) - = log_sum_exp_signed(new_val, factor_sign * new_val_sign, current_val, factor_sign * current_sign); + double new_val = GradW ? log(fabs(square(w) - offset)) - square(w) * scaling + : mult * log(w) - square(w) * scaling; + int new_val_sign + = GradW ? (w > sqrt_offset ? 1 : -1) : (new_val > 0 ? 1 : -1); + int factor_sign = GradW ? 1 : -1; + std::forward_as_tuple(current_val, current_sign) + = log_sum_exp_signed(new_val, factor_sign * new_val_sign, current_val, + factor_sign * current_sign); } else { double mult = 3; if (Density) { @@ -223,14 +228,14 @@ inline std::tuple wiener5_ergsign(double y, double a, double wn, } else if (GradW) { mult = 2; } - for (size_t k = kll; k >= 1; k--) { + for (size_t k = n_terms_large_t; k >= 1; k--) { const double pi_k = k * pi(); const double check = (GradW) ? cos(pi_k * w) : sin(pi_k * w); int check_sign = sign(check); - double kll_quant + double n_terms_large_t_quant = mult * log(k) - square(pi_k) * scaling + log(fabs(check)); - std::forward_as_tuple(current_val, current_sign) - = log_sum_exp_signed(prev_val, prev_sign, kll_quant, check_sign); + std::forward_as_tuple(current_val, current_sign) = log_sum_exp_signed( + prev_val, prev_sign, n_terms_large_t_quant, check_sign); prev_val = current_val; prev_sign = current_sign; } @@ -241,220 +246,251 @@ inline std::tuple wiener5_ergsign(double y, double a, double wn, /** * Calculate the wiener5 density * - * @tparam NaturalScale Whether to return the density on natural or log-scale + * @tparam NaturalScale Whether to return the density on natural (true) or + * log-scale (false) * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation - * @param vn The relative starting point - * @param wn The drift rate + * @param v_value The drift rate + * @param w_value The relative starting point * @param sv The inter-trial variability of the drift rate * @param err The log error tolerance * @return density */ template -inline double wiener5_density(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) noexcept { - const double lg1 = wiener5_lg1(y, a, vn, wn, sv); - const double es = (err - lg1); - const double kss = wiener5_kss(y, a, wn, es); - const double kll = wiener5_kll(y, a, wn, es); - - double erg; +inline double wiener5_density(double y, double a, double v_value, + double w_value, double sv, + double err = log(1e-12)) noexcept { + const double error_term + = wiener5_compute_error_term(y, a, v_value, w_value, sv); + const double error = (err - error_term); + const double n_terms_small_t + = wiener5_n_terms_small_t(y, a, w_value, error); + const double n_terms_large_t + = wiener5_n_terms_largel_t(y, a, w_value, error); + + double result; int newsign; - double ld; - std::forward_as_tuple(erg, newsign) - = wiener5_ergsign(y, a, wn, kss, kll); - if (2 * kss <= kll) { - ld = lg1 - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * (log(y) - 2 * log(a)) + erg; + double log_density; + std::forward_as_tuple(result, newsign) = wiener5_log_sum_exp( + y, a, w_value, n_terms_small_t, n_terms_large_t); + if (2 * n_terms_small_t <= n_terms_large_t) { + log_density = error_term - 0.5 * LOG_TWO - LOG_SQRT_PI + - 1.5 * (log(y) - 2 * log(a)) + result; } else { - ld = lg1 + erg + LOG_PI; + log_density = error_term + result + LOG_PI; } - return NaturalScale ? exp(ld) : ld; + return NaturalScale ? exp(log_density) : log_density; } /** * Calculate the derivative of the wiener5 density w.r.t. 't' * * @tparam WrtLog Whether to return the derivative w.r.t. - * the natural or log-scale density + * the natural (true) or log-scale (false) density * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation - * @param vn The relative starting point - * @param wn The drift rate + * @param v_value The drift rate + * @param w_value The relative starting point * @param sv The inter-trial variability of the drift rate * @param err The log error tolerance * @return Gradient w.r.t. t */ template -inline double grad_wiener5_t(double y, double a, double vn, double wn, +inline double grad_wiener5_t(double y, double a, double v_value, double w_value, double sv, double err = log(1e-12)) noexcept { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; - const double lg1 = wiener5_lg1(y, a, vn, wn, sv); - const double ans0 = wiener5_ans0(y, a, vn, wn, sv); - const double es = (err - lg1) + two_log_a; - - const double kss = wiener5_kss(y, a, wn, es); - const double kll = wiener5_kll(y, a, wn, es); - double erg; + const double error_term + = wiener5_compute_error_term(y, a, v_value, w_value, sv); + const double density_part_one + = wiener5_density_part_one(y, a, v_value, w_value, sv); + const double error = (err - error_term) + two_log_a; + + const double n_terms_small_t + = wiener5_n_terms_small_t(y, a, w_value, error); + const double n_terms_large_t + = wiener5_n_terms_largel_t(y, a, w_value, error); + double result; int newsign; - std::forward_as_tuple(erg, newsign) - = wiener5_ergsign(y, a, wn, kss, kll); + std::forward_as_tuple(result, newsign) = wiener5_log_sum_exp( + y, a, w_value, n_terms_small_t, n_terms_large_t); - const double ld_err = log(max(fabs(ans0 - 1.5 / y), fabs(ans0))); - const double ld = wiener5_density(y, a, vn, wn, sv, err - ld_err); + const double error_log_density + = log(max(fabs(density_part_one - 1.5 / y), fabs(density_part_one))); + const double log_density + = wiener5_density(y, a, v_value, w_value, sv, err - error_log_density); double ans; - if (2 * kss < kll) { - ans = ans0 - 1.5 / y + if (2 * n_terms_small_t < n_terms_large_t) { + ans = density_part_one - 1.5 / y + newsign - * exp(lg1 - two_log_a - 1.5 * LOG_TWO - LOG_SQRT_PI - - 3.5 * log_y_asq + erg - ld); + * exp(error_term - two_log_a - 1.5 * LOG_TWO - LOG_SQRT_PI + - 3.5 * log_y_asq + result - log_density); } else { - ans = ans0 - - newsign * exp(lg1 - two_log_a + 3.0 * LOG_PI - LOG_TWO + erg - ld); + ans = density_part_one + - newsign + * exp(error_term - two_log_a + 3.0 * LOG_PI - LOG_TWO + result + - log_density); } - return WrtLog ? ans * exp(ld) : ans; + return WrtLog ? ans * exp(log_density) : ans; } /** * Calculate the derivative of the wiener5 density w.r.t. 'a' * * @tparam WrtLog Whether to return the derivative w.r.t. - * the natural or log-scale density + * the natural (true) or log-scale (false) density * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation - * @param vn The relative starting point - * @param wn The drift rate + * @param v_value The drift rate + * @param w_value The relative starting point * @param sv The inter-trial variability of the drift rate * @param err The log error tolerance * @return Gradient w.r.t. a */ template -inline double grad_wiener5_a(double y, double a, double vn, double wn, +inline double grad_wiener5_a(double y, double a, double v_value, double w_value, double sv, double err = log(1e-12)) noexcept { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; - const double lg1 = wiener5_lg1(y, a, vn, wn, sv); - const double ans0 = wiener5_ans0(y, a, vn, wn, sv); - const double es = err - lg1 + 3*log(a) - log(y) - LOG_TWO; - - const double kss = wiener5_kss(y, a, wn, es); - const double kll = wiener5_kll(y, a, wn, es); - double erg; + const double error_term + = wiener5_compute_error_term(y, a, v_value, w_value, sv); + const double density_part_one + = wiener5_density_part_one(y, a, v_value, w_value, sv); + const double error = err - error_term + 3 * log(a) - log(y) - LOG_TWO; + + const double n_terms_small_t + = wiener5_n_terms_small_t(y, a, w_value, error); + const double n_terms_large_t + = wiener5_n_terms_largel_t(y, a, w_value, error); + double result; int newsign; - std::forward_as_tuple(erg, newsign) - = wiener5_ergsign(y, a, wn, kss, kll); + std::forward_as_tuple(result, newsign) = wiener5_log_sum_exp( + y, a, w_value, n_terms_small_t, n_terms_large_t); - const double ld_err = log(max(fabs(ans0 + 1.0 / a), fabs(ans0 - 2.0 / a))); - const double ld = wiener5_density(y, a, vn, wn, sv, err - ld_err); + const double error_log_density = log( + max(fabs(density_part_one + 1.0 / a), fabs(density_part_one - 2.0 / a))); + const double log_density + = wiener5_density(y, a, v_value, w_value, sv, err - error_log_density); double ans; - if (2 * kss < kll) { - ans = ans0 + 1.0 / a + if (2 * n_terms_small_t < n_terms_large_t) { + ans = density_part_one + 1.0 / a - newsign * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * log(y) - + 2.0 * two_log_a + lg1 + erg - ld); + + 2.0 * two_log_a + error_term + result - log_density); } else { - ans = ans0 - 2.0 / a - + newsign * exp(log(y) + lg1 - 3 * (log(a) - LOG_PI) + erg - ld); + ans = density_part_one - 2.0 / a + + newsign + * exp(log(y) + error_term - 3 * (log(a) - LOG_PI) + result + - log_density); } - return WrtLog ? ans * exp(ld) : ans; + return WrtLog ? ans * exp(log_density) : ans; } /** * Calculate the derivative of the wiener5 density w.r.t. 'v' * * @tparam WrtLog Whether to return the derivative w.r.t. - * the natural or log-scale density + * the natural (true) or log-scale (false) density * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation - * @param vn The relative starting point - * @param wn The drift rate + * @param v_value The drift rate + * @param w_value The relative starting point * @param sv The inter-trial variability of the drift rate * @param err The log error tolerance * @return Gradient w.r.t. v */ template -inline double grad_wiener5_v(double y, double a, double vn, double wn, +inline double grad_wiener5_v(double y, double a, double v_value, double w_value, double sv, double err = log(1e-12)) noexcept { - double ans = (a * (1 - wn) - vn * y); + double ans = (a * (1 - w_value) - v_value * y); if (sv != 0) { ans /= 1 + square(sv) * y; } - return WrtLog ? ans * wiener5_density(y, a, vn, wn, sv, err) : ans; + return WrtLog ? ans * wiener5_density(y, a, v_value, w_value, sv, err) + : ans; } /** * Calculate the derivative of the wiener5 density w.r.t. 'w' * * @tparam WrtLog Whether to return the derivative w.r.t. - * the natural or log-scale density + * the natural (true) or log-scale (false) density * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation - * @param vn The relative starting point - * @param wn The drift rate + * @param v_value The drift rate + * @param w_value The relative starting point * @param sv The inter-trial variability of the drift rate * @param err The log error tolerance * @return Gradient w.r.t. w */ template -inline double grad_wiener5_w(double y, double a, double vn, double wn, +inline double grad_wiener5_w(double y, double a, double v_value, double w_value, double sv, double err = log(1e-12)) noexcept { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; - const double lg1 = wiener5_lg1(y, a, vn, wn, sv); - const double ans0 = wiener5_ans0(y, a, vn, wn, sv); - const double es = (err - lg1); - - const double kss = wiener5_kss(y, a, wn, es); - const double kll = wiener5_kll(y, a, wn, es); - double erg; + const double error_term + = wiener5_compute_error_term(y, a, v_value, w_value, sv); + const double density_part_one + = wiener5_density_part_one(y, a, v_value, w_value, sv); + const double error = (err - error_term); + + const double n_terms_small_t + = wiener5_n_terms_small_t(y, a, w_value, error); + const double n_terms_large_t + = wiener5_n_terms_largel_t(y, a, w_value, error); + double result; int newsign; - std::forward_as_tuple(erg, newsign) - = wiener5_ergsign(y, a, wn, kss, kll); + std::forward_as_tuple(result, newsign) = wiener5_log_sum_exp( + y, a, w_value, n_terms_small_t, n_terms_large_t); - const double ld = wiener5_density(y, a, vn, wn, sv, err - log(fabs(ans0))); + const double log_density = wiener5_density(y, a, v_value, w_value, sv, + err - log(fabs(density_part_one))); double ans; - if (2 * kss < kll) { - ans = -(ans0 + if (2 * n_terms_small_t < n_terms_large_t) { + ans = -(density_part_one - newsign - * exp(erg - (ld - lg1) - 2.5 * log_y_asq - 0.5 * LOG_TWO - - 0.5 * LOG_PI)); + * exp(result - (log_density - error_term) - 2.5 * log_y_asq + - 0.5 * LOG_TWO - 0.5 * LOG_PI)); } else { - ans = -(ans0 + newsign * exp(erg - (ld - lg1) + 2 * LOG_PI)); + ans = -(density_part_one + + newsign * exp(result - (log_density - error_term) + 2 * LOG_PI)); } - return WrtLog ? ans * exp(ld) : ans; + return WrtLog ? ans * exp(log_density) : ans; } /** * Calculate the derivative of the wiener5 density w.r.t. 'sv' * * @tparam WrtLog Whether to return the derivative w.r.t. - * the natural or log-scale density + * the natural (true) or log-scale (false) density * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation - * @param vn The relative starting point - * @param wn The drift rate + * @param v_value The drift rate + * @param w_value The relative starting point * @param sv The inter-trial variability of the drift rate * @param err The log error tolerance * @return Gradient w.r.t. sv */ template -inline double grad_wiener5_sv(double y, double a, double vn, double wn, - double sv, double err = log(1e-12)) noexcept { +inline double grad_wiener5_sv(double y, double a, double v_value, + double w_value, double sv, + double err = log(1e-12)) noexcept { const double one_plus_svsqr_y = 1 + square(sv) * y; - const double w = 1.0 - wn; - const double v = -vn; + const double w = 1.0 - w_value; + const double v = -v_value; const double t1 = -y / one_plus_svsqr_y; const double t2 = (square(a * w) + 2 * a * v * w * y + square(v * y)) - / square(one_plus_svsqr_y); + / square(one_plus_svsqr_y); const double ans = sv * (t1 + t2); - return WrtLog ? ans * wiener5_density(y, a, vn, wn, sv, err) : ans; + return WrtLog ? ans * wiener5_density(y, a, v_value, w_value, sv, err) + : ans; } /** @@ -489,20 +525,20 @@ inline void assign_err(std::tuple& args_tuple, double err) { * @param args_tuple Tuple of arguments to pass to functor * @param log_result Whether the function result is already on the log-scale */ -template +template double estimate_with_err_check(const F& functor, double err, ArgsTupleT&& args_tuple, bool log_result = true) { double result = math::apply([&](auto&&... args) { return functor(args...); }, args_tuple); - double lfabs_result = log_result ? log(fabs(result)) : fabs(result); - if (lfabs_result < err) { - lfabs_result = std::isinf(lfabs_result) ? 0 : lfabs_result; + double log_fabs_result = log_result ? log(fabs(result)) : fabs(result); + if (log_fabs_result < err) { + log_fabs_result = std::isinf(log_fabs_result) ? 0 : log_fabs_result; ArgsTupleT err_args_tuple = args_tuple; - const double new_error = GradW7 ? err + lfabs_result + LOG_TWO : err + lfabs_result; - assign_err(std::get(err_args_tuple), - new_error); + const double new_error + = GradW7 ? err + log_fabs_result + LOG_TWO : err + log_fabs_result; + assign_err(std::get(err_args_tuple), new_error); result = math::apply([&](auto&&... args) { return functor(args...); }, err_args_tuple); } @@ -527,7 +563,7 @@ double estimate_with_err_check(const F& functor, double err, * @param w The relative starting point * @param v The drift rate * @param sv The inter-trial variability of the drift rate - * @param prec Level of precision in estimation + * @param precision_derivatives Level of precision in estimation * @return The log of the Wiener first passage time density with * the specified arguments for upper boundary responses */ @@ -535,7 +571,7 @@ template inline return_type_t wiener5_lpdf( const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, - const T_sv& sv, const double& prec) { + const T_sv& sv, const double& precision_derivatives) { using T_y_ref = ref_type_t; using T_a_ref = ref_type_t; using T_t0_ref = ref_type_t; @@ -602,11 +638,11 @@ inline return_type_t wiener5_lpdf( } } - const double lerror_bound_dens = log(1e-6); // precision for density - const double lerror_bound = log(prec); // precision for derivatives - const double labstol_wiener5 = log(1e-12); // eps_abs(wiener5) - double dens = 0.0; - double ld = 0.0; + const double log_error_density = log(1e-6); + const double log_error_derivative = log(precision_derivatives); + const double log_error_absolute = log(1e-12); + double density = 0.0; + double log_density = 0.0; operands_and_partials ops_partials(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref); @@ -625,14 +661,14 @@ inline return_type_t wiener5_lpdf( const double sv_val = sv_vec.val(i); const auto params = std::make_tuple(y_val - t0_val, a_val, v_val, w_val, - sv_val, labstol_wiener5); + sv_val, log_error_absolute); - dens = internal::estimate_with_err_check<5>( + density = internal::estimate_with_err_check<5>( [&](auto&&... args) { return internal::wiener5_density(args...); }, - lerror_bound_dens - LOG_TWO, params, false); - ld += dens; + log_error_density - LOG_TWO, params, false); + log_density += density; - const double new_est_err = dens + lerror_bound - LOG_FOUR; + const double new_est_err = density + log_error_derivative - LOG_FOUR; // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 @@ -666,7 +702,7 @@ inline return_type_t wiener5_lpdf( y_val - t0_val, a_val, v_val, w_val, sv_val); } } // end for loop - return ops_partials.build(ld); + return ops_partials.build(log_density); } // end wiener5_lpdf } // namespace math } // namespace stan diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index a53620ad841..36092d16592 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -18,19 +18,20 @@ namespace internal { * @param w The relative starting point * @param sv The inter-trial variability of the drift rate * @param sw The inter-trial variability of the relative starting point - * @param lerr The log error tolerance + * @param log_error The log error tolerance * @return Gradient w.r.t. sw */ inline double grad_wiener7_sw(double y, double a, double v, double w, double sv, - double sw, double lerr) { + double sw, double log_error) { double low = w - sw / 2.0; low = (0 > low) ? 0 : low; double high = w + sw / 2.0; high = (1 < high) ? 1 : high; - const double fl = wiener5_density(y, a, v, low, sv, lerr); - const double fu = wiener5_density(y, a, v, high, sv, lerr); - return 0.5 * (fl + fu) / sw; + const double lower_value = wiener5_density(y, a, v, low, sv, log_error); + const double upper_value + = wiener5_density(y, a, v, high, sv, log_error); + return 0.5 * (lower_value + upper_value) / sw; } /** @@ -52,14 +53,14 @@ inline double grad_wiener7_sw(double y, double a, double v, double w, double sv, * @param sv The inter-trial variability of the drift rate * @param sw The inter-trial variability of the relative starting point * @param st0 The inter-trial variability of the non-decision time - * @param lerr The log error tolerance + * @param log_error The log error tolerance * @return Functor applied to arguments */ template * = nullptr> inline double call_wiener7_function(const F& functor, double y, double a, double v, double w, double t0, double sv, - double sw, double lerr) { - return functor(y - t0, a, v, w, sv, lerr); + double sw, double log_error) { + return functor(y - t0, a, v, w, sv, log_error); } /** @@ -81,14 +82,14 @@ inline double call_wiener7_function(const F& functor, double y, double a, * @param sv The inter-trial variability of the drift rate * @param sw The inter-trial variability of the relative starting point * @param st0 The inter-trial variability of the non-decision time - * @param lerr The log error tolerance + * @param log_error The log error tolerance * @return Functor applied to arguments */ template * = nullptr> inline double call_wiener7_function(const F& functor, double y, double a, double v, double w, double t0, double sv, - double sw, double lerr) { - return functor(y - t0, a, v, w, sv, sw, lerr); + double sw, double log_error) { + return functor(y - t0, a, v, w, sv, sw, log_error); } /** @@ -105,29 +106,30 @@ inline double call_wiener7_function(const F& functor, double y, double a, * @param args Additional arguments to be passed to the hcubature function * @return Wiener7 density or gradient calculated by integration */ -template //added GradW7 +template auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, double hcubature_err, TArgs&&... args) { const auto& wiener7_integrand_impl = [&](std::vector x, double y, double a, double v, double w, - double t0, double sv, double sw, double st0, double lerr) { + double t0, double sv, double sw, double st0, double log_error) { scalar_seq_view x_vec(x); - const double sw_val = GradSW ? 0 : sw; - const double omega = sw_val ? w + sw_val * (x_vec[0] - 0.5) : w; - const double t0_ = sw_val ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); - if (y - t0_ <= 0) { + const double sw_val = GradSW ? 0 : sw; + const double new_w = sw_val ? w + sw_val * (x_vec[0] - 0.5) : w; + const double new_t0 = sw_val ? (st0 ? t0 + st0 * x_vec[1] : t0) + : (st0 ? t0 + st0 * x_vec[0] : t0); + if (y - new_t0 <= 0) { return 0.0; } else { - return call_wiener7_function(wiener7_functor, y, a, v, - omega, t0_, sv, sw, lerr); + return call_wiener7_function( + wiener7_functor, y, a, v, new_w, new_t0, sv, sw, log_error); } }; const auto& functor = [&](auto&&... int_args) { return hcubature(wiener7_integrand_impl, int_args...); }; return estimate_with_err_check<0, GradW7, 8>(functor, hcubature_err, - std::make_tuple(args...)); + std::make_tuple(args...)); } } // namespace internal @@ -172,7 +174,7 @@ auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, * which are selected depending on the number of components \f$k\f$, needed to * guarantee a certain precision. * - * Note that the parametrization for non-decision time and relative starting + * Note that the parameterization for non-decision time and relative starting point is as follows: * \c t0 is the lower bound of the variability interval; * \c w is the mean of the variability interval. @@ -180,7 +182,7 @@ auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, * See \b Details below for more details on how to use \c wiener_full_lpdf(). * * @tparam T_y type of scalar - * @tparam T_a type of boundary + * @tparam T_a type of boundary separation * @tparam T_t0 type of non-decision time * @tparam T_w type of relative starting point * @tparam T_v type of drift rate @@ -196,7 +198,8 @@ auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, * @param sv The inter-trial variability of the drift rate * @param sw The inter-trial variability of the relative starting point * @param st0 The inter-trial variability of the non-decision time - * @param prec Level of precision in estimation + * @param precision_derivatives Level of precision in estimation of partial + derivatives * @return The log of the Wiener first passage time density with * the specified arguments for upper boundary responses * @throw std::domain_error if non-decision time \c t0 is greater than reaction @@ -280,7 +283,7 @@ template ; using T_a_ref = ref_type_t; using T_v_ref = ref_type_t; @@ -388,16 +391,17 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, return 0; } - const double lerror_bound_dens = log(1e-6); // precision for density - const double error_bound = prec; // precision for + const double log_error_density = log(1e-6); // precision for density + const double error_bound = precision_derivatives; // precision for // derivatives (controllable by user) - const double lerror_bound = log(error_bound); - const double abstol = 0.0; - const double reltol = .9 * error_bound; // eps_rel(Integration) - const double labstol_wiener5 = log(1e-12); - const int Meval = 6000; - double dens = 0.0; - double ld = 0.0; + const double log_error_derivative = log(error_bound); + const double absolute_error_hcubature = 0.0; + const double relative_error_hcubature + = .9 * error_bound; // eps_rel(Integration) + const double log_error_absolute = log(1e-12); + const int maximal_evaluations_hcubature = 6000; + double density = 0.0; + double log_density = 0.0; operands_and_partials ops_partials(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref, sw_ref, st0_ref); @@ -406,8 +410,9 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, // calculate density and partials for (size_t i = 0; i < N; i++) { if (sw_vec[i] == 0 && st0_vec[i] == 0) { - result += wiener5_lpdf(y_vec[i], a_vec[i], t0_vec[i], w_vec[i], - v_vec[i], sv_vec[i], prec); + result + += wiener5_lpdf(y_vec[i], a_vec[i], t0_vec[i], w_vec[i], + v_vec[i], sv_vec[i], precision_derivatives); continue; } const double y_val = y_vec.val(i); @@ -420,7 +425,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const double st0_val = st0_vec.val(i); const auto params = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, - st0_val, labstol_wiener5 - LOG_TWO); + st0_val, log_error_absolute - LOG_TWO); const int dim = (sw_val != 0) + (st0_val != 0); check_positive(function_name, "(Inter-trial variability in A-priori bias) + " @@ -433,17 +438,19 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); } - double hcubature_err = labstol_wiener5 - lerror_bound_dens + LOG_TWO + 1; + double hcubature_err = log_error_absolute - log_error_density + LOG_TWO + 1; - dens = internal::wiener7_integrate( + density = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_density(args...); }, - hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2); - const double log_dens = log(dens); - ld += log_dens; + hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, + absolute_error_hcubature, relative_error_hcubature / 2); + const double log_dens = log(density); + log_density += log_dens; - hcubature_err = labstol_wiener5 - lerror_bound + log(fabs(dens)) + LOG_TWO + 1; + hcubature_err = log_error_absolute - log_error_derivative + + log(fabs(density)) + LOG_TWO + 1; // computation of derivative for t and precision check in order to give // the value as deriv_t to edge1 and as -deriv_t to edge5 @@ -452,11 +459,13 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, [&](auto&&... args) { return internal::grad_wiener5_t(args...); }, - hcubature_err, params, dim, xmin, xmax, Meval, abstol, reltol / 2) - / dens; + hcubature_err, params, dim, xmin, xmax, + maximal_evaluations_hcubature, absolute_error_hcubature, + relative_error_hcubature / 2) + / density; // computation of derivatives and precision checks - double deriv; + double derivative; if (!is_constant_all::value) { ops_partials.edge1_.partials_[i] = deriv_t_7; } @@ -466,9 +475,10 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, [&](auto&&... args) { return internal::grad_wiener5_a(args...); }, - hcubature_err, params, dim, xmin, xmax, Meval, abstol, - reltol / 2) - / dens; + hcubature_err, params, dim, xmin, xmax, + maximal_evaluations_hcubature, absolute_error_hcubature, + relative_error_hcubature / 2) + / density; } if (!is_constant_all::value) { ops_partials.edge3_.partials_[i] = -deriv_t_7; @@ -479,9 +489,10 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, [&](auto&&... args) { return internal::grad_wiener5_w(args...); }, - hcubature_err, params, dim, xmin, xmax, Meval, abstol, - reltol / 2) - / dens; + hcubature_err, params, dim, xmin, xmax, + maximal_evaluations_hcubature, absolute_error_hcubature, + relative_error_hcubature / 2) + / density; } if (!is_constant_all::value) { ops_partials.edge5_.partials_[i] @@ -489,9 +500,10 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, [&](auto&&... args) { return internal::grad_wiener5_v(args...); }, - hcubature_err, params, dim, xmin, xmax, Meval, abstol, - reltol / 2) - / dens; + hcubature_err, params, dim, xmin, xmax, + maximal_evaluations_hcubature, absolute_error_hcubature, + relative_error_hcubature / 2) + / density; } if (!is_constant_all::value) { ops_partials.edge6_.partials_[i] @@ -499,9 +511,10 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, [&](auto&&... args) { return internal::grad_wiener5_sv(args...); }, - hcubature_err, params, dim, xmin, xmax, Meval, abstol, - reltol / 2) - / dens; + hcubature_err, params, dim, xmin, xmax, + maximal_evaluations_hcubature, absolute_error_hcubature, + relative_error_hcubature / 2) + / density; } if (!is_constant_all::value) { if (sw_val == 0) { @@ -510,21 +523,23 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, if (st0_val == 0) { const auto sw_params = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, - sw_val, labstol_wiener5 - LOG_TWO); - deriv = internal::estimate_with_err_check<5>( + sw_val, log_error_absolute - LOG_TWO); + derivative = internal::estimate_with_err_check<5>( [&](auto&&... args) { return internal::call_wiener7_function( internal::grad_wiener7_sw, args...); }, hcubature_err, sw_params); } else { - deriv = internal::wiener7_integrate( + derivative = internal::wiener7_integrate( [&](auto&&... args) { return internal::grad_wiener7_sw(args...); }, - hcubature_err, params, 1, xmin, xmax, Meval, abstol, reltol / 2); + hcubature_err, params, 1, xmin, xmax, + maximal_evaluations_hcubature, absolute_error_hcubature, + relative_error_hcubature / 2); } - ops_partials.edge7_.partials_[i] = deriv / dens - 1 / sw_val; + ops_partials.edge7_.partials_[i] = derivative / density - 1 / sw_val; } } if (!is_constant_all::value) { @@ -538,31 +553,32 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, if (sw_val == 0) { const auto st_params = std::make_tuple(y_val, a_val, v_val, w_val, t0_st0, sv_val, - sw_val, labstol_wiener5 - LOG_TWO); + sw_val, log_error_absolute - LOG_TWO); f = internal::estimate_with_err_check<5>( [&](auto&&... args) { return internal::call_wiener7_function( internal::wiener5_density, args...); }, - lerror_bound + log(st0_val), st_params); + log_error_derivative + log(st0_val), st_params); } else { - const double new_error = labstol_wiener5 - LOG_TWO; + const double new_error = log_error_absolute - LOG_TWO; const auto& params_st = std::make_tuple( y_val, a_val, v_val, w_val, t0_st0, sv_val, sw_val, 0, new_error); f = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_density(args...); }, - hcubature_err, params_st, 1, xmin, xmax, Meval, abstol, - reltol / 2); + hcubature_err, params_st, 1, xmin, xmax, + maximal_evaluations_hcubature, absolute_error_hcubature, + relative_error_hcubature / 2); } - ops_partials.edge8_.partials_[i] = -1 / st0_val + f / st0_val / dens; + ops_partials.edge8_.partials_[i] = -1 / st0_val + f / st0_val / density; } } std::vector().swap(xmin); std::vector().swap(xmax); } - return result + ops_partials.build(ld); + return result + ops_partials.build(log_density); } } // namespace math } // namespace stan From 212c0788d4de567ca190cc50098919759730cfba Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Wed, 26 Jul 2023 11:25:40 +0200 Subject: [PATCH 069/179] changes hcubature --- stan/math/prim/functor/hcubature.hpp | 121 +++++++++++++++------------ 1 file changed, 67 insertions(+), 54 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index cd8fbe47cc3..2d666c6c3a8 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -63,21 +63,27 @@ static constexpr double gwd7[4] = {1.2948496616886969327061143267787e-01, * Vol. 3, No. 2, June 1977. User lucaroni from * https://stackoverflow.com/questions/561/how-to-use-combinations-of-sets-as-test-data#794 * - * @param c output vector + * @param[out] c output vector * @param dim dimension * @param p number of elements * @param x x-th lexicographically ordered set */ inline void combination(Eigen::VectorXi& c, const int dim, const int p, const int x) { - size_t r, k = 0; - for (std::size_t i = 0; i < p - 1; i++) { - c[i] = (i != 0) ? c[i - 1] : 0; - do { + int r = 0; + int k = 0; + c[0] = 0; + for (;k < x; k = k + r) { + c[0]++; + r = choose(dim - c[0], p - 1); + } + k = k - r; + for (int i = 1; i < p - 1; i++) { + c[i] = c[i - 1]; + for (;k < x; k = k + r) { c[i]++; r = choose(dim - c[i], p - (i + 1)); - k = k + r; - } while (k < x); + }; k = k - r; } if (p > 1) { @@ -91,13 +97,13 @@ inline void combination(Eigen::VectorXi& c, const int dim, const int p, * Compute a vector [p] of all [dim]-component vectors * with [k] components equal to [lambda] and other components equal to zero. * + * @param[in,out] p vector of vectors * @param k number of components equal to lambda * @param lambda scalar * @param dim dimension - * @param p vector of vectors */ -inline void combos(const int k, const double lambda, const int dim, - Eigen::MatrixXd& p) { +inline void combos(Eigen::MatrixXd& p, const int k, const double lambda, + const int dim) { Eigen::VectorXi c(k); const auto choose_dimk = choose(dim, k); p = Eigen::MatrixXd::Zero(dim, choose_dimk); @@ -110,13 +116,16 @@ inline void combos(const int k, const double lambda, const int dim, } /** - * Helper function for signcombos + * Helper function for signcombos. Create vector temp with k components equal + * to [±lambda] and other components equal to zero (with all possible signs), + * depending on the input vector inp. * - * @param index helper vector + * @param index boolsher helper vector to walk through temp, remembers which + * positions already were considered * @param k number of components equal to lambda * @param lambda scalar * @param c ordered vector - * @param inp Input vector to be incremented + * @param[in] inp Input vector to be incremented */ inline Eigen::VectorXd increment(std::vector& index, const int k, const double lambda, const Eigen::VectorXi& c, @@ -124,7 +133,7 @@ inline Eigen::VectorXd increment(std::vector& index, const int k, Eigen::VectorXd temp = inp; if (index.size() == 0) { index.push_back(false); - for (std::size_t j = 0; j != k; j++) { + for (int j = 0; j != k; j++) { temp[c[j] - 1] = lambda; } return temp; @@ -135,13 +144,13 @@ inline Eigen::VectorXd increment(std::vector& index, const int k, } if (first_zero == index.size()) { index.flip(); - for (std::size_t j = 0; j != index.size(); j++) { + for (int j = 0; j != index.size(); j++) { temp[c[j] - 1] *= -1; } index.push_back(true); temp[c[index.size() - 1] - 1] = -lambda; } else { - for (std::size_t i = 0; i != first_zero + 1; i++) { + for (int i = 0; i != first_zero + 1; i++) { if (index[i]) { index[i] = 0; } else { @@ -158,24 +167,23 @@ inline Eigen::VectorXd increment(std::vector& index, const int k, * with [k] components equal to [±lambda] and other components equal to zero * (with all possible signs). * + * @param[in,out] p vector of vectors * @param k number of components equal to lambda * @param lambda scalar * @param dim dimension - * @param p vector of vectors */ -inline void signcombos(const int k, const double lambda, const int dim, - Eigen::MatrixXd& p) { +inline void signcombos(Eigen::MatrixXd& p, const int k, const double lambda, + const int dim) { Eigen::VectorXi c(k); const auto choose_dimk = choose(dim, k); p.resize(dim, choose_dimk * std::pow(2, k)); p.setZero(); int current_col = 0; - for (std::size_t i = 1; i != choose_dimk + 1; i++) { + for (int i = 1; i != choose_dimk + 1; i++) { combination(c, dim, k, i); std::vector index; - index.clear(); - for (std::size_t j = 0; j != std::pow(2, k); j++) { - size_t prev_col = j == 0 ? current_col : current_col - 1; + for (int j = 0; j != std::pow(2, k); j++) { + int prev_col = (j == 0) ? current_col : current_col - 1; p.col(current_col) = increment(index, k, lambda, c, p.col(prev_col)); current_col += 1; } @@ -187,17 +195,17 @@ inline void signcombos(const int k, const double lambda, const int dim, * for one dimension. * * @tparam F type of the integrand - * @tparam ParsTupleT type of the tuple of parameters for the integrand + * @tparam ParsPairT type of the pair of parameters for the integrand * @param integrand function to be integrated * @param a lower limit of integration * @param b upper limit of integration - * @param pars_tuple Tuple of parameters for the integrand + * @param pars_pair Pair of parameters for the integrand * @return numeric integral of the integrand and error */ -template -std::tuple gauss_kronrod(const F& integrand, const double a, +template +std::pair gauss_kronrod(const F& integrand, const double a, const double b, - const ParsTupleT& pars_tuple) { + const ParsPairT& pars_pair) { std::vector c(1, 0); std::vector cp(1, 0); std::vector cm(1, 0); @@ -205,7 +213,7 @@ std::tuple gauss_kronrod(const F& integrand, const double a, double delta = 0.5 * (b - a); double f0 = math::apply( [&integrand, &c](auto&&... args) { return integrand(c, args...); }, - pars_tuple); + pars_pair); double I = f0 * wd7[7]; double Idash = f0 * gwd7[3]; @@ -215,10 +223,10 @@ std::tuple gauss_kronrod(const F& integrand, const double a, cm[0] = c[0] - deltax; double fx = math::apply( [&integrand, &cp](auto&&... args) { return integrand(cp, args...); }, - pars_tuple); + pars_pair); double temp = math::apply( [&integrand, &cm](auto&&... args) { return integrand(cm, args...); }, - pars_tuple); + pars_pair); fx += temp; I += fx * wd7[i]; if (i % 2 == 1) { @@ -228,20 +236,23 @@ std::tuple gauss_kronrod(const F& integrand, const double a, double V = fabs(delta); I *= V; Idash *= V; - return std::make_tuple(I, fabs(I - Idash)); + return std::make_pair(I, fabs(I - Idash)); } /** * Compute the points and weights corresponding to a [dim]-dimensional * Genz-Malik cubature rule * + * @param[in,out] p points for the last 4 GenzMalik weights + * @param[in,out] w weights for the 5 terms in the GenzMalik rule + * @param[in,out] wd weights for the embedded lower-degree rule * @param dim dimension - * @param p points for the last 4 GenzMalik weights - * @param w weights for the 5 terms in the GenzMalik rule - * @param wd weights for the embedded lower-degree rule */ -inline void make_GenzMalik(const int dim, std::vector& p, - std::vector& w, std::vector& wd) { +inline std::tuple, Eigen::VectorXd, + Eigen::VectorXd> make_GenzMalik(const int dim) { + std::vector p(4); + Eigen::VectorXd w(5); + Eigen::VectorXd wd(4); double l4 = std::sqrt(9 * 1.0 / 10); double l2 = std::sqrt(9 * 1.0 / 70); double l3 = l4; @@ -259,10 +270,11 @@ inline void make_GenzMalik(const int dim, std::vector& p, wd[1] = twopn * (245.0 / 486); wd[0] = twopn * ((729 - 950 * dim + 50 * dim * dim) * 1.0 / 729); - combos(1, l2, dim, p[0]); - combos(1, l3, dim, p[1]); - signcombos(2, l4, dim, p[2]); - signcombos(dim, l5, dim, p[3]); + combos(p[0], 1, l2, dim); + combos(p[1], 1, l3, dim); + signcombos(p[2], 2, l4, dim); + signcombos(p[3], dim, l5, dim); + return std::make_tuple(p, w, wd); } /** @@ -271,10 +283,10 @@ inline void make_GenzMalik(const int dim, std::vector& p, * * @tparam F type of the integrand * @tparam ParsTupleT type of the tuple of parameters for the integrand - * @param integrand function to be integrated - * @param p - * @param w - * @param wd + * @param[out] integrand function to be integrated + * @param[in] p + * @param[in] w + * @param[in] wd * @param dim dimension of the multidimensional integral * @param a lower limit of integration * @param b upper limit of integration @@ -284,8 +296,8 @@ inline void make_GenzMalik(const int dim, std::vector& p, */ template std::tuple integrate_GenzMalik( - const F& integrand, std::vector& p, std::vector& w, - std::vector& wd, const int dim, const std::vector& a, + std::vector& p, Eigen::VectorXd& w, + Eigen::VectorXd& wd, const F& integrand, const int dim, const std::vector& a, const std::vector& b, const ParsTupleT& pars_tuple) { std::vector c(dim, 0); std::vector deltac(dim, 0); @@ -472,20 +484,21 @@ double hcubature(const F& integrand, const ParsTuple& pars, const int dim, maxEval = 1000000; } - double result, err; + double result; + double err; int kdivide = 0; std::vector p(4); - std::vector w_five(5); - std::vector wd_four(4); + Eigen::VectorXd w_five(5); + Eigen::VectorXd wd_four(4); if (dim == 1) { std::tie(result, err) = internal::gauss_kronrod(integrand, a[0], b[0], pars); } else { - internal::make_GenzMalik(dim, p, w_five, wd_four); + std::tie(p, w_five, wd_four) = internal::make_GenzMalik(dim); std::tie(result, err, kdivide) = internal::integrate_GenzMalik( - integrand, p, w_five, wd_four, dim, a, b, pars); + p, w_five, wd_four, integrand, dim, a, b, pars); } int numevals = (dim == 1) ? 15 : 1 + 4 * dim + 2 * dim * (dim - 1) + std::pow(2, dim); @@ -525,9 +538,9 @@ double hcubature(const F& integrand, const ParsTuple& pars, const int dim, = internal::gauss_kronrod(integrand, box.a[0], mb[0], pars); } else { std::tie(result_1, err_1, kdivide_1) = internal::integrate_GenzMalik( - integrand, p, w_five, wd_four, dim, ma, box.b, pars); + p, w_five, wd_four, integrand, dim, ma, box.b, pars); std::tie(result_2, err_2, kdivide_2) = internal::integrate_GenzMalik( - integrand, p, w_five, wd_four, dim, box.a, mb, pars); + p, w_five, wd_four, integrand, dim, box.a, mb, pars); } internal::Box box1(ma, box.b, result_1, err_1, kdivide_1); ms.push(box1); From ea7d2af9e6a262333608fccbc60997266f397ffb Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 26 Jul 2023 05:27:21 -0400 Subject: [PATCH 070/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/functor/hcubature.hpp | 29 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 2d666c6c3a8..ed072d97128 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -73,14 +73,14 @@ inline void combination(Eigen::VectorXi& c, const int dim, const int p, int r = 0; int k = 0; c[0] = 0; - for (;k < x; k = k + r) { - c[0]++; - r = choose(dim - c[0], p - 1); + for (; k < x; k = k + r) { + c[0]++; + r = choose(dim - c[0], p - 1); } k = k - r; for (int i = 1; i < p - 1; i++) { c[i] = c[i - 1]; - for (;k < x; k = k + r) { + for (; k < x; k = k + r) { c[i]++; r = choose(dim - c[i], p - (i + 1)); }; @@ -102,8 +102,8 @@ inline void combination(Eigen::VectorXi& c, const int dim, const int p, * @param lambda scalar * @param dim dimension */ -inline void combos(Eigen::MatrixXd& p, const int k, const double lambda, - const int dim) { +inline void combos(Eigen::MatrixXd& p, const int k, const double lambda, + const int dim) { Eigen::VectorXi c(k); const auto choose_dimk = choose(dim, k); p = Eigen::MatrixXd::Zero(dim, choose_dimk); @@ -172,8 +172,8 @@ inline Eigen::VectorXd increment(std::vector& index, const int k, * @param lambda scalar * @param dim dimension */ -inline void signcombos(Eigen::MatrixXd& p, const int k, const double lambda, - const int dim) { +inline void signcombos(Eigen::MatrixXd& p, const int k, const double lambda, + const int dim) { Eigen::VectorXi c(k); const auto choose_dimk = choose(dim, k); p.resize(dim, choose_dimk * std::pow(2, k)); @@ -204,8 +204,8 @@ inline void signcombos(Eigen::MatrixXd& p, const int k, const double lambda, */ template std::pair gauss_kronrod(const F& integrand, const double a, - const double b, - const ParsPairT& pars_pair) { + const double b, + const ParsPairT& pars_pair) { std::vector c(1, 0); std::vector cp(1, 0); std::vector cm(1, 0); @@ -248,8 +248,9 @@ std::pair gauss_kronrod(const F& integrand, const double a, * @param[in,out] wd weights for the embedded lower-degree rule * @param dim dimension */ -inline std::tuple, Eigen::VectorXd, - Eigen::VectorXd> make_GenzMalik(const int dim) { +inline std::tuple, Eigen::VectorXd, + Eigen::VectorXd> +make_GenzMalik(const int dim) { std::vector p(4); Eigen::VectorXd w(5); Eigen::VectorXd wd(4); @@ -296,8 +297,8 @@ inline std::tuple, Eigen::VectorXd, */ template std::tuple integrate_GenzMalik( - std::vector& p, Eigen::VectorXd& w, - Eigen::VectorXd& wd, const F& integrand, const int dim, const std::vector& a, + std::vector& p, Eigen::VectorXd& w, Eigen::VectorXd& wd, + const F& integrand, const int dim, const std::vector& a, const std::vector& b, const ParsTupleT& pars_tuple) { std::vector c(dim, 0); std::vector deltac(dim, 0); From 43da07f895f93e270f4d78a568b398f00b3d3fb8 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Wed, 26 Jul 2023 11:34:44 +0200 Subject: [PATCH 071/179] delete }; --- stan/math/prim/functor/hcubature.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index ed072d97128..aeb30001cf2 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -83,7 +83,7 @@ inline void combination(Eigen::VectorXi& c, const int dim, const int p, for (; k < x; k = k + r) { c[i]++; r = choose(dim - c[i], p - (i + 1)); - }; + } k = k - r; } if (p > 1) { From d8dc1e09df7b2e089841281c9f0e7da1008f4ae0 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Wed, 26 Jul 2023 17:00:18 +0200 Subject: [PATCH 072/179] bring increment into signcombo --- stan/math/prim/functor/hcubature.hpp | 78 +++++++++++----------------- 1 file changed, 30 insertions(+), 48 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index aeb30001cf2..2d45495809d 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -115,53 +115,6 @@ inline void combos(Eigen::MatrixXd& p, const int k, const double lambda, } } -/** - * Helper function for signcombos. Create vector temp with k components equal - * to [±lambda] and other components equal to zero (with all possible signs), - * depending on the input vector inp. - * - * @param index boolsher helper vector to walk through temp, remembers which - * positions already were considered - * @param k number of components equal to lambda - * @param lambda scalar - * @param c ordered vector - * @param[in] inp Input vector to be incremented - */ -inline Eigen::VectorXd increment(std::vector& index, const int k, - const double lambda, const Eigen::VectorXi& c, - const Eigen::VectorXd& inp) { - Eigen::VectorXd temp = inp; - if (index.size() == 0) { - index.push_back(false); - for (int j = 0; j != k; j++) { - temp[c[j] - 1] = lambda; - } - return temp; - } - int first_zero = 0; - while ((first_zero < index.size()) && index[first_zero]) { - first_zero++; - } - if (first_zero == index.size()) { - index.flip(); - for (int j = 0; j != index.size(); j++) { - temp[c[j] - 1] *= -1; - } - index.push_back(true); - temp[c[index.size() - 1] - 1] = -lambda; - } else { - for (int i = 0; i != first_zero + 1; i++) { - if (index[i]) { - index[i] = 0; - } else { - index[i] = 1; - } - temp[c[i] - 1] *= -1; - } - } - return temp; -} - /** * Compute a vector [p] of all [dim]-component vectors * with [k] components equal to [±lambda] and other components equal to zero @@ -184,7 +137,36 @@ inline void signcombos(Eigen::MatrixXd& p, const int k, const double lambda, std::vector index; for (int j = 0; j != std::pow(2, k); j++) { int prev_col = (j == 0) ? current_col : current_col - 1; - p.col(current_col) = increment(index, k, lambda, c, p.col(prev_col)); + p.col(current_col) = p.col(prev_col); + + if (index.size() == 0) { + index.push_back(false); + for (int h = 0; h != k; h++) { + p.col(current_col)[c[h] - 1] = lambda; + } + } else { + int first_zero = 0; + while ((first_zero < index.size()) && index[first_zero]) { + first_zero++; + } + if (first_zero == index.size()) { + index.flip(); + for (int h = 0; h != index.size(); h++) { + p.col(current_col)[c[h] - 1] *= -1; + } + index.push_back(true); + p.col(current_col)[c[index.size() - 1] - 1] = -lambda; + } else { + for (int h = 0; h != first_zero + 1; h++) { + if (index[h]) { + index[h] = 0; + } else { + index[h] = 1; + } + p.col(current_col)[c[h] - 1] *= -1; + } + } + } current_col += 1; } } From 9c2bbe48a3a5d6b3609124d6f4e4732b237f2361 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 26 Jul 2023 16:11:49 -0400 Subject: [PATCH 073/179] fixes --- stan/math/prim/functor/hcubature.hpp | 115 ++++++++++++++------------- 1 file changed, 61 insertions(+), 54 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 2d45495809d..4d0dbcfa68b 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -26,13 +26,14 @@ #include #include #include +#include namespace stan { namespace math { namespace internal { -static constexpr double xd7[8] = {-9.9145537112081263920685469752598e-01, +static constexpr std::array xd7{-9.9145537112081263920685469752598e-01, -9.4910791234275852452618968404809e-01, -8.6486442335976907278971278864098e-01, -7.415311855993944398638647732811e-01, @@ -41,7 +42,7 @@ static constexpr double xd7[8] = {-9.9145537112081263920685469752598e-01, -2.0778495500789846760068940377309e-01, 0.0}; -static constexpr double wd7[8] = {2.2935322010529224963732008059913e-02, +static constexpr std::array wd7{2.2935322010529224963732008059913e-02, 6.3092092629978553290700663189093e-02, 1.0479001032225018383987632254189e-01, 1.4065325971552591874518959051021e-01, @@ -50,7 +51,7 @@ static constexpr double wd7[8] = {2.2935322010529224963732008059913e-02, 2.0443294007529889241416199923466e-01, 2.0948214108472782801299917489173e-01}; -static constexpr double gwd7[4] = {1.2948496616886969327061143267787e-01, +static constexpr std::array gwd7{1.2948496616886969327061143267787e-01, 2.797053914892766679014677714229e-01, 3.8183005050511894495036977548818e-01, 4.1795918367346938775510204081658e-01}; @@ -102,17 +103,18 @@ inline void combination(Eigen::VectorXi& c, const int dim, const int p, * @param lambda scalar * @param dim dimension */ -inline void combos(Eigen::MatrixXd& p, const int k, const double lambda, +inline Eigen::MatrixXd combos(const int k, const double lambda, const int dim) { Eigen::VectorXi c(k); const auto choose_dimk = choose(dim, k); - p = Eigen::MatrixXd::Zero(dim, choose_dimk); + Eigen::MatrixXd p = Eigen::MatrixXd::Zero(dim, choose_dimk); for (size_t i = 0; i < choose_dimk; i++) { combination(c, dim, k, i + 1); for (size_t j = 0; j < k; j++) { p.coeffRef(c.coeff(j) - 1, i) = lambda; } - } + } + return p; } /** @@ -125,12 +127,11 @@ inline void combos(Eigen::MatrixXd& p, const int k, const double lambda, * @param lambda scalar * @param dim dimension */ -inline void signcombos(Eigen::MatrixXd& p, const int k, const double lambda, +inline Eigen::MatrixXd signcombos(const int k, const double lambda, const int dim) { Eigen::VectorXi c(k); const auto choose_dimk = choose(dim, k); - p.resize(dim, choose_dimk * std::pow(2, k)); - p.setZero(); + Eigen::MatrixXd p = Eigen::MatrixXd::Zero(dim, choose_dimk * std::pow(2, k)); int current_col = 0; for (int i = 1; i != choose_dimk + 1; i++) { combination(c, dim, k, i); @@ -170,6 +171,7 @@ inline void signcombos(Eigen::MatrixXd& p, const int k, const double lambda, current_col += 1; } } + return p; } /** @@ -252,12 +254,11 @@ make_GenzMalik(const int dim) { wd[2] = twopn * ((265 - 100 * dim) * 1.0 / 1458); wd[1] = twopn * (245.0 / 486); wd[0] = twopn * ((729 - 950 * dim + 50 * dim * dim) * 1.0 / 729); - - combos(p[0], 1, l2, dim); - combos(p[1], 1, l3, dim); - signcombos(p[2], 2, l4, dim); - signcombos(p[3], dim, l5, dim); - return std::make_tuple(p, w, wd); + p[0] = combos(1, l2, dim); + p[1] = combos(1, l3, dim); + p[2] = signcombos(2, l4, dim); + p[3] = signcombos(dim, l5, dim); + return std::make_tuple(std::move(p), std::move(w), std::move(wd)); } /** @@ -279,8 +280,8 @@ make_GenzMalik(const int dim) { */ template std::tuple integrate_GenzMalik( - std::vector& p, Eigen::VectorXd& w, Eigen::VectorXd& wd, - const F& integrand, const int dim, const std::vector& a, + const F& integrand, const std::vector& p, const Eigen::VectorXd& w, const Eigen::VectorXd& wd, + const int dim, const std::vector& a, const std::vector& b, const ParsTupleT& pars_tuple) { std::vector c(dim, 0); std::vector deltac(dim, 0); @@ -399,17 +400,17 @@ std::tuple integrate_GenzMalik( } return std::make_tuple(I, E, kdivide); } - +// DOCUMENT THIS struct Box { - Box(const std::vector& a, const std::vector& b, double I, - double err, int kdivide) - : a(a), b(b), I(I), E(err), kdiv(kdivide) {} - bool operator<(const Box& box) const { return E < box.E; } - std::vector a; - std::vector b; - double I; - double E; - int kdiv; + template + Box(Vec1&& a, Vec2&& b, double I, double err, int kdivide) + : a_(std::forward(a)), b_(std::forward(b)), I_(I), E_(err), kdiv_(kdivide) {} + bool operator<(const Box& box) const { return E_ < box.E_; } + std::vector a_; + std::vector b_; + double I_; + double E_; + int kdiv_; }; } // namespace internal @@ -481,7 +482,7 @@ double hcubature(const F& integrand, const ParsTuple& pars, const int dim, } else { std::tie(p, w_five, wd_four) = internal::make_GenzMalik(dim); std::tie(result, err, kdivide) = internal::integrate_GenzMalik( - p, w_five, wd_four, integrand, dim, a, b, pars); + integrand, p, w_five, wd_four, dim, a, b, pars); } int numevals = (dim == 1) ? 15 : 1 + 4 * dim + 2 * dim * (dim - 1) + std::pow(2, dim); @@ -494,52 +495,58 @@ double hcubature(const F& integrand, const ParsTuple& pars, const int dim, || (numevals >= maxEval)) { return val; } - std::priority_queue ms; - internal::Box box(a, b, result, err, kdivide); - ms.push(box); - numevals += 2 * evals_per_box; + std::vector ms; + ms.reserve(numevals); + ms.emplace_back(std::move(a), std::move(b), result, err, kdivide); + auto get_largest_box_idx = [](auto&& box_vec) { + auto max_it = std::max_element(box_vec.begin(), box_vec.end()); + return std::distance(box_vec.begin(), max_it); + }; while ((numevals < maxEval) && (error > max(reqRelError * fabs(val), reqAbsError)) && std::isfinite(val)) { - internal::Box box = ms.top(); - ms.pop(); + auto box_idx = get_largest_box_idx(ms); + auto&& box = ms[box_idx]; - double w = (box.b[box.kdiv] - box.a[box.kdiv]) / 2; - std::vector ma(box.a); + double w = (box.b_[box.kdiv_] - box.a_[box.kdiv_]) / 2; + std::vector ma(box.a_); - ma[box.kdiv] += w; - std::vector mb(box.b); - mb[box.kdiv] -= w; + ma[box.kdiv_] += w; + std::vector mb(box.b_); + mb[box.kdiv_] -= w; double result_1, result_2, err_1, err_2, kdivide_1, kdivide_2; if (dim == 1) { std::tie(result_1, err_1) - = internal::gauss_kronrod(integrand, ma[0], box.b[0], pars); + = internal::gauss_kronrod(integrand, ma[0], box.b_[0], pars); std::tie(result_2, err_2) - = internal::gauss_kronrod(integrand, box.a[0], mb[0], pars); + = internal::gauss_kronrod(integrand, box.a_[0], mb[0], pars); } else { std::tie(result_1, err_1, kdivide_1) = internal::integrate_GenzMalik( - p, w_five, wd_four, integrand, dim, ma, box.b, pars); + integrand, p, w_five, wd_four, dim, ma, box.b_, pars); std::tie(result_2, err_2, kdivide_2) = internal::integrate_GenzMalik( - p, w_five, wd_four, integrand, dim, box.a, mb, pars); + integrand, p, w_five, wd_four, dim, box.a_, mb, pars); } - internal::Box box1(ma, box.b, result_1, err_1, kdivide_1); - ms.push(box1); - internal::Box box2(box.a, mb, result_2, err_2, kdivide_2); - ms.push(box2); - val += box1.I + box2.I - box.I; - error += box1.E + box2.E - box.E; + internal::Box box1(ma, box.b_, result_1, err_1, kdivide_1); + internal::Box box2(box.a_, mb, result_2, err_2, kdivide_2); + val += box1.I_ + box2.I_ - box.I_; + error += box1.E_ + box2.E_ - box.E_; + ms[box_idx].E_ = 0; + ms[box_idx].I_ = 0; + ms.push_back(std::move(box1)); + ms.push_back(std::move(box2)); + + //std::sort(ms.begin(), ms.end()); numevals += 2 * evals_per_box; - } + } val = 0.0; error = 0.0; - for (; !ms.empty(); ms.pop()) { - internal::Box box = ms.top(); - val += box.I; - error += box.E; + for (auto&& box : ms) { + val += box.I_; + error += box.E_; } return val; } // hcubature From a68fafb8c24a961123f4d55163f733a619268568 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Fri, 28 Jul 2023 12:34:38 -0400 Subject: [PATCH 074/179] cleanup hcubature --- stan/math/prim/functor/hcubature.hpp | 62 +++++++++++++++------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 4d0dbcfa68b..cf8aa4b3b23 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -403,13 +403,11 @@ std::tuple integrate_GenzMalik( // DOCUMENT THIS struct Box { template - Box(Vec1&& a, Vec2&& b, double I, double err, int kdivide) - : a_(std::forward(a)), b_(std::forward(b)), I_(I), E_(err), kdiv_(kdivide) {} - bool operator<(const Box& box) const { return E_ < box.E_; } + Box(Vec1&& a, Vec2&& b, double I, int kdivide) + : a_(std::forward(a)), b_(std::forward(b)), I_(I), kdiv_(kdivide) {} std::vector a_; std::vector b_; double I_; - double E_; int kdiv_; }; @@ -487,27 +485,26 @@ double hcubature(const F& integrand, const ParsTuple& pars, const int dim, int numevals = (dim == 1) ? 15 : 1 + 4 * dim + 2 * dim * (dim - 1) + std::pow(2, dim); int evals_per_box = numevals; - int kdiv = kdivide; - double error = err; - double val = result; - - if ((error <= fmax(reqRelError * fabs(val), reqAbsError)) + if ((err <= fmax(reqRelError * fabs(result), reqAbsError)) || (numevals >= maxEval)) { - return val; + return result; } numevals += 2 * evals_per_box; std::vector ms; ms.reserve(numevals); - ms.emplace_back(std::move(a), std::move(b), result, err, kdivide); + ms.emplace_back(std::move(a), std::move(b), result, kdivide); auto get_largest_box_idx = [](auto&& box_vec) { auto max_it = std::max_element(box_vec.begin(), box_vec.end()); return std::distance(box_vec.begin(), max_it); }; + std::vector err_vec; + err_vec.reserve(numevals); + err_vec.push_back(err); while ((numevals < maxEval) - && (error > max(reqRelError * fabs(val), reqAbsError)) - && std::isfinite(val)) { - auto box_idx = get_largest_box_idx(ms); - auto&& box = ms[box_idx]; + && (err > max(reqRelError * fabs(result), reqAbsError)) + && std::isfinite(result)) { + auto err_idx = get_largest_box_idx(err_vec); + auto&& box = ms[err_idx]; double w = (box.b_[box.kdiv_] - box.a_[box.kdiv_]) / 2; std::vector ma(box.a_); @@ -516,7 +513,12 @@ double hcubature(const F& integrand, const ParsTuple& pars, const int dim, std::vector mb(box.b_); mb[box.kdiv_] -= w; - double result_1, result_2, err_1, err_2, kdivide_1, kdivide_2; + double result_1; + double result_2; + double err_1; + double err_2; + double kdivide_1{0}; + double kdivide_2{0}; if (dim == 1) { std::tie(result_1, err_1) @@ -529,26 +531,28 @@ double hcubature(const F& integrand, const ParsTuple& pars, const int dim, std::tie(result_2, err_2, kdivide_2) = internal::integrate_GenzMalik( integrand, p, w_five, wd_four, dim, box.a_, mb, pars); } - internal::Box box1(ma, box.b_, result_1, err_1, kdivide_1); - internal::Box box2(box.a_, mb, result_2, err_2, kdivide_2); - val += box1.I_ + box2.I_ - box.I_; - error += box1.E_ + box2.E_ - box.E_; - ms[box_idx].E_ = 0; - ms[box_idx].I_ = 0; + internal::Box box1(std::move(ma), std::move(box.b_), result_1, kdivide_1); + internal::Box box2(std::move(box.a_), std::move(mb), result_2, kdivide_2); + result += result_1 + result_2 - box.I_; + err += err_1 + err_2 - err_vec[err_idx]; + ms[err_idx].I_ = 0; + err_vec[err_idx] = 0; ms.push_back(std::move(box1)); ms.push_back(std::move(box2)); - - //std::sort(ms.begin(), ms.end()); + err_vec.push_back(err_1); + err_vec.push_back(err_2); numevals += 2 * evals_per_box; } - val = 0.0; - error = 0.0; + result = 0.0; + err = 0.0; for (auto&& box : ms) { - val += box.I_; - error += box.E_; + result += box.I_; + } + for (auto err_i : err_vec) { + err += err_i; } - return val; + return result; } // hcubature } // namespace math From ceaa2742706ed3a1590874eede41b6d7539ad1ad Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Fri, 28 Jul 2023 16:06:15 -0400 Subject: [PATCH 075/179] remove some unneeded functors, general cleanup --- stan/math/prim/functor/hcubature.hpp | 7 +-- stan/math/prim/prob/wiener5_lpdf.hpp | 52 ++++++++------- stan/math/prim/prob/wiener_full_lpdf.hpp | 80 +++++++++++------------- 3 files changed, 62 insertions(+), 77 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index cf8aa4b3b23..488b4828c44 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -460,12 +460,9 @@ struct Box { template double hcubature(const F& integrand, const ParsTuple& pars, const int dim, const std::vector& a, const std::vector& b, - int& maxEval, const double reqAbsError, + const int max_eval, const double reqAbsError, const double reqRelError) { - if (maxEval <= 0) { - maxEval = 1000000; - } - + const auto maxEval = max_eval <= 0 ? 1000000 : max_eval; double result; double err; int kdivide = 0; diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 02b77478ad0..6c41a5830aa 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -299,7 +299,7 @@ inline double wiener5_density(double y, double a, double v_value, * @return Gradient w.r.t. t */ template -inline double grad_wiener5_t(double y, double a, double v_value, double w_value, +inline double wiener5_grad_t(double y, double a, double v_value, double w_value, double sv, double err = log(1e-12)) noexcept { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; @@ -352,7 +352,7 @@ inline double grad_wiener5_t(double y, double a, double v_value, double w_value, * @return Gradient w.r.t. a */ template -inline double grad_wiener5_a(double y, double a, double v_value, double w_value, +inline double wiener5_grad_a(double y, double a, double v_value, double w_value, double sv, double err = log(1e-12)) noexcept { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; @@ -405,7 +405,7 @@ inline double grad_wiener5_a(double y, double a, double v_value, double w_value, * @return Gradient w.r.t. v */ template -inline double grad_wiener5_v(double y, double a, double v_value, double w_value, +inline double wiener5_grad_v(double y, double a, double v_value, double w_value, double sv, double err = log(1e-12)) noexcept { double ans = (a * (1 - w_value) - v_value * y); if (sv != 0) { @@ -430,7 +430,7 @@ inline double grad_wiener5_v(double y, double a, double v_value, double w_value, * @return Gradient w.r.t. w */ template -inline double grad_wiener5_w(double y, double a, double v_value, double w_value, +inline double wiener5_grad_w(double y, double a, double v_value, double w_value, double sv, double err = log(1e-12)) noexcept { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; @@ -479,7 +479,7 @@ inline double grad_wiener5_w(double y, double a, double v_value, double w_value, * @return Gradient w.r.t. sv */ template -inline double grad_wiener5_sv(double y, double a, double v_value, +inline double wiener5_grad_sv(double y, double a, double v_value, double w_value, double sv, double err = log(1e-12)) noexcept { const double one_plus_svsqr_y = 1 + square(sv) * y; @@ -525,17 +525,14 @@ inline void assign_err(std::tuple& args_tuple, double err) { * @param args_tuple Tuple of arguments to pass to functor * @param log_result Whether the function result is already on the log-scale */ -template -double estimate_with_err_check(const F& functor, double err, - ArgsTupleT&& args_tuple, - bool log_result = true) { - double result = math::apply([&](auto&&... args) { return functor(args...); }, - args_tuple); - double log_fabs_result = log_result ? log(fabs(result)) : fabs(result); +template +double estimate_with_err_check(const F& functor, double err, ArgsTupleT&&... args_tuple) { + double result = functor(args_tuple...); + double log_fabs_result = LogResult ? log(fabs(result)) : fabs(result); if (log_fabs_result < err) { log_fabs_result = std::isinf(log_fabs_result) ? 0 : log_fabs_result; - ArgsTupleT err_args_tuple = args_tuple; + auto err_args_tuple = std::make_tuple(args_tuple...); const double new_error = GradW7 ? err + log_fabs_result + LOG_TWO : err + log_fabs_result; assign_err(std::get(err_args_tuple), new_error); @@ -660,12 +657,10 @@ inline return_type_t wiener5_lpdf( const double v_val = v_vec.val(i); const double sv_val = sv_vec.val(i); - const auto params = std::make_tuple(y_val - t0_val, a_val, v_val, w_val, - sv_val, log_error_absolute); - - density = internal::estimate_with_err_check<5>( + density = internal::estimate_with_err_check<5, false, 0, false>( [&](auto&&... args) { return internal::wiener5_density(args...); }, - log_error_density - LOG_TWO, params, false); + log_error_density - LOG_TWO, y_val - t0_val, a_val, v_val, w_val, + sv_val, log_error_absolute); log_density += density; const double new_est_err = density + log_error_derivative - LOG_FOUR; @@ -673,8 +668,9 @@ inline return_type_t wiener5_lpdf( // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 const double deriv_y = internal::estimate_with_err_check<5>( - [&](auto&&... args) { return internal::grad_wiener5_t(args...); }, - new_est_err, params); + [&](auto&&... args) { return internal::wiener5_grad_t(args...); }, + new_est_err, y_val - t0_val, a_val, v_val, w_val, + sv_val, log_error_absolute); // computation of derivatives and precision checks if (!is_constant_all::value) { @@ -682,23 +678,25 @@ inline return_type_t wiener5_lpdf( } if (!is_constant_all::value) { ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check<5>( - [&](auto&&... args) { return internal::grad_wiener5_a(args...); }, - new_est_err, params); + [&](auto&&... args) { return internal::wiener5_grad_a(args...); }, + new_est_err, y_val - t0_val, a_val, v_val, w_val, + sv_val, log_error_absolute); } if (!is_constant_all::value) { ops_partials.edge3_.partials_[i] = -deriv_y; } if (!is_constant_all::value) { ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check<5>( - [&](auto&&... args) { return internal::grad_wiener5_w(args...); }, - new_est_err, params); + [&](auto&&... args) { return internal::wiener5_grad_w(args...); }, + new_est_err, y_val - t0_val, a_val, v_val, w_val, + sv_val, log_error_absolute); } if (!is_constant_all::value) { - ops_partials.edge5_.partials_[i] = internal::grad_wiener5_v( + ops_partials.edge5_.partials_[i] = internal::wiener5_grad_v( y_val - t0_val, a_val, v_val, w_val, sv_val); } if (!is_constant_all::value) { - ops_partials.edge6_.partials_[i] = internal::grad_wiener5_sv( + ops_partials.edge6_.partials_[i] = internal::wiener5_grad_sv( y_val - t0_val, a_val, v_val, w_val, sv_val); } } // end for loop diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 36092d16592..a163a94fb81 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -21,7 +21,7 @@ namespace internal { * @param log_error The log error tolerance * @return Gradient w.r.t. sw */ -inline double grad_wiener7_sw(double y, double a, double v, double w, double sv, +inline double wiener7_grad_sw(double y, double a, double v, double w, double sv, double sw, double log_error) { double low = w - sw / 2.0; low = (0 > low) ? 0 : low; @@ -57,10 +57,10 @@ inline double grad_wiener7_sw(double y, double a, double v, double w, double sv, * @return Functor applied to arguments */ template * = nullptr> -inline double call_wiener7_function(const F& functor, double y, double a, - double v, double w, double t0, double sv, +inline double conditionally_grad_sw(const F& functor, double y_diff, double a, + double v, double w, double sv, double sw, double log_error) { - return functor(y - t0, a, v, w, sv, log_error); + return functor(y_diff, a, v, w, sv, log_error); } /** @@ -74,7 +74,7 @@ inline double call_wiener7_function(const F& functor, double y, double a, * @tparam F Type of Gradient/density functor * * @param functor Gradient/density functor to apply - * @param y A scalar variable; the reaction time in seconds + * @param y_diff A scalar variable; the reaction time minus the non-decision in seconds * @param a The boundary separation * @param v The drift rate * @param w The relative starting point @@ -86,10 +86,10 @@ inline double call_wiener7_function(const F& functor, double y, double a, * @return Functor applied to arguments */ template * = nullptr> -inline double call_wiener7_function(const F& functor, double y, double a, - double v, double w, double t0, double sv, +inline double conditionally_grad_sw(const F& functor, double y_diff, double a, + double v, double w, double sv, double sw, double log_error) { - return functor(y - t0, a, v, w, sv, sw, log_error); + return functor(y_diff, a, v, w, sv, sw, log_error); } /** @@ -111,7 +111,7 @@ template x, double y, double a, double v, double w, + = [&](auto&& x, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double log_error) { scalar_seq_view x_vec(x); const double sw_val = GradSW ? 0 : sw; @@ -121,15 +121,14 @@ auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, if (y - new_t0 <= 0) { return 0.0; } else { - return call_wiener7_function( - wiener7_functor, y, a, v, new_w, new_t0, sv, sw, log_error); + return conditionally_grad_sw( + wiener7_functor, y - new_t0, a, v, new_w, sv, sw, log_error); } }; const auto& functor = [&](auto&&... int_args) { return hcubature(wiener7_integrand_impl, int_args...); }; - return estimate_with_err_check<0, GradW7, 8>(functor, hcubature_err, - std::make_tuple(args...)); + return estimate_with_err_check<0, GradW7, 8>(functor, hcubature_err, args...); } } // namespace internal @@ -402,9 +401,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const int maximal_evaluations_hcubature = 6000; double density = 0.0; double log_density = 0.0; - operands_and_partials - ops_partials(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref, sw_ref, st0_ref); + auto ops_partials = make_partials_propagator(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref, sw_ref, st0_ref); ReturnT result = 0; // calculate density and partials @@ -457,7 +454,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const double deriv_t_7 = internal::wiener7_integrate( [&](auto&&... args) { - return internal::grad_wiener5_t(args...); + return internal::wiener5_grad_t(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, @@ -467,13 +464,13 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, // computation of derivatives and precision checks double derivative; if (!is_constant_all::value) { - ops_partials.edge1_.partials_[i] = deriv_t_7; + partials<0>(ops_partials)[i] = deriv_t_7; } if (!is_constant_all::value) { - ops_partials.edge2_.partials_[i] + partials<1>(ops_partials)[i] = internal::wiener7_integrate( [&](auto&&... args) { - return internal::grad_wiener5_a(args...); + return internal::wiener5_grad_a(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, @@ -481,13 +478,13 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, / density; } if (!is_constant_all::value) { - ops_partials.edge3_.partials_[i] = -deriv_t_7; + partials<2>(ops_partials)[i] = -deriv_t_7; } if (!is_constant_all::value) { - ops_partials.edge4_.partials_[i] + partials<3>(ops_partials)[i] = internal::wiener7_integrate( [&](auto&&... args) { - return internal::grad_wiener5_w(args...); + return internal::wiener5_grad_w(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, @@ -495,10 +492,10 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, / density; } if (!is_constant_all::value) { - ops_partials.edge5_.partials_[i] + partials<4>(ops_partials)[i] = internal::wiener7_integrate( [&](auto&&... args) { - return internal::grad_wiener5_v(args...); + return internal::wiener5_grad_v(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, @@ -506,10 +503,10 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, / density; } if (!is_constant_all::value) { - ops_partials.edge6_.partials_[i] + partials<5>(ops_partials)[i] = internal::wiener7_integrate( [&](auto&&... args) { - return internal::grad_wiener5_sv(args...); + return internal::wiener5_grad_sv(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, @@ -518,48 +515,41 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } if (!is_constant_all::value) { if (sw_val == 0) { - ops_partials.edge7_.partials_[i] = 0; + partials<6>(ops_partials)[i] = 0; } else { if (st0_val == 0) { - const auto sw_params - = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, - sw_val, log_error_absolute - LOG_TWO); derivative = internal::estimate_with_err_check<5>( [&](auto&&... args) { - return internal::call_wiener7_function( - internal::grad_wiener7_sw, args...); + return internal::wiener7_grad_sw(args...); }, - hcubature_err, sw_params); + hcubature_err, y_val - t0_val, a_val, v_val, w_val, sv_val, + sw_val, log_error_absolute - LOG_TWO); } else { derivative = internal::wiener7_integrate( [&](auto&&... args) { - return internal::grad_wiener7_sw(args...); + return internal::wiener7_grad_sw(args...); }, hcubature_err, params, 1, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2); } - ops_partials.edge7_.partials_[i] = derivative / density - 1 / sw_val; + partials<6>(ops_partials)[i] = derivative / density - 1 / sw_val; } } if (!is_constant_all::value) { double f; if (st0_val == 0) { - ops_partials.edge8_.partials_[i] = 0; + partials<7>(ops_partials)[i] = 0; } else if (y_val - (t0_val + st0_val) <= 0) { - ops_partials.edge8_.partials_[i] = -1 / st0_val; + partials<7>(ops_partials)[i] = -1 / st0_val; } else { const double t0_st0 = t0_val + st0_val; if (sw_val == 0) { - const auto st_params - = std::make_tuple(y_val, a_val, v_val, w_val, t0_st0, sv_val, - sw_val, log_error_absolute - LOG_TWO); f = internal::estimate_with_err_check<5>( [&](auto&&... args) { - return internal::call_wiener7_function( - internal::wiener5_density, args...); + return internal::wiener5_density(args...); }, - log_error_derivative + log(st0_val), st_params); + log_error_derivative + log(st0_val), y_val - t0_st0, a_val, v_val, w_val, sv_val, log_error_absolute - LOG_TWO); } else { const double new_error = log_error_absolute - LOG_TWO; const auto& params_st = std::make_tuple( @@ -572,7 +562,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2); } - ops_partials.edge8_.partials_[i] = -1 / st0_val + f / st0_val / density; + partials<7>(ops_partials)[i] = -1 / st0_val + f / st0_val / density; } } std::vector().swap(xmin); From cfefed6a1ce7b22f241a7549fb5626a231725ba6 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Mon, 31 Jul 2023 14:58:31 +0200 Subject: [PATCH 076/179] changes in names and docs --- stan/math/prim/functor/hcubature.hpp | 84 ++++++++++++++++------------ 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 488b4828c44..936d07db9c2 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -69,7 +69,7 @@ static constexpr std::array gwd7{1.2948496616886969327061143267787e-0 * @param p number of elements * @param x x-th lexicographically ordered set */ -inline void combination(Eigen::VectorXi& c, const int dim, const int p, +inline Eigen::VectorXi combination(Eigen::VectorXi& c, const int dim, const int p, const int x) { int r = 0; int k = 0; @@ -92,6 +92,7 @@ inline void combination(Eigen::VectorXi& c, const int dim, const int p, } else { c[0] = x; } + return std::move(c); } /** @@ -109,7 +110,7 @@ inline Eigen::MatrixXd combos(const int k, const double lambda, const auto choose_dimk = choose(dim, k); Eigen::MatrixXd p = Eigen::MatrixXd::Zero(dim, choose_dimk); for (size_t i = 0; i < choose_dimk; i++) { - combination(c, dim, k, i + 1); + c = combination(c, dim, k, i + 1); for (size_t j = 0; j < k; j++) { p.coeffRef(c.coeff(j) - 1, i) = lambda; } @@ -134,7 +135,7 @@ inline Eigen::MatrixXd signcombos(const int k, const double lambda, Eigen::MatrixXd p = Eigen::MatrixXd::Zero(dim, choose_dimk * std::pow(2, k)); int current_col = 0; for (int i = 1; i != choose_dimk + 1; i++) { - combination(c, dim, k, i); + c = combination(c, dim, k, i); std::vector index; for (int j = 0; j != std::pow(2, k); j++) { int prev_col = (j == 0) ? current_col : current_col - 1; @@ -227,17 +228,17 @@ std::pair gauss_kronrod(const F& integrand, const double a, * Compute the points and weights corresponding to a [dim]-dimensional * Genz-Malik cubature rule * - * @param[in,out] p points for the last 4 GenzMalik weights - * @param[in,out] w weights for the 5 terms in the GenzMalik rule - * @param[in,out] wd weights for the embedded lower-degree rule + * @param[in,out] points points for the last 4 GenzMalik weights + * @param[in,out] weights weights for the 5 terms in the GenzMalik rule + * @param[in,out] weights_low_deg weights for the embedded lower-degree rule * @param dim dimension */ inline std::tuple, Eigen::VectorXd, Eigen::VectorXd> make_GenzMalik(const int dim) { - std::vector p(4); - Eigen::VectorXd w(5); - Eigen::VectorXd wd(4); + std::vector points(4); + Eigen::VectorXd weights(5); + Eigen::VectorXd weights_low_deg(4); double l4 = std::sqrt(9 * 1.0 / 10); double l2 = std::sqrt(9 * 1.0 / 70); double l3 = l4; @@ -245,20 +246,20 @@ make_GenzMalik(const int dim) { double twopn = std::pow(2, dim); - w[0] = twopn * ((12824 - 9120 * dim + 400 * dim * dim) * 1.0 / 19683); - w[1] = twopn * (980.0 / 6561); - w[2] = twopn * ((1820 - 400 * dim) * 1.0 / 19683); - w[3] = twopn * (200.0 / 19683); - w[4] = 6859.0 / 19683; - wd[3] = twopn * (25.0 / 729); - wd[2] = twopn * ((265 - 100 * dim) * 1.0 / 1458); - wd[1] = twopn * (245.0 / 486); - wd[0] = twopn * ((729 - 950 * dim + 50 * dim * dim) * 1.0 / 729); - p[0] = combos(1, l2, dim); - p[1] = combos(1, l3, dim); - p[2] = signcombos(2, l4, dim); - p[3] = signcombos(dim, l5, dim); - return std::make_tuple(std::move(p), std::move(w), std::move(wd)); + weights[0] = twopn * ((12824 - 9120 * dim + 400 * dim * dim) * 1.0 / 19683); + weights[1] = twopn * (980.0 / 6561); + weights[2] = twopn * ((1820 - 400 * dim) * 1.0 / 19683); + weights[3] = twopn * (200.0 / 19683); + weights[4] = 6859.0 / 19683; + weights_low_deg[3] = twopn * (25.0 / 729); + weights_low_deg[2] = twopn * ((265 - 100 * dim) * 1.0 / 1458); + weights_low_deg[1] = twopn * (245.0 / 486); + weights_low_deg[0] = twopn * ((729 - 950 * dim + 50 * dim * dim) * 1.0 / 729); + points[0] = combos(1, l2, dim); + points[1] = combos(1, l3, dim); + points[2] = signcombos(2, l4, dim); + points[3] = signcombos(dim, l5, dim); + return std::make_tuple(std::move(points), std::move(weights), std::move(weights_low_deg)); } /** @@ -268,9 +269,9 @@ make_GenzMalik(const int dim) { * @tparam F type of the integrand * @tparam ParsTupleT type of the tuple of parameters for the integrand * @param[out] integrand function to be integrated - * @param[in] p - * @param[in] w - * @param[in] wd + * @param[in] points points for the last 4 GenzMalik weights + * @param[in] weights weights for the 5 terms in the GenzMalik rule + * @param[in] weights_low_deg weights for the embedded lower-degree rule * @param dim dimension of the multidimensional integral * @param a lower limit of integration * @param b upper limit of integration @@ -280,7 +281,7 @@ make_GenzMalik(const int dim) { */ template std::tuple integrate_GenzMalik( - const F& integrand, const std::vector& p, const Eigen::VectorXd& w, const Eigen::VectorXd& wd, + const F& integrand, const std::vector& points, const Eigen::VectorXd& weights, const Eigen::VectorXd& weights_low_deg, const int dim, const std::vector& a, const std::vector& b, const ParsTupleT& pars_tuple) { std::vector c(dim, 0); @@ -316,7 +317,7 @@ std::tuple integrate_GenzMalik( for (std::size_t i = 0; i != dim; i++) { for (std::size_t j = 0; j != dim; j++) { - p2[j] = deltac[j] * p[0](j, i); + p2[j] = deltac[j] * points[0](j, i); } for (std::size_t j = 0; j != dim; j++) { @@ -334,7 +335,7 @@ std::tuple integrate_GenzMalik( f2i += temp; for (std::size_t j = 0; j != dim; j++) { - p3[j] = deltac[j] * p[1](j, i); + p3[j] = deltac[j] * points[1](j, i); } for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] + p3[j]; @@ -355,9 +356,9 @@ std::tuple integrate_GenzMalik( } std::vector p4(dim); double f4 = 0.0; - for (std::size_t i = 0; i != p[2].cols(); i++) { + for (std::size_t i = 0; i != points[2].cols(); i++) { for (std::size_t j = 0; j != dim; j++) { - p4[j] = deltac[j] * p[2](j, i); + p4[j] = deltac[j] * points[2](j, i); } for (std::size_t j = 0; j != dim; j++) { cc[j] = c[j] + p4[j]; @@ -369,9 +370,9 @@ std::tuple integrate_GenzMalik( } double f5 = 0.0; std::vector p5(dim); - for (std::size_t i = 0; i != p[3].cols(); i++) { + for (std::size_t i = 0; i != points[3].cols(); i++) { for (std::size_t j = 0; j != dim; j++) { - p5[j] = deltac[j] * p[3](j, i); + p5[j] = deltac[j] * points[3](j, i); } for (std::size_t j = 0; j != dim; j++) { @@ -383,8 +384,8 @@ std::tuple integrate_GenzMalik( f5 += temp; } - double I = v * (w[0] * f1 + w[1] * f2 + w[2] * f3 + w[3] * f4 + w[4] * f5); - double Idash = v * (wd[0] * f1 + wd[1] * f2 + wd[2] * f3 + wd[3] * f4); + double I = v * (weights[0] * f1 + weights[1] * f2 + weights[2] * f3 + weights[3] * f4 + weights[4] * f5); + double Idash = v * (weights_low_deg[0] * f1 + weights_low_deg[1] * f2 + weights_low_deg[2] * f3 + weights_low_deg[3] * f4); double E = fabs(I - Idash); int kdivide = 0; @@ -400,7 +401,18 @@ std::tuple integrate_GenzMalik( } return std::make_tuple(I, E, kdivide); } -// DOCUMENT THIS + +/** + * Compute the integral of the function to be integrated (integrand) from a to b + * for more than one dimensions. + * + * @tparam Vec1 Type of vector 1 + * @tparam Vec2 Type of vector 2 + * @param a lower bounds of the integral + * @param b upper bounds of the integral + * @param I value of the integral + * @param kdivide number of subdividing the integration volume + */ struct Box { template Box(Vec1&& a, Vec2&& b, double I, int kdivide) From 97af29c153f8b66f8bce439d95b58ba3a709205c Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 31 Jul 2023 08:59:59 -0400 Subject: [PATCH 077/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/functor/hcubature.hpp | 82 +++++++++++++----------- stan/math/prim/prob/wiener5_lpdf.hpp | 21 +++--- stan/math/prim/prob/wiener_full_lpdf.hpp | 27 ++++---- 3 files changed, 72 insertions(+), 58 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 936d07db9c2..70e02f4b39b 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -33,28 +33,30 @@ namespace math { namespace internal { -static constexpr std::array xd7{-9.9145537112081263920685469752598e-01, - -9.4910791234275852452618968404809e-01, - -8.6486442335976907278971278864098e-01, - -7.415311855993944398638647732811e-01, - -5.8608723546769113029414483825842e-01, - -4.0584515137739716690660641207707e-01, - -2.0778495500789846760068940377309e-01, - 0.0}; - -static constexpr std::array wd7{2.2935322010529224963732008059913e-02, - 6.3092092629978553290700663189093e-02, - 1.0479001032225018383987632254189e-01, - 1.4065325971552591874518959051021e-01, - 1.6900472663926790282658342659795e-01, - 1.9035057806478540991325640242055e-01, - 2.0443294007529889241416199923466e-01, - 2.0948214108472782801299917489173e-01}; - -static constexpr std::array gwd7{1.2948496616886969327061143267787e-01, - 2.797053914892766679014677714229e-01, - 3.8183005050511894495036977548818e-01, - 4.1795918367346938775510204081658e-01}; +static constexpr std::array xd7{ + -9.9145537112081263920685469752598e-01, + -9.4910791234275852452618968404809e-01, + -8.6486442335976907278971278864098e-01, + -7.415311855993944398638647732811e-01, + -5.8608723546769113029414483825842e-01, + -4.0584515137739716690660641207707e-01, + -2.0778495500789846760068940377309e-01, + 0.0}; + +static constexpr std::array wd7{ + 2.2935322010529224963732008059913e-02, + 6.3092092629978553290700663189093e-02, + 1.0479001032225018383987632254189e-01, + 1.4065325971552591874518959051021e-01, + 1.6900472663926790282658342659795e-01, + 1.9035057806478540991325640242055e-01, + 2.0443294007529889241416199923466e-01, + 2.0948214108472782801299917489173e-01}; + +static constexpr std::array gwd7{ + 1.2948496616886969327061143267787e-01, 2.797053914892766679014677714229e-01, + 3.8183005050511894495036977548818e-01, + 4.1795918367346938775510204081658e-01}; /** * Get the [x]-th lexicographically ordered set of [p] elements in [dim] @@ -69,8 +71,8 @@ static constexpr std::array gwd7{1.2948496616886969327061143267787e-0 * @param p number of elements * @param x x-th lexicographically ordered set */ -inline Eigen::VectorXi combination(Eigen::VectorXi& c, const int dim, const int p, - const int x) { +inline Eigen::VectorXi combination(Eigen::VectorXi& c, const int dim, + const int p, const int x) { int r = 0; int k = 0; c[0] = 0; @@ -104,8 +106,7 @@ inline Eigen::VectorXi combination(Eigen::VectorXi& c, const int dim, const int * @param lambda scalar * @param dim dimension */ -inline Eigen::MatrixXd combos(const int k, const double lambda, - const int dim) { +inline Eigen::MatrixXd combos(const int k, const double lambda, const int dim) { Eigen::VectorXi c(k); const auto choose_dimk = choose(dim, k); Eigen::MatrixXd p = Eigen::MatrixXd::Zero(dim, choose_dimk); @@ -114,7 +115,7 @@ inline Eigen::MatrixXd combos(const int k, const double lambda, for (size_t j = 0; j < k; j++) { p.coeffRef(c.coeff(j) - 1, i) = lambda; } - } + } return p; } @@ -129,7 +130,7 @@ inline Eigen::MatrixXd combos(const int k, const double lambda, * @param dim dimension */ inline Eigen::MatrixXd signcombos(const int k, const double lambda, - const int dim) { + const int dim) { Eigen::VectorXi c(k); const auto choose_dimk = choose(dim, k); Eigen::MatrixXd p = Eigen::MatrixXd::Zero(dim, choose_dimk * std::pow(2, k)); @@ -259,7 +260,8 @@ make_GenzMalik(const int dim) { points[1] = combos(1, l3, dim); points[2] = signcombos(2, l4, dim); points[3] = signcombos(dim, l5, dim); - return std::make_tuple(std::move(points), std::move(weights), std::move(weights_low_deg)); + return std::make_tuple(std::move(points), std::move(weights), + std::move(weights_low_deg)); } /** @@ -281,9 +283,10 @@ make_GenzMalik(const int dim) { */ template std::tuple integrate_GenzMalik( - const F& integrand, const std::vector& points, const Eigen::VectorXd& weights, const Eigen::VectorXd& weights_low_deg, - const int dim, const std::vector& a, - const std::vector& b, const ParsTupleT& pars_tuple) { + const F& integrand, const std::vector& points, + const Eigen::VectorXd& weights, const Eigen::VectorXd& weights_low_deg, + const int dim, const std::vector& a, const std::vector& b, + const ParsTupleT& pars_tuple) { std::vector c(dim, 0); std::vector deltac(dim, 0); @@ -384,8 +387,12 @@ std::tuple integrate_GenzMalik( f5 += temp; } - double I = v * (weights[0] * f1 + weights[1] * f2 + weights[2] * f3 + weights[3] * f4 + weights[4] * f5); - double Idash = v * (weights_low_deg[0] * f1 + weights_low_deg[1] * f2 + weights_low_deg[2] * f3 + weights_low_deg[3] * f4); + double I = v + * (weights[0] * f1 + weights[1] * f2 + weights[2] * f3 + + weights[3] * f4 + weights[4] * f5); + double Idash = v + * (weights_low_deg[0] * f1 + weights_low_deg[1] * f2 + + weights_low_deg[2] * f3 + weights_low_deg[3] * f4); double E = fabs(I - Idash); int kdivide = 0; @@ -416,7 +423,10 @@ std::tuple integrate_GenzMalik( struct Box { template Box(Vec1&& a, Vec2&& b, double I, int kdivide) - : a_(std::forward(a)), b_(std::forward(b)), I_(I), kdiv_(kdivide) {} + : a_(std::forward(a)), + b_(std::forward(b)), + I_(I), + kdiv_(kdivide) {} std::vector a_; std::vector b_; double I_; @@ -551,7 +561,7 @@ double hcubature(const F& integrand, const ParsTuple& pars, const int dim, err_vec.push_back(err_1); err_vec.push_back(err_2); numevals += 2 * evals_per_box; - } + } result = 0.0; err = 0.0; diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 6c41a5830aa..c3bc2df9669 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -525,9 +525,10 @@ inline void assign_err(std::tuple& args_tuple, double err) { * @param args_tuple Tuple of arguments to pass to functor * @param log_result Whether the function result is already on the log-scale */ -template -double estimate_with_err_check(const F& functor, double err, ArgsTupleT&&... args_tuple) { +template +double estimate_with_err_check(const F& functor, double err, + ArgsTupleT&&... args_tuple) { double result = functor(args_tuple...); double log_fabs_result = LogResult ? log(fabs(result)) : fabs(result); if (log_fabs_result < err) { @@ -660,7 +661,7 @@ inline return_type_t wiener5_lpdf( density = internal::estimate_with_err_check<5, false, 0, false>( [&](auto&&... args) { return internal::wiener5_density(args...); }, log_error_density - LOG_TWO, y_val - t0_val, a_val, v_val, w_val, - sv_val, log_error_absolute); + sv_val, log_error_absolute); log_density += density; const double new_est_err = density + log_error_derivative - LOG_FOUR; @@ -669,8 +670,8 @@ inline return_type_t wiener5_lpdf( // the value as deriv_y to edge1 and as -deriv_y to edge5 const double deriv_y = internal::estimate_with_err_check<5>( [&](auto&&... args) { return internal::wiener5_grad_t(args...); }, - new_est_err, y_val - t0_val, a_val, v_val, w_val, - sv_val, log_error_absolute); + new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, + log_error_absolute); // computation of derivatives and precision checks if (!is_constant_all::value) { @@ -679,8 +680,8 @@ inline return_type_t wiener5_lpdf( if (!is_constant_all::value) { ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check<5>( [&](auto&&... args) { return internal::wiener5_grad_a(args...); }, - new_est_err, y_val - t0_val, a_val, v_val, w_val, - sv_val, log_error_absolute); + new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, + log_error_absolute); } if (!is_constant_all::value) { ops_partials.edge3_.partials_[i] = -deriv_y; @@ -688,8 +689,8 @@ inline return_type_t wiener5_lpdf( if (!is_constant_all::value) { ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check<5>( [&](auto&&... args) { return internal::wiener5_grad_w(args...); }, - new_est_err, y_val - t0_val, a_val, v_val, w_val, - sv_val, log_error_absolute); + new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, + log_error_absolute); } if (!is_constant_all::value) { ops_partials.edge5_.partials_[i] = internal::wiener5_grad_v( diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index a163a94fb81..1b36c09aca8 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -58,8 +58,8 @@ inline double wiener7_grad_sw(double y, double a, double v, double w, double sv, */ template * = nullptr> inline double conditionally_grad_sw(const F& functor, double y_diff, double a, - double v, double w, double sv, - double sw, double log_error) { + double v, double w, double sv, double sw, + double log_error) { return functor(y_diff, a, v, w, sv, log_error); } @@ -74,7 +74,8 @@ inline double conditionally_grad_sw(const F& functor, double y_diff, double a, * @tparam F Type of Gradient/density functor * * @param functor Gradient/density functor to apply - * @param y_diff A scalar variable; the reaction time minus the non-decision in seconds + * @param y_diff A scalar variable; the reaction time minus the non-decision in + * seconds * @param a The boundary separation * @param v The drift rate * @param w The relative starting point @@ -87,8 +88,8 @@ inline double conditionally_grad_sw(const F& functor, double y_diff, double a, */ template * = nullptr> inline double conditionally_grad_sw(const F& functor, double y_diff, double a, - double v, double w, double sv, - double sw, double log_error) { + double v, double w, double sv, double sw, + double log_error) { return functor(y_diff, a, v, w, sv, sw, log_error); } @@ -111,8 +112,8 @@ template x_vec(x); const double sw_val = GradSW ? 0 : sw; const double new_w = sw_val ? w + sw_val * (x_vec[0] - 0.5) : w; @@ -121,8 +122,8 @@ auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, if (y - new_t0 <= 0) { return 0.0; } else { - return conditionally_grad_sw( - wiener7_functor, y - new_t0, a, v, new_w, sv, sw, log_error); + return conditionally_grad_sw(wiener7_functor, y - new_t0, a, + v, new_w, sv, sw, log_error); } }; const auto& functor = [&](auto&&... int_args) { @@ -401,7 +402,8 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const int maximal_evaluations_hcubature = 6000; double density = 0.0; double log_density = 0.0; - auto ops_partials = make_partials_propagator(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref, sw_ref, st0_ref); + auto ops_partials = make_partials_propagator(y_ref, a_ref, t0_ref, w_ref, + v_ref, sv_ref, sw_ref, st0_ref); ReturnT result = 0; // calculate density and partials @@ -523,7 +525,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, return internal::wiener7_grad_sw(args...); }, hcubature_err, y_val - t0_val, a_val, v_val, w_val, sv_val, - sw_val, log_error_absolute - LOG_TWO); + sw_val, log_error_absolute - LOG_TWO); } else { derivative = internal::wiener7_integrate( [&](auto&&... args) { @@ -549,7 +551,8 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, [&](auto&&... args) { return internal::wiener5_density(args...); }, - log_error_derivative + log(st0_val), y_val - t0_st0, a_val, v_val, w_val, sv_val, log_error_absolute - LOG_TWO); + log_error_derivative + log(st0_val), y_val - t0_st0, a_val, v_val, + w_val, sv_val, log_error_absolute - LOG_TWO); } else { const double new_error = log_error_absolute - LOG_TWO; const auto& params_st = std::make_tuple( From b24decafd5d7c2652a6f033bee1d23c14ab4fdc2 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Mon, 31 Jul 2023 15:07:37 +0200 Subject: [PATCH 078/179] doc --- stan/math/prim/functor/hcubature.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 70e02f4b39b..c71ca6c9a09 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -470,7 +470,7 @@ struct Box { * @param dim dimension of the integral * @param a lower limit of integration as vector * @param b upper limit of integration as vector - * @param maxEval maximal number of evaluations + * @param max_eval maximal number of evaluations * @param reqAbsError absolute error * @param reqRelError relative error as vector * @param val correct value of integral From 39ce59cbc5fc0c910a221678518b3e495b413d4b Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 31 Jul 2023 12:19:19 -0400 Subject: [PATCH 079/179] make a, b into Eigen vectors instead of std vectors --- stan/math/prim/functor/hcubature.hpp | 21 +++++--------- stan/math/prim/prob/wiener_full_lpdf.hpp | 37 +++++++++++------------- 2 files changed, 25 insertions(+), 33 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index c71ca6c9a09..f12eccdc966 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -285,21 +285,16 @@ template std::tuple integrate_GenzMalik( const F& integrand, const std::vector& points, const Eigen::VectorXd& weights, const Eigen::VectorXd& weights_low_deg, - const int dim, const std::vector& a, const std::vector& b, + const int dim, const Eigen::VectorXd& a, const Eigen::VectorXd& b, const ParsTupleT& pars_tuple) { - std::vector c(dim, 0); - std::vector deltac(dim, 0); - + Eigen::VectorXd c = Eigen::VectorXd::Zero(dim); for (std::size_t i = 0; i != dim; i++) { if (a[i] == b[i]) { return std::make_tuple(0.0, 0.0, 0); } c[i] = (a[i] + b[i]) / 2; } - - for (std::size_t i = 0; i != dim; i++) { - deltac[i] = fabs(b[i] - a[i]) / 2; - } + Eigen::VectorXd deltac = ((b - a).array() / 2.0).matrix(); double v = 1.0; for (std::size_t i = 0; i != dim; i++) { v *= deltac[i]; @@ -427,8 +422,8 @@ struct Box { b_(std::forward(b)), I_(I), kdiv_(kdivide) {} - std::vector a_; - std::vector b_; + Eigen::VectorXd a_; + Eigen::VectorXd b_; double I_; int kdiv_; }; @@ -481,7 +476,7 @@ struct Box { */ template double hcubature(const F& integrand, const ParsTuple& pars, const int dim, - const std::vector& a, const std::vector& b, + const Eigen::VectorXd& a, const Eigen::VectorXd& b, const int max_eval, const double reqAbsError, const double reqRelError) { const auto maxEval = max_eval <= 0 ? 1000000 : max_eval; @@ -526,10 +521,10 @@ double hcubature(const F& integrand, const ParsTuple& pars, const int dim, auto&& box = ms[err_idx]; double w = (box.b_[box.kdiv_] - box.a_[box.kdiv_]) / 2; - std::vector ma(box.a_); + Eigen::VectorXd ma = Eigen::Map(box.a_.data(), box.a_.size()); ma[box.kdiv_] += w; - std::vector mb(box.b_); + Eigen::VectorXd mb = Eigen::Map(box.b_.data(), box.b_.size()); mb[box.kdiv_] -= w; double result_1; diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 1b36c09aca8..88e8e5246db 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -111,7 +111,7 @@ template auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, double hcubature_err, TArgs&&... args) { - const auto& wiener7_integrand_impl + const auto wiener7_integrand_impl = [&](auto&& x, double y, double a, double v, double w, double t0, double sv, double sw, double st0, double log_error) { scalar_seq_view x_vec(x); @@ -126,7 +126,7 @@ auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, v, new_w, sv, sw, log_error); } }; - const auto& functor = [&](auto&&... int_args) { + const auto functor = [&](auto&&... int_args) { return hcubature(wiener7_integrand_impl, int_args...); }; return estimate_with_err_check<0, GradW7, 8>(functor, hcubature_err, args...); @@ -284,6 +284,11 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, const T_sv& sv, const T_sw& sw, const T_st0& st0, double precision_derivatives = 1e-4) { + if (!include_summand::value) { + return 0; + } + using T_y_ref = ref_type_t; using T_a_ref = ref_type_t; using T_v_ref = ref_type_t; @@ -368,7 +373,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } size_t N_beta_sw = max_size(w, sw); for (size_t i = 0; i < N_beta_sw; ++i) { - if (w_vec[i] - .5 * sw_vec[i] <= 0) { + if (unlikely(w_vec[i] - .5 * sw_vec[i] <= 0)) { std::stringstream msg; msg << ", but must be smaller than 2*(A-priori bias) = " << 2 * w_vec[i]; std::string msg_str(msg.str()); @@ -376,7 +381,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, "Inter-trial variability in A-priori bias", sw_vec[i], " = ", msg_str.c_str()); } - if (w_vec[i] + .5 * sw_vec[i] >= 1) { + if (unlikely(w_vec[i] + .5 * sw_vec[i] >= 1)) { std::stringstream msg; msg << ", but must be smaller than 2*(1-A-priori bias) = " << 2 * (1 - w_vec[i]); @@ -386,10 +391,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, " = ", msg_str.c_str()); } } - if (!include_summand::value) { - return 0; - } + const double log_error_density = log(1e-6); // precision for density const double error_bound = precision_derivatives; // precision for @@ -400,7 +402,6 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, = .9 * error_bound; // eps_rel(Integration) const double log_error_absolute = log(1e-12); const int maximal_evaluations_hcubature = 6000; - double density = 0.0; double log_density = 0.0; auto ops_partials = make_partials_propagator(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref, sw_ref, st0_ref); @@ -422,31 +423,29 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const double sv_val = sv_vec.val(i); const double sw_val = sw_vec.val(i); const double st0_val = st0_vec.val(i); - const auto params - = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, - st0_val, log_error_absolute - LOG_TWO); const int dim = (sw_val != 0) + (st0_val != 0); check_positive(function_name, "(Inter-trial variability in A-priori bias) + " "(Inter-trial variability in nondecision time)", dim); - std::vector xmin(dim, 0); - std::vector xmax(dim, 1); + Eigen::VectorXd xmin = Eigen::VectorXd::Zero(dim); + Eigen::VectorXd xmax = Eigen::VectorXd::Ones(dim); if (st0_val) { xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); } double hcubature_err = log_error_absolute - log_error_density + LOG_TWO + 1; - - density = internal::wiener7_integrate( + const auto params + = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, + st0_val, log_error_absolute - LOG_TWO); + double density = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_density(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2); - const double log_dens = log(density); - log_density += log_dens; + log_density += log(density); hcubature_err = log_error_absolute - log_error_derivative + log(fabs(density)) + LOG_TWO + 1; @@ -568,8 +567,6 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, partials<7>(ops_partials)[i] = -1 / st0_val + f / st0_val / density; } } - std::vector().swap(xmin); - std::vector().swap(xmax); } return result + ops_partials.build(log_density); } From 0d188e949dbe6fd6652fe62f5c7e3eb2368bdb7f Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 1 Aug 2023 02:58:17 -0400 Subject: [PATCH 080/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/functor/hcubature.hpp | 6 ++++-- stan/math/prim/prob/wiener_full_lpdf.hpp | 3 +-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index f12eccdc966..4f0867d6ad3 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -521,10 +521,12 @@ double hcubature(const F& integrand, const ParsTuple& pars, const int dim, auto&& box = ms[err_idx]; double w = (box.b_[box.kdiv_] - box.a_[box.kdiv_]) / 2; - Eigen::VectorXd ma = Eigen::Map(box.a_.data(), box.a_.size()); + Eigen::VectorXd ma + = Eigen::Map(box.a_.data(), box.a_.size()); ma[box.kdiv_] += w; - Eigen::VectorXd mb = Eigen::Map(box.b_.data(), box.b_.size()); + Eigen::VectorXd mb + = Eigen::Map(box.b_.data(), box.b_.size()); mb[box.kdiv_] -= w; double result_1; diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 88e8e5246db..b0431524cb9 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -288,7 +288,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, T_st0>::value) { return 0; } - + using T_y_ref = ref_type_t; using T_a_ref = ref_type_t; using T_v_ref = ref_type_t; @@ -392,7 +392,6 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } } - const double log_error_density = log(1e-6); // precision for density const double error_bound = precision_derivatives; // precision for // derivatives (controllable by user) From 24759b4e6e8f80557aef315ac35b46c0538737a8 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 1 Aug 2023 10:39:22 +0200 Subject: [PATCH 081/179] changed test --- stan/math/prim/functor/hcubature.hpp | 25 ++++---- stan/math/prim/prob/wiener_full_lpdf.hpp | 3 +- .../unit/math/prim/functor/hcubature_test.cpp | 62 +++++++++---------- 3 files changed, 43 insertions(+), 47 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 4f0867d6ad3..4066d4999a2 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -192,10 +192,9 @@ template std::pair gauss_kronrod(const F& integrand, const double a, const double b, const ParsPairT& pars_pair) { - std::vector c(1, 0); - std::vector cp(1, 0); - std::vector cm(1, 0); - c[0] = 0.5 * (a + b); + Eigen::VectorXd c {{0.5 * (a + b)}}; + Eigen::VectorXd cp(1); + Eigen::VectorXd cm(1); double delta = 0.5 * (b - a); double f0 = math::apply( [&integrand, &c](auto&&... args) { return integrand(c, args...); }, @@ -308,10 +307,10 @@ std::tuple integrate_GenzMalik( double twelvef1 = 12 * f1; double maxdivdiff = 0.0; - std::vector divdiff(dim); - std::vector p2(dim); - std::vector p3(dim); - std::vector cc(dim, 0); + Eigen::VectorXd divdiff(dim); + Eigen::VectorXd p2(dim); + Eigen::VectorXd p3(dim); + Eigen::VectorXd cc(dim); for (std::size_t i = 0; i != dim; i++) { for (std::size_t j = 0; j != dim; j++) { @@ -352,7 +351,7 @@ std::tuple integrate_GenzMalik( f3 += f3i; divdiff[i] = fabs(f3i + twelvef1 - 7 * f2i); } - std::vector p4(dim); + Eigen::VectorXd p4(dim); double f4 = 0.0; for (std::size_t i = 0; i != points[2].cols(); i++) { for (std::size_t j = 0; j != dim; j++) { @@ -367,7 +366,7 @@ std::tuple integrate_GenzMalik( f4 += temp; } double f5 = 0.0; - std::vector p5(dim); + Eigen::VectorXd p5(dim); for (std::size_t i = 0; i != points[3].cols(); i++) { for (std::size_t j = 0; j != dim; j++) { p5[j] = deltac[j] * points[3](j, i); @@ -521,12 +520,10 @@ double hcubature(const F& integrand, const ParsTuple& pars, const int dim, auto&& box = ms[err_idx]; double w = (box.b_[box.kdiv_] - box.a_[box.kdiv_]) / 2; - Eigen::VectorXd ma - = Eigen::Map(box.a_.data(), box.a_.size()); + Eigen::VectorXd ma = Eigen::Map(box.a_.data(), box.a_.size()); ma[box.kdiv_] += w; - Eigen::VectorXd mb - = Eigen::Map(box.b_.data(), box.b_.size()); + Eigen::VectorXd mb = Eigen::Map(box.b_.data(), box.b_.size()); mb[box.kdiv_] -= w; double result_1; diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index b0431524cb9..88e8e5246db 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -288,7 +288,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, T_st0>::value) { return 0; } - + using T_y_ref = ref_type_t; using T_a_ref = ref_type_t; using T_v_ref = ref_type_t; @@ -392,6 +392,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } } + const double log_error_density = log(1e-6); // precision for density const double error_bound = precision_derivatives; // precision for // derivatives (controllable by user) diff --git a/test/unit/math/prim/functor/hcubature_test.cpp b/test/unit/math/prim/functor/hcubature_test.cpp index 26e0b647a91..2b1df83761d 100644 --- a/test/unit/math/prim/functor/hcubature_test.cpp +++ b/test/unit/math/prim/functor/hcubature_test.cpp @@ -105,8 +105,8 @@ stan::return_type_t f7(const T_x& x, double a) { template void test_integration(const F& f, const ArgsTupleT& pars, int dim, - std::vector a, std::vector b, int maxEval, - double reqAbsError, std::vector reqRelError, + const Eigen::VectorXd& a, const Eigen::VectorXd& b, int maxEval, + double reqAbsError, const Eigen::VectorXd& reqRelError, double val) { using stan::math::hcubature; @@ -122,46 +122,44 @@ TEST(StanMath_hcubature_prim, test1) { // https://www.quantargo.com/help/r/latest/packages/cubature/2.0.4.1/hcubature int dim = 1; - std::vector a = {0.0}; - std::vector b = {1.0}; - std::vector reqRelError = {1e-4, 1e-6, 1e-7}; - test_integration(hcubature_test::f1>, std::make_tuple(), + const Eigen::VectorXd a {{0.0}}; + const Eigen::VectorXd b {{1.0}}; + const Eigen::VectorXd reqRelError {{1e-4, 1e-6, 1e-7}}; + test_integration(hcubature_test::f1, std::make_tuple(), dim, a, b, 6000, 0.0, reqRelError, 0.841471); dim = 2; - a = {0.0, 0.0}; - b = {1.0, 1.0}; - reqRelError = {1e-4, 1e-6, 1e-7}; - test_integration(hcubature_test::f2>, std::make_tuple(), - dim, a, b, 6000, 0.0, reqRelError, 0.7080734); + const Eigen::VectorXd a_2 {{0.0, 0.0}}; + const Eigen::VectorXd b_2 {{1.0, 1.0}}; + test_integration(hcubature_test::f2, std::make_tuple(), + dim, a_2, b_2, 6000, 0.0, reqRelError, 0.7080734); - reqRelError = {1e-4}; - test_integration(hcubature_test::f3>, - std::make_tuple(0.50124145262344534123412), dim, a, b, 10000, - 0.0, reqRelError, 0.1972807); + const Eigen::VectorXd reqRelError_2 {{1e-4}}; + test_integration(hcubature_test::f3, + std::make_tuple(0.50124145262344534123412), dim, a_2, b_2, 10000, + 0.0, reqRelError_2, 0.1972807); // (Gaussian centered at 1/2) - reqRelError = {1e-4, 1e-6, 1e-7}; - test_integration(hcubature_test::f4>, - std::make_tuple(0.1), dim, a, b, 6000, 0.0, reqRelError, 1); + test_integration(hcubature_test::f4, + std::make_tuple(0.1), dim, a_2, b_2, 6000, 0.0, reqRelError, 1); dim = 3; - a = {0.0, 0.0, 0.0}; - b = {1.0, 1.0, 1.0}; - reqRelError = {1e-4, 1e-6}; - test_integration(hcubature_test::f5>, std::make_tuple(), - dim, a, b, 6000, 0.0, reqRelError, 1.00001); + const Eigen::VectorXd a_3 {{0.0, 0.0, 0.0}}; + const Eigen::VectorXd b_3 {{1.0, 1.0, 1.0}}; + const Eigen::VectorXd reqRelError_3 {{1e-4, 1e-6}}; + test_integration(hcubature_test::f5, std::make_tuple(), + dim, a_3, b_3, 6000, 0.0, reqRelError_3, 1.00001); - reqRelError = {1e-4, 1e-6, 1e-8}; - test_integration(hcubature_test::f6>, std::make_tuple(), - dim, a, b, 6000, 0.0, reqRelError, 1); + const Eigen::VectorXd reqRelError_4 {{1e-4, 1e-6, 1e-8}}; + test_integration(hcubature_test::f6, std::make_tuple(), + dim, a_3, b_3, 6000, 0.0, reqRelError_4, 1); // (Tsuda's example) dim = 4; - a = {0.0, 0.0, 0.0, 0.0}; - b = {1.0, 1.0, 1.0, 1.0}; - reqRelError = {1e-4, 1e-6}; - test_integration(hcubature_test::f7>, - std::make_tuple((1 + sqrt(10.0)) / 9.0), dim, a, b, 20000, - 0.0, reqRelError, 0.999998); + const Eigen::VectorXd a_4 {{0.0, 0.0, 0.0, 0.0}}; + const Eigen::VectorXd b_4 {{1.0, 1.0, 1.0, 1.0}}; + test_integration(hcubature_test::f7, + std::make_tuple((1 + sqrt(10.0)) / 9.0), dim, a_4, b_4, 20000, + 0.0, reqRelError_3, 0.999998); + } From 58b3e6b8b864b957ce05a2a87e03bb9427d2f530 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 1 Aug 2023 04:40:40 -0400 Subject: [PATCH 082/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/functor/hcubature.hpp | 8 ++-- stan/math/prim/prob/wiener_full_lpdf.hpp | 3 +- .../unit/math/prim/functor/hcubature_test.cpp | 42 +++++++++---------- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 4066d4999a2..e0668850be2 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -192,7 +192,7 @@ template std::pair gauss_kronrod(const F& integrand, const double a, const double b, const ParsPairT& pars_pair) { - Eigen::VectorXd c {{0.5 * (a + b)}}; + Eigen::VectorXd c{{0.5 * (a + b)}}; Eigen::VectorXd cp(1); Eigen::VectorXd cm(1); double delta = 0.5 * (b - a); @@ -520,10 +520,12 @@ double hcubature(const F& integrand, const ParsTuple& pars, const int dim, auto&& box = ms[err_idx]; double w = (box.b_[box.kdiv_] - box.a_[box.kdiv_]) / 2; - Eigen::VectorXd ma = Eigen::Map(box.a_.data(), box.a_.size()); + Eigen::VectorXd ma + = Eigen::Map(box.a_.data(), box.a_.size()); ma[box.kdiv_] += w; - Eigen::VectorXd mb = Eigen::Map(box.b_.data(), box.b_.size()); + Eigen::VectorXd mb + = Eigen::Map(box.b_.data(), box.b_.size()); mb[box.kdiv_] -= w; double result_1; diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 88e8e5246db..b0431524cb9 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -288,7 +288,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, T_st0>::value) { return 0; } - + using T_y_ref = ref_type_t; using T_a_ref = ref_type_t; using T_v_ref = ref_type_t; @@ -392,7 +392,6 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } } - const double log_error_density = log(1e-6); // precision for density const double error_bound = precision_derivatives; // precision for // derivatives (controllable by user) diff --git a/test/unit/math/prim/functor/hcubature_test.cpp b/test/unit/math/prim/functor/hcubature_test.cpp index 2b1df83761d..774b1464a56 100644 --- a/test/unit/math/prim/functor/hcubature_test.cpp +++ b/test/unit/math/prim/functor/hcubature_test.cpp @@ -105,9 +105,9 @@ stan::return_type_t f7(const T_x& x, double a) { template void test_integration(const F& f, const ArgsTupleT& pars, int dim, - const Eigen::VectorXd& a, const Eigen::VectorXd& b, int maxEval, - double reqAbsError, const Eigen::VectorXd& reqRelError, - double val) { + const Eigen::VectorXd& a, const Eigen::VectorXd& b, + int maxEval, double reqAbsError, + const Eigen::VectorXd& reqRelError, double val) { using stan::math::hcubature; for (auto tolerance : reqRelError) { @@ -122,44 +122,44 @@ TEST(StanMath_hcubature_prim, test1) { // https://www.quantargo.com/help/r/latest/packages/cubature/2.0.4.1/hcubature int dim = 1; - const Eigen::VectorXd a {{0.0}}; - const Eigen::VectorXd b {{1.0}}; - const Eigen::VectorXd reqRelError {{1e-4, 1e-6, 1e-7}}; + const Eigen::VectorXd a{{0.0}}; + const Eigen::VectorXd b{{1.0}}; + const Eigen::VectorXd reqRelError{{1e-4, 1e-6, 1e-7}}; test_integration(hcubature_test::f1, std::make_tuple(), dim, a, b, 6000, 0.0, reqRelError, 0.841471); dim = 2; - const Eigen::VectorXd a_2 {{0.0, 0.0}}; - const Eigen::VectorXd b_2 {{1.0, 1.0}}; + const Eigen::VectorXd a_2{{0.0, 0.0}}; + const Eigen::VectorXd b_2{{1.0, 1.0}}; test_integration(hcubature_test::f2, std::make_tuple(), dim, a_2, b_2, 6000, 0.0, reqRelError, 0.7080734); - const Eigen::VectorXd reqRelError_2 {{1e-4}}; + const Eigen::VectorXd reqRelError_2{{1e-4}}; test_integration(hcubature_test::f3, - std::make_tuple(0.50124145262344534123412), dim, a_2, b_2, 10000, - 0.0, reqRelError_2, 0.1972807); + std::make_tuple(0.50124145262344534123412), dim, a_2, b_2, + 10000, 0.0, reqRelError_2, 0.1972807); // (Gaussian centered at 1/2) test_integration(hcubature_test::f4, - std::make_tuple(0.1), dim, a_2, b_2, 6000, 0.0, reqRelError, 1); + std::make_tuple(0.1), dim, a_2, b_2, 6000, 0.0, reqRelError, + 1); dim = 3; - const Eigen::VectorXd a_3 {{0.0, 0.0, 0.0}}; - const Eigen::VectorXd b_3 {{1.0, 1.0, 1.0}}; - const Eigen::VectorXd reqRelError_3 {{1e-4, 1e-6}}; + const Eigen::VectorXd a_3{{0.0, 0.0, 0.0}}; + const Eigen::VectorXd b_3{{1.0, 1.0, 1.0}}; + const Eigen::VectorXd reqRelError_3{{1e-4, 1e-6}}; test_integration(hcubature_test::f5, std::make_tuple(), dim, a_3, b_3, 6000, 0.0, reqRelError_3, 1.00001); - const Eigen::VectorXd reqRelError_4 {{1e-4, 1e-6, 1e-8}}; + const Eigen::VectorXd reqRelError_4{{1e-4, 1e-6, 1e-8}}; test_integration(hcubature_test::f6, std::make_tuple(), dim, a_3, b_3, 6000, 0.0, reqRelError_4, 1); // (Tsuda's example) dim = 4; - const Eigen::VectorXd a_4 {{0.0, 0.0, 0.0, 0.0}}; - const Eigen::VectorXd b_4 {{1.0, 1.0, 1.0, 1.0}}; + const Eigen::VectorXd a_4{{0.0, 0.0, 0.0, 0.0}}; + const Eigen::VectorXd b_4{{1.0, 1.0, 1.0, 1.0}}; test_integration(hcubature_test::f7, - std::make_tuple((1 + sqrt(10.0)) / 9.0), dim, a_4, b_4, 20000, - 0.0, reqRelError_3, 0.999998); - + std::make_tuple((1 + sqrt(10.0)) / 9.0), dim, a_4, b_4, + 20000, 0.0, reqRelError_3, 0.999998); } From b36ce4230108259c6575d364f988c41479122ee8 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 1 Aug 2023 11:43:07 +0200 Subject: [PATCH 083/179] delete ErrIndex --- stan/math/prim/prob/wiener5_lpdf.hpp | 13 +++++++------ stan/math/prim/prob/wiener_full_lpdf.hpp | 6 +++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index c3bc2df9669..2a7a0c9d659 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -525,7 +525,7 @@ inline void assign_err(std::tuple& args_tuple, double err) { * @param args_tuple Tuple of arguments to pass to functor * @param log_result Whether the function result is already on the log-scale */ -template double estimate_with_err_check(const F& functor, double err, ArgsTupleT&&... args_tuple) { @@ -534,9 +534,10 @@ double estimate_with_err_check(const F& functor, double err, if (log_fabs_result < err) { log_fabs_result = std::isinf(log_fabs_result) ? 0 : log_fabs_result; auto err_args_tuple = std::make_tuple(args_tuple...); + const int size_tuple = std::tuple_size::value - 1; const double new_error = GradW7 ? err + log_fabs_result + LOG_TWO : err + log_fabs_result; - assign_err(std::get(err_args_tuple), new_error); + assign_err(std::get(err_args_tuple), new_error); result = math::apply([&](auto&&... args) { return functor(args...); }, err_args_tuple); } @@ -658,7 +659,7 @@ inline return_type_t wiener5_lpdf( const double v_val = v_vec.val(i); const double sv_val = sv_vec.val(i); - density = internal::estimate_with_err_check<5, false, 0, false>( + density = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener5_density(args...); }, log_error_density - LOG_TWO, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); @@ -668,7 +669,7 @@ inline return_type_t wiener5_lpdf( // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 - const double deriv_y = internal::estimate_with_err_check<5>( + const double deriv_y = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener5_grad_t(args...); }, new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); @@ -678,7 +679,7 @@ inline return_type_t wiener5_lpdf( ops_partials.edge1_.partials_[i] = deriv_y; } if (!is_constant_all::value) { - ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check<5>( + ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener5_grad_a(args...); }, new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); @@ -687,7 +688,7 @@ inline return_type_t wiener5_lpdf( ops_partials.edge3_.partials_[i] = -deriv_y; } if (!is_constant_all::value) { - ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check<5>( + ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener5_grad_w(args...); }, new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index b0431524cb9..01a5f24169e 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -129,7 +129,7 @@ auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, const auto functor = [&](auto&&... int_args) { return hcubature(wiener7_integrand_impl, int_args...); }; - return estimate_with_err_check<0, GradW7, 8>(functor, hcubature_err, args...); + return estimate_with_err_check(functor, hcubature_err, args...); } } // namespace internal @@ -518,7 +518,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, partials<6>(ops_partials)[i] = 0; } else { if (st0_val == 0) { - derivative = internal::estimate_with_err_check<5>( + derivative = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener7_grad_sw(args...); }, @@ -545,7 +545,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } else { const double t0_st0 = t0_val + st0_val; if (sw_val == 0) { - f = internal::estimate_with_err_check<5>( + f = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener5_density(args...); }, From e3eeb1967d78990c9036b7302c899df1d9f2b742 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 1 Aug 2023 05:44:32 -0400 Subject: [PATCH 084/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 2a7a0c9d659..159355d3fe3 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -525,8 +525,8 @@ inline void assign_err(std::tuple& args_tuple, double err) { * @param args_tuple Tuple of arguments to pass to functor * @param log_result Whether the function result is already on the log-scale */ -template +template double estimate_with_err_check(const F& functor, double err, ArgsTupleT&&... args_tuple) { double result = functor(args_tuple...); @@ -534,7 +534,7 @@ double estimate_with_err_check(const F& functor, double err, if (log_fabs_result < err) { log_fabs_result = std::isinf(log_fabs_result) ? 0 : log_fabs_result; auto err_args_tuple = std::make_tuple(args_tuple...); - const int size_tuple = std::tuple_size::value - 1; + const int size_tuple = std::tuple_size::value - 1; const double new_error = GradW7 ? err + log_fabs_result + LOG_TWO : err + log_fabs_result; assign_err(std::get(err_args_tuple), new_error); From ddc6247ca7c22b4e02fbe1b12505abe3031ee374 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 1 Aug 2023 12:55:44 +0200 Subject: [PATCH 085/179] back to ErrIndex --- stan/math/prim/prob/wiener5_lpdf.hpp | 14 +++++++------- stan/math/prim/prob/wiener_full_lpdf.hpp | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 159355d3fe3..0d4bf449965 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -525,7 +525,7 @@ inline void assign_err(std::tuple& args_tuple, double err) { * @param args_tuple Tuple of arguments to pass to functor * @param log_result Whether the function result is already on the log-scale */ -template double estimate_with_err_check(const F& functor, double err, ArgsTupleT&&... args_tuple) { @@ -534,10 +534,10 @@ double estimate_with_err_check(const F& functor, double err, if (log_fabs_result < err) { log_fabs_result = std::isinf(log_fabs_result) ? 0 : log_fabs_result; auto err_args_tuple = std::make_tuple(args_tuple...); - const int size_tuple = std::tuple_size::value - 1; + //const int size_tuple = std::tuple_size::value - 1; const double new_error = GradW7 ? err + log_fabs_result + LOG_TWO : err + log_fabs_result; - assign_err(std::get(err_args_tuple), new_error); + assign_err(std::get(err_args_tuple), new_error); result = math::apply([&](auto&&... args) { return functor(args...); }, err_args_tuple); } @@ -659,7 +659,7 @@ inline return_type_t wiener5_lpdf( const double v_val = v_vec.val(i); const double sv_val = sv_vec.val(i); - density = internal::estimate_with_err_check( + density = internal::estimate_with_err_check<5, false, 0, false>( [&](auto&&... args) { return internal::wiener5_density(args...); }, log_error_density - LOG_TWO, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); @@ -669,7 +669,7 @@ inline return_type_t wiener5_lpdf( // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 - const double deriv_y = internal::estimate_with_err_check( + const double deriv_y = internal::estimate_with_err_check<5>( [&](auto&&... args) { return internal::wiener5_grad_t(args...); }, new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); @@ -679,7 +679,7 @@ inline return_type_t wiener5_lpdf( ops_partials.edge1_.partials_[i] = deriv_y; } if (!is_constant_all::value) { - ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check( + ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check<5>( [&](auto&&... args) { return internal::wiener5_grad_a(args...); }, new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); @@ -688,7 +688,7 @@ inline return_type_t wiener5_lpdf( ops_partials.edge3_.partials_[i] = -deriv_y; } if (!is_constant_all::value) { - ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check( + ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check<5>( [&](auto&&... args) { return internal::wiener5_grad_w(args...); }, new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 01a5f24169e..6970a4f604d 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -129,7 +129,7 @@ auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, const auto functor = [&](auto&&... int_args) { return hcubature(wiener7_integrand_impl, int_args...); }; - return estimate_with_err_check(functor, hcubature_err, args...); + return estimate_with_err_check<0, GradW7, 8>(functor, hcubature_err, args...); } } // namespace internal @@ -518,7 +518,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, partials<6>(ops_partials)[i] = 0; } else { if (st0_val == 0) { - derivative = internal::estimate_with_err_check( + derivative = internal::estimate_with_err_check<6>( [&](auto&&... args) { return internal::wiener7_grad_sw(args...); }, @@ -545,7 +545,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } else { const double t0_st0 = t0_val + st0_val; if (sw_val == 0) { - f = internal::estimate_with_err_check( + f = internal::estimate_with_err_check<5>( [&](auto&&... args) { return internal::wiener5_density(args...); }, From 3fe5b71575dd1114ffa8d208ee597a43f206563d Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 1 Aug 2023 06:57:18 -0400 Subject: [PATCH 086/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 0d4bf449965..7fcba541c05 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -525,8 +525,8 @@ inline void assign_err(std::tuple& args_tuple, double err) { * @param args_tuple Tuple of arguments to pass to functor * @param log_result Whether the function result is already on the log-scale */ -template +template double estimate_with_err_check(const F& functor, double err, ArgsTupleT&&... args_tuple) { double result = functor(args_tuple...); @@ -534,7 +534,8 @@ double estimate_with_err_check(const F& functor, double err, if (log_fabs_result < err) { log_fabs_result = std::isinf(log_fabs_result) ? 0 : log_fabs_result; auto err_args_tuple = std::make_tuple(args_tuple...); - //const int size_tuple = std::tuple_size::value - 1; + // const int size_tuple = std::tuple_size::value - + // 1; const double new_error = GradW7 ? err + log_fabs_result + LOG_TWO : err + log_fabs_result; assign_err(std::get(err_args_tuple), new_error); From 6142042e94c7705353239d8030f857e913289f52 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 9 Aug 2023 14:15:58 -0400 Subject: [PATCH 087/179] start setting up code to be vectorized --- stan/math/prim/prob/wiener5_lpdf.hpp | 103 ++++++++++++----------- stan/math/prim/prob/wiener_full_lpdf.hpp | 53 +++++++----- 2 files changed, 83 insertions(+), 73 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 7fcba541c05..b1fa5c3ffa5 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -16,20 +16,22 @@ namespace internal { * @param sv The inter-trial variability of the drift rate * @return 'error_term' term */ -inline double wiener5_compute_error_term(double y, double a, double v_value, - double w_value, double sv) noexcept { - const double w = 1.0 - w_value; - const double v = -v_value; - const double sv_sqr = square(sv); - const double one_plus_svsqr_y = 1 + sv_sqr * y; - const double two_avw = 2 * a * v * w; - const double two_log_a = 2 * log(a); +template +inline auto wiener5_compute_error_term(T_y&& y, T_a&& a, T_v&& v_value, + T_w&& w_value, T_sv&& sv) noexcept { + const auto w = 1.0 - w_value; + const auto v = -v_value; + const auto sv_sqr = square(sv); + const auto one_plus_svsqr_y = 1 + sv_sqr * y; + const auto two_avw = 2 * a * v * w; + const auto two_log_a = 2 * log(a); if (sv != 0) { - return (sv_sqr * square(a * w) - two_avw - square(v) * y) / 2.0 + return stan::math::eval((sv_sqr * square(a * w) - two_avw - square(v) * y) / 2.0 / one_plus_svsqr_y - - two_log_a - 0.5 * log(one_plus_svsqr_y); + - two_log_a - 0.5 * log(one_plus_svsqr_y)); } else { - return (-two_avw - square(v) * y) / 2.0 - two_log_a; + return stan::math::eval((-two_avw - square(v) * y) / 2.0 - two_log_a); } } @@ -173,35 +175,33 @@ inline double wiener5_n_terms_largel_t(double y, double a, double w_value, * @param n_terms_large_t The n_terms_large_t term * @return 'result' sum and its sign */ -template -inline std::tuple wiener5_log_sum_exp( - double y, double a, double w_value, size_t n_terms_small_t, - size_t n_terms_large_t) noexcept { - const double y_asq = y / square(a); - const double w = 1.0 - w_value; +template +inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, T_nsmall&& n_terms_small_t, T_nlarge&& n_terms_large_t) noexcept { + const auto y_asq = y / square(a); + const auto w = 1.0 - w_value; const bool small_n_terms_small_t = Density ? (2 * n_terms_small_t <= n_terms_large_t) : (2 * n_terms_small_t < n_terms_large_t); - const double scaling = small_n_terms_small_t ? inv(2.0 * y_asq) : y_asq / 2.0; + const auto scaling = small_n_terms_small_t ? inv(2.0 * y_asq) : y_asq / 2.0; - double prev_val = NEGATIVE_INFTY; - double current_val = NEGATIVE_INFTY; + auto prev_val = NEGATIVE_INFTY; + auto current_val = NEGATIVE_INFTY; int prev_sign = 1; int current_sign = 1; if (small_n_terms_small_t) { - const double mult = Density ? 1 : 3; - const double offset = GradW ? y_asq : 0; - const double sqrt_offset = sqrt(offset); + const auto mult = Density ? 1 : 3; + const auto offset = GradW ? y_asq : 0; + const auto sqrt_offset = sqrt(offset); for (size_t k = n_terms_small_t; k >= 1; k--) { - const double wp2k = w + 2.0 * k; - const double wm2k = w - 2.0 * k; + const auto wp2k = w + 2.0 * k; + const auto wm2k = w - 2.0 * k; int wp2k_sign = (wp2k > sqrt_offset) ?: 1 - 1; int wm2k_sign = (wm2k > sqrt_offset) ? 1 : -1; - double wp2k_quant + auto wp2k_quant = GradW ? log(fabs((square(wp2k) - offset))) - square(wp2k) * scaling : mult * log(wp2k_sign * wp2k) - square(wp2k) * scaling; - double wm2k_quant + auto wm2k_quant = GradW ? log(fabs((square(wm2k) - offset))) - square(wm2k) * scaling : mult * log(wm2k_sign * wm2k) - square(wm2k) * scaling; double k_term; @@ -213,7 +213,7 @@ inline std::tuple wiener5_log_sum_exp( prev_val = current_val; prev_sign = current_sign; } - double new_val = GradW ? log(fabs(square(w) - offset)) - square(w) * scaling + auto new_val = GradW ? log(fabs(square(w) - offset)) - square(w) * scaling : mult * log(w) - square(w) * scaling; int new_val_sign = GradW ? (w > sqrt_offset ? 1 : -1) : (new_val > 0 ? 1 : -1); @@ -240,7 +240,7 @@ inline std::tuple wiener5_log_sum_exp( prev_sign = current_sign; } } - return std::make_tuple(current_val, current_sign); + return std::make_pair(current_val, current_sign); } /** @@ -261,27 +261,25 @@ template inline double wiener5_density(double y, double a, double v_value, double w_value, double sv, double err = log(1e-12)) noexcept { - const double error_term + const auto error_term = wiener5_compute_error_term(y, a, v_value, w_value, sv); - const double error = (err - error_term); - const double n_terms_small_t + const auto error = (err - error_term); + const auto n_terms_small_t = wiener5_n_terms_small_t(y, a, w_value, error); - const double n_terms_large_t + const auto n_terms_large_t = wiener5_n_terms_largel_t(y, a, w_value, error); - double result; - int newsign; - double log_density; - std::forward_as_tuple(result, newsign) = wiener5_log_sum_exp( - y, a, w_value, n_terms_small_t, n_terms_large_t); + // 0 is result, 1 is newwsign + auto res = wiener5_log_sum_exp( + y, a, w_value, n_terms_small_t, n_terms_large_t).first; if (2 * n_terms_small_t <= n_terms_large_t) { - log_density = error_term - 0.5 * LOG_TWO - LOG_SQRT_PI - - 1.5 * (log(y) - 2 * log(a)) + result; + auto log_density = error_term - 0.5 * LOG_TWO - LOG_SQRT_PI + - 1.5 * (log(y) - 2 * log(a)) + res; + return NaturalScale ? exp(log_density) : log_density; } else { - log_density = error_term + result + LOG_PI; + auto log_density = error_term + res + LOG_PI; + return NaturalScale ? exp(log_density) : log_density; } - - return NaturalScale ? exp(log_density) : log_density; } /** @@ -572,14 +570,14 @@ template wiener5_lpdf( const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, const T_sv& sv, const double& precision_derivatives) { - using T_y_ref = ref_type_t; - using T_a_ref = ref_type_t; - using T_t0_ref = ref_type_t; - using T_w_ref = ref_type_t; - using T_v_ref = ref_type_t; - using T_sv_ref = ref_type_t; - - const char* function_name = "wiener5_lpdf"; + using T_y_ref = ref_type_if_t::value, T_y>; + using T_a_ref = ref_type_if_t::value, T_a>; + using T_t0_ref = ref_type_if_t::value, T_t0>; + using T_w_ref = ref_type_if_t::value, T_w>; + using T_v_ref = ref_type_if_t::value, T_v>; + using T_sv_ref = ref_type_if_t::value, T_sv>; + + static constexpr const char* function_name = "wiener5_lpdf"; if (size_zero(y, a, t0, w, v, sv)) { return 0; } @@ -591,6 +589,8 @@ inline return_type_t wiener5_lpdf( "Boundary separation", a, "Drift rate", v, "A-priori bias", w, "Nondecision time", t0, "Inter-trial variability in drift rate", sv); + + /* check_consistent_size(function_name, "Random variable", y, 1); check_consistent_size(function_name, "Boundary separation", a, 1); check_consistent_size(function_name, "Nondecision time", t0, 1); @@ -598,6 +598,7 @@ inline return_type_t wiener5_lpdf( check_consistent_size(function_name, "Drift rate", v, 1); check_consistent_size(function_name, "Inter-trial variability in drift rate", sv, 1); + */ T_y_ref y_ref = y; T_a_ref a_ref = a; diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 6970a4f604d..6cb5ddc3f1a 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -289,22 +289,23 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, return 0; } - using T_y_ref = ref_type_t; - using T_a_ref = ref_type_t; - using T_v_ref = ref_type_t; - using T_w_ref = ref_type_t; - using T_t0_ref = ref_type_t; - using T_sv_ref = ref_type_t; - using T_sw_ref = ref_type_t; - using T_st0_ref = ref_type_t; + using T_y_ref = ref_type_if_t::value, T_y>; + using T_a_ref = ref_type_if_t::value, T_a>; + using T_v_ref = ref_type_if_t::value, T_v>; + using T_w_ref = ref_type_if_t::value, T_w>; + using T_t0_ref = ref_type_if_t::value, T_t0>; + using T_sv_ref = ref_type_if_t::value, T_sv>; + using T_sw_ref = ref_type_if_t::value, T_sw>; + using T_st0_ref = ref_type_if_t::value, T_st0>; - const char* function_name = "wiener_full_lpdf"; + static constexpr const char* function_name = "wiener_full_lpdf"; check_consistent_sizes(function_name, "Random variable", y, "Boundary separation", a, "Drift rate", v, "A-priori bias", w, "Nondecision time", t0, "Inter-trial variability in drift rate", sv, "Inter-trial variability in A-priori bias", sw, "Inter-trial variability in Nondecision time", st0); + /* This should support mixes of scalars and vectors check_consistent_size(function_name, "Random variable", y, 1); check_consistent_size(function_name, "Boundary separation", a, 1); check_consistent_size(function_name, "Drift rate", v, 1); @@ -316,7 +317,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, "Inter-trial variability in A-priori bias", sw, 1); check_consistent_size(function_name, "Inter-trial variability in Nondecision time", st0, 1); - + */ T_y_ref y_ref = y; T_a_ref a_ref = a; T_v_ref v_ref = v; @@ -326,24 +327,32 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, T_sw_ref sw_ref = sw; T_st0_ref st0_ref = st0; - check_positive_finite(function_name, "Random variable", value_of(y_ref)); - check_positive_finite(function_name, "Boundary separation", value_of(a_ref)); - check_finite(function_name, "Drift rate", value_of(v_ref)); - check_less(function_name, "A-priori bias", value_of(w_ref), 1); - check_greater(function_name, "A-priori bias", value_of(w_ref), 0); - check_nonnegative(function_name, "Nondecision time", value_of(t0_ref)); - check_finite(function_name, "Nondecision time", value_of(t0_ref)); + decltype(auto) y_val = to_ref(as_value_column_array_or_scalar(y_ref)); + decltype(auto) a_val = to_ref(as_value_column_array_or_scalar(a_ref)); + decltype(auto) v_val = to_ref(as_value_column_array_or_scalar(v_ref)); + decltype(auto) w_val = to_ref(as_value_column_array_or_scalar(w_ref)); + decltype(auto) t0_val = to_ref(as_value_column_array_or_scalar(t0_ref)); + decltype(auto) sv_val = to_ref(as_value_column_array_or_scalar(sv_ref)); + decltype(auto) sw_val = to_ref(as_value_column_array_or_scalar(sw_ref)); + decltype(auto) st0_val = to_ref(as_value_column_array_or_scalar(st0_ref)); + check_positive_finite(function_name, "Random variable", y_val); + check_positive_finite(function_name, "Boundary separation", a_val); + check_finite(function_name, "Drift rate", v_val); + check_less(function_name, "A-priori bias", w_val, 1); + check_greater(function_name, "A-priori bias", w_val, 0); + check_nonnegative(function_name, "Nondecision time", t0_val); + check_finite(function_name, "Nondecision time", t0_val); check_nonnegative(function_name, "Inter-trial variability in drift rate", - value_of(sv_ref)); + sv_val); check_finite(function_name, "Inter-trial variability in drift rate", - value_of(sv_ref)); + sv_val); check_bounded(function_name, "Inter-trial variability in A-priori bias", - value_of(sw_ref), 0, 1); + sw_val, 0, 1); check_nonnegative(function_name, "Inter-trial variability in Nondecision time", - value_of(st0_ref)); + st0_val); check_finite(function_name, "Inter-trial variability in Nondecision time", - value_of(st0_ref)); + st0_val); if (size_zero(y, a, v, w, t0) || size_zero(sv, sw, st0)) { return 0; From d583d0c1596e4ec4242c187331ca2840426f1002 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Thu, 10 Aug 2023 09:18:57 +0200 Subject: [PATCH 088/179] bugfix wiener5, cite Henrich et al. --- stan/math/prim/prob/wiener5_lpdf.hpp | 2 +- stan/math/prim/prob/wiener_full_lpdf.hpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 7fcba541c05..6a0777cc5d3 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -196,7 +196,7 @@ inline std::tuple wiener5_log_sum_exp( for (size_t k = n_terms_small_t; k >= 1; k--) { const double wp2k = w + 2.0 * k; const double wm2k = w - 2.0 * k; - int wp2k_sign = (wp2k > sqrt_offset) ?: 1 - 1; + int wp2k_sign = (wp2k > sqrt_offset) ? 1 : -1; int wm2k_sign = (wm2k > sqrt_offset) ? 1 : -1; double wp2k_quant = GradW ? log(fabs((square(wp2k) - offset))) - square(wp2k) * scaling diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 6970a4f604d..71d9d86ef53 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -270,6 +270,9 @@ auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, * first-passage time distribution in Wiener diffusion models. * *Journal of Mathematical Psychology, 103*, 102550. * https://doi.org/10.1016/j.jmp.2021.102550 + * - Henrich, F., Hartmann, R., Pratz, V., Voss, A., & Klauer, K.C. (in press). + * The Seven-parameter Diffusion Model: An Implementation in Stan for Bayesian + * Analyses. *Behavior Research Methods*. * - Navarro, D. J., & Fuss, I. G. (2009). Fast and accurate calculations for * first-passage times in Wiener diffusion models. * *Journal of Mathematical Psychology, 53*(4), 222–230. From 3e8cedd0fd7ff50338ce28b0e3068a8c51d9b9cb Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 11 Aug 2023 13:19:08 +0200 Subject: [PATCH 089/179] change [=] to [&] in rev test --- test/unit/math/rev/prob/wiener_full_test.cpp | 32 ++++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/test/unit/math/rev/prob/wiener_full_test.cpp b/test/unit/math/rev/prob/wiener_full_test.cpp index 3097afefefe..e13a51e84f6 100644 --- a/test/unit/math/rev/prob/wiener_full_test.cpp +++ b/test/unit/math/rev/prob/wiener_full_test.cpp @@ -68,49 +68,49 @@ TEST(ProbWienerFull, wiener_full_all_scalar) { for (int i = 0; i < result.size(); i++) { // rt - auto f_rt = [=](auto value) { + auto f_rt = [&](auto value) { return wiener_full_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_rt, rt[i], result[i], drt[i]); // a - auto f_a = [=](auto value) { + auto f_a = [&](auto value) { return wiener_full_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_a, a[i], result[i], da[i]); // v - auto f_v = [=](auto value) { + auto f_v = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], st0[i]); }; check_scalar_types(f_v, v[i], result[i], dv[i]); // w - auto f_w = [=](auto value) { + auto f_w = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_w, w[i], result[i], dw[i]); // t0 - auto f_t0 = [=](auto value) { + auto f_t0 = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_t0, t0[i], result[i], dt0[i]); // sv - auto f_sv = [=](auto value) { + auto f_sv = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], st0[i]); }; check_scalar_types(f_sv, sv[i], result[i], dsv[i]); // sw - auto f_sw = [=](auto value) { + auto f_sw = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, st0[i]); }; check_scalar_types(f_sw, sw[i], result[i], dsw[i]); // st0 - auto f_st0 = [=](auto value) { + auto f_st0 = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], value); }; @@ -158,49 +158,49 @@ TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { for (int i = 0; i < result.size(); i++) { // rt - auto f_rt = [=](auto value) { + auto f_rt = [&](auto value) { return wiener_full_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types(f_rt, rt[i], result[i], drt[i]); // a - auto f_a = [=](auto value) { + auto f_a = [&](auto value) { return wiener_full_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types(f_a, a[i], result[i], da[i]); // v - auto f_v = [=](auto value) { + auto f_v = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types(f_v, v[i], result[i], dv[i]); // w - auto f_w = [=](auto value) { + auto f_w = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types(f_w, w[i], result[i], dw[i]); // t0 - auto f_t0 = [=](auto value) { + auto f_t0 = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types(f_t0, t0[i], result[i], dt0[i]); // sv - auto f_sv = [=](auto value) { + auto f_sv = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], st0[i], 1e-6); }; check_scalar_types(f_sv, sv[i], result[i], dsv[i]); // sw - auto f_sw = [=](auto value) { + auto f_sw = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, st0[i], 1e-6); }; check_scalar_types(f_sw, sw[i], result[i], dsw[i]); // st0 - auto f_st0 = [=](auto value) { + auto f_st0 = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], value, 1e-6); }; From d0bf1257b38620a35a0f6d60662ad826506bc2de Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 11 Aug 2023 13:25:14 +0200 Subject: [PATCH 090/179] merge verctorization --- stan/math/prim/prob/wiener5_lpdf.hpp | 2 +- stan/math/prim/prob/wiener_full_lpdf.hpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index b1fa5c3ffa5..115821b95d8 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -196,7 +196,7 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, T_nsmall&& n_te for (size_t k = n_terms_small_t; k >= 1; k--) { const auto wp2k = w + 2.0 * k; const auto wm2k = w - 2.0 * k; - int wp2k_sign = (wp2k > sqrt_offset) ?: 1 - 1; + int wp2k_sign = (wp2k > sqrt_offset) ? 1: - 1; int wm2k_sign = (wm2k > sqrt_offset) ? 1 : -1; auto wp2k_quant = GradW ? log(fabs((square(wp2k) - offset))) - square(wp2k) * scaling diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 6cb5ddc3f1a..2fff988b2d1 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -270,6 +270,9 @@ auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, * first-passage time distribution in Wiener diffusion models. * *Journal of Mathematical Psychology, 103*, 102550. * https://doi.org/10.1016/j.jmp.2021.102550 + * - Henrich, F., Hartmann, R., Pratz, V., Voss, A., & Klauer, K.C. (in press). + * The Seven-parameter Diffusion Model: An Implementation in Stan for Bayesian + * Analyses. *Behavior Research Methods*. * - Navarro, D. J., & Fuss, I. G. (2009). Fast and accurate calculations for * first-passage times in Wiener diffusion models. * *Journal of Mathematical Psychology, 53*(4), 222–230. From fb33e7434809f8d46e13de52703e3d76c7d30d9e Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 11 Aug 2023 13:19:08 +0200 Subject: [PATCH 091/179] change [=] to [&] in rev test --- test/unit/math/rev/prob/wiener_full_test.cpp | 32 ++++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/test/unit/math/rev/prob/wiener_full_test.cpp b/test/unit/math/rev/prob/wiener_full_test.cpp index 3097afefefe..e13a51e84f6 100644 --- a/test/unit/math/rev/prob/wiener_full_test.cpp +++ b/test/unit/math/rev/prob/wiener_full_test.cpp @@ -68,49 +68,49 @@ TEST(ProbWienerFull, wiener_full_all_scalar) { for (int i = 0; i < result.size(); i++) { // rt - auto f_rt = [=](auto value) { + auto f_rt = [&](auto value) { return wiener_full_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_rt, rt[i], result[i], drt[i]); // a - auto f_a = [=](auto value) { + auto f_a = [&](auto value) { return wiener_full_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_a, a[i], result[i], da[i]); // v - auto f_v = [=](auto value) { + auto f_v = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], st0[i]); }; check_scalar_types(f_v, v[i], result[i], dv[i]); // w - auto f_w = [=](auto value) { + auto f_w = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_w, w[i], result[i], dw[i]); // t0 - auto f_t0 = [=](auto value) { + auto f_t0 = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_t0, t0[i], result[i], dt0[i]); // sv - auto f_sv = [=](auto value) { + auto f_sv = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], st0[i]); }; check_scalar_types(f_sv, sv[i], result[i], dsv[i]); // sw - auto f_sw = [=](auto value) { + auto f_sw = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, st0[i]); }; check_scalar_types(f_sw, sw[i], result[i], dsw[i]); // st0 - auto f_st0 = [=](auto value) { + auto f_st0 = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], value); }; @@ -158,49 +158,49 @@ TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { for (int i = 0; i < result.size(); i++) { // rt - auto f_rt = [=](auto value) { + auto f_rt = [&](auto value) { return wiener_full_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types(f_rt, rt[i], result[i], drt[i]); // a - auto f_a = [=](auto value) { + auto f_a = [&](auto value) { return wiener_full_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types(f_a, a[i], result[i], da[i]); // v - auto f_v = [=](auto value) { + auto f_v = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types(f_v, v[i], result[i], dv[i]); // w - auto f_w = [=](auto value) { + auto f_w = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types(f_w, w[i], result[i], dw[i]); // t0 - auto f_t0 = [=](auto value) { + auto f_t0 = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types(f_t0, t0[i], result[i], dt0[i]); // sv - auto f_sv = [=](auto value) { + auto f_sv = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], st0[i], 1e-6); }; check_scalar_types(f_sv, sv[i], result[i], dsv[i]); // sw - auto f_sw = [=](auto value) { + auto f_sw = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, st0[i], 1e-6); }; check_scalar_types(f_sw, sw[i], result[i], dsw[i]); // st0 - auto f_st0 = [=](auto value) { + auto f_st0 = [&](auto value) { return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], value, 1e-6); }; From def6d26f2b15ca64258074b2b0b2e1e52887a2f8 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Fri, 11 Aug 2023 07:29:53 -0400 Subject: [PATCH 092/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 27 +++++++++++++----------- stan/math/prim/prob/wiener_full_lpdf.hpp | 6 ++---- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 31e2a95cd27..34a1424d2bf 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -16,10 +16,9 @@ namespace internal { * @param sv The inter-trial variability of the drift rate * @return 'error_term' term */ -template +template inline auto wiener5_compute_error_term(T_y&& y, T_a&& a, T_v&& v_value, - T_w&& w_value, T_sv&& sv) noexcept { + T_w&& w_value, T_sv&& sv) noexcept { const auto w = 1.0 - w_value; const auto v = -v_value; const auto sv_sqr = square(sv); @@ -27,9 +26,9 @@ inline auto wiener5_compute_error_term(T_y&& y, T_a&& a, T_v&& v_value, const auto two_avw = 2 * a * v * w; const auto two_log_a = 2 * log(a); if (sv != 0) { - return stan::math::eval((sv_sqr * square(a * w) - two_avw - square(v) * y) / 2.0 - / one_plus_svsqr_y - - two_log_a - 0.5 * log(one_plus_svsqr_y)); + return stan::math::eval((sv_sqr * square(a * w) - two_avw - square(v) * y) + / 2.0 / one_plus_svsqr_y + - two_log_a - 0.5 * log(one_plus_svsqr_y)); } else { return stan::math::eval((-two_avw - square(v) * y) / 2.0 - two_log_a); } @@ -175,8 +174,11 @@ inline double wiener5_n_terms_largel_t(double y, double a, double w_value, * @param n_terms_large_t The n_terms_large_t term * @return 'result' sum and its sign */ -template -inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, T_nsmall&& n_terms_small_t, T_nlarge&& n_terms_large_t) noexcept { +template +inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, + T_nsmall&& n_terms_small_t, + T_nlarge&& n_terms_large_t) noexcept { const auto y_asq = y / square(a); const auto w = 1.0 - w_value; const bool small_n_terms_small_t @@ -214,7 +216,7 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, T_nsmall&& n_te prev_sign = current_sign; } auto new_val = GradW ? log(fabs(square(w) - offset)) - square(w) * scaling - : mult * log(w) - square(w) * scaling; + : mult * log(w) - square(w) * scaling; int new_val_sign = GradW ? (w > sqrt_offset ? 1 : -1) : (new_val > 0 ? 1 : -1); int factor_sign = GradW ? 1 : -1; @@ -270,11 +272,12 @@ inline double wiener5_density(double y, double a, double v_value, = wiener5_n_terms_largel_t(y, a, w_value, error); // 0 is result, 1 is newwsign - auto res = wiener5_log_sum_exp( - y, a, w_value, n_terms_small_t, n_terms_large_t).first; + auto res = wiener5_log_sum_exp(y, a, w_value, n_terms_small_t, + n_terms_large_t) + .first; if (2 * n_terms_small_t <= n_terms_large_t) { auto log_density = error_term - 0.5 * LOG_TWO - LOG_SQRT_PI - - 1.5 * (log(y) - 2 * log(a)) + res; + - 1.5 * (log(y) - 2 * log(a)) + res; return NaturalScale ? exp(log_density) : log_density; } else { auto log_density = error_term + res + LOG_PI; diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 2fff988b2d1..adb411e4fdb 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -347,13 +347,11 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, check_finite(function_name, "Nondecision time", t0_val); check_nonnegative(function_name, "Inter-trial variability in drift rate", sv_val); - check_finite(function_name, "Inter-trial variability in drift rate", - sv_val); + check_finite(function_name, "Inter-trial variability in drift rate", sv_val); check_bounded(function_name, "Inter-trial variability in A-priori bias", sw_val, 0, 1); check_nonnegative(function_name, - "Inter-trial variability in Nondecision time", - st0_val); + "Inter-trial variability in Nondecision time", st0_val); check_finite(function_name, "Inter-trial variability in Nondecision time", st0_val); From 937b8403522857ed61baaaef620ec7ed7ad8fb2c Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Mon, 14 Aug 2023 11:35:22 +0200 Subject: [PATCH 093/179] extend rev test --- test/unit/math/rev/prob/wiener_full_test.cpp | 93 ++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/test/unit/math/rev/prob/wiener_full_test.cpp b/test/unit/math/rev/prob/wiener_full_test.cpp index e13a51e84f6..262e6ad354a 100644 --- a/test/unit/math/rev/prob/wiener_full_test.cpp +++ b/test/unit/math/rev/prob/wiener_full_test.cpp @@ -207,3 +207,96 @@ TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { check_scalar_types(f_st0, st0[i], result[i], dst0[i]); } } + + + + + + + + +// CHECK THAT ALL VALID Vector TYPES ARE ACCEPTED +template +void check_vector_types(F& f, std::vector value, double res) { + // - f: Function where all inputs are vectors + // - value: value to be used for the parameter + // - res: expected result of calling `f` with `value` + // - deriv: expected result of partial of f with respect to + // the parameter in `value` + using stan::math::var; + double err_tol = 2e-4; + + // type double + EXPECT_NEAR(f(value), res, err_tol); + + // type var with derivative + var result_var = f(value); + result_var.grad(); + EXPECT_NEAR(value_of(result_var), res, err_tol); +} + +TEST(ProbWienerFull, wiener_full_all_vector) { + // tests all parameter types individually, with other + // parameters set to std::vector + using stan::math::wiener_full_lpdf; + + std::vector rt{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector a{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector v{1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector w{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; + std::vector t0{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0}; + std::vector sv{0.1, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0}; + std::vector sw{0.1, 0.1, 0, 0.1, 0, 0.1, 0, 0, 0}; + std::vector st0{0.1, 0, 0.1, 0.1, 0, 0, 0.1, 0, 0}; + + double result{-24.307593}; + + // rt + auto f_rt = [&](auto value) { + return wiener_full_lpdf(value, a, t0, w, v, sv, sw, + st0); + }; + check_vector_types(f_rt, rt, result); + // a + auto f_a = [&](auto value) { + return wiener_full_lpdf(rt, value, t0, w, v, sv, sw, + st0); + }; + check_vector_types(f_a, a, result); + // v + auto f_v = [&](auto value) { + return wiener_full_lpdf(rt, a, t0, w, value, sv, sw, + st0); + }; + check_vector_types(f_v, v, result); + // w + auto f_w = [&](auto value) { + return wiener_full_lpdf(rt, a, t0, value, v, sv, sw, + st0); + }; + check_vector_types(f_w, w, result); + // t0 + auto f_t0 = [&](auto value) { + return wiener_full_lpdf(rt, a, value, w, v, sv, sw, + st0); + }; + check_vector_types(f_t0, t0, result); + // sv + auto f_sv = [&](auto value) { + return wiener_full_lpdf(rt, a, t0, w, v, value, sw, + st0); + }; + check_vector_types(f_sv, sv, result); + // sw + auto f_sw = [&](auto value) { + return wiener_full_lpdf(rt, a, t0, w, v, sv, value, + st0); + }; + check_vector_types(f_sw, sw, result); + // st0 + auto f_st0 = [&](auto value) { + return wiener_full_lpdf(rt, a, t0, w, v, sv, sw, + value); + }; + check_vector_types(f_st0, st0, result); + } \ No newline at end of file From b10e21679985f63e7b4017fa526d522f1d725468 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 14 Aug 2023 05:36:43 -0400 Subject: [PATCH 094/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- test/unit/math/rev/prob/wiener_full_test.cpp | 97 +++++++++----------- 1 file changed, 41 insertions(+), 56 deletions(-) diff --git a/test/unit/math/rev/prob/wiener_full_test.cpp b/test/unit/math/rev/prob/wiener_full_test.cpp index 262e6ad354a..13cc613a7bf 100644 --- a/test/unit/math/rev/prob/wiener_full_test.cpp +++ b/test/unit/math/rev/prob/wiener_full_test.cpp @@ -208,13 +208,6 @@ TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { } } - - - - - - - // CHECK THAT ALL VALID Vector TYPES ARE ACCEPTED template void check_vector_types(F& f, std::vector value, double res) { @@ -251,52 +244,44 @@ TEST(ProbWienerFull, wiener_full_all_vector) { double result{-24.307593}; - // rt - auto f_rt = [&](auto value) { - return wiener_full_lpdf(value, a, t0, w, v, sv, sw, - st0); - }; - check_vector_types(f_rt, rt, result); - // a - auto f_a = [&](auto value) { - return wiener_full_lpdf(rt, value, t0, w, v, sv, sw, - st0); - }; - check_vector_types(f_a, a, result); - // v - auto f_v = [&](auto value) { - return wiener_full_lpdf(rt, a, t0, w, value, sv, sw, - st0); - }; - check_vector_types(f_v, v, result); - // w - auto f_w = [&](auto value) { - return wiener_full_lpdf(rt, a, t0, value, v, sv, sw, - st0); - }; - check_vector_types(f_w, w, result); - // t0 - auto f_t0 = [&](auto value) { - return wiener_full_lpdf(rt, a, value, w, v, sv, sw, - st0); - }; - check_vector_types(f_t0, t0, result); - // sv - auto f_sv = [&](auto value) { - return wiener_full_lpdf(rt, a, t0, w, v, value, sw, - st0); - }; - check_vector_types(f_sv, sv, result); - // sw - auto f_sw = [&](auto value) { - return wiener_full_lpdf(rt, a, t0, w, v, sv, value, - st0); - }; - check_vector_types(f_sw, sw, result); - // st0 - auto f_st0 = [&](auto value) { - return wiener_full_lpdf(rt, a, t0, w, v, sv, sw, - value); - }; - check_vector_types(f_st0, st0, result); - } \ No newline at end of file + // rt + auto f_rt = [&](auto value) { + return wiener_full_lpdf(value, a, t0, w, v, sv, sw, st0); + }; + check_vector_types(f_rt, rt, result); + // a + auto f_a = [&](auto value) { + return wiener_full_lpdf(rt, value, t0, w, v, sv, sw, st0); + }; + check_vector_types(f_a, a, result); + // v + auto f_v = [&](auto value) { + return wiener_full_lpdf(rt, a, t0, w, value, sv, sw, st0); + }; + check_vector_types(f_v, v, result); + // w + auto f_w = [&](auto value) { + return wiener_full_lpdf(rt, a, t0, value, v, sv, sw, st0); + }; + check_vector_types(f_w, w, result); + // t0 + auto f_t0 = [&](auto value) { + return wiener_full_lpdf(rt, a, value, w, v, sv, sw, st0); + }; + check_vector_types(f_t0, t0, result); + // sv + auto f_sv = [&](auto value) { + return wiener_full_lpdf(rt, a, t0, w, v, value, sw, st0); + }; + check_vector_types(f_sv, sv, result); + // sw + auto f_sw = [&](auto value) { + return wiener_full_lpdf(rt, a, t0, w, v, sv, value, st0); + }; + check_vector_types(f_sw, sw, result); + // st0 + auto f_st0 = [&](auto value) { + return wiener_full_lpdf(rt, a, t0, w, v, sv, sw, value); + }; + check_vector_types(f_st0, st0, result); +} \ No newline at end of file From 453360bf0f407654e43c7e6c9945c7fe3acafdf0 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Mon, 14 Aug 2023 11:44:21 +0200 Subject: [PATCH 095/179] new line --- test/unit/math/rev/prob/wiener_full_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/math/rev/prob/wiener_full_test.cpp b/test/unit/math/rev/prob/wiener_full_test.cpp index 13cc613a7bf..96f9abe7f1a 100644 --- a/test/unit/math/rev/prob/wiener_full_test.cpp +++ b/test/unit/math/rev/prob/wiener_full_test.cpp @@ -284,4 +284,4 @@ TEST(ProbWienerFull, wiener_full_all_vector) { return wiener_full_lpdf(rt, a, t0, w, v, sv, sw, value); }; check_vector_types(f_st0, st0, result); -} \ No newline at end of file +} From db5b67dfe1ef1797030ffc385df9474b6b1ca2ed Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Wed, 16 Aug 2023 13:20:39 +0200 Subject: [PATCH 096/179] more partial types --- stan/math/prim/prob/wiener5_lpdf.hpp | 98 +++++++++++--------- stan/math/prim/prob/wiener_full_lpdf.hpp | 112 ++++++++++++----------- 2 files changed, 115 insertions(+), 95 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 34a1424d2bf..1e537fb92e5 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -259,9 +259,11 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, * @param err The log error tolerance * @return density */ -template -inline double wiener5_density(double y, double a, double v_value, - double w_value, double sv, +template > +inline ReturnT wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, + const T_w& w_value, const T_sv& sv, double err = log(1e-12)) noexcept { const auto error_term = wiener5_compute_error_term(y, a, v_value, w_value, sv); @@ -273,8 +275,7 @@ inline double wiener5_density(double y, double a, double v_value, // 0 is result, 1 is newwsign auto res = wiener5_log_sum_exp(y, a, w_value, n_terms_small_t, - n_terms_large_t) - .first; + n_terms_large_t).first; if (2 * n_terms_small_t <= n_terms_large_t) { auto log_density = error_term - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * (log(y) - 2 * log(a)) + res; @@ -299,9 +300,11 @@ inline double wiener5_density(double y, double a, double v_value, * @param err The log error tolerance * @return Gradient w.r.t. t */ -template -inline double wiener5_grad_t(double y, double a, double v_value, double w_value, - double sv, double err = log(1e-12)) noexcept { +template > +inline ReturnT wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, + const T_w& w_value, const T_sv& sv, double err = log(1e-12)) noexcept { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; const double error_term @@ -352,9 +355,11 @@ inline double wiener5_grad_t(double y, double a, double v_value, double w_value, * @param err The log error tolerance * @return Gradient w.r.t. a */ -template -inline double wiener5_grad_a(double y, double a, double v_value, double w_value, - double sv, double err = log(1e-12)) noexcept { +template > +inline ReturnT wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, + const T_w& w_value, const T_sv& sv, double err = log(1e-12)) noexcept { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; const double error_term @@ -405,9 +410,11 @@ inline double wiener5_grad_a(double y, double a, double v_value, double w_value, * @param err The log error tolerance * @return Gradient w.r.t. v */ -template -inline double wiener5_grad_v(double y, double a, double v_value, double w_value, - double sv, double err = log(1e-12)) noexcept { +template > +inline ReturnT wiener5_grad_v(const T_y& y, const T_a& a, const T_v& v_value, + const T_w& w_value, const T_sv& sv, double err = log(1e-12)) noexcept { double ans = (a * (1 - w_value) - v_value * y); if (sv != 0) { ans /= 1 + square(sv) * y; @@ -430,9 +437,11 @@ inline double wiener5_grad_v(double y, double a, double v_value, double w_value, * @param err The log error tolerance * @return Gradient w.r.t. w */ -template -inline double wiener5_grad_w(double y, double a, double v_value, double w_value, - double sv, double err = log(1e-12)) noexcept { +template > +inline ReturnT wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, + const T_w& w_value, const T_sv& sv, double err = log(1e-12)) noexcept { const double two_log_a = 2 * log(a); const double log_y_asq = log(y) - two_log_a; const double error_term @@ -479,9 +488,11 @@ inline double wiener5_grad_w(double y, double a, double v_value, double w_value, * @param err The log error tolerance * @return Gradient w.r.t. sv */ -template -inline double wiener5_grad_sv(double y, double a, double v_value, - double w_value, double sv, +template > +inline ReturnT wiener5_grad_sv(const T_y& y, const T_a& a, const T_v& v_value, + const T_w& w_value, const T_sv& sv, double err = log(1e-12)) noexcept { const double one_plus_svsqr_y = 1 + square(sv) * y; const double w = 1.0 - w_value; @@ -527,17 +538,18 @@ inline void assign_err(std::tuple& args_tuple, double err) { * @param log_result Whether the function result is already on the log-scale */ template -double estimate_with_err_check(const F& functor, double err, + bool LogResult = true, typename T_partials, typename F, typename... ArgsTupleT, + typename ReturnT = return_type_t> +ReturnT estimate_with_err_check(const F& functor, double err, ArgsTupleT&&... args_tuple) { - double result = functor(args_tuple...); - double log_fabs_result = LogResult ? log(fabs(result)) : fabs(result); + T_partials result = functor(args_tuple...); + T_partials log_fabs_result = LogResult ? log(fabs(result)) : fabs(result); if (log_fabs_result < err) { log_fabs_result = std::isinf(log_fabs_result) ? 0 : log_fabs_result; auto err_args_tuple = std::make_tuple(args_tuple...); // const int size_tuple = std::tuple_size::value - // 1; - const double new_error + const T_partials new_error = GradW7 ? err + log_fabs_result + LOG_TWO : err + log_fabs_result; assign_err(std::get(err_args_tuple), new_error); result = math::apply([&](auto&&... args) { return functor(args...); }, @@ -579,6 +591,8 @@ inline return_type_t wiener5_lpdf( using T_w_ref = ref_type_if_t::value, T_w>; using T_v_ref = ref_type_if_t::value, T_v>; using T_sv_ref = ref_type_if_t::value, T_sv>; + + using T_partials = partials_type_t>; static constexpr const char* function_name = "wiener5_lpdf"; if (size_zero(y, a, t0, w, v, sv)) { @@ -642,11 +656,11 @@ inline return_type_t wiener5_lpdf( } } - const double log_error_density = log(1e-6); - const double log_error_derivative = log(precision_derivatives); - const double log_error_absolute = log(1e-12); - double density = 0.0; - double log_density = 0.0; + const T_partials log_error_density = log(1e-6); + const T_partials log_error_derivative = log(precision_derivatives); + const T_partials log_error_absolute = log(1e-12); + T_partials density = 0.0; + T_partials log_density = 0.0; operands_and_partials ops_partials(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref); @@ -657,24 +671,24 @@ inline return_type_t wiener5_lpdf( // Calculate 4-parameter model without inter-trial variabilities (if // sv_vec[i] == 0) or 5-parameter model with inter-trial variability in // drift rate (if sv_vec[i] != 0) - const double y_val = y_vec.val(i); - const double a_val = a_vec.val(i); - const double t0_val = t0_vec.val(i); - const double w_val = w_vec.val(i); - const double v_val = v_vec.val(i); - const double sv_val = sv_vec.val(i); - - density = internal::estimate_with_err_check<5, false, 0, false>( + const T_partials y_val = y_vec.val(i); + const T_partials a_val = a_vec.val(i); + const T_partials t0_val = t0_vec.val(i); + const T_partials w_val = w_vec.val(i); + const T_partials v_val = v_vec.val(i); + const T_partials sv_val = sv_vec.val(i); + + density = internal::estimate_with_err_check<5, false, 0, false, T_partials>( [&](auto&&... args) { return internal::wiener5_density(args...); }, log_error_density - LOG_TWO, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); log_density += density; - const double new_est_err = density + log_error_derivative - LOG_FOUR; + const T_partials new_est_err = density + log_error_derivative - LOG_FOUR; // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 - const double deriv_y = internal::estimate_with_err_check<5>( + const T_partials deriv_y = internal::estimate_with_err_check<5, false, 0, true, T_partials>( [&](auto&&... args) { return internal::wiener5_grad_t(args...); }, new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); @@ -684,7 +698,7 @@ inline return_type_t wiener5_lpdf( ops_partials.edge1_.partials_[i] = deriv_y; } if (!is_constant_all::value) { - ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check<5>( + ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check<5, false, 0, true, T_partials>( [&](auto&&... args) { return internal::wiener5_grad_a(args...); }, new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); @@ -693,7 +707,7 @@ inline return_type_t wiener5_lpdf( ops_partials.edge3_.partials_[i] = -deriv_y; } if (!is_constant_all::value) { - ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check<5>( + ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check<5, false, 0, true, T_partials>( [&](auto&&... args) { return internal::wiener5_grad_w(args...); }, new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index adb411e4fdb..20ff7811c5d 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -21,15 +21,17 @@ namespace internal { * @param log_error The log error tolerance * @return Gradient w.r.t. sw */ -inline double wiener7_grad_sw(double y, double a, double v, double w, double sv, - double sw, double log_error) { - double low = w - sw / 2.0; +template > +inline ReturnT wiener7_grad_sw(const T_y& y, const T_a& a, const T_v& v, const T_w& w, const T_sv& sv, + const T_sw& sw, double log_error) { + T_partials low = w - sw / 2.0; low = (0 > low) ? 0 : low; - double high = w + sw / 2.0; + T_partials high = w + sw / 2.0; high = (1 < high) ? 1 : high; - const double lower_value = wiener5_density(y, a, v, low, sv, log_error); - const double upper_value + const T_partials lower_value = wiener5_density(y, a, v, low, sv, log_error); + const T_partials upper_value = wiener5_density(y, a, v, high, sv, log_error); return 0.5 * (lower_value + upper_value) / sw; } @@ -107,17 +109,17 @@ inline double conditionally_grad_sw(const F& functor, double y_diff, double a, * @param args Additional arguments to be passed to the hcubature function * @return Wiener7 density or gradient calculated by integration */ -template -auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, - double hcubature_err, TArgs&&... args) { +template > +ReturnT wiener7_integrate(const Wiener7FunctorT& wiener7_functor, + T_hcub hcubature_err, TArgs&&... args) { const auto wiener7_integrand_impl - = [&](auto&& x, double y, double a, double v, double w, double t0, - double sv, double sw, double st0, double log_error) { + = [&](auto&& x, auto y, auto a, auto v, auto w, auto t0, + auto sv, auto sw, auto st0, auto log_error) { scalar_seq_view x_vec(x); - const double sw_val = GradSW ? 0 : sw; - const double new_w = sw_val ? w + sw_val * (x_vec[0] - 0.5) : w; - const double new_t0 = sw_val ? (st0 ? t0 + st0 * x_vec[1] : t0) + const auto sw_val = GradSW ? 0 : sw; + const auto new_w = sw_val ? w + sw_val * (x_vec[0] - 0.5) : w; + const auto new_t0 = sw_val ? (st0 ? t0 + st0 * x_vec[1] : t0) : (st0 ? t0 + st0 * x_vec[0] : t0); if (y - new_t0 <= 0) { return 0.0; @@ -129,7 +131,7 @@ auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, const auto functor = [&](auto&&... int_args) { return hcubature(wiener7_integrand_impl, int_args...); }; - return estimate_with_err_check<0, GradW7, 8>(functor, hcubature_err, args...); + return estimate_with_err_check<0, GradW7, 8, true, T_partials>(functor, hcubature_err, args...); } } // namespace internal @@ -300,6 +302,10 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, using T_sv_ref = ref_type_if_t::value, T_sv>; using T_sw_ref = ref_type_if_t::value, T_sw>; using T_st0_ref = ref_type_if_t::value, T_st0>; + + using T_partials_return = partials_return_t; + + using T_partials = partials_type_t>; static constexpr const char* function_name = "wiener_full_lpdf"; check_consistent_sizes(function_name, "Random variable", y, @@ -402,16 +408,16 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } } - const double log_error_density = log(1e-6); // precision for density - const double error_bound = precision_derivatives; // precision for + const T_partials log_error_density = log(1e-6); // precision for density + const T_partials error_bound = precision_derivatives; // precision for // derivatives (controllable by user) - const double log_error_derivative = log(error_bound); - const double absolute_error_hcubature = 0.0; - const double relative_error_hcubature + const T_partials log_error_derivative = log(error_bound); + const T_partials absolute_error_hcubature = 0.0; + const T_partials relative_error_hcubature = .9 * error_bound; // eps_rel(Integration) - const double log_error_absolute = log(1e-12); + const T_partials log_error_absolute = log(1e-12); const int maximal_evaluations_hcubature = 6000; - double log_density = 0.0; + T_partials log_density = 0.0; auto ops_partials = make_partials_propagator(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref, sw_ref, st0_ref); ReturnT result = 0; @@ -424,45 +430,45 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, v_vec[i], sv_vec[i], precision_derivatives); continue; } - const double y_val = y_vec.val(i); - const double a_val = a_vec.val(i); - const double v_val = v_vec.val(i); - const double w_val = w_vec.val(i); - const double t0_val = t0_vec.val(i); - const double sv_val = sv_vec.val(i); - const double sw_val = sw_vec.val(i); - const double st0_val = st0_vec.val(i); + const T_partials_return y_val = y_vec.val(i); + const T_partials_return a_val = a_vec.val(i); + const T_partials_return v_val = v_vec.val(i); + const T_partials_return w_val = w_vec.val(i); + const T_partials_return t0_val = t0_vec.val(i); + const T_partials_return sv_val = sv_vec.val(i); + const T_partials_return sw_val = sw_vec.val(i); + const T_partials_return st0_val = st0_vec.val(i); const int dim = (sw_val != 0) + (st0_val != 0); check_positive(function_name, "(Inter-trial variability in A-priori bias) + " "(Inter-trial variability in nondecision time)", dim); - Eigen::VectorXd xmin = Eigen::VectorXd::Zero(dim); - Eigen::VectorXd xmax = Eigen::VectorXd::Ones(dim); - if (st0_val) { + Eigen::Array xmin = Eigen::VectorXd::Zero(dim); + Eigen::Array xmax = Eigen::VectorXd::Ones(dim); + if (st0_val != 0) { xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); } - double hcubature_err = log_error_absolute - log_error_density + LOG_TWO + 1; + T_partials_return hcubature_err = log_error_absolute - log_error_density + LOG_TWO + 1; const auto params = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, st0_val, log_error_absolute - LOG_TWO); - double density = internal::wiener7_integrate( + T_partials density = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_density(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2); - log_density += log(density); + log_density = log_density + log(density); hcubature_err = log_error_absolute - log_error_derivative + log(fabs(density)) + LOG_TWO + 1; // computation of derivative for t and precision check in order to give // the value as deriv_t to edge1 and as -deriv_t to edge5 - const double deriv_t_7 - = internal::wiener7_integrate( + const T_partials deriv_t_7 + = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_t(args...); }, @@ -472,13 +478,13 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, / density; // computation of derivatives and precision checks - double derivative; + T_partials_return derivative; if (!is_constant_all::value) { partials<0>(ops_partials)[i] = deriv_t_7; } if (!is_constant_all::value) { partials<1>(ops_partials)[i] - = internal::wiener7_integrate( + = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_a(args...); }, @@ -492,7 +498,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } if (!is_constant_all::value) { partials<3>(ops_partials)[i] - = internal::wiener7_integrate( + = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_w(args...); }, @@ -503,7 +509,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } if (!is_constant_all::value) { partials<4>(ops_partials)[i] - = internal::wiener7_integrate( + = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_v(args...); }, @@ -514,7 +520,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } if (!is_constant_all::value) { partials<5>(ops_partials)[i] - = internal::wiener7_integrate( + = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_sv(args...); }, @@ -528,16 +534,16 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, partials<6>(ops_partials)[i] = 0; } else { if (st0_val == 0) { - derivative = internal::estimate_with_err_check<6>( + derivative = internal::estimate_with_err_check<6, false, 0, true, T_partials_return>( [&](auto&&... args) { - return internal::wiener7_grad_sw(args...); + return internal::wiener7_grad_sw(args...); }, hcubature_err, y_val - t0_val, a_val, v_val, w_val, sv_val, sw_val, log_error_absolute - LOG_TWO); } else { - derivative = internal::wiener7_integrate( + derivative = internal::wiener7_integrate( [&](auto&&... args) { - return internal::wiener7_grad_sw(args...); + return internal::wiener7_grad_sw(args...); }, hcubature_err, params, 1, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, @@ -547,25 +553,25 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } } if (!is_constant_all::value) { - double f; + T_partials f; if (st0_val == 0) { partials<7>(ops_partials)[i] = 0; } else if (y_val - (t0_val + st0_val) <= 0) { partials<7>(ops_partials)[i] = -1 / st0_val; } else { - const double t0_st0 = t0_val + st0_val; + const T_partials t0_st0 = t0_val + st0_val; if (sw_val == 0) { - f = internal::estimate_with_err_check<5>( + f = internal::estimate_with_err_check<5, false, 0, true, T_partials>( [&](auto&&... args) { return internal::wiener5_density(args...); }, log_error_derivative + log(st0_val), y_val - t0_st0, a_val, v_val, w_val, sv_val, log_error_absolute - LOG_TWO); } else { - const double new_error = log_error_absolute - LOG_TWO; + const T_partials new_error = log_error_absolute - LOG_TWO; const auto& params_st = std::make_tuple( y_val, a_val, v_val, w_val, t0_st0, sv_val, sw_val, 0, new_error); - f = internal::wiener7_integrate( + f = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_density(args...); }, From faa0f33286510f80ab6d278f63353d358b55e680 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Thu, 17 Aug 2023 22:05:00 +0200 Subject: [PATCH 097/179] added test file --- test/unit/math/mix/prob/wiener_full_test.cpp | 82 ++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 test/unit/math/mix/prob/wiener_full_test.cpp diff --git a/test/unit/math/mix/prob/wiener_full_test.cpp b/test/unit/math/mix/prob/wiener_full_test.cpp new file mode 100644 index 00000000000..10e93df25bc --- /dev/null +++ b/test/unit/math/mix/prob/wiener_full_test.cpp @@ -0,0 +1,82 @@ +#include +#include + +TEST(mathMixScalFun, wiener_full_lpdf) { + auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { + return [&y, &a, &t0, &w, &v](const auto& sv, const auto& sw, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + +/* auto f2 = [](const auto& y, const auto& a, const auto& sv, const auto& sw, const auto& st0) { + return [&y, &a, &sv, &sw, &st0](const auto& t0, const auto& w, const auto& v) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + auto f3 = [](const auto& w, const auto& v, const auto& sv, const auto& sw, const auto& st0) { + return [&w, &v, &sv, &sw, &st0](const auto& y, const auto& a, const auto& t0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + };*/ + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f1(y, a, t0, w, v), sv, sw, st0); +// stan::test::expect_ad(f2(y, a, sv, sw, st0), t0, w, v); +// stan::test::expect_ad(f3(w, v, sv, sw, st0), y, a, t0); + + +} + + +TEST(mathMixVecFun, wiener_full_lpdf) { + auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { + return [&y, &a, &t0, &w, &v](const auto& sv, const auto& sw, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + +/* auto f2 = [](const auto& y, const auto& a, const auto& sv, const auto& sw, const auto& st0) { + return [&y, &a, &sv, &sw, &st0](const auto& t0, const auto& w, const auto& v) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + auto f3 = [](const auto& w, const auto& v, const auto& sv, const auto& sw, const auto& st0) { + return [&w, &v, &sv, &sw, &st0](const auto& y, const auto& a, const auto& t0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + };*/ + + Eigen::VectorXd y(2); + y << 1.0, 1.5; + Eigen::VectorXd a(2); + a << 2.0, 2.5; + Eigen::VectorXd t0(2); + t0 << 0.2, 0.1; + Eigen::VectorXd w(2); + w << 0.5, 0.45; + Eigen::VectorXd v(2); + v << 2.0, 1.0; + Eigen::VectorXd sv(2); + sv << 0.2, 0.1; + Eigen::VectorXd sw(2); + sw << 0.1, 0.2; + Eigen::VectorXd st0(2); + st0 << 0.3, 0.2; + + stan::test::expect_ad(f1(y, a, t0, w, v), sv, sw, st0); +// stan::test::expect_ad(f2(y, a, sv, sw, st0), t0, w, v); +// stan::test::expect_ad(f3(w, v, sv, sw, st0), y, a, t0); + + +} + From 4ef8810870421ecbeac21e721b343cdfff41831a Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 29 Aug 2023 10:02:29 +0200 Subject: [PATCH 098/179] some types changed --- stan/math/prim/prob/wiener5_lpdf.hpp | 2 +- stan/math/prim/prob/wiener_full_lpdf.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 1e537fb92e5..e7bba6ab399 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -540,7 +540,7 @@ inline void assign_err(std::tuple& args_tuple, double err) { template > -ReturnT estimate_with_err_check(const F& functor, double err, +ReturnT estimate_with_err_check(const F& functor, T_partials err, ArgsTupleT&&... args_tuple) { T_partials result = functor(args_tuple...); T_partials log_fabs_result = LogResult ? log(fabs(result)) : fabs(result); diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 20ff7811c5d..07c6d27ed6c 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -559,7 +559,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } else if (y_val - (t0_val + st0_val) <= 0) { partials<7>(ops_partials)[i] = -1 / st0_val; } else { - const T_partials t0_st0 = t0_val + st0_val; + const T_partials_return t0_st0 = t0_val + st0_val; if (sw_val == 0) { f = internal::estimate_with_err_check<5, false, 0, true, T_partials>( [&](auto&&... args) { From f909cfcd75a45c9ce884e55742c97fa401faa02c Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Sat, 16 Sep 2023 14:06:07 +0200 Subject: [PATCH 099/179] wiener5 mix test --- stan/math/prim/prob/wiener5_lpdf.hpp | 401 +++++++++--------- stan/math/prim/prob/wiener_full_lpdf.hpp | 4 +- test/unit/math/mix/prob/wiener5_lpdf_test.cpp | 131 ++++++ test/unit/math/mix/prob/wiener_full_test.cpp | 23 +- 4 files changed, 351 insertions(+), 208 deletions(-) create mode 100644 test/unit/math/mix/prob/wiener5_lpdf_test.cpp diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index e7bba6ab399..cebd5757445 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -16,15 +16,15 @@ namespace internal { * @param sv The inter-trial variability of the drift rate * @return 'error_term' term */ -template -inline auto wiener5_compute_error_term(T_y&& y, T_a&& a, T_v&& v_value, +template +inline Scalar wiener5_compute_error_term(T_y&& y, T_a&& a, T_v&& v_value, T_w&& w_value, T_sv&& sv) noexcept { - const auto w = 1.0 - w_value; - const auto v = -v_value; - const auto sv_sqr = square(sv); - const auto one_plus_svsqr_y = 1 + sv_sqr * y; - const auto two_avw = 2 * a * v * w; - const auto two_log_a = 2 * log(a); + const Scalar w = 1.0 - w_value; + const Scalar v = -v_value; + const Scalar sv_sqr = square(sv); + const Scalar one_plus_svsqr_y = 1 + sv_sqr * y; + const Scalar two_avw = 2 * a * v * w; + const Scalar two_log_a = 2 * log(a); if (sv != 0) { return stan::math::eval((sv_sqr * square(a * w) - two_avw - square(v) * y) / 2.0 / one_plus_svsqr_y @@ -47,17 +47,17 @@ inline auto wiener5_compute_error_term(T_y&& y, T_a&& a, T_v&& v_value, * @param sv The inter-trial variability of the drift rate * @return 'density_part_one' term */ -template -inline double wiener5_density_part_one(double y, double a, double v_value, - double w_value, double sv) noexcept { - const double w = 1.0 - w_value; - const double v = -v_value; - const double sv_sqr = square(sv); - const double one_plus_svsqr_y = 1 + sv_sqr * y; - const double two_avw = 2 * a * v * w; - - const double var_a = GradA ? w : a; - const double var_b = GradA ? a : w; +template +inline Scalar wiener5_density_part_one(T_y&& y, T_a&& a, T_v_value&& v_value, + T_w_value&& w_value, T_sv&& sv) noexcept { + const Scalar w = 1.0 - w_value; + const Scalar v = -v_value; + const Scalar sv_sqr = square(sv); + const Scalar one_plus_svsqr_y = 1 + sv_sqr * y; + const Scalar two_avw = 2 * a * v * w; + + const Scalar var_a = GradA ? w : a; + const Scalar var_b = GradA ? a : w; if (GradT) { if (sv != 0) { @@ -89,28 +89,28 @@ inline double wiener5_density_part_one(double y, double a, double v_value, * @param error The error tolerance * @return 'n_terms_small_t' term */ -template -inline double wiener5_n_terms_small_t(double y, double a, double w_value, - double error) noexcept { - const double two_error = 2.0 * error; - const double y_asq = y / square(a); - const double two_log_a = 2 * log(a); - const double log_y_asq = log(y) - two_log_a; - const double w = 1.0 - w_value; - - const double n_1_factor = Density ? 2 : 3; - const double n_1 = (sqrt(n_1_factor * y_asq) + w) / 2.0; - double u_eps; +template +inline Scalar wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, + Scalar error) noexcept { + const Scalar two_error = 2.0 * error; + const Scalar y_asq = y / square(a); + const Scalar two_log_a = 2 * log(a); + const Scalar log_y_asq = log(y) - two_log_a; + const Scalar w = 1.0 - w_value; + + const Scalar n_1_factor = Density ? 2 : 3; + const Scalar n_1 = (sqrt(n_1_factor * y_asq) + w) / 2.0; + Scalar u_eps; if (Density || GradW) { u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log_y_asq + two_error); } else { u_eps = fmin(-3.0, (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_error)); } - const double arg_mult = (Density || GradW) ? 1 : 3; - const double arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + const Scalar arg_mult = (Density || GradW) ? 1 : 3; + const Scalar arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - const double n_2 + const Scalar n_2 = (arg > 0) ? GradW ? 0.5 * (sqrt(arg) + w) : 0.5 * (sqrt(arg) - w) : n_1; return ceil(fmax(n_1, n_2)); } @@ -127,33 +127,33 @@ inline double wiener5_n_terms_small_t(double y, double a, double w_value, * @param error The error tolerance * @return 'n_terms_large_t' term */ -template -inline double wiener5_n_terms_largel_t(double y, double a, double w_value, - double error) noexcept { - const double two_error = 2.0 * error; - const double y_asq = y / square(a); - const double two_log_a = 2 * log(a); - const double log_y_asq = log(y) - two_log_a; - const double w = 1.0 - w_value; - - const double n_1_factor = GradW ? 2 : 3; +template +inline Scalar wiener5_n_terms_largel_t(T_y&& y, T_a&& a, T_w_value&& w_value, + Scalar error) noexcept { + const Scalar two_error = 2.0 * error; + const Scalar y_asq = y / square(a); + const Scalar two_log_a = 2 * log(a); + const Scalar log_y_asq = log(y) - two_log_a; + const Scalar w = 1.0 - w_value; + + const Scalar n_1_factor = GradW ? 2 : 3; static constexpr double PI_SQUARED = pi() * pi(); - double n_1; - double n_2; + Scalar n_1; + Scalar n_2; if (Density) { n_1 = 1.0 / (pi() * sqrt(y_asq)); - const double two_log_piy = -2.0 * (LOG_PI + log_y_asq + error); + const Scalar two_log_piy = -2.0 * (LOG_PI + log_y_asq + error); n_2 = (two_log_piy >= 0) ? sqrt(two_log_piy / (PI_SQUARED * y_asq)) : 0.0; } else { n_1 = sqrt(n_1_factor / y_asq) / pi(); - const double u_eps_arg + const Scalar u_eps_arg = GradW ? log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_error : log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + error; - const double u_eps = fmin(-1, u_eps_arg); - const double arg_mult = GradW ? 1 : (2.0 / PI_SQUARED / y_asq); - const double arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + const Scalar u_eps = fmin(-1, u_eps_arg); + const Scalar arg_mult = GradW ? 1 : (2.0 / PI_SQUARED / y_asq); + const Scalar arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); n_2 = GradW ? (arg > 0) ? sqrt(arg / y_asq) / pi() : n_1 : (arg > 0) ? sqrt(arg) : n_1; } @@ -174,39 +174,39 @@ inline double wiener5_n_terms_largel_t(double y, double a, double w_value, * @param n_terms_large_t The n_terms_large_t term * @return 'result' sum and its sign */ -template -inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, +inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, T_nsmall&& n_terms_small_t, T_nlarge&& n_terms_large_t) noexcept { - const auto y_asq = y / square(a); - const auto w = 1.0 - w_value; + const Scalar y_asq = y / square(a); + const Scalar w = 1.0 - w_value; const bool small_n_terms_small_t = Density ? (2 * n_terms_small_t <= n_terms_large_t) : (2 * n_terms_small_t < n_terms_large_t); - const auto scaling = small_n_terms_small_t ? inv(2.0 * y_asq) : y_asq / 2.0; + const Scalar scaling = small_n_terms_small_t ? inv(2.0 * y_asq) : y_asq / 2.0; - auto prev_val = NEGATIVE_INFTY; - auto current_val = NEGATIVE_INFTY; + Scalar prev_val = NEGATIVE_INFTY; + Scalar current_val = NEGATIVE_INFTY; int prev_sign = 1; int current_sign = 1; if (small_n_terms_small_t) { - const auto mult = Density ? 1 : 3; - const auto offset = GradW ? y_asq : 0; - const auto sqrt_offset = sqrt(offset); - for (size_t k = n_terms_small_t; k >= 1; k--) { - const auto wp2k = w + 2.0 * k; - const auto wm2k = w - 2.0 * k; + const Scalar mult = Density ? 1 : 3; + const Scalar offset = GradW ? y_asq : 0; + const Scalar sqrt_offset = sqrt(offset); + for (auto k = n_terms_small_t; k >= 1; k--) { //instead of size_t + const Scalar wp2k = w + 2.0 * k; + const Scalar wm2k = w - 2.0 * k; int wp2k_sign = (wp2k > sqrt_offset) ? 1 : -1; int wm2k_sign = (wm2k > sqrt_offset) ? 1 : -1; - auto wp2k_quant + Scalar wp2k_quant = GradW ? log(fabs((square(wp2k) - offset))) - square(wp2k) * scaling : mult * log(wp2k_sign * wp2k) - square(wp2k) * scaling; - auto wm2k_quant + Scalar wm2k_quant = GradW ? log(fabs((square(wm2k) - offset))) - square(wm2k) * scaling : mult * log(wm2k_sign * wm2k) - square(wm2k) * scaling; - double k_term; + Scalar k_term; int k_sign; std::forward_as_tuple(k_term, k_sign) = log_sum_exp_signed( wm2k_quant, -1 * wm2k_sign, wp2k_quant, wp2k_sign); @@ -215,7 +215,7 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, prev_val = current_val; prev_sign = current_sign; } - auto new_val = GradW ? log(fabs(square(w) - offset)) - square(w) * scaling + Scalar new_val = GradW ? log(fabs(square(w) - offset)) - square(w) * scaling : mult * log(w) - square(w) * scaling; int new_val_sign = GradW ? (w > sqrt_offset ? 1 : -1) : (new_val > 0 ? 1 : -1); @@ -224,17 +224,17 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, = log_sum_exp_signed(new_val, factor_sign * new_val_sign, current_val, factor_sign * current_sign); } else { - double mult = 3; + Scalar mult = 3; if (Density) { mult = 1; } else if (GradW) { mult = 2; } - for (size_t k = n_terms_large_t; k >= 1; k--) { - const double pi_k = k * pi(); - const double check = (GradW) ? cos(pi_k * w) : sin(pi_k * w); + for (auto k = n_terms_large_t; k >= 1; k--) { //instead of size_t + const Scalar pi_k = k * pi(); + const Scalar check = (GradW) ? cos(pi_k * w) : sin(pi_k * w); int check_sign = sign(check); - double n_terms_large_t_quant + Scalar n_terms_large_t_quant = mult * log(k) - square(pi_k) * scaling + log(fabs(check)); std::forward_as_tuple(current_val, current_sign) = log_sum_exp_signed( prev_val, prev_sign, n_terms_large_t_quant, check_sign); @@ -259,29 +259,29 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, * @param err The log error tolerance * @return density */ -template > -inline ReturnT wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, +inline Scalar wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, const T_w& w_value, const T_sv& sv, - double err = log(1e-12)) noexcept { - const auto error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); - const auto error = (err - error_term); - const auto n_terms_small_t - = wiener5_n_terms_small_t(y, a, w_value, error); - const auto n_terms_large_t - = wiener5_n_terms_largel_t(y, a, w_value, error); + Scalar err = log(1e-12)) noexcept { + const Scalar error_term + = wiener5_compute_error_term(y, a, v_value, w_value, sv); + const Scalar error = (err - error_term); + const Scalar n_terms_small_t + = wiener5_n_terms_small_t(y, a, w_value, error); + const Scalar n_terms_large_t + = wiener5_n_terms_largel_t(y, a, w_value, error); // 0 is result, 1 is newwsign - auto res = wiener5_log_sum_exp(y, a, w_value, n_terms_small_t, + auto res = wiener5_log_sum_exp(y, a, w_value, n_terms_small_t, n_terms_large_t).first; if (2 * n_terms_small_t <= n_terms_large_t) { - auto log_density = error_term - 0.5 * LOG_TWO - LOG_SQRT_PI + Scalar log_density = error_term - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * (log(y) - 2 * log(a)) + res; return NaturalScale ? exp(log_density) : log_density; } else { - auto log_density = error_term + res + LOG_PI; + Scalar log_density = error_term + res + LOG_PI; return NaturalScale ? exp(log_density) : log_density; } } @@ -300,33 +300,33 @@ inline ReturnT wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, * @param err The log error tolerance * @return Gradient w.r.t. t */ -template > -inline ReturnT wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, - const T_w& w_value, const T_sv& sv, double err = log(1e-12)) noexcept { - const double two_log_a = 2 * log(a); - const double log_y_asq = log(y) - two_log_a; - const double error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); - const double density_part_one - = wiener5_density_part_one(y, a, v_value, w_value, sv); - const double error = (err - error_term) + two_log_a; - - const double n_terms_small_t - = wiener5_n_terms_small_t(y, a, w_value, error); - const double n_terms_large_t - = wiener5_n_terms_largel_t(y, a, w_value, error); - double result; +inline Scalar wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, + const T_w& w_value, const T_sv& sv, Scalar err = log(1e-12)) noexcept { + const Scalar two_log_a = 2 * log(a); + const Scalar log_y_asq = log(y) - two_log_a; + const Scalar error_term + = wiener5_compute_error_term(y, a, v_value, w_value, sv); + const Scalar density_part_one + = wiener5_density_part_one(y, a, v_value, w_value, sv); + const Scalar error = (err - error_term) + two_log_a; + + const Scalar n_terms_small_t + = wiener5_n_terms_small_t(y, a, w_value, error); + const Scalar n_terms_large_t + = wiener5_n_terms_largel_t(y, a, w_value, error); + Scalar result; int newsign; - std::forward_as_tuple(result, newsign) = wiener5_log_sum_exp( + std::forward_as_tuple(result, newsign) = wiener5_log_sum_exp( y, a, w_value, n_terms_small_t, n_terms_large_t); - const double error_log_density - = log(max(fabs(density_part_one - 1.5 / y), fabs(density_part_one))); - const double log_density - = wiener5_density(y, a, v_value, w_value, sv, err - error_log_density); - double ans; + const Scalar error_log_density + = log(fmax(fabs(density_part_one - 1.5 / y), fabs(density_part_one))); + const Scalar log_density + = wiener5_density(y, a, v_value, w_value, sv, err - error_log_density); + Scalar ans; if (2 * n_terms_small_t < n_terms_large_t) { ans = density_part_one - 1.5 / y + newsign @@ -355,33 +355,33 @@ inline ReturnT wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, * @param err The log error tolerance * @return Gradient w.r.t. a */ -template > -inline ReturnT wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, - const T_w& w_value, const T_sv& sv, double err = log(1e-12)) noexcept { - const double two_log_a = 2 * log(a); - const double log_y_asq = log(y) - two_log_a; - const double error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); - const double density_part_one - = wiener5_density_part_one(y, a, v_value, w_value, sv); - const double error = err - error_term + 3 * log(a) - log(y) - LOG_TWO; - - const double n_terms_small_t - = wiener5_n_terms_small_t(y, a, w_value, error); - const double n_terms_large_t - = wiener5_n_terms_largel_t(y, a, w_value, error); - double result; +inline Scalar wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, + const T_w& w_value, const T_sv& sv, Scalar err = log(1e-12)) noexcept { + const Scalar two_log_a = 2 * log(a); + const Scalar log_y_asq = log(y) - two_log_a; + const Scalar error_term + = wiener5_compute_error_term(y, a, v_value, w_value, sv); + const Scalar density_part_one + = wiener5_density_part_one(y, a, v_value, w_value, sv); + const Scalar error = err - error_term + 3 * log(a) - log(y) - LOG_TWO; + + const Scalar n_terms_small_t + = wiener5_n_terms_small_t(y, a, w_value, error); + const Scalar n_terms_large_t + = wiener5_n_terms_largel_t(y, a, w_value, error); + Scalar result; int newsign; - std::forward_as_tuple(result, newsign) = wiener5_log_sum_exp( + std::forward_as_tuple(result, newsign) = wiener5_log_sum_exp( y, a, w_value, n_terms_small_t, n_terms_large_t); - const double error_log_density = log( - max(fabs(density_part_one + 1.0 / a), fabs(density_part_one - 2.0 / a))); - const double log_density - = wiener5_density(y, a, v_value, w_value, sv, err - error_log_density); - double ans; + const Scalar error_log_density = log( + fmax(fabs(density_part_one + 1.0 / a), fabs(density_part_one - 2.0 / a))); + const Scalar log_density + = wiener5_density(y, a, v_value, w_value, sv, err - error_log_density); + Scalar ans; if (2 * n_terms_small_t < n_terms_large_t) { ans = density_part_one + 1.0 / a - newsign @@ -410,16 +410,16 @@ inline ReturnT wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, * @param err The log error tolerance * @return Gradient w.r.t. v */ -template > -inline ReturnT wiener5_grad_v(const T_y& y, const T_a& a, const T_v& v_value, - const T_w& w_value, const T_sv& sv, double err = log(1e-12)) noexcept { - double ans = (a * (1 - w_value) - v_value * y); +inline Scalar wiener5_grad_v(const T_y& y, const T_a& a, const T_v& v_value, + const T_w& w_value, const T_sv& sv, Scalar err = log(1e-12)) noexcept { + Scalar ans = (a * (1 - w_value) - v_value * y); if (sv != 0) { ans /= 1 + square(sv) * y; } - return WrtLog ? ans * wiener5_density(y, a, v_value, w_value, sv, err) + return WrtLog ? ans * wiener5_density(y, a, v_value, w_value, sv, err) : ans; } @@ -437,31 +437,31 @@ inline ReturnT wiener5_grad_v(const T_y& y, const T_a& a, const T_v& v_value, * @param err The log error tolerance * @return Gradient w.r.t. w */ -template > -inline ReturnT wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, - const T_w& w_value, const T_sv& sv, double err = log(1e-12)) noexcept { - const double two_log_a = 2 * log(a); - const double log_y_asq = log(y) - two_log_a; - const double error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); - const double density_part_one - = wiener5_density_part_one(y, a, v_value, w_value, sv); - const double error = (err - error_term); - - const double n_terms_small_t - = wiener5_n_terms_small_t(y, a, w_value, error); - const double n_terms_large_t - = wiener5_n_terms_largel_t(y, a, w_value, error); - double result; +inline Scalar wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, + const T_w& w_value, const T_sv& sv, Scalar err = log(1e-12)) noexcept { + const Scalar two_log_a = 2 * log(a); + const Scalar log_y_asq = log(y) - two_log_a; + const Scalar error_term + = wiener5_compute_error_term(y, a, v_value, w_value, sv); + const Scalar density_part_one + = wiener5_density_part_one(y, a, v_value, w_value, sv); + const Scalar error = (err - error_term); + + const Scalar n_terms_small_t + = wiener5_n_terms_small_t(y, a, w_value, error); + const Scalar n_terms_large_t + = wiener5_n_terms_largel_t(y, a, w_value, error); + Scalar result; int newsign; - std::forward_as_tuple(result, newsign) = wiener5_log_sum_exp( + std::forward_as_tuple(result, newsign) = wiener5_log_sum_exp( y, a, w_value, n_terms_small_t, n_terms_large_t); - const double log_density = wiener5_density(y, a, v_value, w_value, sv, + const Scalar log_density = wiener5_density(y, a, v_value, w_value, sv, err - log(fabs(density_part_one))); - double ans; + Scalar ans; if (2 * n_terms_small_t < n_terms_large_t) { ans = -(density_part_one - newsign @@ -488,28 +488,28 @@ inline ReturnT wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, * @param err The log error tolerance * @return Gradient w.r.t. sv */ -template > -inline ReturnT wiener5_grad_sv(const T_y& y, const T_a& a, const T_v& v_value, +inline Scalar wiener5_grad_sv(const T_y& y, const T_a& a, const T_v& v_value, const T_w& w_value, const T_sv& sv, - double err = log(1e-12)) noexcept { - const double one_plus_svsqr_y = 1 + square(sv) * y; - const double w = 1.0 - w_value; - const double v = -v_value; - const double t1 = -y / one_plus_svsqr_y; - const double t2 = (square(a * w) + 2 * a * v * w * y + square(v * y)) + Scalar err = log(1e-12)) noexcept { + const Scalar one_plus_svsqr_y = 1 + square(sv) * y; + const Scalar w = 1.0 - w_value; + const Scalar v = -v_value; + const Scalar t1 = -y / one_plus_svsqr_y; + const Scalar t2 = (square(a * w) + 2 * a * v * w * y + square(v * y)) / square(one_plus_svsqr_y); - const double ans = sv * (t1 + t2); - return WrtLog ? ans * wiener5_density(y, a, v_value, w_value, sv, err) + const Scalar ans = sv * (t1 + t2); + return WrtLog ? ans * wiener5_density(y, a, v_value, w_value, sv, err) : ans; } /** * Utility function for replacing a value with a specified error value */ -template -inline void assign_err(double arg, double err) { +template +inline void assign_err(Scalar arg, Scalar err) { arg = err; } @@ -517,8 +517,8 @@ inline void assign_err(double arg, double err) { * Utility function for replacing a value with a specified error value, * overload for use when the value is stored within a tuple. */ -template -inline void assign_err(std::tuple& args_tuple, double err) { +template +inline void assign_err(std::tuple& args_tuple, Scalar err) { std::get(args_tuple) = err; } @@ -537,19 +537,18 @@ inline void assign_err(std::tuple& args_tuple, double err) { * @param args_tuple Tuple of arguments to pass to functor * @param log_result Whether the function result is already on the log-scale */ -template > -ReturnT estimate_with_err_check(const F& functor, T_partials err, +Scalar estimate_with_err_check(const F& functor, T_partials err, ArgsTupleT&&... args_tuple) { - T_partials result = functor(args_tuple...); - T_partials log_fabs_result = LogResult ? log(fabs(result)) : fabs(result); + Scalar result = functor(args_tuple...); + Scalar log_fabs_result = LogResult ? log(fabs(result)) : fabs(result); if (log_fabs_result < err) { - log_fabs_result = std::isinf(log_fabs_result) ? 0 : log_fabs_result; + //log_fabs_result = std::isinf(log_fabs_result) ? 0 : log_fabs_result; + log_fabs_result = is_inf(log_fabs_result) ? 0 : log_fabs_result; auto err_args_tuple = std::make_tuple(args_tuple...); - // const int size_tuple = std::tuple_size::value - - // 1; - const T_partials new_error + const Scalar new_error = GradW7 ? err + log_fabs_result + LOG_TWO : err + log_fabs_result; assign_err(std::get(err_args_tuple), new_error); result = math::apply([&](auto&&... args) { return functor(args...); }, @@ -580,7 +579,7 @@ ReturnT estimate_with_err_check(const F& functor, T_partials err, * @return The log of the Wiener first passage time density with * the specified arguments for upper boundary responses */ -template inline return_type_t wiener5_lpdf( const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, @@ -593,6 +592,7 @@ inline return_type_t wiener5_lpdf( using T_sv_ref = ref_type_if_t::value, T_sv>; using T_partials = partials_type_t>; + using T_partials_return = partials_return_t; static constexpr const char* function_name = "wiener5_lpdf"; if (size_zero(y, a, t0, w, v, sv)) { @@ -656,11 +656,11 @@ inline return_type_t wiener5_lpdf( } } - const T_partials log_error_density = log(1e-6); - const T_partials log_error_derivative = log(precision_derivatives); - const T_partials log_error_absolute = log(1e-12); - T_partials density = 0.0; - T_partials log_density = 0.0; + const T_partials_return log_error_density = log(1e-6); + const T_partials_return log_error_derivative = log(precision_derivatives); + const T_partials_return log_error_absolute = log(1e-12); + T_partials_return density = 0.0; + T_partials_return log_density = 0.0; operands_and_partials ops_partials(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref); @@ -671,25 +671,24 @@ inline return_type_t wiener5_lpdf( // Calculate 4-parameter model without inter-trial variabilities (if // sv_vec[i] == 0) or 5-parameter model with inter-trial variability in // drift rate (if sv_vec[i] != 0) - const T_partials y_val = y_vec.val(i); - const T_partials a_val = a_vec.val(i); - const T_partials t0_val = t0_vec.val(i); - const T_partials w_val = w_vec.val(i); - const T_partials v_val = v_vec.val(i); - const T_partials sv_val = sv_vec.val(i); - - density = internal::estimate_with_err_check<5, false, 0, false, T_partials>( - [&](auto&&... args) { return internal::wiener5_density(args...); }, + const T_partials_return y_val = y_vec.val(i); + const T_partials_return a_val = a_vec.val(i); + const T_partials_return t0_val = t0_vec.val(i); + const T_partials_return w_val = w_vec.val(i); + const T_partials_return v_val = v_vec.val(i); + const T_partials_return sv_val = sv_vec.val(i); + + density = internal::estimate_with_err_check<5, T_partials_return, false, 0, false>( + [&](auto&&... args) { return internal::wiener5_density(args...); }, log_error_density - LOG_TWO, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); - log_density += density; - const T_partials new_est_err = density + log_error_derivative - LOG_FOUR; + const T_partials_return new_est_err = density + log_error_derivative - LOG_FOUR; // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 - const T_partials deriv_y = internal::estimate_with_err_check<5, false, 0, true, T_partials>( - [&](auto&&... args) { return internal::wiener5_grad_t(args...); }, + const T_partials_return deriv_y = internal::estimate_with_err_check<5, T_partials_return, false, 0, true>( + [&](auto&&... args) { return internal::wiener5_grad_t(args...); }, new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); @@ -698,8 +697,8 @@ inline return_type_t wiener5_lpdf( ops_partials.edge1_.partials_[i] = deriv_y; } if (!is_constant_all::value) { - ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check<5, false, 0, true, T_partials>( - [&](auto&&... args) { return internal::wiener5_grad_a(args...); }, + ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check<5, T_partials_return, false, 0, true>( + [&](auto&&... args) { return internal::wiener5_grad_a(args...); }, new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); } @@ -707,17 +706,17 @@ inline return_type_t wiener5_lpdf( ops_partials.edge3_.partials_[i] = -deriv_y; } if (!is_constant_all::value) { - ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check<5, false, 0, true, T_partials>( - [&](auto&&... args) { return internal::wiener5_grad_w(args...); }, + ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check<5, T_partials_return, false, 0, true>( + [&](auto&&... args) { return internal::wiener5_grad_w(args...); }, new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); } if (!is_constant_all::value) { - ops_partials.edge5_.partials_[i] = internal::wiener5_grad_v( + ops_partials.edge5_.partials_[i] = internal::wiener5_grad_v( y_val - t0_val, a_val, v_val, w_val, sv_val); } if (!is_constant_all::value) { - ops_partials.edge6_.partials_[i] = internal::wiener5_grad_sv( + ops_partials.edge6_.partials_[i] = internal::wiener5_grad_sv( y_val - t0_val, a_val, v_val, w_val, sv_val); } } // end for loop diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 07c6d27ed6c..2f843d5edfc 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -444,8 +444,8 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, "(Inter-trial variability in nondecision time)", dim); - Eigen::Array xmin = Eigen::VectorXd::Zero(dim); - Eigen::Array xmax = Eigen::VectorXd::Ones(dim); + Eigen::Matrix xmin = Eigen::VectorXd::Zero(dim); + Eigen::Matrix xmax = Eigen::VectorXd::Ones(dim); if (st0_val != 0) { xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); } diff --git a/test/unit/math/mix/prob/wiener5_lpdf_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_test.cpp new file mode 100644 index 00000000000..a7ac2e36ee0 --- /dev/null +++ b/test/unit/math/mix/prob/wiener5_lpdf_test.cpp @@ -0,0 +1,131 @@ +#include +#include + + +TEST(mathMixDouble, wiener5_lpdf) { + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 1.5; + double sv = 0.2; + stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); +} + + +TEST(mathMixVar, wiener5_lpdf) { + using stan::math::var; + var y = 1.0; + var a = 2.0; + var t0 = 0.2; + var w = 0.5; + var v = 1.5; + var sv = 0.2; + stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); +} + + +TEST(mathMixFVar, wiener5_lpdf) { + using stan::math::fvar; + using stan::math::var; + fvar y = 1.0; + fvar a = 2.0; + fvar t0 = 0.2; + fvar w = 0.5; + fvar v = 1.5; + fvar sv = 0.2; + stan::math::wiener5_lpdf>(y, a, t0, w, v, sv, 1e-4); +} + + + +TEST(mathMixDouble1Fun, wiener5_lpdf) { + using stan::math::var; + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 1.5; + double sv = 0.2; + auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { + return [&y, &a, &t0, &w, &v](const auto& sv) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + stan::test::expect_ad(f1(y, a, t0, w, v), sv); +} +//-0.147527191875488 + +/* +TEST(mathMixDouble1Fun, wiener5_lpdf) { + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 1.5; + double sv = 0.2; + auto f1 = [](const auto& w, const auto& v, const auto& sv) { + return [&w, &v, &sv](const auto& y, const auto& a, const auto& t0) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + stan::test::expect_ad(f1(w, v, sv), y, a, t0); +}*/ + +/* +TEST(mathMixDouble2Fun, wiener5_lpdf) { + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 1.5; + double sv = 0.2; + auto f1 = [](const auto& y, const auto& a, const auto& t0) { + return [&y, &a, &t0](const auto& w, const auto& v, const auto& sv) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + stan::test::expect_ad(f1(y, a, t0), w, v, sv); +}*/ + +/* +TEST(mathMixVarFun, wiener5_lpdf) { + using stan::math::var; + var y = 1.0; + var a = 2.0; + var t0 = 0.2; + var w = 0.5; + var v = 1.5; + var sv = 0.2; + auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { + return [&y, &a, &t0, &w, &v](const auto& sv) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + stan::test::expect_ad(f1(y, a, t0, w, v), sv); +}*/ + + + +/* + //using stan::math::fvar; + //using stan::math::var; + auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { + return [&y, &a, &t0, &w, &v](const auto& sv, const auto& sw, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double st0 = 0.3; + + stan::test::expect_ad(f1(y, a, t0, w, v), sv, st0); + +}*/ \ No newline at end of file diff --git a/test/unit/math/mix/prob/wiener_full_test.cpp b/test/unit/math/mix/prob/wiener_full_test.cpp index 10e93df25bc..bb23803a8fd 100644 --- a/test/unit/math/mix/prob/wiener_full_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_test.cpp @@ -1,6 +1,19 @@ #include #include +TEST(mathMixDouble, wiener5_lpdf) { + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 1.5; + double sv = 0.2; + double sw = 0.2; + double st0 = 0.2; + stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); +} + +/* TEST(mathMixScalFun, wiener_full_lpdf) { auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { return [&y, &a, &t0, &w, &v](const auto& sv, const auto& sw, const auto& st0) { @@ -18,7 +31,7 @@ TEST(mathMixScalFun, wiener_full_lpdf) { return [&w, &v, &sv, &sw, &st0](const auto& y, const auto& a, const auto& t0) { return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); }; - };*/ + }; double y = 0.1; double a = 2.0; @@ -35,8 +48,8 @@ TEST(mathMixScalFun, wiener_full_lpdf) { } - - +*/ +/* TEST(mathMixVecFun, wiener_full_lpdf) { auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { return [&y, &a, &t0, &w, &v](const auto& sv, const auto& sw, const auto& st0) { @@ -54,7 +67,7 @@ TEST(mathMixVecFun, wiener_full_lpdf) { return [&w, &v, &sv, &sw, &st0](const auto& y, const auto& a, const auto& t0) { return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); }; - };*/ + }; Eigen::VectorXd y(2); y << 1.0, 1.5; @@ -79,4 +92,4 @@ TEST(mathMixVecFun, wiener_full_lpdf) { } - +*/ From 11598d85a77d6d7e67b1d33fc4eeead8224364ea Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 19 Sep 2023 10:56:45 +0200 Subject: [PATCH 100/179] test for wiener5, first attempt --- stan/math/prim/functor/hcubature.hpp | 261 ++++++++++-------- stan/math/prim/prob/wiener5_lpdf.hpp | 14 +- test/unit/math/mix/prob/wiener5_lpdf_test.cpp | 10 +- 3 files changed, 167 insertions(+), 118 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index e0668850be2..320bc06b8c2 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -71,7 +71,7 @@ static constexpr std::array gwd7{ * @param p number of elements * @param x x-th lexicographically ordered set */ -inline Eigen::VectorXi combination(Eigen::VectorXi& c, const int dim, +inline Eigen::Matrix combination(Eigen::Matrix& c, const int dim, const int p, const int x) { int r = 0; int k = 0; @@ -106,10 +106,11 @@ inline Eigen::VectorXi combination(Eigen::VectorXi& c, const int dim, * @param lambda scalar * @param dim dimension */ -inline Eigen::MatrixXd combos(const int k, const double lambda, const int dim) { - Eigen::VectorXi c(k); +template +inline Eigen::Matrix combos(const int k, const Scalar lambda, const int dim) { + Eigen::Matrix c(k); const auto choose_dimk = choose(dim, k); - Eigen::MatrixXd p = Eigen::MatrixXd::Zero(dim, choose_dimk); + Eigen::Matrix p = Eigen::MatrixXd::Zero(dim, choose_dimk); for (size_t i = 0; i < choose_dimk; i++) { c = combination(c, dim, k, i + 1); for (size_t j = 0; j < k; j++) { @@ -129,11 +130,14 @@ inline Eigen::MatrixXd combos(const int k, const double lambda, const int dim) { * @param lambda scalar * @param dim dimension */ -inline Eigen::MatrixXd signcombos(const int k, const double lambda, +template +inline Eigen::Matrix signcombos(const int k, const Scalar lambda, const int dim) { - Eigen::VectorXi c(k); +// Eigen::VectorXi c(k); + Eigen::Matrix c(k); const auto choose_dimk = choose(dim, k); - Eigen::MatrixXd p = Eigen::MatrixXd::Zero(dim, choose_dimk * std::pow(2, k)); +// Eigen::MatrixXd p = Eigen::MatrixXd::Zero(dim, choose_dimk * std::pow(2, k)); + Eigen::Matrix p = Eigen::MatrixXd::Zero(dim, choose_dimk * std::pow(2, k)); int current_col = 0; for (int i = 1; i != choose_dimk + 1; i++) { c = combination(c, dim, k, i); @@ -188,28 +192,28 @@ inline Eigen::MatrixXd signcombos(const int k, const double lambda, * @param pars_pair Pair of parameters for the integrand * @return numeric integral of the integrand and error */ -template -std::pair gauss_kronrod(const F& integrand, const double a, - const double b, +template +std::pair gauss_kronrod(const F& integrand, const Scalar a, + const Scalar b, const ParsPairT& pars_pair) { - Eigen::VectorXd c{{0.5 * (a + b)}}; - Eigen::VectorXd cp(1); - Eigen::VectorXd cm(1); - double delta = 0.5 * (b - a); - double f0 = math::apply( + Eigen::Matrix c{{0.5 * (a + b)}}; + Eigen::Matrix cp(1); + Eigen::Matrix cm(1); + Scalar delta = 0.5 * (b - a); + Scalar f0 = math::apply( [&integrand, &c](auto&&... args) { return integrand(c, args...); }, pars_pair); - double I = f0 * wd7[7]; - double Idash = f0 * gwd7[3]; - for (std::size_t i = 0; i != 7; i++) { - double deltax = delta * xd7[i]; + Scalar I = f0 * wd7[7]; + Scalar Idash = f0 * gwd7[3]; + for (auto i = 0; i != 7; i++) { + Scalar deltax = delta * xd7[i]; cp[0] = c[0] + deltax; cm[0] = c[0] - deltax; - double fx = math::apply( + Scalar fx = math::apply( [&integrand, &cp](auto&&... args) { return integrand(cp, args...); }, pars_pair); - double temp = math::apply( + Scalar temp = math::apply( [&integrand, &cm](auto&&... args) { return integrand(cm, args...); }, pars_pair); fx += temp; @@ -218,7 +222,7 @@ std::pair gauss_kronrod(const F& integrand, const double a, Idash += fx * gwd7[i / 2]; } } - double V = fabs(delta); + Scalar V = fabs(delta); I *= V; Idash *= V; return std::make_pair(I, fabs(I - Idash)); @@ -233,18 +237,19 @@ std::pair gauss_kronrod(const F& integrand, const double a, * @param[in,out] weights_low_deg weights for the embedded lower-degree rule * @param dim dimension */ -inline std::tuple, Eigen::VectorXd, - Eigen::VectorXd> +template +inline std::tuple, -1, 1>, Eigen::Matrix, + Eigen::Matrix> make_GenzMalik(const int dim) { - std::vector points(4); - Eigen::VectorXd weights(5); - Eigen::VectorXd weights_low_deg(4); - double l4 = std::sqrt(9 * 1.0 / 10); - double l2 = std::sqrt(9 * 1.0 / 70); - double l3 = l4; - double l5 = std::sqrt(9 * 1.0 / 19); + Eigen::Matrix, -1, 1> points(4); + Eigen::Matrix weights(5); + Eigen::Matrix weights_low_deg(4); + Scalar l4 = std::sqrt(9 * 1.0 / 10); + Scalar l2 = std::sqrt(9 * 1.0 / 70); + Scalar l3 = l4; + Scalar l5 = std::sqrt(9 * 1.0 / 19); - double twopn = std::pow(2, dim); + Scalar twopn = std::pow(2, dim); weights[0] = twopn * ((12824 - 9120 * dim + 400 * dim * dim) * 1.0 / 19683); weights[1] = twopn * (980.0 / 6561); @@ -280,67 +285,68 @@ make_GenzMalik(const int dim) { * @return numeric integral of the integrand, error, and suggested coordinate to * subdivide next */ -template -std::tuple integrate_GenzMalik( - const F& integrand, const std::vector& points, - const Eigen::VectorXd& weights, const Eigen::VectorXd& weights_low_deg, - const int dim, const Eigen::VectorXd& a, const Eigen::VectorXd& b, +template +std::tuple integrate_GenzMalik( + const F& integrand, const Eigen::Matrix, -1, 1>& points, + const Eigen::Matrix& weights, const Eigen::Matrix& weights_low_deg, + const int dim, const Eigen::Matrix& a, const Eigen::Matrix& b, const ParsTupleT& pars_tuple) { - Eigen::VectorXd c = Eigen::VectorXd::Zero(dim); - for (std::size_t i = 0; i != dim; i++) { + using eig_vec = Eigen::Matrix; + eig_vec c = Eigen::VectorXd::Zero(dim); + for (auto i = 0; i != dim; i++) { if (a[i] == b[i]) { return std::make_tuple(0.0, 0.0, 0); } c[i] = (a[i] + b[i]) / 2; } - Eigen::VectorXd deltac = ((b - a).array() / 2.0).matrix(); - double v = 1.0; + eig_vec deltac = ((b - a).array() / 2.0).matrix(); + Scalar v = 1.0; for (std::size_t i = 0; i != dim; i++) { v *= deltac[i]; } - double f1 = math::apply( + Scalar f1 = math::apply( [&integrand, &c](auto&&... args) { return integrand(c, args...); }, pars_tuple); - double f2 = 0.0; - double f3 = 0.0; - double twelvef1 = 12 * f1; - - double maxdivdiff = 0.0; - Eigen::VectorXd divdiff(dim); - Eigen::VectorXd p2(dim); - Eigen::VectorXd p3(dim); - Eigen::VectorXd cc(dim); - - for (std::size_t i = 0; i != dim; i++) { - for (std::size_t j = 0; j != dim; j++) { + Scalar f2 = 0.0; + Scalar f3 = 0.0; + Scalar twelvef1 = 12 * f1; + + Scalar maxdivdiff = 0.0; + eig_vec divdiff(dim); + eig_vec p2(dim); + eig_vec p3(dim); + eig_vec cc(dim); + + for (auto i = 0; i != dim; i++) { + for (auto j = 0; j != dim; j++) { p2[j] = deltac[j] * points[0](j, i); } - for (std::size_t j = 0; j != dim; j++) { + for (auto j = 0; j != dim; j++) { cc[j] = c[j] + p2[j]; } - double f2i = math::apply( + Scalar f2i = math::apply( [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, pars_tuple); - for (std::size_t j = 0; j != dim; j++) { + for (auto j = 0; j != dim; j++) { cc[j] = c[j] - p2[j]; } - double temp = math::apply( + Scalar temp = math::apply( [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, pars_tuple); f2i += temp; - for (std::size_t j = 0; j != dim; j++) { + for (auto j = 0; j != dim; j++) { p3[j] = deltac[j] * points[1](j, i); } - for (std::size_t j = 0; j != dim; j++) { + for (auto j = 0; j != dim; j++) { cc[j] = c[j] + p3[j]; } - double f3i = math::apply( + Scalar f3i = math::apply( [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, pars_tuple); - for (std::size_t j = 0; j != dim; j++) { + for (auto j = 0; j != dim; j++) { cc[j] = c[j] - p3[j]; } temp = math::apply( @@ -351,48 +357,48 @@ std::tuple integrate_GenzMalik( f3 += f3i; divdiff[i] = fabs(f3i + twelvef1 - 7 * f2i); } - Eigen::VectorXd p4(dim); - double f4 = 0.0; - for (std::size_t i = 0; i != points[2].cols(); i++) { - for (std::size_t j = 0; j != dim; j++) { + eig_vec p4(dim); + Scalar f4 = 0.0; + for (auto i = 0; i != points[2].cols(); i++) { + for (auto j = 0; j != dim; j++) { p4[j] = deltac[j] * points[2](j, i); } - for (std::size_t j = 0; j != dim; j++) { + for (auto j = 0; j != dim; j++) { cc[j] = c[j] + p4[j]; } - double temp = math::apply( + Scalar temp = math::apply( [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, pars_tuple); f4 += temp; } - double f5 = 0.0; - Eigen::VectorXd p5(dim); - for (std::size_t i = 0; i != points[3].cols(); i++) { - for (std::size_t j = 0; j != dim; j++) { + Scalar f5 = 0.0; + eig_vec p5(dim); + for (auto i = 0; i != points[3].cols(); i++) { + for (auto j = 0; j != dim; j++) { p5[j] = deltac[j] * points[3](j, i); } - for (std::size_t j = 0; j != dim; j++) { + for (auto j = 0; j != dim; j++) { cc[j] = c[j] + p5[j]; } - double temp = math::apply( + Scalar temp = math::apply( [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, pars_tuple); f5 += temp; } - double I = v + Scalar I = v * (weights[0] * f1 + weights[1] * f2 + weights[2] * f3 + weights[3] * f4 + weights[4] * f5); - double Idash = v + Scalar Idash = v * (weights_low_deg[0] * f1 + weights_low_deg[1] * f2 + weights_low_deg[2] * f3 + weights_low_deg[3] * f4); - double E = fabs(I - Idash); + Scalar E = fabs(I - Idash); int kdivide = 0; - double deltaf = E / (std::pow(10, dim) * v); - for (std::size_t i = 0; i != dim; i++) { - double delta = divdiff[i] - maxdivdiff; + Scalar deltaf = E / (std::pow(10, dim) * v); + for (auto i = 0; i != dim; i++) { + Scalar delta = divdiff[i] - maxdivdiff; if (delta > deltaf) { kdivide = i; maxdivdiff = divdiff[i]; @@ -414,16 +420,19 @@ std::tuple integrate_GenzMalik( * @param I value of the integral * @param kdivide number of subdividing the integration volume */ +template //, typename Vec1, typename Vec2> struct Box { template - Box(Vec1&& a, Vec2&& b, double I, int kdivide) + Box(Vec1&& a, Vec2&& b, Scalar I, int kdivide) : a_(std::forward(a)), b_(std::forward(b)), I_(I), kdiv_(kdivide) {} +// Eigen::Matrix a_; Eigen::VectorXd a_; +// Eigen::Matrix b_; Eigen::VectorXd b_; - double I_; + Scalar I_; int kdiv_; }; @@ -473,48 +482,60 @@ struct Box { \f$b\f$. * @throw std::domain_error no errors will be thrown. */ -template -double hcubature(const F& integrand, const ParsTuple& pars, const int dim, - const Eigen::VectorXd& a, const Eigen::VectorXd& b, - const int max_eval, const double reqAbsError, - const double reqRelError) { - const auto maxEval = max_eval <= 0 ? 1000000 : max_eval; - double result; - double err; - int kdivide = 0; - - std::vector p(4); - Eigen::VectorXd w_five(5); - Eigen::VectorXd wd_four(4); +template +Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, + const Eigen::Matrix& a, const Eigen::Matrix& b, + const int max_eval, const Scalar reqAbsError, + const Scalar reqRelError) { + using eig_vec = Eigen::Matrix; + const Scalar maxEval = max_eval <= 0 ? 1000000 : max_eval; + Scalar result; + Scalar err; + auto kdivide = 0; + +// std::vector p(4); + Eigen::Matrix p(4); +// Eigen::VectorXd w_five(5); +// Eigen::VectorXd wd_four(4); + eig_vec w_five(5); + eig_vec wd_four(4); if (dim == 1) { std::tie(result, err) - = internal::gauss_kronrod(integrand, a[0], b[0], pars); + = internal::gauss_kronrod(integrand, a[0], b[0], pars); } else { - std::tie(p, w_five, wd_four) = internal::make_GenzMalik(dim); - std::tie(result, err, kdivide) = internal::integrate_GenzMalik( + std::tie(p, w_five, wd_four) = internal::make_GenzMalik(dim); + std::tie(result, err, kdivide) = internal::integrate_GenzMalik( integrand, p, w_five, wd_four, dim, a, b, pars); } - int numevals + auto numevals = (dim == 1) ? 15 : 1 + 4 * dim + 2 * dim * (dim - 1) + std::pow(2, dim); - int evals_per_box = numevals; - if ((err <= fmax(reqRelError * fabs(result), reqAbsError)) + auto evals_per_box = numevals; + Scalar error = err; + Scalar val = result; + + if ((error <= fmax(reqRelError * fabs(val), reqAbsError)) || (numevals >= maxEval)) { return result; } numevals += 2 * evals_per_box; - std::vector ms; + std::vector> ms; +// Eigen::Matrix, -1, 1> ms; ms.reserve(numevals); +// ms.conservativeResize(numevals); ms.emplace_back(std::move(a), std::move(b), result, kdivide); auto get_largest_box_idx = [](auto&& box_vec) { auto max_it = std::max_element(box_vec.begin(), box_vec.end()); return std::distance(box_vec.begin(), max_it); }; - std::vector err_vec; +// std::vector err_vec; + std::vector err_vec; +// eig_vec err_vec; err_vec.reserve(numevals); +// err_vec.conservativeResize(numevals); err_vec.push_back(err); while ((numevals < maxEval) - && (err > max(reqRelError * fabs(result), reqAbsError)) + /* && (err > max(reqRelError * fabs(result), reqAbsError)) && std::isfinite(result)) { auto err_idx = get_largest_box_idx(err_vec); auto&& box = ms[err_idx]; @@ -533,21 +554,39 @@ double hcubature(const F& integrand, const ParsTuple& pars, const int dim, double err_1; double err_2; double kdivide_1{0}; - double kdivide_2{0}; + double kdivide_2{0};*/ + + && (error > max(reqRelError * fabs(val), reqAbsError)) + && std::isfinite(val)) { + auto err_idx = get_largest_box_idx(err_vec); + internal::Box box = ms.top(); + ms.pop(); + + Scalar w = (box.b_[box.kdiv_] - box.a_[box.kdiv_]) / 2; +// std::vector ma(box.a); + eig_vec ma(box.a_); + ma[box.kdiv_] += w; +// std::vector mb(box.b); + eig_vec mb(box.b_); + mb[box.kdiv_] -= w; + + Scalar result_1, result_2, err_1, err_2; + Scalar kdivide_1 = math::NOT_A_NUMBER; + Scalar kdivide_2 = math::NOT_A_NUMBER; if (dim == 1) { std::tie(result_1, err_1) - = internal::gauss_kronrod(integrand, ma[0], box.b_[0], pars); + = internal::gauss_kronrod(integrand, ma[0], box.b_[0], pars); std::tie(result_2, err_2) - = internal::gauss_kronrod(integrand, box.a_[0], mb[0], pars); + = internal::gauss_kronrod(integrand, box.a_[0], mb[0], pars); } else { - std::tie(result_1, err_1, kdivide_1) = internal::integrate_GenzMalik( + std::tie(result_1, err_1, kdivide_1) = internal::integrate_GenzMalik( integrand, p, w_five, wd_four, dim, ma, box.b_, pars); - std::tie(result_2, err_2, kdivide_2) = internal::integrate_GenzMalik( + std::tie(result_2, err_2, kdivide_2) = internal::integrate_GenzMalik( integrand, p, w_five, wd_four, dim, box.a_, mb, pars); } - internal::Box box1(std::move(ma), std::move(box.b_), result_1, kdivide_1); - internal::Box box2(std::move(box.a_), std::move(mb), result_2, kdivide_2); + internal::Box box1(std::move(ma), std::move(box.b_), result_1, kdivide_1); + internal::Box box2(std::move(box.a_), std::move(mb), result_2, kdivide_2); result += result_1 + result_2 - box.I_; err += err_1 + err_2 - err_vec[err_idx]; ms[err_idx].I_ = 0; diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index cebd5757445..a204cbe4a92 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -579,7 +579,7 @@ Scalar estimate_with_err_check(const F& functor, T_partials err, * @return The log of the Wiener first passage time density with * the specified arguments for upper boundary responses */ -template inline return_type_t wiener5_lpdf( const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, @@ -591,7 +591,6 @@ inline return_type_t wiener5_lpdf( using T_v_ref = ref_type_if_t::value, T_v>; using T_sv_ref = ref_type_if_t::value, T_sv>; - using T_partials = partials_type_t>; using T_partials_return = partials_return_t; static constexpr const char* function_name = "wiener5_lpdf"; @@ -718,6 +717,17 @@ inline return_type_t wiener5_lpdf( if (!is_constant_all::value) { ops_partials.edge6_.partials_[i] = internal::wiener5_grad_sv( y_val - t0_val, a_val, v_val, w_val, sv_val); +/* const auto params + = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, log(1e-5)); + Eigen::Matrix xmin = Eigen::VectorXd::Zero(1); + Eigen::Matrix xmax = Eigen::VectorXd::Ones(1); + int max_eval = 1000; + int dim = 1; + T_partials_return abs = 0.0; + T_partials_return rel = 1e-5; + ops_partials.edge6_.partials_[i] = hcubature(internal::wiener5_grad_a, + params, dim, xmin, xmax, max_eval, abs, rel); */ } } // end for loop return ops_partials.build(log_density); diff --git a/test/unit/math/mix/prob/wiener5_lpdf_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_test.cpp index a7ac2e36ee0..746535a4175 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_test.cpp @@ -9,7 +9,7 @@ TEST(mathMixDouble, wiener5_lpdf) { double w = 0.5; double v = 1.5; double sv = 0.2; - stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); } @@ -21,7 +21,7 @@ TEST(mathMixVar, wiener5_lpdf) { var w = 0.5; var v = 1.5; var sv = 0.2; - stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); } @@ -34,7 +34,7 @@ TEST(mathMixFVar, wiener5_lpdf) { fvar w = 0.5; fvar v = 1.5; fvar sv = 0.2; - stan::math::wiener5_lpdf>(y, a, t0, w, v, sv, 1e-4); + stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); } @@ -49,12 +49,12 @@ TEST(mathMixDouble1Fun, wiener5_lpdf) { double sv = 0.2; auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { return [&y, &a, &t0, &w, &v](const auto& sv) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; stan::test::expect_ad(f1(y, a, t0, w, v), sv); } -//-0.147527191875488 +//correct value for grad_sv from R: -0.147527191875488 /* TEST(mathMixDouble1Fun, wiener5_lpdf) { From 8efd5836568ee0a5d22a04d7ec888600cc94cae2 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Wed, 20 Sep 2023 12:10:05 +0200 Subject: [PATCH 101/179] another error in math::apply --- stan/math/prim/functor/hcubature.hpp | 43 +++++++++++++++------------- stan/math/prim/prob/wiener5_lpdf.hpp | 4 +-- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 320bc06b8c2..db8bddd0768 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -196,9 +196,11 @@ template std::pair gauss_kronrod(const F& integrand, const Scalar a, const Scalar b, const ParsPairT& pars_pair) { - Eigen::Matrix c{{0.5 * (a + b)}}; - Eigen::Matrix cp(1); - Eigen::Matrix cm(1); + //Eigen::Matrix c{{0.5 * (a + b)}}; + //Eigen::Matrix cp(1); + //Eigen::Matrix cm(1); + Scalar c = 0.5 * (a+b); + Scalar delta = 0.5 * (b - a); Scalar f0 = math::apply( [&integrand, &c](auto&&... args) { return integrand(c, args...); }, @@ -208,8 +210,10 @@ std::pair gauss_kronrod(const F& integrand, const Scalar a, Scalar Idash = f0 * gwd7[3]; for (auto i = 0; i != 7; i++) { Scalar deltax = delta * xd7[i]; - cp[0] = c[0] + deltax; - cm[0] = c[0] - deltax; +// cp[0] = c[0] + deltax; +// cm[0] = c[0] - deltax; + Scalar cp = c + deltax; + Scalar cm = c - deltax; Scalar fx = math::apply( [&integrand, &cp](auto&&... args) { return integrand(cp, args...); }, pars_pair); @@ -535,9 +539,10 @@ Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, // err_vec.conservativeResize(numevals); err_vec.push_back(err); while ((numevals < maxEval) - /* && (err > max(reqRelError * fabs(result), reqAbsError)) - && std::isfinite(result)) { + && (error > fmax(reqRelError * fabs(val), reqAbsError)) + && fabs(val) < INFTY){ //isfinite(val)) { auto err_idx = get_largest_box_idx(err_vec); +//---------------- auto&& box = ms[err_idx]; double w = (box.b_[box.kdiv_] - box.a_[box.kdiv_]) / 2; @@ -549,17 +554,15 @@ Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, = Eigen::Map(box.b_.data(), box.b_.size()); mb[box.kdiv_] -= w; - double result_1; + /*double result_1; double result_2; double err_1; - double err_2; - double kdivide_1{0}; - double kdivide_2{0};*/ - - && (error > max(reqRelError * fabs(val), reqAbsError)) - && std::isfinite(val)) { - auto err_idx = get_largest_box_idx(err_vec); - internal::Box box = ms.top(); + double err_2;*/ + int kdivide_1{0}; + int kdivide_2{0}; +//-------------------------- + /* + internal::Box box = ms.top(); ms.pop(); Scalar w = (box.b_[box.kdiv_] - box.a_[box.kdiv_]) / 2; @@ -568,12 +571,12 @@ Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, ma[box.kdiv_] += w; // std::vector mb(box.b); eig_vec mb(box.b_); - mb[box.kdiv_] -= w; + mb[box.kdiv_] -= w; */ Scalar result_1, result_2, err_1, err_2; - Scalar kdivide_1 = math::NOT_A_NUMBER; - Scalar kdivide_2 = math::NOT_A_NUMBER; - + //Scalar kdivide_1 = math::NOT_A_NUMBER; + //Scalar kdivide_2 = math::NOT_A_NUMBER; +//----------------------- if (dim == 1) { std::tie(result_1, err_1) = internal::gauss_kronrod(integrand, ma[0], box.b_[0], pars); diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index a204cbe4a92..f7bc1229b90 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -717,8 +717,8 @@ inline return_type_t wiener5_lpdf( if (!is_constant_all::value) { ops_partials.edge6_.partials_[i] = internal::wiener5_grad_sv( y_val - t0_val, a_val, v_val, w_val, sv_val); -/* const auto params - = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, log(1e-5)); + /* const auto params + = std::make_tuple(y_val-t0_val, a_val, v_val, w_val, sv_val); Eigen::Matrix xmin = Eigen::VectorXd::Zero(1); Eigen::Matrix xmax = Eigen::VectorXd::Ones(1); int max_eval = 1000; From 86976ac2493302d4f38ec11bfa3060d20899d74b Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Sat, 30 Sep 2023 12:23:15 +0200 Subject: [PATCH 102/179] it works a bit more, still some errors --- stan/math/prim/functor/hcubature.hpp | 58 ++++---- stan/math/prim/prob/wiener5_lpdf.hpp | 108 +++++++++++---- stan/math/prim/prob/wiener_full_lpdf.hpp | 130 +++++++++--------- test/unit/math/mix/prob/wiener5_lpdf_test.cpp | 7 +- test/unit/math/mix/prob/wiener_full_test.cpp | 17 ++- 5 files changed, 187 insertions(+), 133 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index db8bddd0768..28813b86105 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -196,10 +196,9 @@ template std::pair gauss_kronrod(const F& integrand, const Scalar a, const Scalar b, const ParsPairT& pars_pair) { - //Eigen::Matrix c{{0.5 * (a + b)}}; - //Eigen::Matrix cp(1); - //Eigen::Matrix cm(1); - Scalar c = 0.5 * (a+b); + Eigen::Matrix c{{0.5 * (a + b)}}; + Eigen::Matrix cp(1); + Eigen::Matrix cm(1); Scalar delta = 0.5 * (b - a); Scalar f0 = math::apply( @@ -210,10 +209,8 @@ std::pair gauss_kronrod(const F& integrand, const Scalar a, Scalar Idash = f0 * gwd7[3]; for (auto i = 0; i != 7; i++) { Scalar deltax = delta * xd7[i]; -// cp[0] = c[0] + deltax; -// cm[0] = c[0] - deltax; - Scalar cp = c + deltax; - Scalar cm = c - deltax; + cp[0] = c[0] + deltax; + cm[0] = c[0] - deltax; Scalar fx = math::apply( [&integrand, &cp](auto&&... args) { return integrand(cp, args...); }, pars_pair); @@ -245,7 +242,7 @@ template inline std::tuple, -1, 1>, Eigen::Matrix, Eigen::Matrix> make_GenzMalik(const int dim) { - Eigen::Matrix, -1, 1> points(4); + Eigen::Matrix, -1, 1> points(4); // is this line correct? It has been: std::vector points(4); Eigen::Matrix weights(5); Eigen::Matrix weights_low_deg(4); Scalar l4 = std::sqrt(9 * 1.0 / 10); @@ -254,7 +251,6 @@ make_GenzMalik(const int dim) { Scalar l5 = std::sqrt(9 * 1.0 / 19); Scalar twopn = std::pow(2, dim); - weights[0] = twopn * ((12824 - 9120 * dim + 400 * dim * dim) * 1.0 / 19683); weights[1] = twopn * (980.0 / 6561); weights[2] = twopn * ((1820 - 400 * dim) * 1.0 / 19683); @@ -264,10 +260,14 @@ make_GenzMalik(const int dim) { weights_low_deg[2] = twopn * ((265 - 100 * dim) * 1.0 / 1458); weights_low_deg[1] = twopn * (245.0 / 486); weights_low_deg[0] = twopn * ((729 - 950 * dim + 50 * dim * dim) * 1.0 / 729); +std::cout << "In make_GenzMalik Stelle vor combos" << std::endl; points[0] = combos(1, l2, dim); +std::cout << "In make_GenzMalik Stelle vor combos2" << std::endl; points[1] = combos(1, l3, dim); +std::cout << "In make_GenzMalik nach combos" << std::endl; points[2] = signcombos(2, l4, dim); points[3] = signcombos(dim, l5, dim); +std::cout << "In make_GenzMalik Stelle 4" << std::endl; return std::make_tuple(std::move(points), std::move(weights), std::move(weights_low_deg)); } @@ -296,7 +296,7 @@ std::tuple integrate_GenzMalik( const int dim, const Eigen::Matrix& a, const Eigen::Matrix& b, const ParsTupleT& pars_tuple) { using eig_vec = Eigen::Matrix; - eig_vec c = Eigen::VectorXd::Zero(dim); + Eigen::Matrix c = Eigen::VectorXd::Zero(dim); for (auto i = 0; i != dim; i++) { if (a[i] == b[i]) { return std::make_tuple(0.0, 0.0, 0); @@ -424,7 +424,7 @@ std::tuple integrate_GenzMalik( * @param I value of the integral * @param kdivide number of subdividing the integration volume */ -template //, typename Vec1, typename Vec2> +template struct Box { template Box(Vec1&& a, Vec2&& b, Scalar I, int kdivide) @@ -432,10 +432,8 @@ struct Box { b_(std::forward(b)), I_(I), kdiv_(kdivide) {} -// Eigen::Matrix a_; - Eigen::VectorXd a_; -// Eigen::Matrix b_; - Eigen::VectorXd b_; + Eigen::Matrix a_; + Eigen::Matrix b_; Scalar I_; int kdiv_; }; @@ -497,10 +495,7 @@ Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, Scalar err; auto kdivide = 0; -// std::vector p(4); Eigen::Matrix p(4); -// Eigen::VectorXd w_five(5); -// Eigen::VectorXd wd_four(4); eig_vec w_five(5); eig_vec wd_four(4); @@ -508,7 +503,9 @@ Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, std::tie(result, err) = internal::gauss_kronrod(integrand, a[0], b[0], pars); } else { +std::cout << "vor make_GenzMalik" << std::endl; std::tie(p, w_five, wd_four) = internal::make_GenzMalik(dim); +std::cout << "nach make_GenzMalik" << std::endl; std::tie(result, err, kdivide) = internal::integrate_GenzMalik( integrand, p, w_five, wd_four, dim, a, b, pars); } @@ -532,11 +529,9 @@ Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, auto max_it = std::max_element(box_vec.begin(), box_vec.end()); return std::distance(box_vec.begin(), max_it); }; -// std::vector err_vec; std::vector err_vec; // eig_vec err_vec; err_vec.reserve(numevals); -// err_vec.conservativeResize(numevals); err_vec.push_back(err); while ((numevals < maxEval) && (error > fmax(reqRelError * fabs(val), reqAbsError)) @@ -545,19 +540,15 @@ Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, //---------------- auto&& box = ms[err_idx]; - double w = (box.b_[box.kdiv_] - box.a_[box.kdiv_]) / 2; - Eigen::VectorXd ma - = Eigen::Map(box.a_.data(), box.a_.size()); + Scalar w = (box.b_[box.kdiv_] - box.a_[box.kdiv_]) / 2; + eig_vec ma + = Eigen::Map(box.a_.data(), box.a_.size()); ma[box.kdiv_] += w; - Eigen::VectorXd mb - = Eigen::Map(box.b_.data(), box.b_.size()); + eig_vec mb + = Eigen::Map(box.b_.data(), box.b_.size()); mb[box.kdiv_] -= w; - /*double result_1; - double result_2; - double err_1; - double err_2;*/ int kdivide_1{0}; int kdivide_2{0}; //-------------------------- @@ -573,9 +564,10 @@ Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, eig_vec mb(box.b_); mb[box.kdiv_] -= w; */ - Scalar result_1, result_2, err_1, err_2; - //Scalar kdivide_1 = math::NOT_A_NUMBER; - //Scalar kdivide_2 = math::NOT_A_NUMBER; + Scalar result_1; + Scalar result_2; + Scalar err_1; + Scalar err_2; //----------------------- if (dim == 1) { std::tie(result_1, err_1) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index f7bc1229b90..b71eb993086 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -6,6 +6,7 @@ namespace stan { namespace math { namespace internal { + /** * Calculate the 'error_term' term for a wiener5 density or gradient * @@ -260,8 +261,7 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, * @return density */ template > + typename T_w, typename T_v, typename T_sv> inline Scalar wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, const T_w& w_value, const T_sv& sv, Scalar err = log(1e-12)) noexcept { @@ -301,8 +301,7 @@ inline Scalar wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, * @return Gradient w.r.t. t */ template > + typename T_w, typename T_v, typename T_sv> inline Scalar wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, const T_w& w_value, const T_sv& sv, Scalar err = log(1e-12)) noexcept { const Scalar two_log_a = 2 * log(a); @@ -356,8 +355,7 @@ inline Scalar wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, * @return Gradient w.r.t. a */ template > + typename T_w, typename T_v, typename T_sv> inline Scalar wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, const T_w& w_value, const T_sv& sv, Scalar err = log(1e-12)) noexcept { const Scalar two_log_a = 2 * log(a); @@ -411,8 +409,7 @@ inline Scalar wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, * @return Gradient w.r.t. v */ template > + typename T_w, typename T_v, typename T_sv> inline Scalar wiener5_grad_v(const T_y& y, const T_a& a, const T_v& v_value, const T_w& w_value, const T_sv& sv, Scalar err = log(1e-12)) noexcept { Scalar ans = (a * (1 - w_value) - v_value * y); @@ -438,8 +435,7 @@ inline Scalar wiener5_grad_v(const T_y& y, const T_a& a, const T_v& v_value, * @return Gradient w.r.t. w */ template > + typename T_w, typename T_v, typename T_sv> inline Scalar wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, const T_w& w_value, const T_sv& sv, Scalar err = log(1e-12)) noexcept { const Scalar two_log_a = 2 * log(a); @@ -489,8 +485,7 @@ inline Scalar wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, * @return Gradient w.r.t. sv */ template > + typename T_w, typename T_v, typename T_sv> inline Scalar wiener5_grad_sv(const T_y& y, const T_a& a, const T_v& v_value, const T_w& w_value, const T_sv& sv, Scalar err = log(1e-12)) noexcept { @@ -537,15 +532,13 @@ inline void assign_err(std::tuple& args_tuple, Scalar err) { * @param args_tuple Tuple of arguments to pass to functor * @param log_result Whether the function result is already on the log-scale */ -template > -Scalar estimate_with_err_check(const F& functor, T_partials err, +template +Scalar estimate_with_err_check(const F& functor, Scalar err, ArgsTupleT&&... args_tuple) { Scalar result = functor(args_tuple...); Scalar log_fabs_result = LogResult ? log(fabs(result)) : fabs(result); if (log_fabs_result < err) { - //log_fabs_result = std::isinf(log_fabs_result) ? 0 : log_fabs_result; log_fabs_result = is_inf(log_fabs_result) ? 0 : log_fabs_result; auto err_args_tuple = std::make_tuple(args_tuple...); const Scalar new_error @@ -556,6 +549,55 @@ Scalar estimate_with_err_check(const F& functor, T_partials err, } return result; } + + + + + +template * = nullptr> +inline Scalar conditionally_grad_sw_2(const F& functor, Scalar y_diff, Scalar a, + Scalar v, Scalar w, Scalar sv, Scalar sw, + Scalar log_error) { + return functor(y_diff, a, v, w, sv, log_error); +} + +template * = nullptr> +inline Scalar conditionally_grad_sw_2(const F& functor, Scalar y_diff, Scalar a, + Scalar v, Scalar w, Scalar sv, Scalar sw, + Scalar log_error) { + return functor(y_diff, a, v, w, sv, sw, log_error); +} + + +template > +ReturnT wiener7_integrate_2(const Wiener7FunctorT& wiener7_functor, + Scalar hcubature_err, TArgs&&... args) { + const auto wiener7_integrand_impl + = [&](auto&& x, Scalar y, Scalar a, Scalar v, Scalar w, Scalar t0, + Scalar sv, Scalar sw, Scalar st0, Scalar log_error) { + scalar_seq_view x_vec(x); + const Scalar sw_val = GradSW ? 0 : sw; + const Scalar new_w = (sw_val!= 0) ? w + sw_val * (x_vec[0] - 0.5) : w; + const Scalar new_t0 = (sw_val!= 0) ? ((st0 != 0) ? t0 + st0 * x_vec[1] : t0) + : ((st0 != 0) ? t0 + st0 * x_vec[0] : t0); + if (y - new_t0 <= 0) { + return 0.0; + } else { + return conditionally_grad_sw_2(wiener7_functor, y - new_t0, a, + v, new_w, sv, sw, + log_error); + } + }; + const auto functor = [&](auto&&... int_args) { + return hcubature(wiener7_integrand_impl, int_args...); + }; + return estimate_with_err_check(functor, hcubature_err, args...); +} + + + + } // namespace internal /** @@ -580,10 +622,11 @@ Scalar estimate_with_err_check(const F& functor, T_partials err, * the specified arguments for upper boundary responses */ template + typename T_w, typename T_v, typename T_sv, typename ReturnT + = return_type_t> inline return_type_t wiener5_lpdf( const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, - const T_sv& sv, const double& precision_derivatives) { + const T_sv& sv, const ReturnT& precision_derivatives) { using T_y_ref = ref_type_if_t::value, T_y>; using T_a_ref = ref_type_if_t::value, T_a>; using T_t0_ref = ref_type_if_t::value, T_t0>; @@ -677,7 +720,7 @@ inline return_type_t wiener5_lpdf( const T_partials_return v_val = v_vec.val(i); const T_partials_return sv_val = sv_vec.val(i); - density = internal::estimate_with_err_check<5, T_partials_return, false, 0, false>( + density = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener5_density(args...); }, log_error_density - LOG_TWO, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); @@ -686,7 +729,7 @@ inline return_type_t wiener5_lpdf( // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 - const T_partials_return deriv_y = internal::estimate_with_err_check<5, T_partials_return, false, 0, true>( + const T_partials_return deriv_y = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener5_grad_t(args...); }, new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); @@ -696,7 +739,7 @@ inline return_type_t wiener5_lpdf( ops_partials.edge1_.partials_[i] = deriv_y; } if (!is_constant_all::value) { - ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check<5, T_partials_return, false, 0, true>( + ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener5_grad_a(args...); }, new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); @@ -705,7 +748,7 @@ inline return_type_t wiener5_lpdf( ops_partials.edge3_.partials_[i] = -deriv_y; } if (!is_constant_all::value) { - ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check<5, T_partials_return, false, 0, true>( + ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener5_grad_w(args...); }, new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, log_error_absolute); @@ -715,19 +758,24 @@ inline return_type_t wiener5_lpdf( y_val - t0_val, a_val, v_val, w_val, sv_val); } if (!is_constant_all::value) { - ops_partials.edge6_.partials_[i] = internal::wiener5_grad_sv( - y_val - t0_val, a_val, v_val, w_val, sv_val); - /* const auto params - = std::make_tuple(y_val-t0_val, a_val, v_val, w_val, sv_val); + // ops_partials.edge6_.partials_[i] = internal::wiener5_grad_sv( + // y_val - t0_val, a_val, v_val, w_val, sv_val); + const auto params + = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, 0, + 0, log_error_absolute - LOG_TWO); Eigen::Matrix xmin = Eigen::VectorXd::Zero(1); Eigen::Matrix xmax = Eigen::VectorXd::Ones(1); int max_eval = 1000; int dim = 1; + T_partials_return hcubature_err = 1e-4; T_partials_return abs = 0.0; T_partials_return rel = 1e-5; - ops_partials.edge6_.partials_[i] = hcubature(internal::wiener5_grad_a, - params, dim, xmin, xmax, max_eval, abs, rel); */ + ops_partials.edge6_.partials_[i] = internal::wiener7_integrate_2( + [&](auto&&... args) { + return internal::wiener5_grad_a(args...); + }, + hcubature_err, params, dim, xmin, xmax, max_eval, abs, rel); } } // end for loop return ops_partials.build(log_density); diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 2f843d5edfc..7a0199c8481 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -21,17 +21,17 @@ namespace internal { * @param log_error The log error tolerance * @return Gradient w.r.t. sw */ -template > +template > inline ReturnT wiener7_grad_sw(const T_y& y, const T_a& a, const T_v& v, const T_w& w, const T_sv& sv, - const T_sw& sw, double log_error) { - T_partials low = w - sw / 2.0; + const T_sw& sw, Scalar log_error) { + Scalar low = w - sw / 2.0; low = (0 > low) ? 0 : low; - T_partials high = w + sw / 2.0; + Scalar high = w + sw / 2.0; high = (1 < high) ? 1 : high; - const T_partials lower_value = wiener5_density(y, a, v, low, sv, log_error); - const T_partials upper_value + const Scalar lower_value = wiener5_density(y, a, v, low, sv, log_error); + const Scalar upper_value = wiener5_density(y, a, v, high, sv, log_error); return 0.5 * (lower_value + upper_value) / sw; } @@ -58,12 +58,12 @@ inline ReturnT wiener7_grad_sw(const T_y& y, const T_a& a, const T_v& v, const T * @param log_error The log error tolerance * @return Functor applied to arguments */ -template * = nullptr> -inline double conditionally_grad_sw(const F& functor, double y_diff, double a, - double v, double w, double sv, double sw, - double log_error) { +template * = nullptr> +inline Scalar conditionally_grad_sw(const F& functor, Scalar y_diff, Scalar a, + Scalar v, Scalar w, Scalar sv, Scalar sw, + Scalar log_error) { return functor(y_diff, a, v, w, sv, log_error); -} +} /** * Helper function for agnostically calling wiener5 functions @@ -88,12 +88,12 @@ inline double conditionally_grad_sw(const F& functor, double y_diff, double a, * @param log_error The log error tolerance * @return Functor applied to arguments */ -template * = nullptr> -inline double conditionally_grad_sw(const F& functor, double y_diff, double a, - double v, double w, double sv, double sw, - double log_error) { +template * = nullptr> +inline Scalar conditionally_grad_sw(const F& functor, Scalar y_diff, Scalar a, + Scalar v, Scalar w, Scalar sv, Scalar sw, + Scalar log_error) { return functor(y_diff, a, v, w, sv, sw, log_error); -} +} /** * Implementation function for preparing arguments and functor to be passed @@ -109,29 +109,30 @@ inline double conditionally_grad_sw(const F& functor, double y_diff, double a, * @param args Additional arguments to be passed to the hcubature function * @return Wiener7 density or gradient calculated by integration */ -template > ReturnT wiener7_integrate(const Wiener7FunctorT& wiener7_functor, - T_hcub hcubature_err, TArgs&&... args) { + Scalar hcubature_err, TArgs&&... args) { const auto wiener7_integrand_impl - = [&](auto&& x, auto y, auto a, auto v, auto w, auto t0, - auto sv, auto sw, auto st0, auto log_error) { + = [&](auto&& x, Scalar y, Scalar a, Scalar v, Scalar w, Scalar t0, + Scalar sv, Scalar sw, Scalar st0, Scalar log_error) { scalar_seq_view x_vec(x); - const auto sw_val = GradSW ? 0 : sw; - const auto new_w = sw_val ? w + sw_val * (x_vec[0] - 0.5) : w; - const auto new_t0 = sw_val ? (st0 ? t0 + st0 * x_vec[1] : t0) - : (st0 ? t0 + st0 * x_vec[0] : t0); + const Scalar sw_val = GradSW ? 0 : sw; + const Scalar new_w = (sw_val!= 0) ? w + sw_val * (x_vec[0] - 0.5) : w; + const Scalar new_t0 = (sw_val!= 0) ? ((st0 != 0) ? t0 + st0 * x_vec[1] : t0) + : ((st0 != 0) ? t0 + st0 * x_vec[0] : t0); if (y - new_t0 <= 0) { return 0.0; } else { - return conditionally_grad_sw(wiener7_functor, y - new_t0, a, - v, new_w, sv, sw, log_error); + return conditionally_grad_sw(wiener7_functor, y - new_t0, a, + v, new_w, sv, sw, + log_error); } }; const auto functor = [&](auto&&... int_args) { return hcubature(wiener7_integrand_impl, int_args...); }; - return estimate_with_err_check<0, GradW7, 8, true, T_partials>(functor, hcubature_err, args...); + return estimate_with_err_check(functor, hcubature_err, args...); } } // namespace internal @@ -288,7 +289,7 @@ template ::value) { return 0; @@ -304,8 +305,6 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, using T_st0_ref = ref_type_if_t::value, T_st0>; using T_partials_return = partials_return_t; - - using T_partials = partials_type_t>; static constexpr const char* function_name = "wiener_full_lpdf"; check_consistent_sizes(function_name, "Random variable", y, @@ -408,25 +407,25 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } } - const T_partials log_error_density = log(1e-6); // precision for density - const T_partials error_bound = precision_derivatives; // precision for + const T_partials_return log_error_density = log(1e-6); // precision for density + const T_partials_return error_bound = precision_derivatives; // precision for // derivatives (controllable by user) - const T_partials log_error_derivative = log(error_bound); - const T_partials absolute_error_hcubature = 0.0; - const T_partials relative_error_hcubature + const T_partials_return log_error_derivative = log(error_bound); + const T_partials_return absolute_error_hcubature = 0.0; + const T_partials_return relative_error_hcubature = .9 * error_bound; // eps_rel(Integration) - const T_partials log_error_absolute = log(1e-12); + const T_partials_return log_error_absolute = log(1e-12); const int maximal_evaluations_hcubature = 6000; - T_partials log_density = 0.0; + T_partials_return log_density = 0.0; auto ops_partials = make_partials_propagator(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref, sw_ref, st0_ref); - ReturnT result = 0; + T_partials_return result = 0; // calculate density and partials for (size_t i = 0; i < N; i++) { if (sw_vec[i] == 0 && st0_vec[i] == 0) { result - += wiener5_lpdf(y_vec[i], a_vec[i], t0_vec[i], w_vec[i], + = result + wiener5_lpdf(y_vec[i], a_vec[i], t0_vec[i], w_vec[i], v_vec[i], sv_vec[i], precision_derivatives); continue; } @@ -449,12 +448,12 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, if (st0_val != 0) { xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); } - + T_partials_return hcubature_err = log_error_absolute - log_error_density + LOG_TWO + 1; const auto params = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, st0_val, log_error_absolute - LOG_TWO); - T_partials density = internal::wiener7_integrate( + T_partials_return density = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_density(args...); }, @@ -467,15 +466,15 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, // computation of derivative for t and precision check in order to give // the value as deriv_t to edge1 and as -deriv_t to edge5 - const T_partials deriv_t_7 - = internal::wiener7_integrate( + const T_partials_return deriv_t_7 + = 0;/*internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_t(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2) - / density; + / density;*/ // computation of derivatives and precision checks T_partials_return derivative; @@ -484,76 +483,77 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } if (!is_constant_all::value) { partials<1>(ops_partials)[i] - = internal::wiener7_integrate( + = 0;/*internal::wiener7_integrate( [&](auto&&... args) { - return internal::wiener5_grad_a(args...); + return internal::wiener5_grad_a(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2) - / density; + / density;*/ } if (!is_constant_all::value) { partials<2>(ops_partials)[i] = -deriv_t_7; } if (!is_constant_all::value) { partials<3>(ops_partials)[i] - = internal::wiener7_integrate( + = 0;/*internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_w(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2) - / density; + / density;*/ } if (!is_constant_all::value) { partials<4>(ops_partials)[i] - = internal::wiener7_integrate( + = 0;/*internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_v(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2) - / density; + / density;*/ } if (!is_constant_all::value) { partials<5>(ops_partials)[i] - = internal::wiener7_integrate( + = 0;/*internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_sv(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2) - / density; + / density;*/ } if (!is_constant_all::value) { if (sw_val == 0) { partials<6>(ops_partials)[i] = 0; } else { if (st0_val == 0) { - derivative = internal::estimate_with_err_check<6, false, 0, true, T_partials_return>( + derivative = 0;/*internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener7_grad_sw(args...); }, hcubature_err, y_val - t0_val, a_val, v_val, w_val, sv_val, - sw_val, log_error_absolute - LOG_TWO); + sw_val, log_error_absolute - LOG_TWO);*/ } else { - derivative = internal::wiener7_integrate( + derivative = 0;/*internal::wiener7_integrate( [&](auto&&... args) { - return internal::wiener7_grad_sw(args...); + return internal::wiener7_grad_sw(args...); }, hcubature_err, params, 1, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, - relative_error_hcubature / 2); + relative_error_hcubature / 2);*/ } partials<6>(ops_partials)[i] = derivative / density - 1 / sw_val; } } if (!is_constant_all::value) { - T_partials f; + T_partials_return f; if (st0_val == 0) { partials<7>(ops_partials)[i] = 0; } else if (y_val - (t0_val + st0_val) <= 0) { @@ -561,23 +561,23 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } else { const T_partials_return t0_st0 = t0_val + st0_val; if (sw_val == 0) { - f = internal::estimate_with_err_check<5, false, 0, true, T_partials>( + f = 0;/*internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener5_density(args...); }, log_error_derivative + log(st0_val), y_val - t0_st0, a_val, v_val, - w_val, sv_val, log_error_absolute - LOG_TWO); + w_val, sv_val, log_error_absolute - LOG_TWO);*/ } else { - const T_partials new_error = log_error_absolute - LOG_TWO; + const T_partials_return new_error = log_error_absolute - LOG_TWO; const auto& params_st = std::make_tuple( y_val, a_val, v_val, w_val, t0_st0, sv_val, sw_val, 0, new_error); - f = internal::wiener7_integrate( + f = 0;/*internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_density(args...); }, hcubature_err, params_st, 1, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, - relative_error_hcubature / 2); + relative_error_hcubature / 2);*/ } partials<7>(ops_partials)[i] = -1 / st0_val + f / st0_val / density; } diff --git a/test/unit/math/mix/prob/wiener5_lpdf_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_test.cpp index 746535a4175..3fd10677993 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_test.cpp @@ -24,7 +24,7 @@ TEST(mathMixVar, wiener5_lpdf) { stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); } - +/* TEST(mathMixFVar, wiener5_lpdf) { using stan::math::fvar; using stan::math::var; @@ -34,7 +34,8 @@ TEST(mathMixFVar, wiener5_lpdf) { fvar w = 0.5; fvar v = 1.5; fvar sv = 0.2; - stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + double error = 1e-4; + stan::math::wiener5_lpdf(y, a, t0, w, v, sv, error); } @@ -53,7 +54,7 @@ TEST(mathMixDouble1Fun, wiener5_lpdf) { }; }; stan::test::expect_ad(f1(y, a, t0, w, v), sv); -} +}*/ //correct value for grad_sv from R: -0.147527191875488 /* diff --git a/test/unit/math/mix/prob/wiener_full_test.cpp b/test/unit/math/mix/prob/wiener_full_test.cpp index bb23803a8fd..487e1868b39 100644 --- a/test/unit/math/mix/prob/wiener_full_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_test.cpp @@ -1,18 +1,31 @@ #include #include -TEST(mathMixDouble, wiener5_lpdf) { +TEST(mathMixDouble, wiener_full_lpdf) { double y = 1.0; double a = 2.0; double t0 = 0.2; double w = 0.5; double v = 1.5; double sv = 0.2; - double sw = 0.2; + double sw = 0; // if = 0 no errors, if = 0.2 'Invalid sizes when resizing a matrix or array.' in hcubature 'points[0] = combos(1, l2, dim);' double st0 = 0.2; stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); } +TEST(mathMixVar, wiener_full_lpdf) { + using stan::math::var; + var y = 1.0; + var a = 2.0; + var t0 = 0.2; + var w = 0.5; + var v = 1.5; + var sv = 0.2; + var sw = 0; // if = 0 no errors, if = 0.2 'Invalid sizes when resizing a matrix or array.' in hcubature 'points[0] = combos(1, l2, dim);' + var st0 = 0.2; + stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0, 1e-4); +} + /* TEST(mathMixScalFun, wiener_full_lpdf) { auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { From 0c17681ebcc7908bfbcff76d57f25645c340ea11 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 10 Oct 2023 19:59:53 +0200 Subject: [PATCH 103/179] hcubature resize error in combo solved --- stan/math/prim/functor/hcubature.hpp | 14 ++++---------- test/unit/math/mix/prob/wiener5_lpdf_test.cpp | 13 +++++++------ test/unit/math/mix/prob/wiener_full_test.cpp | 9 +++++---- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 28813b86105..d4efcfdded5 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -239,10 +239,10 @@ std::pair gauss_kronrod(const F& integrand, const Scalar a, * @param dim dimension */ template -inline std::tuple, -1, 1>, Eigen::Matrix, +inline std::tuple>, Eigen::Matrix, Eigen::Matrix> make_GenzMalik(const int dim) { - Eigen::Matrix, -1, 1> points(4); // is this line correct? It has been: std::vector points(4); + std::vector> points(4); // is this line correct? It has been: std::vector points(4); Eigen::Matrix weights(5); Eigen::Matrix weights_low_deg(4); Scalar l4 = std::sqrt(9 * 1.0 / 10); @@ -260,14 +260,10 @@ make_GenzMalik(const int dim) { weights_low_deg[2] = twopn * ((265 - 100 * dim) * 1.0 / 1458); weights_low_deg[1] = twopn * (245.0 / 486); weights_low_deg[0] = twopn * ((729 - 950 * dim + 50 * dim * dim) * 1.0 / 729); -std::cout << "In make_GenzMalik Stelle vor combos" << std::endl; points[0] = combos(1, l2, dim); -std::cout << "In make_GenzMalik Stelle vor combos2" << std::endl; points[1] = combos(1, l3, dim); -std::cout << "In make_GenzMalik nach combos" << std::endl; points[2] = signcombos(2, l4, dim); points[3] = signcombos(dim, l5, dim); -std::cout << "In make_GenzMalik Stelle 4" << std::endl; return std::make_tuple(std::move(points), std::move(weights), std::move(weights_low_deg)); } @@ -291,7 +287,7 @@ std::cout << "In make_GenzMalik Stelle 4" << std::endl; */ template std::tuple integrate_GenzMalik( - const F& integrand, const Eigen::Matrix, -1, 1>& points, + const F& integrand, const std::vector>& points, const Eigen::Matrix& weights, const Eigen::Matrix& weights_low_deg, const int dim, const Eigen::Matrix& a, const Eigen::Matrix& b, const ParsTupleT& pars_tuple) { @@ -495,7 +491,7 @@ Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, Scalar err; auto kdivide = 0; - Eigen::Matrix p(4); + std::vector> p(4); eig_vec w_five(5); eig_vec wd_four(4); @@ -503,9 +499,7 @@ Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, std::tie(result, err) = internal::gauss_kronrod(integrand, a[0], b[0], pars); } else { -std::cout << "vor make_GenzMalik" << std::endl; std::tie(p, w_five, wd_four) = internal::make_GenzMalik(dim); -std::cout << "nach make_GenzMalik" << std::endl; std::tie(result, err, kdivide) = internal::integrate_GenzMalik( integrand, p, w_five, wd_four, dim, a, b, pars); } diff --git a/test/unit/math/mix/prob/wiener5_lpdf_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_test.cpp index 3fd10677993..5694def28ef 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_test.cpp @@ -2,7 +2,7 @@ #include -TEST(mathMixDouble, wiener5_lpdf) { +TEST(mathMixDouble, wiener5_lpdf) { // runs successfully with and without hcubature double y = 1.0; double a = 2.0; double t0 = 0.2; @@ -13,7 +13,7 @@ TEST(mathMixDouble, wiener5_lpdf) { } -TEST(mathMixVar, wiener5_lpdf) { +TEST(mathMixVar, wiener5_lpdf) { // runs successfully with and without hcubature using stan::math::var; var y = 1.0; var a = 2.0; @@ -25,7 +25,8 @@ TEST(mathMixVar, wiener5_lpdf) { } /* -TEST(mathMixFVar, wiener5_lpdf) { +TEST(mathMixFVar, wiener5_lpdf) { // error with and without hcubature +//error: inconsistent types ‘double’ and ‘stan::math::var_value’ deduced for lambda return 589 | log_error); using stan::math::fvar; using stan::math::var; fvar y = 1.0; @@ -36,11 +37,11 @@ TEST(mathMixFVar, wiener5_lpdf) { fvar sv = 0.2; double error = 1e-4; stan::math::wiener5_lpdf(y, a, t0, w, v, sv, error); -} - +}*/ -TEST(mathMixDouble1Fun, wiener5_lpdf) { +/* +TEST(mathMixDouble1Fun, wiener5_lpdf) { // with hcubature same error as above in mathMixFVar using stan::math::var; double y = 1.0; double a = 2.0; diff --git a/test/unit/math/mix/prob/wiener_full_test.cpp b/test/unit/math/mix/prob/wiener_full_test.cpp index 487e1868b39..6c9633191ba 100644 --- a/test/unit/math/mix/prob/wiener_full_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_test.cpp @@ -1,19 +1,20 @@ #include #include -TEST(mathMixDouble, wiener_full_lpdf) { +TEST(mathMixDouble, wiener_full_lpdf) { // runs successfully! double y = 1.0; double a = 2.0; double t0 = 0.2; double w = 0.5; double v = 1.5; double sv = 0.2; - double sw = 0; // if = 0 no errors, if = 0.2 'Invalid sizes when resizing a matrix or array.' in hcubature 'points[0] = combos(1, l2, dim);' + double sw = 0.2; double st0 = 0.2; stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); } -TEST(mathMixVar, wiener_full_lpdf) { + +TEST(mathMixVar, wiener_full_lpdf) { // error: cannot convert ‘stan::math::var’ {aka ‘stan::math::var_value’} to ‘T_partials_return’ {aka ‘double’} in assignment 428 | = result + wiener5_lpdf(y_vec[i], a_vec[i], t0_vec[i], w_vec[i], using stan::math::var; var y = 1.0; var a = 2.0; @@ -21,7 +22,7 @@ TEST(mathMixVar, wiener_full_lpdf) { var w = 0.5; var v = 1.5; var sv = 0.2; - var sw = 0; // if = 0 no errors, if = 0.2 'Invalid sizes when resizing a matrix or array.' in hcubature 'points[0] = combos(1, l2, dim);' + var sw = 0; var st0 = 0.2; stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0, 1e-4); } From ec18781163b6d1551a76e2d004df25cea3f8bebb Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 13 Oct 2023 17:58:48 +0200 Subject: [PATCH 104/179] yey, one error gone --- stan/math/prim/prob/wiener5_lpdf.hpp | 2 +- stan/math/prim/prob/wiener_full_lpdf.hpp | 2 +- test/unit/math/mix/prob/wiener5_lpdf_test.cpp | 4 ++-- test/unit/math/mix/prob/wiener_full_test.cpp | 7 ++++--- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index b71eb993086..e2bd759cb40 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -582,7 +582,7 @@ ReturnT wiener7_integrate_2(const Wiener7FunctorT& wiener7_functor, const Scalar new_t0 = (sw_val!= 0) ? ((st0 != 0) ? t0 + st0 * x_vec[1] : t0) : ((st0 != 0) ? t0 + st0 * x_vec[0] : t0); if (y - new_t0 <= 0) { - return 0.0; + return static_cast(0.0); } else { return conditionally_grad_sw_2(wiener7_functor, y - new_t0, a, v, new_w, sv, sw, diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 7a0199c8481..33cc879f3b1 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -122,7 +122,7 @@ ReturnT wiener7_integrate(const Wiener7FunctorT& wiener7_functor, const Scalar new_t0 = (sw_val!= 0) ? ((st0 != 0) ? t0 + st0 * x_vec[1] : t0) : ((st0 != 0) ? t0 + st0 * x_vec[0] : t0); if (y - new_t0 <= 0) { - return 0.0; + return static_cast(0.0); } else { return conditionally_grad_sw(wiener7_functor, y - new_t0, a, v, new_w, sv, sw, diff --git a/test/unit/math/mix/prob/wiener5_lpdf_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_test.cpp index 5694def28ef..a0d930b3749 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_test.cpp @@ -24,7 +24,7 @@ TEST(mathMixVar, wiener5_lpdf) { // runs successfully with and without hcubature stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); } -/* + TEST(mathMixFVar, wiener5_lpdf) { // error with and without hcubature //error: inconsistent types ‘double’ and ‘stan::math::var_value’ deduced for lambda return 589 | log_error); using stan::math::fvar; @@ -37,7 +37,7 @@ TEST(mathMixFVar, wiener5_lpdf) { // error with and without hcubature fvar sv = 0.2; double error = 1e-4; stan::math::wiener5_lpdf(y, a, t0, w, v, sv, error); -}*/ +} /* diff --git a/test/unit/math/mix/prob/wiener_full_test.cpp b/test/unit/math/mix/prob/wiener_full_test.cpp index 6c9633191ba..83e294eaefc 100644 --- a/test/unit/math/mix/prob/wiener_full_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_test.cpp @@ -10,11 +10,12 @@ TEST(mathMixDouble, wiener_full_lpdf) { // runs successfully! double sv = 0.2; double sw = 0.2; double st0 = 0.2; - stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0, 1e-4); } -TEST(mathMixVar, wiener_full_lpdf) { // error: cannot convert ‘stan::math::var’ {aka ‘stan::math::var_value’} to ‘T_partials_return’ {aka ‘double’} in assignment 428 | = result + wiener5_lpdf(y_vec[i], a_vec[i], t0_vec[i], w_vec[i], +TEST(mathMixVar, wiener_full_lpdf) { // if hcubature is included in wiener5: error: cannot convert ‘stan::math::var’ {aka ‘stan::math::var_value’} to ‘T_partials_return’ {aka ‘double’} in assignment 428 | = result + wiener5_lpdf(y_vec[i], a_vec[i], t0_vec[i], w_vec[i], + //without hcubature in wiener5: error: cannot convert ‘const stan::math::var_value’ to ‘const T_partials_return’ {aka ‘const double’} in initialization 411 | const T_partials_return error_bound = precision_derivatives; using stan::math::var; var y = 1.0; var a = 2.0; @@ -24,7 +25,7 @@ TEST(mathMixVar, wiener_full_lpdf) { // error: cannot convert ‘stan::math::var var sv = 0.2; var sw = 0; var st0 = 0.2; - stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0, 1e-4); + stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); } /* From 140b9fe32ff6fd9c16b405668476a505e728f2ae Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 13 Oct 2023 18:38:13 +0200 Subject: [PATCH 105/179] no commentation --- stan/math/prim/prob/wiener5_lpdf.hpp | 12 +++--- stan/math/prim/prob/wiener_full_lpdf.hpp | 40 +++++++++---------- test/unit/math/mix/prob/wiener5_lpdf_test.cpp | 9 ++--- test/unit/math/mix/prob/wiener_full_test.cpp | 20 +++++++++- 4 files changed, 48 insertions(+), 33 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index e2bd759cb40..b7730edc6dd 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -553,7 +553,7 @@ Scalar estimate_with_err_check(const F& functor, Scalar err, - +/* template * = nullptr> inline Scalar conditionally_grad_sw_2(const F& functor, Scalar y_diff, Scalar a, Scalar v, Scalar w, Scalar sv, Scalar sw, @@ -593,7 +593,7 @@ ReturnT wiener7_integrate_2(const Wiener7FunctorT& wiener7_functor, return hcubature(wiener7_integrand_impl, int_args...); }; return estimate_with_err_check(functor, hcubature_err, args...); -} +}*/ @@ -758,9 +758,9 @@ inline return_type_t wiener5_lpdf( y_val - t0_val, a_val, v_val, w_val, sv_val); } if (!is_constant_all::value) { - // ops_partials.edge6_.partials_[i] = internal::wiener5_grad_sv( - // y_val - t0_val, a_val, v_val, w_val, sv_val); - const auto params + ops_partials.edge6_.partials_[i] = internal::wiener5_grad_sv( + y_val - t0_val, a_val, v_val, w_val, sv_val); + /* const auto params = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, 0, 0, log_error_absolute - LOG_TWO); Eigen::Matrix xmin = Eigen::VectorXd::Zero(1); @@ -775,7 +775,7 @@ inline return_type_t wiener5_lpdf( return internal::wiener5_grad_a(args...); }, - hcubature_err, params, dim, xmin, xmax, max_eval, abs, rel); + hcubature_err, params, dim, xmin, xmax, max_eval, abs, rel);*/ } } // end for loop return ops_partials.build(log_density); diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 33cc879f3b1..cecfc506a2b 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -289,7 +289,7 @@ template ::value) { return 0; @@ -419,7 +419,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, T_partials_return log_density = 0.0; auto ops_partials = make_partials_propagator(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref, sw_ref, st0_ref); - T_partials_return result = 0; + ReturnT result = 0; // calculate density and partials for (size_t i = 0; i < N; i++) { @@ -467,14 +467,14 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, // computation of derivative for t and precision check in order to give // the value as deriv_t to edge1 and as -deriv_t to edge5 const T_partials_return deriv_t_7 - = 0;/*internal::wiener7_integrate( + = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_t(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2) - / density;*/ + / density; // computation of derivatives and precision checks T_partials_return derivative; @@ -483,7 +483,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } if (!is_constant_all::value) { partials<1>(ops_partials)[i] - = 0;/*internal::wiener7_integrate( + = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_a(args...); @@ -491,63 +491,63 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2) - / density;*/ + / density; } if (!is_constant_all::value) { partials<2>(ops_partials)[i] = -deriv_t_7; } if (!is_constant_all::value) { partials<3>(ops_partials)[i] - = 0;/*internal::wiener7_integrate( + = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_w(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2) - / density;*/ + / density; } if (!is_constant_all::value) { partials<4>(ops_partials)[i] - = 0;/*internal::wiener7_integrate( + = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_v(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2) - / density;*/ + / density; } if (!is_constant_all::value) { partials<5>(ops_partials)[i] - = 0;/*internal::wiener7_integrate( + = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_sv(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2) - / density;*/ + / density; } if (!is_constant_all::value) { if (sw_val == 0) { partials<6>(ops_partials)[i] = 0; } else { if (st0_val == 0) { - derivative = 0;/*internal::estimate_with_err_check( + derivative = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener7_grad_sw(args...); }, hcubature_err, y_val - t0_val, a_val, v_val, w_val, sv_val, - sw_val, log_error_absolute - LOG_TWO);*/ + sw_val, log_error_absolute - LOG_TWO); } else { - derivative = 0;/*internal::wiener7_integrate( + derivative = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener7_grad_sw(args...); }, hcubature_err, params, 1, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, - relative_error_hcubature / 2);*/ + relative_error_hcubature / 2); } partials<6>(ops_partials)[i] = derivative / density - 1 / sw_val; } @@ -561,23 +561,23 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } else { const T_partials_return t0_st0 = t0_val + st0_val; if (sw_val == 0) { - f = 0;/*internal::estimate_with_err_check( + f = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener5_density(args...); }, log_error_derivative + log(st0_val), y_val - t0_st0, a_val, v_val, - w_val, sv_val, log_error_absolute - LOG_TWO);*/ + w_val, sv_val, log_error_absolute - LOG_TWO); } else { const T_partials_return new_error = log_error_absolute - LOG_TWO; const auto& params_st = std::make_tuple( y_val, a_val, v_val, w_val, t0_st0, sv_val, sw_val, 0, new_error); - f = 0;/*internal::wiener7_integrate( + f = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_density(args...); }, hcubature_err, params_st, 1, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, - relative_error_hcubature / 2);*/ + relative_error_hcubature / 2); } partials<7>(ops_partials)[i] = -1 / st0_val + f / st0_val / density; } diff --git a/test/unit/math/mix/prob/wiener5_lpdf_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_test.cpp index a0d930b3749..c9c540e0c60 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_test.cpp @@ -25,8 +25,7 @@ TEST(mathMixVar, wiener5_lpdf) { // runs successfully with and without hcubature } -TEST(mathMixFVar, wiener5_lpdf) { // error with and without hcubature -//error: inconsistent types ‘double’ and ‘stan::math::var_value’ deduced for lambda return 589 | log_error); +TEST(mathMixFVar, wiener5_lpdf) { // runs successfully using stan::math::fvar; using stan::math::var; fvar y = 1.0; @@ -40,8 +39,8 @@ TEST(mathMixFVar, wiener5_lpdf) { // error with and without hcubature } -/* -TEST(mathMixDouble1Fun, wiener5_lpdf) { // with hcubature same error as above in mathMixFVar + +TEST(mathMixDouble1Fun, wiener5_lpdf) { // error: x1 evaluates to 0 using stan::math::var; double y = 1.0; double a = 2.0; @@ -55,7 +54,7 @@ TEST(mathMixDouble1Fun, wiener5_lpdf) { // with hcubature same error as above in }; }; stan::test::expect_ad(f1(y, a, t0, w, v), sv); -}*/ +} //correct value for grad_sv from R: -0.147527191875488 /* diff --git a/test/unit/math/mix/prob/wiener_full_test.cpp b/test/unit/math/mix/prob/wiener_full_test.cpp index 83e294eaefc..98b3ba1424a 100644 --- a/test/unit/math/mix/prob/wiener_full_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_test.cpp @@ -14,8 +14,7 @@ TEST(mathMixDouble, wiener_full_lpdf) { // runs successfully! } -TEST(mathMixVar, wiener_full_lpdf) { // if hcubature is included in wiener5: error: cannot convert ‘stan::math::var’ {aka ‘stan::math::var_value’} to ‘T_partials_return’ {aka ‘double’} in assignment 428 | = result + wiener5_lpdf(y_vec[i], a_vec[i], t0_vec[i], w_vec[i], - //without hcubature in wiener5: error: cannot convert ‘const stan::math::var_value’ to ‘const T_partials_return’ {aka ‘const double’} in initialization 411 | const T_partials_return error_bound = precision_derivatives; +TEST(mathMixVar, wiener_full_lpdf) { // runs successfully! using stan::math::var; var y = 1.0; var a = 2.0; @@ -28,6 +27,23 @@ TEST(mathMixVar, wiener_full_lpdf) { // if hcubature is included in wiener5: err stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); } +TEST(mathMixFVar, wiener_full_lpdf) { // runs successfully! + using stan::math::var; + using stan::math::fvar; + fvar y = 1.0; + fvar a = 2.0; + fvar t0 = 0.2; + fvar w = 0.5; + fvar v = 1.5; + fvar sv = 0.2; + fvar sw = 0; + fvar st0 = 0.2; + stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); +} + + + + /* TEST(mathMixScalFun, wiener_full_lpdf) { auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { From e48c6a216e114087e3c3de0b27940b63922cb2be Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 13 Oct 2023 19:31:24 +0200 Subject: [PATCH 106/179] wiener_full mix tests run successfully!!!! --- stan/math/prim/functor/hcubature.hpp | 21 +----- stan/math/prim/prob/wiener5_lpdf.hpp | 65 ------------------- test/unit/math/mix/prob/wiener5_lpdf_test.cpp | 4 +- test/unit/math/mix/prob/wiener_full_test.cpp | 35 ++++------ 4 files changed, 17 insertions(+), 108 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index d4efcfdded5..83be657ced6 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -242,7 +242,7 @@ template inline std::tuple>, Eigen::Matrix, Eigen::Matrix> make_GenzMalik(const int dim) { - std::vector> points(4); // is this line correct? It has been: std::vector points(4); + std::vector> points(4); Eigen::Matrix weights(5); Eigen::Matrix weights_low_deg(4); Scalar l4 = std::sqrt(9 * 1.0 / 10); @@ -515,23 +515,19 @@ Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, } numevals += 2 * evals_per_box; std::vector> ms; -// Eigen::Matrix, -1, 1> ms; ms.reserve(numevals); -// ms.conservativeResize(numevals); ms.emplace_back(std::move(a), std::move(b), result, kdivide); auto get_largest_box_idx = [](auto&& box_vec) { auto max_it = std::max_element(box_vec.begin(), box_vec.end()); return std::distance(box_vec.begin(), max_it); }; std::vector err_vec; -// eig_vec err_vec; err_vec.reserve(numevals); err_vec.push_back(err); while ((numevals < maxEval) && (error > fmax(reqRelError * fabs(val), reqAbsError)) - && fabs(val) < INFTY){ //isfinite(val)) { + && fabs(val) < INFTY){ auto err_idx = get_largest_box_idx(err_vec); -//---------------- auto&& box = ms[err_idx]; Scalar w = (box.b_[box.kdiv_] - box.a_[box.kdiv_]) / 2; @@ -545,24 +541,11 @@ Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, int kdivide_1{0}; int kdivide_2{0}; -//-------------------------- - /* - internal::Box box = ms.top(); - ms.pop(); - - Scalar w = (box.b_[box.kdiv_] - box.a_[box.kdiv_]) / 2; -// std::vector ma(box.a); - eig_vec ma(box.a_); - ma[box.kdiv_] += w; -// std::vector mb(box.b); - eig_vec mb(box.b_); - mb[box.kdiv_] -= w; */ Scalar result_1; Scalar result_2; Scalar err_1; Scalar err_2; -//----------------------- if (dim == 1) { std::tie(result_1, err_1) = internal::gauss_kronrod(integrand, ma[0], box.b_[0], pars); diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index b7730edc6dd..22a1f946691 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -549,55 +549,6 @@ Scalar estimate_with_err_check(const F& functor, Scalar err, } return result; } - - - - -/* -template * = nullptr> -inline Scalar conditionally_grad_sw_2(const F& functor, Scalar y_diff, Scalar a, - Scalar v, Scalar w, Scalar sv, Scalar sw, - Scalar log_error) { - return functor(y_diff, a, v, w, sv, log_error); -} - -template * = nullptr> -inline Scalar conditionally_grad_sw_2(const F& functor, Scalar y_diff, Scalar a, - Scalar v, Scalar w, Scalar sv, Scalar sw, - Scalar log_error) { - return functor(y_diff, a, v, w, sv, sw, log_error); -} - - -template > -ReturnT wiener7_integrate_2(const Wiener7FunctorT& wiener7_functor, - Scalar hcubature_err, TArgs&&... args) { - const auto wiener7_integrand_impl - = [&](auto&& x, Scalar y, Scalar a, Scalar v, Scalar w, Scalar t0, - Scalar sv, Scalar sw, Scalar st0, Scalar log_error) { - scalar_seq_view x_vec(x); - const Scalar sw_val = GradSW ? 0 : sw; - const Scalar new_w = (sw_val!= 0) ? w + sw_val * (x_vec[0] - 0.5) : w; - const Scalar new_t0 = (sw_val!= 0) ? ((st0 != 0) ? t0 + st0 * x_vec[1] : t0) - : ((st0 != 0) ? t0 + st0 * x_vec[0] : t0); - if (y - new_t0 <= 0) { - return static_cast(0.0); - } else { - return conditionally_grad_sw_2(wiener7_functor, y - new_t0, a, - v, new_w, sv, sw, - log_error); - } - }; - const auto functor = [&](auto&&... int_args) { - return hcubature(wiener7_integrand_impl, int_args...); - }; - return estimate_with_err_check(functor, hcubature_err, args...); -}*/ - - - - } // namespace internal /** @@ -760,22 +711,6 @@ inline return_type_t wiener5_lpdf( if (!is_constant_all::value) { ops_partials.edge6_.partials_[i] = internal::wiener5_grad_sv( y_val - t0_val, a_val, v_val, w_val, sv_val); - /* const auto params - = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, 0, - 0, log_error_absolute - LOG_TWO); - Eigen::Matrix xmin = Eigen::VectorXd::Zero(1); - Eigen::Matrix xmax = Eigen::VectorXd::Ones(1); - int max_eval = 1000; - int dim = 1; - T_partials_return hcubature_err = 1e-4; - T_partials_return abs = 0.0; - T_partials_return rel = 1e-5; - ops_partials.edge6_.partials_[i] = internal::wiener7_integrate_2( - [&](auto&&... args) { - return internal::wiener5_grad_a(args...); - }, - hcubature_err, params, dim, xmin, xmax, max_eval, abs, rel);*/ } } // end for loop return ops_partials.build(log_density); diff --git a/test/unit/math/mix/prob/wiener5_lpdf_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_test.cpp index c9c540e0c60..58e48766ebd 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_test.cpp @@ -2,7 +2,7 @@ #include -TEST(mathMixDouble, wiener5_lpdf) { // runs successfully with and without hcubature +TEST(mathMixDouble, wiener5_lpdf) { // runs successfully double y = 1.0; double a = 2.0; double t0 = 0.2; @@ -13,7 +13,7 @@ TEST(mathMixDouble, wiener5_lpdf) { // runs successfully with and without hcubat } -TEST(mathMixVar, wiener5_lpdf) { // runs successfully with and without hcubature +TEST(mathMixVar, wiener5_lpdf) { // runs successfully using stan::math::var; var y = 1.0; var a = 2.0; diff --git a/test/unit/math/mix/prob/wiener_full_test.cpp b/test/unit/math/mix/prob/wiener_full_test.cpp index 98b3ba1424a..0cefe0f2cdb 100644 --- a/test/unit/math/mix/prob/wiener_full_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_test.cpp @@ -1,7 +1,7 @@ #include #include -TEST(mathMixDouble, wiener_full_lpdf) { // runs successfully! +TEST(mathMixDouble, wiener_full_lpdf) { double y = 1.0; double a = 2.0; double t0 = 0.2; @@ -14,7 +14,7 @@ TEST(mathMixDouble, wiener_full_lpdf) { // runs successfully! } -TEST(mathMixVar, wiener_full_lpdf) { // runs successfully! +TEST(mathMixVar, wiener_full_lpdf) { using stan::math::var; var y = 1.0; var a = 2.0; @@ -27,7 +27,8 @@ TEST(mathMixVar, wiener_full_lpdf) { // runs successfully! stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); } -TEST(mathMixFVar, wiener_full_lpdf) { // runs successfully! + +TEST(mathMixFVar, wiener_full_lpdf) { using stan::math::var; using stan::math::fvar; fvar y = 1.0; @@ -42,28 +43,20 @@ TEST(mathMixFVar, wiener_full_lpdf) { // runs successfully! } - - -/* -TEST(mathMixScalFun, wiener_full_lpdf) { - auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { - return [&y, &a, &t0, &w, &v](const auto& sv, const auto& sw, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; +TEST(mathMixScalFun, wiener_full_lpdf) { // ... runs within a few minutes when 1 parameter is tested ... TODO: have to add tests for the other 5 parameters -/* auto f2 = [](const auto& y, const auto& a, const auto& sv, const auto& sw, const auto& st0) { - return [&y, &a, &sv, &sw, &st0](const auto& t0, const auto& w, const auto& v) { + auto f_sw = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v, const auto& sv, const auto& st0) { + return [&y, &a, &t0, &w, &v, &sv, &st0](const auto& sw) { return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - auto f3 = [](const auto& w, const auto& v, const auto& sv, const auto& sw, const auto& st0) { - return [&w, &v, &sv, &sw, &st0](const auto& y, const auto& a, const auto& t0) { + auto f_st0 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v, const auto& sv, const auto& sw) { + return [&y, &a, &t0, &w, &v, &sv, &sw](const auto& st0) { return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - + double y = 0.1; double a = 2.0; double t0 = 0.2; @@ -73,13 +66,11 @@ TEST(mathMixScalFun, wiener_full_lpdf) { double sw = 0.1; double st0 = 0.3; - stan::test::expect_ad(f1(y, a, t0, w, v), sv, sw, st0); -// stan::test::expect_ad(f2(y, a, sv, sw, st0), t0, w, v); -// stan::test::expect_ad(f3(w, v, sv, sw, st0), y, a, t0); - + stan::test::expect_ad(f_st0(y, a, t0, w, v, sv, st0), sw); + stan::test::expect_ad(f_st0(y, a, t0, w, v, sv, sw), st0); } -*/ + /* TEST(mathMixVecFun, wiener_full_lpdf) { auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { From a5a96c1f925aa1908d0886740f68c5a4c532f0f6 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Sat, 14 Oct 2023 12:44:19 +0200 Subject: [PATCH 107/179] all wiener_full_tests work! --- test/unit/math/mix/prob/wiener_full_test.cpp | 97 ++++++++++++-------- 1 file changed, 60 insertions(+), 37 deletions(-) diff --git a/test/unit/math/mix/prob/wiener_full_test.cpp b/test/unit/math/mix/prob/wiener_full_test.cpp index 0cefe0f2cdb..f4fa2f9b2e1 100644 --- a/test/unit/math/mix/prob/wiener_full_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_test.cpp @@ -43,7 +43,43 @@ TEST(mathMixFVar, wiener_full_lpdf) { } -TEST(mathMixScalFun, wiener_full_lpdf) { // ... runs within a few minutes when 1 parameter is tested ... TODO: have to add tests for the other 5 parameters +TEST(mathMixScalFun, wiener_full_lpdf) { + + auto f_y = [](const auto& a, const auto& t0, const auto& w, const auto& v, const auto& sv, const auto& sw, const auto& st0) { + return [&a, &t0, &w, &v, &sv, &sw, &st0](const auto& y) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + auto f_a = [](const auto& y, const auto& t0, const auto& w, const auto& v, const auto& sv, const auto& sw, const auto& st0) { + return [&y, &t0, &w, &v, &sv, &sw, &st0](const auto& a) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + auto f_t0 = [](const auto& y, const auto& a, const auto& w, const auto& v, const auto& sv, const auto& sw, const auto& st0) { + return [&y, &a, &w, &v, &sv, &sw, &st0](const auto& t0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + auto f_w = [](const auto& y, const auto& a, const auto& t0, const auto& v, const auto& sv, const auto& sw, const auto& st0) { + return [&y, &a, &t0, &v, &sv, &sw, &st0](const auto& w) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + auto f_v = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& sv, const auto& sw, const auto& st0) { + return [&y, &a, &t0, &w, &sv, &sw, &st0](const auto& v) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + auto f_sv = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v, const auto& sw, const auto& st0) { + return [&y, &a, &t0, &w, &v, &sw, &st0](const auto& sv) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; auto f_sw = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v, const auto& sv, const auto& st0) { return [&y, &a, &t0, &w, &v, &sv, &st0](const auto& sw) { @@ -57,29 +93,14 @@ TEST(mathMixScalFun, wiener_full_lpdf) { // ... runs within a few minutes when 1 }; }; - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - - stan::test::expect_ad(f_st0(y, a, t0, w, v, sv, st0), sw); - stan::test::expect_ad(f_st0(y, a, t0, w, v, sv, sw), st0); - -} - -/* -TEST(mathMixVecFun, wiener_full_lpdf) { + auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { return [&y, &a, &t0, &w, &v](const auto& sv, const auto& sw, const auto& st0) { return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; -/* auto f2 = [](const auto& y, const auto& a, const auto& sv, const auto& sw, const auto& st0) { + auto f2 = [](const auto& y, const auto& a, const auto& sv, const auto& sw, const auto& st0) { return [&y, &a, &sv, &sw, &st0](const auto& t0, const auto& w, const auto& v) { return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); }; @@ -91,27 +112,29 @@ TEST(mathMixVecFun, wiener_full_lpdf) { }; }; - Eigen::VectorXd y(2); - y << 1.0, 1.5; - Eigen::VectorXd a(2); - a << 2.0, 2.5; - Eigen::VectorXd t0(2); - t0 << 0.2, 0.1; - Eigen::VectorXd w(2); - w << 0.5, 0.45; - Eigen::VectorXd v(2); - v << 2.0, 1.0; - Eigen::VectorXd sv(2); - sv << 0.2, 0.1; - Eigen::VectorXd sw(2); - sw << 0.1, 0.2; - Eigen::VectorXd st0(2); - st0 << 0.3, 0.2; + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + stan::test::expect_ad(f1(y, a, t0, w, v), sv, sw, st0); -// stan::test::expect_ad(f2(y, a, sv, sw, st0), t0, w, v); -// stan::test::expect_ad(f3(w, v, sv, sw, st0), y, a, t0); + stan::test::expect_ad(f2(y, a, sv, sw, st0), t0, w, v); + stan::test::expect_ad(f3(w, v, sv, sw, st0), y, a, t0); + + stan::test::expect_ad(f_y(a, t0, w, v, sv, sw, st0), y); + stan::test::expect_ad(f_a(y, t0, w, v, sv, sw, st0), a); + stan::test::expect_ad(f_t0(y, a, w, v, sv, sw, st0), t0); + stan::test::expect_ad(f_w(y, a, t0, v, sv, sw, st0), w); + stan::test::expect_ad(f_v(y, a, t0, w, sv, sw, st0), v); + stan::test::expect_ad(f_sv(y, a, t0, w, v, sw, st0), sv); + stan::test::expect_ad(f_sw(y, a, t0, w, v, sv, st0), sw); + stan::test::expect_ad(f_st0(y, a, t0, w, v, sv, sw), st0); } -*/ + From a59948572b15477c79550bece67769f66951688e Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 20 Oct 2023 16:02:29 +0200 Subject: [PATCH 108/179] add some T_partials_return --- stan/math/prim/prob/wiener_full_lpdf.hpp | 30 ++++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index cecfc506a2b..6dca5b8d151 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -30,9 +30,9 @@ inline ReturnT wiener7_grad_sw(const T_y& y, const T_a& a, const T_v& v, const T Scalar high = w + sw / 2.0; high = (1 < high) ? 1 : high; - const Scalar lower_value = wiener5_density(y, a, v, low, sv, log_error); + const Scalar lower_value = wiener5_density(y, a, v, low, sv, log_error); const Scalar upper_value - = wiener5_density(y, a, v, high, sv, log_error); + = wiener5_density(y, a, v, high, sv, log_error); return 0.5 * (lower_value + upper_value) / sw; } @@ -109,8 +109,8 @@ inline Scalar conditionally_grad_sw(const F& functor, Scalar y_diff, Scalar a, * @param args Additional arguments to be passed to the hcubature function * @return Wiener7 density or gradient calculated by integration */ -template > +template > ReturnT wiener7_integrate(const Wiener7FunctorT& wiener7_functor, Scalar hcubature_err, TArgs&&... args) { const auto wiener7_integrand_impl @@ -453,9 +453,9 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const auto params = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, st0_val, log_error_absolute - LOG_TWO); - T_partials_return density = internal::wiener7_integrate( + T_partials_return density = internal::wiener7_integrate( [&](auto&&... args) { - return internal::wiener5_density(args...); + return internal::wiener5_density(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2); @@ -467,7 +467,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, // computation of derivative for t and precision check in order to give // the value as deriv_t to edge1 and as -deriv_t to edge5 const T_partials_return deriv_t_7 - = internal::wiener7_integrate( + = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_t(args...); }, @@ -483,7 +483,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } if (!is_constant_all::value) { partials<1>(ops_partials)[i] - = internal::wiener7_integrate( + = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_a(args...); @@ -498,7 +498,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } if (!is_constant_all::value) { partials<3>(ops_partials)[i] - = internal::wiener7_integrate( + = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_w(args...); }, @@ -509,7 +509,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } if (!is_constant_all::value) { partials<4>(ops_partials)[i] - = internal::wiener7_integrate( + = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_v(args...); }, @@ -520,7 +520,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } if (!is_constant_all::value) { partials<5>(ops_partials)[i] - = internal::wiener7_integrate( + = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_grad_sv(args...); }, @@ -541,7 +541,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, hcubature_err, y_val - t0_val, a_val, v_val, w_val, sv_val, sw_val, log_error_absolute - LOG_TWO); } else { - derivative = internal::wiener7_integrate( + derivative = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener7_grad_sw(args...); }, @@ -563,7 +563,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, if (sw_val == 0) { f = internal::estimate_with_err_check( [&](auto&&... args) { - return internal::wiener5_density(args...); + return internal::wiener5_density(args...); }, log_error_derivative + log(st0_val), y_val - t0_st0, a_val, v_val, w_val, sv_val, log_error_absolute - LOG_TWO); @@ -571,9 +571,9 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_partials_return new_error = log_error_absolute - LOG_TWO; const auto& params_st = std::make_tuple( y_val, a_val, v_val, w_val, t0_st0, sv_val, sw_val, 0, new_error); - f = internal::wiener7_integrate( + f = internal::wiener7_integrate( [&](auto&&... args) { - return internal::wiener5_density(args...); + return internal::wiener5_density(args...); }, hcubature_err, params_st, 1, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, From 49bad1081f9eab4729dbc02783d953a2d392bc02 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 20 Oct 2023 16:06:01 +0200 Subject: [PATCH 109/179] add scalar to docu text --- stan/math/prim/prob/wiener5_lpdf.hpp | 10 ++++++++++ stan/math/prim/prob/wiener_full_lpdf.hpp | 3 +++ 2 files changed, 13 insertions(+) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 22a1f946691..c02ad5a30ff 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -40,6 +40,7 @@ inline Scalar wiener5_compute_error_term(T_y&& y, T_a&& a, T_v&& v_value, * * @tparam GradA Whether the calculation is for gradient w.r.t. 'a' * @tparam GradT Whether the calculation is for gradient w.r.t. 't' + * @tparam Scalar type of scalars * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -83,6 +84,7 @@ inline Scalar wiener5_density_part_one(T_y&& y, T_a&& a, T_v_value&& v_value, * * @tparam Density Whether the calculation is for the density * @tparam GradW Whether the calculation is for gradient w.r.t. 'w' + * @tparam Scalar type of scalars * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -121,6 +123,7 @@ inline Scalar wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, * * @tparam Density Whether the calculation is for the density * @tparam GradT Whether the calculation is for gradient w.r.t. 't' + * @tparam Scalar type of scalars * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -167,6 +170,7 @@ inline Scalar wiener5_n_terms_largel_t(T_y&& y, T_a&& a, T_w_value&& w_value, * * @tparam Density Whether the calculation is for the density * @tparam GradW Whether the calculation is for gradient w.r.t. 'w' + * @tparam Scalar type of scalars * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -291,6 +295,7 @@ inline Scalar wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, * * @tparam WrtLog Whether to return the derivative w.r.t. * the natural (true) or log-scale (false) density + * @tparam Scalar type of scalars * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -345,6 +350,7 @@ inline Scalar wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, * * @tparam WrtLog Whether to return the derivative w.r.t. * the natural (true) or log-scale (false) density + * @tparam Scalar type of scalars * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -399,6 +405,7 @@ inline Scalar wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, * * @tparam WrtLog Whether to return the derivative w.r.t. * the natural (true) or log-scale (false) density + * @tparam Scalar type of scalars * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -425,6 +432,7 @@ inline Scalar wiener5_grad_v(const T_y& y, const T_a& a, const T_v& v_value, * * @tparam WrtLog Whether to return the derivative w.r.t. * the natural (true) or log-scale (false) density + * @tparam Scalar type of scalars * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -475,6 +483,7 @@ inline Scalar wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, * * @tparam WrtLog Whether to return the derivative w.r.t. * the natural (true) or log-scale (false) density + * @tparam Scalar type of scalars * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -522,6 +531,7 @@ inline void assign_err(std::tuple& args_tuple, Scalar err) { * checking the result against a provided error tolerance, and re-estimating * the function with the increased error if it fails. * + * @tparam Scalar type of scalars * @tparam ErrIndex Position of the error argument in the provided arguments * @tparam NestedIndex Nested position if the error argument is within a tuple * @tparam F Type of functor diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 6dca5b8d151..445357b498b 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -43,6 +43,7 @@ inline ReturnT wiener7_grad_sw(const T_y& y, const T_a& a, const T_v& v, const T * * Specialisation for wiener5 functions * + * @tparam Scalar type of scalars * @tparam GradSW Whether the wiener7 gradient function is passed * @tparam F Type of Gradient/density functor * @@ -72,6 +73,7 @@ inline Scalar conditionally_grad_sw(const F& functor, Scalar y_diff, Scalar a, * * Specialisation for wiener7 functions * + * @tparam Scalar type of scalars * @tparam GradSW Whether the wiener7 gradient function is passed * @tparam F Type of Gradient/density functor * @@ -100,6 +102,7 @@ inline Scalar conditionally_grad_sw(const F& functor, Scalar y_diff, Scalar a, * to the hcubature() function for calculating wiener7 parameters via * integration * + * @tparam Scalar type of scalars * @tparam GradSW Whether the wiener7 gradient function is passed * @tparam Wiener7FunctorT Type of functor * @tparam Targs... Types of arguments in parameter pack From 064eb70b1dc367bbc6d23394b20ffe44e79a8688 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 20 Oct 2023 18:17:57 +0200 Subject: [PATCH 110/179] only 1 test in full --- stan/math/prim/prob/wiener5_lpdf.hpp | 69 ++++++++------- stan/math/prim/prob/wiener_full_lpdf.hpp | 70 +++++++--------- test/unit/math/mix/prob/wiener5_lpdf_test.cpp | 83 +------------------ test/unit/math/mix/prob/wiener_full_test.cpp | 35 ++++---- 4 files changed, 92 insertions(+), 165 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index c02ad5a30ff..6eb0ff302cf 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -200,7 +200,7 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, const Scalar mult = Density ? 1 : 3; const Scalar offset = GradW ? y_asq : 0; const Scalar sqrt_offset = sqrt(offset); - for (auto k = n_terms_small_t; k >= 1; k--) { //instead of size_t + for (auto k = n_terms_small_t; k >= 1; k--) { const Scalar wp2k = w + 2.0 * k; const Scalar wm2k = w - 2.0 * k; int wp2k_sign = (wp2k > sqrt_offset) ? 1 : -1; @@ -235,7 +235,7 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, } else if (GradW) { mult = 2; } - for (auto k = n_terms_large_t; k >= 1; k--) { //instead of size_t + for (auto k = n_terms_large_t; k >= 1; k--) { const Scalar pi_k = k * pi(); const Scalar check = (GradW) ? cos(pi_k * w) : sin(pi_k * w); int check_sign = sign(check); @@ -277,7 +277,6 @@ inline Scalar wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, const Scalar n_terms_large_t = wiener5_n_terms_largel_t(y, a, w_value, error); - // 0 is result, 1 is newwsign auto res = wiener5_log_sum_exp(y, a, w_value, n_terms_small_t, n_terms_large_t).first; if (2 * n_terms_small_t <= n_terms_large_t) { @@ -610,22 +609,31 @@ inline return_type_t wiener5_lpdf( "A-priori bias", w, "Nondecision time", t0, "Inter-trial variability in drift rate", sv); - /* - check_consistent_size(function_name, "Random variable", y, 1); - check_consistent_size(function_name, "Boundary separation", a, 1); - check_consistent_size(function_name, "Nondecision time", t0, 1); - check_consistent_size(function_name, "A-priori bias", w, 1); - check_consistent_size(function_name, "Drift rate", v, 1); - check_consistent_size(function_name, "Inter-trial variability in drift rate", - sv, 1); - */ - T_y_ref y_ref = y; T_a_ref a_ref = a; T_t0_ref t0_ref = t0; T_w_ref w_ref = w; T_v_ref v_ref = v; T_sv_ref sv_ref = sv; + + decltype(auto) y_val = to_ref(as_value_column_array_or_scalar(y_ref)); + decltype(auto) a_val = to_ref(as_value_column_array_or_scalar(a_ref)); + decltype(auto) v_val = to_ref(as_value_column_array_or_scalar(v_ref)); + decltype(auto) w_val = to_ref(as_value_column_array_or_scalar(w_ref)); + decltype(auto) t0_val = to_ref(as_value_column_array_or_scalar(t0_ref)); + decltype(auto) sv_val = to_ref(as_value_column_array_or_scalar(sv_ref)); + check_positive_finite(function_name, "Random variable", y_val); + check_positive_finite(function_name, "Boundary separation", a_val); + check_finite(function_name, "Drift rate", v_val); + check_less(function_name, "A-priori bias", w_val, 1); + check_greater(function_name, "A-priori bias", w_val, 0); + check_nonnegative(function_name, "Nondecision time", t0_val); + check_finite(function_name, "Nondecision time", t0_val); + check_nonnegative(function_name, "Inter-trial variability in drift rate", + sv_val); + check_finite(function_name, "Inter-trial variability in drift rate", sv_val); + + check_positive_finite(function_name, "Random variable", value_of(y_ref)); check_positive_finite(function_name, "Boundary separation", value_of(a_ref)); @@ -662,7 +670,6 @@ inline return_type_t wiener5_lpdf( const T_partials_return log_error_density = log(1e-6); const T_partials_return log_error_derivative = log(precision_derivatives); const T_partials_return log_error_absolute = log(1e-12); - T_partials_return density = 0.0; T_partials_return log_density = 0.0; operands_and_partials ops_partials(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref); @@ -674,25 +681,27 @@ inline return_type_t wiener5_lpdf( // Calculate 4-parameter model without inter-trial variabilities (if // sv_vec[i] == 0) or 5-parameter model with inter-trial variability in // drift rate (if sv_vec[i] != 0) - const T_partials_return y_val = y_vec.val(i); - const T_partials_return a_val = a_vec.val(i); - const T_partials_return t0_val = t0_vec.val(i); - const T_partials_return w_val = w_vec.val(i); - const T_partials_return v_val = v_vec.val(i); - const T_partials_return sv_val = sv_vec.val(i); - - density = internal::estimate_with_err_check( + const T_partials_return y_value = y_vec.val(i); + const T_partials_return a_value = a_vec.val(i); + const T_partials_return t0_value = t0_vec.val(i); + const T_partials_return w_value = w_vec.val(i); + const T_partials_return v_value = v_vec.val(i); + const T_partials_return sv_value = sv_vec.val(i); + + T_partials_return l_density = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener5_density(args...); }, - log_error_density - LOG_TWO, y_val - t0_val, a_val, v_val, w_val, - sv_val, log_error_absolute); + log_error_density - LOG_TWO, y_value - t0_value, a_value, v_value, w_value, + sv_value, log_error_absolute); + + log_density += l_density; - const T_partials_return new_est_err = density + log_error_derivative - LOG_FOUR; + const T_partials_return new_est_err = l_density + log_error_derivative - LOG_FOUR; // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 const T_partials_return deriv_y = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener5_grad_t(args...); }, - new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, + new_est_err, y_value - t0_value, a_value, v_value, w_value, sv_value, log_error_absolute); // computation of derivatives and precision checks @@ -702,7 +711,7 @@ inline return_type_t wiener5_lpdf( if (!is_constant_all::value) { ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener5_grad_a(args...); }, - new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, + new_est_err, y_value - t0_value, a_value, v_value, w_value, sv_value, log_error_absolute); } if (!is_constant_all::value) { @@ -711,16 +720,16 @@ inline return_type_t wiener5_lpdf( if (!is_constant_all::value) { ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener5_grad_w(args...); }, - new_est_err, y_val - t0_val, a_val, v_val, w_val, sv_val, + new_est_err, y_value - t0_value, a_value, v_value, w_value, sv_value, log_error_absolute); } if (!is_constant_all::value) { ops_partials.edge5_.partials_[i] = internal::wiener5_grad_v( - y_val - t0_val, a_val, v_val, w_val, sv_val); + y_value - t0_value, a_value, v_value, w_value, sv_value); } if (!is_constant_all::value) { ops_partials.edge6_.partials_[i] = internal::wiener5_grad_sv( - y_val - t0_val, a_val, v_val, w_val, sv_val); + y_value - t0_value, a_value, v_value, w_value, sv_value); } } // end for loop return ops_partials.build(log_density); diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 445357b498b..2cd296f043a 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -316,19 +316,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, "Inter-trial variability in drift rate", sv, "Inter-trial variability in A-priori bias", sw, "Inter-trial variability in Nondecision time", st0); - /* This should support mixes of scalars and vectors - check_consistent_size(function_name, "Random variable", y, 1); - check_consistent_size(function_name, "Boundary separation", a, 1); - check_consistent_size(function_name, "Drift rate", v, 1); - check_consistent_size(function_name, "A-priori bias", w, 1); - check_consistent_size(function_name, "Nondecision time", t0, 1); - check_consistent_size(function_name, "Inter-trial variability in drift rate", - sv, 1); - check_consistent_size(function_name, - "Inter-trial variability in A-priori bias", sw, 1); - check_consistent_size(function_name, - "Inter-trial variability in Nondecision time", st0, 1); - */ + T_y_ref y_ref = y; T_a_ref a_ref = a; T_v_ref v_ref = v; @@ -432,15 +420,15 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, v_vec[i], sv_vec[i], precision_derivatives); continue; } - const T_partials_return y_val = y_vec.val(i); - const T_partials_return a_val = a_vec.val(i); - const T_partials_return v_val = v_vec.val(i); - const T_partials_return w_val = w_vec.val(i); - const T_partials_return t0_val = t0_vec.val(i); - const T_partials_return sv_val = sv_vec.val(i); - const T_partials_return sw_val = sw_vec.val(i); - const T_partials_return st0_val = st0_vec.val(i); - const int dim = (sw_val != 0) + (st0_val != 0); + const T_partials_return y_value = y_vec.val(i); + const T_partials_return a_value = a_vec.val(i); + const T_partials_return v_value = v_vec.val(i); + const T_partials_return w_value = w_vec.val(i); + const T_partials_return t0_value = t0_vec.val(i); + const T_partials_return sv_value = sv_vec.val(i); + const T_partials_return sw_value = sw_vec.val(i); + const T_partials_return st0_value = st0_vec.val(i); + const int dim = (sw_value != 0) + (st0_value != 0); check_positive(function_name, "(Inter-trial variability in A-priori bias) + " "(Inter-trial variability in nondecision time)", @@ -448,21 +436,21 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, Eigen::Matrix xmin = Eigen::VectorXd::Zero(dim); Eigen::Matrix xmax = Eigen::VectorXd::Ones(dim); - if (st0_val != 0) { - xmax[dim - 1] = fmin(1.0, (y_val - t0_val) / st0_val); + if (st0_value != 0) { + xmax[dim - 1] = fmin(1.0, (y_value - t0_value) / st0_value); } T_partials_return hcubature_err = log_error_absolute - log_error_density + LOG_TWO + 1; const auto params - = std::make_tuple(y_val, a_val, v_val, w_val, t0_val, sv_val, sw_val, - st0_val, log_error_absolute - LOG_TWO); + = std::make_tuple(y_value, a_value, v_value, w_value, t0_value, sv_value, sw_value, + st0_value, log_error_absolute - LOG_TWO); T_partials_return density = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_density(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2); - log_density = log_density + log(density); + log_density += log(density); hcubature_err = log_error_absolute - log_error_derivative + log(fabs(density)) + LOG_TWO + 1; @@ -533,16 +521,16 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, / density; } if (!is_constant_all::value) { - if (sw_val == 0) { + if (sw_value == 0) { partials<6>(ops_partials)[i] = 0; } else { - if (st0_val == 0) { + if (st0_value == 0) { derivative = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener7_grad_sw(args...); }, - hcubature_err, y_val - t0_val, a_val, v_val, w_val, sv_val, - sw_val, log_error_absolute - LOG_TWO); + hcubature_err, y_value - t0_value, a_value, v_value, w_value, sv_value, + sw_value, log_error_absolute - LOG_TWO); } else { derivative = internal::wiener7_integrate( [&](auto&&... args) { @@ -552,28 +540,28 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2); } - partials<6>(ops_partials)[i] = derivative / density - 1 / sw_val; + partials<6>(ops_partials)[i] = derivative / density - 1 / sw_value; } } if (!is_constant_all::value) { T_partials_return f; - if (st0_val == 0) { + if (st0_value == 0) { partials<7>(ops_partials)[i] = 0; - } else if (y_val - (t0_val + st0_val) <= 0) { - partials<7>(ops_partials)[i] = -1 / st0_val; + } else if (y_value - (t0_value + st0_value) <= 0) { + partials<7>(ops_partials)[i] = -1 / st0_value; } else { - const T_partials_return t0_st0 = t0_val + st0_val; - if (sw_val == 0) { + const T_partials_return t0_st0 = t0_value + st0_value; + if (sw_value == 0) { f = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener5_density(args...); }, - log_error_derivative + log(st0_val), y_val - t0_st0, a_val, v_val, - w_val, sv_val, log_error_absolute - LOG_TWO); + log_error_derivative + log(st0_value), y_value - t0_st0, a_value, v_value, + w_value, sv_value, log_error_absolute - LOG_TWO); } else { const T_partials_return new_error = log_error_absolute - LOG_TWO; const auto& params_st = std::make_tuple( - y_val, a_val, v_val, w_val, t0_st0, sv_val, sw_val, 0, new_error); + y_value, a_value, v_value, w_value, t0_st0, sv_value, sw_value, 0, new_error); f = internal::wiener7_integrate( [&](auto&&... args) { return internal::wiener5_density(args...); @@ -582,7 +570,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2); } - partials<7>(ops_partials)[i] = -1 / st0_val + f / st0_val / density; + partials<7>(ops_partials)[i] = -1 / st0_value + f / st0_value / density; } } } diff --git a/test/unit/math/mix/prob/wiener5_lpdf_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_test.cpp index 58e48766ebd..b3b7f201680 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_test.cpp @@ -2,7 +2,7 @@ #include -TEST(mathMixDouble, wiener5_lpdf) { // runs successfully +TEST(mathMixDouble, wiener5_lpdf) { double y = 1.0; double a = 2.0; double t0 = 0.2; @@ -13,7 +13,7 @@ TEST(mathMixDouble, wiener5_lpdf) { // runs successfully } -TEST(mathMixVar, wiener5_lpdf) { // runs successfully +TEST(mathMixVar, wiener5_lpdf) { using stan::math::var; var y = 1.0; var a = 2.0; @@ -25,7 +25,7 @@ TEST(mathMixVar, wiener5_lpdf) { // runs successfully } -TEST(mathMixFVar, wiener5_lpdf) { // runs successfully +TEST(mathMixFVar, wiener5_lpdf) { using stan::math::fvar; using stan::math::var; fvar y = 1.0; @@ -40,7 +40,7 @@ TEST(mathMixFVar, wiener5_lpdf) { // runs successfully -TEST(mathMixDouble1Fun, wiener5_lpdf) { // error: x1 evaluates to 0 +TEST(mathMixDouble1Fun, wiener5_lpdf) { using stan::math::var; double y = 1.0; double a = 2.0; @@ -55,78 +55,3 @@ TEST(mathMixDouble1Fun, wiener5_lpdf) { // error: x1 evaluates to 0 }; stan::test::expect_ad(f1(y, a, t0, w, v), sv); } -//correct value for grad_sv from R: -0.147527191875488 - -/* -TEST(mathMixDouble1Fun, wiener5_lpdf) { - double y = 1.0; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 1.5; - double sv = 0.2; - auto f1 = [](const auto& w, const auto& v, const auto& sv) { - return [&w, &v, &sv](const auto& y, const auto& a, const auto& t0) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); - }; - }; - stan::test::expect_ad(f1(w, v, sv), y, a, t0); -}*/ - -/* -TEST(mathMixDouble2Fun, wiener5_lpdf) { - double y = 1.0; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 1.5; - double sv = 0.2; - auto f1 = [](const auto& y, const auto& a, const auto& t0) { - return [&y, &a, &t0](const auto& w, const auto& v, const auto& sv) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); - }; - }; - stan::test::expect_ad(f1(y, a, t0), w, v, sv); -}*/ - -/* -TEST(mathMixVarFun, wiener5_lpdf) { - using stan::math::var; - var y = 1.0; - var a = 2.0; - var t0 = 0.2; - var w = 0.5; - var v = 1.5; - var sv = 0.2; - auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { - return [&y, &a, &t0, &w, &v](const auto& sv) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); - }; - }; - stan::test::expect_ad(f1(y, a, t0, w, v), sv); -}*/ - - - -/* - //using stan::math::fvar; - //using stan::math::var; - auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { - return [&y, &a, &t0, &w, &v](const auto& sv, const auto& sw, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; - - - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double st0 = 0.3; - - stan::test::expect_ad(f1(y, a, t0, w, v), sv, st0); - -}*/ \ No newline at end of file diff --git a/test/unit/math/mix/prob/wiener_full_test.cpp b/test/unit/math/mix/prob/wiener_full_test.cpp index f4fa2f9b2e1..d53e5aac823 100644 --- a/test/unit/math/mix/prob/wiener_full_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_test.cpp @@ -1,6 +1,7 @@ #include #include +/* TEST(mathMixDouble, wiener_full_lpdf) { double y = 1.0; double a = 2.0; @@ -41,11 +42,11 @@ TEST(mathMixFVar, wiener_full_lpdf) { fvar st0 = 0.2; stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); } - +*/ TEST(mathMixScalFun, wiener_full_lpdf) { - auto f_y = [](const auto& a, const auto& t0, const auto& w, const auto& v, const auto& sv, const auto& sw, const auto& st0) { +/* auto f_y = [](const auto& a, const auto& t0, const auto& w, const auto& v, const auto& sv, const auto& sw, const auto& st0) { return [&a, &t0, &w, &v, &sv, &sw, &st0](const auto& y) { return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); }; @@ -93,13 +94,13 @@ TEST(mathMixScalFun, wiener_full_lpdf) { }; }; - + */ auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { return [&y, &a, &t0, &w, &v](const auto& sv, const auto& sw, const auto& st0) { return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - + /* auto f2 = [](const auto& y, const auto& a, const auto& sv, const auto& sw, const auto& st0) { return [&y, &a, &sv, &sw, &st0](const auto& t0, const auto& w, const auto& v) { return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); @@ -111,7 +112,7 @@ TEST(mathMixScalFun, wiener_full_lpdf) { return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - +*/ double y = 0.1; double a = 2.0; @@ -122,19 +123,23 @@ TEST(mathMixScalFun, wiener_full_lpdf) { double sw = 0.1; double st0 = 0.3; + + stan::test::expect_ad(f1(y, a, t0, w, v), sv, sw, st0); - stan::test::expect_ad(f2(y, a, sv, sw, st0), t0, w, v); - stan::test::expect_ad(f3(w, v, sv, sw, st0), y, a, t0); +// stan::test::expect_ad(f2(y, a, sv, sw, st0), t0, w, v); +// stan::test::expect_ad(f3(w, v, sv, sw, st0), y, a, t0); - stan::test::expect_ad(f_y(a, t0, w, v, sv, sw, st0), y); - stan::test::expect_ad(f_a(y, t0, w, v, sv, sw, st0), a); - stan::test::expect_ad(f_t0(y, a, w, v, sv, sw, st0), t0); - stan::test::expect_ad(f_w(y, a, t0, v, sv, sw, st0), w); - stan::test::expect_ad(f_v(y, a, t0, w, sv, sw, st0), v); - stan::test::expect_ad(f_sv(y, a, t0, w, v, sw, st0), sv); - stan::test::expect_ad(f_sw(y, a, t0, w, v, sv, st0), sw); - stan::test::expect_ad(f_st0(y, a, t0, w, v, sv, sw), st0); + + +// stan::test::expect_ad(f_y(a, t0, w, v, sv, sw, st0), y); +// stan::test::expect_ad(f_a(y, t0, w, v, sv, sw, st0), a); +// stan::test::expect_ad(f_t0(y, a, w, v, sv, sw, st0), t0); +// stan::test::expect_ad(f_w(y, a, t0, v, sv, sw, st0), w); +// stan::test::expect_ad(f_v(y, a, t0, w, sv, sw, st0), v); +// stan::test::expect_ad(f_sv(y, a, t0, w, v, sw, st0), sv); +// stan::test::expect_ad(f_sw(y, a, t0, w, v, sv, st0), sw); +// stan::test::expect_ad(f_st0(y, a, t0, w, v, sv, sw), st0); } From cf8d98df3b623257e6cdd3b3cd324712122ef859 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 20 Oct 2023 18:57:17 +0200 Subject: [PATCH 111/179] test mix test --- test/unit/math/mix/prob/wiener_full_test.cpp | 107 +++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/test/unit/math/mix/prob/wiener_full_test.cpp b/test/unit/math/mix/prob/wiener_full_test.cpp index d53e5aac823..d548dfb2b13 100644 --- a/test/unit/math/mix/prob/wiener_full_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_test.cpp @@ -141,5 +141,112 @@ TEST(mathMixScalFun, wiener_full_lpdf) { // stan::test::expect_ad(f_sw(y, a, t0, w, v, sv, st0), sw); // stan::test::expect_ad(f_st0(y, a, t0, w, v, sv, sw), st0); + + } + + +TEST(mathMixScalFun_w_sw_st0, wiener_full_lpdf) { +auto f_w_sw_st0 = [](const auto& y, const auto& a, const auto& t0, const auto& v, const auto& sv) { + return [&y, &a, &t0, &v, &sv](const auto& w, const auto& sw, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_w_sw_st0(y, a, t0, v, sv), w, sw, st0); + } + + + +TEST(mathMixScalFun_v_sv_sw, wiener_full_lpdf) { +auto f_v_sv_sw = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& st0) { + return [&y, &a, &t0, &w, &st0](const auto& v, const auto& sv, const auto& sw) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_v_sv_sw(y, a, t0, w, st0), v, sv, sw); + } + + + +TEST(mathMixScalFun_v_sv_st0, wiener_full_lpdf) { +auto f_v_sv_st0 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& sw) { + return [&y, &a, &t0, &w, &sw](const auto& v, const auto& sv, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_v_sv_st0(y, a, t0, w, sw), v, sv, st0); + } + + + +TEST(mathMixScalFun_v_sw_st0, wiener_full_lpdf) { +auto f_v_sw_st0 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& sv) { + return [&y, &a, &t0, &w, &sv](const auto& v, const auto& sw, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_v_sw_st0(y, a, t0, w, sv), v, sw, st0); + } + + + +TEST(mathMixScalFun_sv_sw_st0, wiener_full_lpdf) { +auto f_sv_sw_st0 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { + return [&y, &a, &t0, &w, &v](const auto& sv, const auto& sw, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_sv_sw_st0(y, a, t0, w, v), sv, sw, st0); + } + From d4737a65345f14a9ce747522ef48e29fa08a2aee Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 20 Oct 2023 20:39:37 +0200 Subject: [PATCH 112/179] wiener_full mix tests --- .../unit/math/mix/prob/wiener_full_0_test.cpp | 62 +++++ .../math/mix/prob/wiener_full_10_test.cpp | 107 ++++++++ .../math/mix/prob/wiener_full_11_test.cpp | 107 ++++++++ .../unit/math/mix/prob/wiener_full_1_test.cpp | 107 ++++++++ .../unit/math/mix/prob/wiener_full_2_test.cpp | 107 ++++++++ .../unit/math/mix/prob/wiener_full_3_test.cpp | 107 ++++++++ .../unit/math/mix/prob/wiener_full_4_test.cpp | 107 ++++++++ .../unit/math/mix/prob/wiener_full_5_test.cpp | 107 ++++++++ .../unit/math/mix/prob/wiener_full_6_test.cpp | 107 ++++++++ .../unit/math/mix/prob/wiener_full_7_test.cpp | 107 ++++++++ .../unit/math/mix/prob/wiener_full_8_test.cpp | 107 ++++++++ .../unit/math/mix/prob/wiener_full_9_test.cpp | 107 ++++++++ test/unit/math/mix/prob/wiener_full_test.cpp | 252 ------------------ 13 files changed, 1239 insertions(+), 252 deletions(-) create mode 100644 test/unit/math/mix/prob/wiener_full_0_test.cpp create mode 100644 test/unit/math/mix/prob/wiener_full_10_test.cpp create mode 100644 test/unit/math/mix/prob/wiener_full_11_test.cpp create mode 100644 test/unit/math/mix/prob/wiener_full_1_test.cpp create mode 100644 test/unit/math/mix/prob/wiener_full_2_test.cpp create mode 100644 test/unit/math/mix/prob/wiener_full_3_test.cpp create mode 100644 test/unit/math/mix/prob/wiener_full_4_test.cpp create mode 100644 test/unit/math/mix/prob/wiener_full_5_test.cpp create mode 100644 test/unit/math/mix/prob/wiener_full_6_test.cpp create mode 100644 test/unit/math/mix/prob/wiener_full_7_test.cpp create mode 100644 test/unit/math/mix/prob/wiener_full_8_test.cpp create mode 100644 test/unit/math/mix/prob/wiener_full_9_test.cpp delete mode 100644 test/unit/math/mix/prob/wiener_full_test.cpp diff --git a/test/unit/math/mix/prob/wiener_full_0_test.cpp b/test/unit/math/mix/prob/wiener_full_0_test.cpp new file mode 100644 index 00000000000..6cc014138a3 --- /dev/null +++ b/test/unit/math/mix/prob/wiener_full_0_test.cpp @@ -0,0 +1,62 @@ +#include +#include + +TEST(mathMixDouble, wiener_full_lpdf) { + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 1.5; + double sv = 0.2; + double sw = 0.2; + double st0 = 0.2; + stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0, 1e-4); +} + +TEST(mathMixVar, wiener_full_lpdf) { + using stan::math::var; + var y = 1.0; + var a = 2.0; + var t0 = 0.2; + var w = 0.5; + var v = 1.5; + var sv = 0.2; + var sw = 0; + var st0 = 0.2; + stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); +} + +TEST(mathMixFVar, wiener_full_lpdf) { + using stan::math::fvar; + using stan::math::var; + fvar y = 1.0; + fvar a = 2.0; + fvar t0 = 0.2; + fvar w = 0.5; + fvar v = 1.5; + fvar sv = 0.2; + fvar sw = 0; + fvar st0 = 0.2; + stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); +} + +TEST(mathMixScalFun_y_a_t0, wiener_full_lpdf) { + auto f_y_a_t0 = [](const auto& w, const auto& v, const auto& sv, + const auto& sw, const auto& st0) { + return + [&w, &v, &sv, &sw, &st0](const auto& y, const auto& a, const auto& t0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_a_t0(w, v, sv, sw, st0), y, a, t0); +} \ No newline at end of file diff --git a/test/unit/math/mix/prob/wiener_full_10_test.cpp b/test/unit/math/mix/prob/wiener_full_10_test.cpp new file mode 100644 index 00000000000..f38a2d274fa --- /dev/null +++ b/test/unit/math/mix/prob/wiener_full_10_test.cpp @@ -0,0 +1,107 @@ +#include +#include + +TEST(mathMixScalFun_w_v_sv, wiener_full_lpdf) { + auto f_w_v_sv = [](const auto& y, const auto& a, const auto& t0, + const auto& sw, const auto& st0) { + return + [&y, &a, &t0, &sw, &st0](const auto& w, const auto& v, const auto& sv) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_w_v_sv(y, a, t0, sw, st0), w, v, sv); +} + +TEST(mathMixScalFun_w_v_sw, wiener_full_lpdf) { + auto f_w_v_sw = [](const auto& y, const auto& a, const auto& t0, + const auto& sv, const auto& st0) { + return + [&y, &a, &t0, &sv, &st0](const auto& w, const auto& v, const auto& sw) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_w_v_sw(y, a, t0, sv, st0), w, v, sw); +} + +TEST(mathMixScalFun_w_v_st0, wiener_full_lpdf) { + auto f_w_v_st0 = [](const auto& y, const auto& a, const auto& t0, + const auto& sv, const auto& sw) { + return + [&y, &a, &t0, &sv, &sw](const auto& w, const auto& v, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_w_v_st0(y, a, t0, sv, sw), w, v, st0); +} + +TEST(mathMixScalFun_w_sv_sw, wiener_full_lpdf) { + auto f_w_sv_sw = [](const auto& y, const auto& a, const auto& t0, + const auto& v, const auto& st0) { + return + [&y, &a, &t0, &v, &st0](const auto& w, const auto& sv, const auto& sw) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_w_sv_sw(y, a, t0, v, st0), w, sv, sw); +} + +TEST(mathMixScalFun_w_sv_st0, wiener_full_lpdf) { + auto f_w_sv_st0 = [](const auto& y, const auto& a, const auto& t0, + const auto& v, const auto& sw) { + return + [&y, &a, &t0, &v, &sw](const auto& w, const auto& sv, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_w_sv_st0(y, a, t0, v, sw), w, sv, st0); +} diff --git a/test/unit/math/mix/prob/wiener_full_11_test.cpp b/test/unit/math/mix/prob/wiener_full_11_test.cpp new file mode 100644 index 00000000000..f1bc94e22f3 --- /dev/null +++ b/test/unit/math/mix/prob/wiener_full_11_test.cpp @@ -0,0 +1,107 @@ +#include +#include + +TEST(mathMixScalFun_w_sw_st0, wiener_full_lpdf) { + auto f_w_sw_st0 = [](const auto& y, const auto& a, const auto& t0, + const auto& v, const auto& sv) { + return + [&y, &a, &t0, &v, &sv](const auto& w, const auto& sw, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_w_sw_st0(y, a, t0, v, sv), w, sw, st0); +} + +TEST(mathMixScalFun_v_sv_sw, wiener_full_lpdf) { + auto f_v_sv_sw = [](const auto& y, const auto& a, const auto& t0, + const auto& w, const auto& st0) { + return + [&y, &a, &t0, &w, &st0](const auto& v, const auto& sv, const auto& sw) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_v_sv_sw(y, a, t0, w, st0), v, sv, sw); +} + +TEST(mathMixScalFun_v_sv_st0, wiener_full_lpdf) { + auto f_v_sv_st0 = [](const auto& y, const auto& a, const auto& t0, + const auto& w, const auto& sw) { + return + [&y, &a, &t0, &w, &sw](const auto& v, const auto& sv, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_v_sv_st0(y, a, t0, w, sw), v, sv, st0); +} + +TEST(mathMixScalFun_v_sw_st0, wiener_full_lpdf) { + auto f_v_sw_st0 = [](const auto& y, const auto& a, const auto& t0, + const auto& w, const auto& sv) { + return + [&y, &a, &t0, &w, &sv](const auto& v, const auto& sw, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_v_sw_st0(y, a, t0, w, sv), v, sw, st0); +} + +TEST(mathMixScalFun_sv_sw_st0, wiener_full_lpdf) { + auto f_sv_sw_st0 = [](const auto& y, const auto& a, const auto& t0, + const auto& w, const auto& v) { + return + [&y, &a, &t0, &w, &v](const auto& sv, const auto& sw, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_sv_sw_st0(y, a, t0, w, v), sv, sw, st0); +} diff --git a/test/unit/math/mix/prob/wiener_full_1_test.cpp b/test/unit/math/mix/prob/wiener_full_1_test.cpp new file mode 100644 index 00000000000..075435ba4ae --- /dev/null +++ b/test/unit/math/mix/prob/wiener_full_1_test.cpp @@ -0,0 +1,107 @@ +#include +#include + +TEST(mathMixScalFun_y_a_w, wiener_full_lpdf) { + auto f_y_a_w = [](const auto& t0, const auto& v, const auto& sv, + const auto& sw, const auto& st0) { + return + [&t0, &v, &sv, &sw, &st0](const auto& y, const auto& a, const auto& w) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_a_w(t0, v, sv, sw, st0), y, a, w); +} + +TEST(mathMixScalFun_y_a_v, wiener_full_lpdf) { + auto f_y_a_v = [](const auto& t0, const auto& w, const auto& sv, + const auto& sw, const auto& st0) { + return + [&t0, &w, &sv, &sw, &st0](const auto& y, const auto& a, const auto& v) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_a_v(t0, w, sv, sw, st0), y, a, v); +} + +TEST(mathMixScalFun_y_a_sv, wiener_full_lpdf) { + auto f_y_a_sv = [](const auto& t0, const auto& w, const auto& v, + const auto& sw, const auto& st0) { + return + [&t0, &w, &v, &sw, &st0](const auto& y, const auto& a, const auto& sv) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_a_sv(t0, w, v, sw, st0), y, a, sv); +} + +TEST(mathMixScalFun_y_a_sw, wiener_full_lpdf) { + auto f_y_a_sw = [](const auto& t0, const auto& w, const auto& v, + const auto& sv, const auto& st0) { + return + [&t0, &w, &v, &sv, &st0](const auto& y, const auto& a, const auto& sw) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_a_sw(t0, w, v, sv, st0), y, a, sw); +} + +TEST(mathMixScalFun_y_a_st0, wiener_full_lpdf) { + auto f_y_a_st0 = [](const auto& t0, const auto& w, const auto& v, + const auto& sv, const auto& sw) { + return + [&t0, &w, &v, &sv, &sw](const auto& y, const auto& a, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_a_st0(t0, w, v, sv, sw), y, a, st0); +} diff --git a/test/unit/math/mix/prob/wiener_full_2_test.cpp b/test/unit/math/mix/prob/wiener_full_2_test.cpp new file mode 100644 index 00000000000..816a97d5539 --- /dev/null +++ b/test/unit/math/mix/prob/wiener_full_2_test.cpp @@ -0,0 +1,107 @@ +#include +#include + +TEST(mathMixScalFun_y_t0_w, wiener_full_lpdf) { + auto f_y_t0_w = [](const auto& a, const auto& v, const auto& sv, + const auto& sw, const auto& st0) { + return + [&a, &v, &sv, &sw, &st0](const auto& y, const auto& t0, const auto& w) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_t0_w(a, v, sv, sw, st0), y, t0, w); +} + +TEST(mathMixScalFun_y_t0_v, wiener_full_lpdf) { + auto f_y_t0_v = [](const auto& a, const auto& w, const auto& sv, + const auto& sw, const auto& st0) { + return + [&a, &w, &sv, &sw, &st0](const auto& y, const auto& t0, const auto& v) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_t0_v(a, w, sv, sw, st0), y, t0, v); +} + +TEST(mathMixScalFun_y_t0_sv, wiener_full_lpdf) { + auto f_y_t0_sv = [](const auto& a, const auto& w, const auto& v, + const auto& sw, const auto& st0) { + return + [&a, &w, &v, &sw, &st0](const auto& y, const auto& t0, const auto& sv) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_t0_sv(a, w, v, sw, st0), y, t0, sv); +} + +TEST(mathMixScalFun_y_t0_sw, wiener_full_lpdf) { + auto f_y_t0_sw = [](const auto& a, const auto& w, const auto& v, + const auto& sv, const auto& st0) { + return + [&a, &w, &v, &sv, &st0](const auto& y, const auto& t0, const auto& sw) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_t0_sw(a, w, v, sv, st0), y, t0, sw); +} + +TEST(mathMixScalFun_y_t0_st0, wiener_full_lpdf) { + auto f_y_t0_st0 = [](const auto& a, const auto& w, const auto& v, + const auto& sv, const auto& sw) { + return + [&a, &w, &v, &sv, &sw](const auto& y, const auto& t0, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_t0_st0(a, w, v, sv, sw), y, t0, st0); +} diff --git a/test/unit/math/mix/prob/wiener_full_3_test.cpp b/test/unit/math/mix/prob/wiener_full_3_test.cpp new file mode 100644 index 00000000000..ee4fc356b91 --- /dev/null +++ b/test/unit/math/mix/prob/wiener_full_3_test.cpp @@ -0,0 +1,107 @@ +#include +#include + +TEST(mathMixScalFun_y_w_v, wiener_full_lpdf) { + auto f_y_w_v = [](const auto& a, const auto& t0, const auto& sv, + const auto& sw, const auto& st0) { + return + [&a, &t0, &sv, &sw, &st0](const auto& y, const auto& w, const auto& v) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_w_v(a, t0, sv, sw, st0), y, w, v); +} + +TEST(mathMixScalFun_y_w_sv, wiener_full_lpdf) { + auto f_y_w_sv = [](const auto& a, const auto& t0, const auto& v, + const auto& sw, const auto& st0) { + return + [&a, &t0, &v, &sw, &st0](const auto& y, const auto& w, const auto& sv) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_w_sv(a, t0, v, sw, st0), y, w, sv); +} + +TEST(mathMixScalFun_y_w_sw, wiener_full_lpdf) { + auto f_y_w_sw = [](const auto& a, const auto& t0, const auto& v, + const auto& sv, const auto& st0) { + return + [&a, &t0, &v, &sv, &st0](const auto& y, const auto& w, const auto& sw) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_w_sw(a, t0, v, sv, st0), y, w, sw); +} + +TEST(mathMixScalFun_y_w_st0, wiener_full_lpdf) { + auto f_y_w_st0 = [](const auto& a, const auto& t0, const auto& v, + const auto& sv, const auto& sw) { + return + [&a, &t0, &v, &sv, &sw](const auto& y, const auto& w, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_w_st0(a, t0, v, sv, sw), y, w, st0); +} + +TEST(mathMixScalFun_y_v_sv, wiener_full_lpdf) { + auto f_y_v_sv = [](const auto& a, const auto& t0, const auto& w, + const auto& sw, const auto& st0) { + return + [&a, &t0, &w, &sw, &st0](const auto& y, const auto& v, const auto& sv) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_v_sv(a, t0, w, sw, st0), y, v, sv); +} diff --git a/test/unit/math/mix/prob/wiener_full_4_test.cpp b/test/unit/math/mix/prob/wiener_full_4_test.cpp new file mode 100644 index 00000000000..0abdaeafc0b --- /dev/null +++ b/test/unit/math/mix/prob/wiener_full_4_test.cpp @@ -0,0 +1,107 @@ +#include +#include + +TEST(mathMixScalFun_y_v_sw, wiener_full_lpdf) { + auto f_y_v_sw = [](const auto& a, const auto& t0, const auto& w, + const auto& sv, const auto& st0) { + return + [&a, &t0, &w, &sv, &st0](const auto& y, const auto& v, const auto& sw) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_v_sw(a, t0, w, sv, st0), y, v, sw); +} + +TEST(mathMixScalFun_y_v_st0, wiener_full_lpdf) { + auto f_y_v_st0 = [](const auto& a, const auto& t0, const auto& w, + const auto& sv, const auto& sw) { + return + [&a, &t0, &w, &sv, &sw](const auto& y, const auto& v, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_v_st0(a, t0, w, sv, sw), y, v, st0); +} + +TEST(mathMixScalFun_y_sv_sw, wiener_full_lpdf) { + auto f_y_sv_sw = [](const auto& a, const auto& t0, const auto& w, + const auto& v, const auto& st0) { + return + [&a, &t0, &w, &v, &st0](const auto& y, const auto& sv, const auto& sw) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_sv_sw(a, t0, w, v, st0), y, sv, sw); +} + +TEST(mathMixScalFun_y_sv_st0, wiener_full_lpdf) { + auto f_y_sv_st0 = [](const auto& a, const auto& t0, const auto& w, + const auto& v, const auto& sw) { + return + [&a, &t0, &w, &v, &sw](const auto& y, const auto& sv, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_sv_st0(a, t0, w, v, sw), y, sv, st0); +} + +TEST(mathMixScalFun_y_sw_st0, wiener_full_lpdf) { + auto f_y_sw_st0 = [](const auto& a, const auto& t0, const auto& w, + const auto& v, const auto& sv) { + return + [&a, &t0, &w, &v, &sv](const auto& y, const auto& sw, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_y_sw_st0(a, t0, w, v, sv), y, sw, st0); +} diff --git a/test/unit/math/mix/prob/wiener_full_5_test.cpp b/test/unit/math/mix/prob/wiener_full_5_test.cpp new file mode 100644 index 00000000000..3fd64d52a70 --- /dev/null +++ b/test/unit/math/mix/prob/wiener_full_5_test.cpp @@ -0,0 +1,107 @@ +#include +#include + +TEST(mathMixScalFun_a_t0_w, wiener_full_lpdf) { + auto f_a_t0_w = [](const auto& y, const auto& v, const auto& sv, + const auto& sw, const auto& st0) { + return + [&y, &v, &sv, &sw, &st0](const auto& a, const auto& t0, const auto& w) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_a_t0_w(y, v, sv, sw, st0), a, t0, w); +} + +TEST(mathMixScalFun_a_t0_v, wiener_full_lpdf) { + auto f_a_t0_v = [](const auto& y, const auto& w, const auto& sv, + const auto& sw, const auto& st0) { + return + [&y, &w, &sv, &sw, &st0](const auto& a, const auto& t0, const auto& v) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_a_t0_v(y, w, sv, sw, st0), a, t0, v); +} + +TEST(mathMixScalFun_a_t0_sv, wiener_full_lpdf) { + auto f_a_t0_sv = [](const auto& y, const auto& w, const auto& v, + const auto& sw, const auto& st0) { + return + [&y, &w, &v, &sw, &st0](const auto& a, const auto& t0, const auto& sv) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_a_t0_sv(y, w, v, sw, st0), a, t0, sv); +} + +TEST(mathMixScalFun_a_t0_sw, wiener_full_lpdf) { + auto f_a_t0_sw = [](const auto& y, const auto& w, const auto& v, + const auto& sv, const auto& st0) { + return + [&y, &w, &v, &sv, &st0](const auto& a, const auto& t0, const auto& sw) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_a_t0_sw(y, w, v, sv, st0), a, t0, sw); +} + +TEST(mathMixScalFun_a_t0_st0, wiener_full_lpdf) { + auto f_a_t0_st0 = [](const auto& y, const auto& w, const auto& v, + const auto& sv, const auto& sw) { + return + [&y, &w, &v, &sv, &sw](const auto& a, const auto& t0, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_a_t0_st0(y, w, v, sv, sw), a, t0, st0); +} diff --git a/test/unit/math/mix/prob/wiener_full_6_test.cpp b/test/unit/math/mix/prob/wiener_full_6_test.cpp new file mode 100644 index 00000000000..45fe9a52b90 --- /dev/null +++ b/test/unit/math/mix/prob/wiener_full_6_test.cpp @@ -0,0 +1,107 @@ +#include +#include + +TEST(mathMixScalFun_a_w_v, wiener_full_lpdf) { + auto f_a_w_v = [](const auto& y, const auto& t0, const auto& sv, + const auto& sw, const auto& st0) { + return + [&y, &t0, &sv, &sw, &st0](const auto& a, const auto& w, const auto& v) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_a_w_v(y, t0, sv, sw, st0), a, w, v); +} + +TEST(mathMixScalFun_a_w_sv, wiener_full_lpdf) { + auto f_a_w_sv = [](const auto& y, const auto& t0, const auto& v, + const auto& sw, const auto& st0) { + return + [&y, &t0, &v, &sw, &st0](const auto& a, const auto& w, const auto& sv) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_a_w_sv(y, t0, v, sw, st0), a, w, sv); +} + +TEST(mathMixScalFun_a_w_sw, wiener_full_lpdf) { + auto f_a_w_sw = [](const auto& y, const auto& t0, const auto& v, + const auto& sv, const auto& st0) { + return + [&y, &t0, &v, &sv, &st0](const auto& a, const auto& w, const auto& sw) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_a_w_sw(y, t0, v, sv, st0), a, w, sw); +} + +TEST(mathMixScalFun_a_w_st0, wiener_full_lpdf) { + auto f_a_w_st0 = [](const auto& y, const auto& t0, const auto& v, + const auto& sv, const auto& sw) { + return + [&y, &t0, &v, &sv, &sw](const auto& a, const auto& w, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_a_w_st0(y, t0, v, sv, sw), a, w, st0); +} + +TEST(mathMixScalFun_a_v_sv, wiener_full_lpdf) { + auto f_a_v_sv = [](const auto& y, const auto& t0, const auto& w, + const auto& sw, const auto& st0) { + return + [&y, &t0, &w, &sw, &st0](const auto& a, const auto& v, const auto& sv) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_a_v_sv(y, t0, w, sw, st0), a, v, sv); +} diff --git a/test/unit/math/mix/prob/wiener_full_7_test.cpp b/test/unit/math/mix/prob/wiener_full_7_test.cpp new file mode 100644 index 00000000000..13fe6364be0 --- /dev/null +++ b/test/unit/math/mix/prob/wiener_full_7_test.cpp @@ -0,0 +1,107 @@ +#include +#include + +TEST(mathMixScalFun_a_v_sw, wiener_full_lpdf) { + auto f_a_v_sw = [](const auto& y, const auto& t0, const auto& w, + const auto& sv, const auto& st0) { + return + [&y, &t0, &w, &sv, &st0](const auto& a, const auto& v, const auto& sw) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_a_v_sw(y, t0, w, sv, st0), a, v, sw); +} + +TEST(mathMixScalFun_a_v_st0, wiener_full_lpdf) { + auto f_a_v_st0 = [](const auto& y, const auto& t0, const auto& w, + const auto& sv, const auto& sw) { + return + [&y, &t0, &w, &sv, &sw](const auto& a, const auto& v, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_a_v_st0(y, t0, w, sv, sw), a, v, st0); +} + +TEST(mathMixScalFun_a_sv_sw, wiener_full_lpdf) { + auto f_a_sv_sw = [](const auto& y, const auto& t0, const auto& w, + const auto& v, const auto& st0) { + return + [&y, &t0, &w, &v, &st0](const auto& a, const auto& sv, const auto& sw) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_a_sv_sw(y, t0, w, v, st0), a, sv, sw); +} + +TEST(mathMixScalFun_a_sv_st0, wiener_full_lpdf) { + auto f_a_sv_st0 = [](const auto& y, const auto& t0, const auto& w, + const auto& v, const auto& sw) { + return + [&y, &t0, &w, &v, &sw](const auto& a, const auto& sv, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_a_sv_st0(y, t0, w, v, sw), a, sv, st0); +} + +TEST(mathMixScalFun_a_sw_st0, wiener_full_lpdf) { + auto f_a_sw_st0 = [](const auto& y, const auto& t0, const auto& w, + const auto& v, const auto& sv) { + return + [&y, &t0, &w, &v, &sv](const auto& a, const auto& sw, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_a_sw_st0(y, t0, w, v, sv), a, sw, st0); +} diff --git a/test/unit/math/mix/prob/wiener_full_8_test.cpp b/test/unit/math/mix/prob/wiener_full_8_test.cpp new file mode 100644 index 00000000000..e40ac07b781 --- /dev/null +++ b/test/unit/math/mix/prob/wiener_full_8_test.cpp @@ -0,0 +1,107 @@ +#include +#include + +TEST(mathMixScalFun_t0_w_v, wiener_full_lpdf) { + auto f_t0_w_v = [](const auto& y, const auto& a, const auto& sv, + const auto& sw, const auto& st0) { + return + [&y, &a, &sv, &sw, &st0](const auto& t0, const auto& w, const auto& v) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_t0_w_v(y, a, sv, sw, st0), t0, w, v); +} + +TEST(mathMixScalFun_t0_w_sv, wiener_full_lpdf) { + auto f_t0_w_sv = [](const auto& y, const auto& a, const auto& v, + const auto& sw, const auto& st0) { + return + [&y, &a, &v, &sw, &st0](const auto& t0, const auto& w, const auto& sv) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_t0_w_sv(y, a, v, sw, st0), t0, w, sv); +} + +TEST(mathMixScalFun_t0_w_sw, wiener_full_lpdf) { + auto f_t0_w_sw = [](const auto& y, const auto& a, const auto& v, + const auto& sv, const auto& st0) { + return + [&y, &a, &v, &sv, &st0](const auto& t0, const auto& w, const auto& sw) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_t0_w_sw(y, a, v, sv, st0), t0, w, sw); +} + +TEST(mathMixScalFun_t0_w_st0, wiener_full_lpdf) { + auto f_t0_w_st0 = [](const auto& y, const auto& a, const auto& v, + const auto& sv, const auto& sw) { + return + [&y, &a, &v, &sv, &sw](const auto& t0, const auto& w, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_t0_w_st0(y, a, v, sv, sw), t0, w, st0); +} + +TEST(mathMixScalFun_t0_v_sv, wiener_full_lpdf) { + auto f_t0_v_sv = [](const auto& y, const auto& a, const auto& w, + const auto& sw, const auto& st0) { + return + [&y, &a, &w, &sw, &st0](const auto& t0, const auto& v, const auto& sv) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_t0_v_sv(y, a, w, sw, st0), t0, v, sv); +} diff --git a/test/unit/math/mix/prob/wiener_full_9_test.cpp b/test/unit/math/mix/prob/wiener_full_9_test.cpp new file mode 100644 index 00000000000..b41b7e30274 --- /dev/null +++ b/test/unit/math/mix/prob/wiener_full_9_test.cpp @@ -0,0 +1,107 @@ +#include +#include + +TEST(mathMixScalFun_t0_v_sw, wiener_full_lpdf) { + auto f_t0_v_sw = [](const auto& y, const auto& a, const auto& w, + const auto& sv, const auto& st0) { + return + [&y, &a, &w, &sv, &st0](const auto& t0, const auto& v, const auto& sw) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_t0_v_sw(y, a, w, sv, st0), t0, v, sw); +} + +TEST(mathMixScalFun_t0_v_st0, wiener_full_lpdf) { + auto f_t0_v_st0 = [](const auto& y, const auto& a, const auto& w, + const auto& sv, const auto& sw) { + return + [&y, &a, &w, &sv, &sw](const auto& t0, const auto& v, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_t0_v_st0(y, a, w, sv, sw), t0, v, st0); +} + +TEST(mathMixScalFun_t0_sv_sw, wiener_full_lpdf) { + auto f_t0_sv_sw = [](const auto& y, const auto& a, const auto& w, + const auto& v, const auto& st0) { + return + [&y, &a, &w, &v, &st0](const auto& t0, const auto& sv, const auto& sw) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_t0_sv_sw(y, a, w, v, st0), t0, sv, sw); +} + +TEST(mathMixScalFun_t0_sv_st0, wiener_full_lpdf) { + auto f_t0_sv_st0 = [](const auto& y, const auto& a, const auto& w, + const auto& v, const auto& sw) { + return + [&y, &a, &w, &v, &sw](const auto& t0, const auto& sv, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_t0_sv_st0(y, a, w, v, sw), t0, sv, st0); +} + +TEST(mathMixScalFun_t0_sw_st0, wiener_full_lpdf) { + auto f_t0_sw_st0 = [](const auto& y, const auto& a, const auto& w, + const auto& v, const auto& sv) { + return + [&y, &a, &w, &v, &sv](const auto& t0, const auto& sw, const auto& st0) { + return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + }; + }; + + double y = 0.1; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + double sw = 0.1; + double st0 = 0.3; + + stan::test::expect_ad(f_t0_sw_st0(y, a, w, v, sv), t0, sw, st0); +} diff --git a/test/unit/math/mix/prob/wiener_full_test.cpp b/test/unit/math/mix/prob/wiener_full_test.cpp deleted file mode 100644 index d548dfb2b13..00000000000 --- a/test/unit/math/mix/prob/wiener_full_test.cpp +++ /dev/null @@ -1,252 +0,0 @@ -#include -#include - -/* -TEST(mathMixDouble, wiener_full_lpdf) { - double y = 1.0; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 1.5; - double sv = 0.2; - double sw = 0.2; - double st0 = 0.2; - stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0, 1e-4); -} - - -TEST(mathMixVar, wiener_full_lpdf) { - using stan::math::var; - var y = 1.0; - var a = 2.0; - var t0 = 0.2; - var w = 0.5; - var v = 1.5; - var sv = 0.2; - var sw = 0; - var st0 = 0.2; - stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); -} - - -TEST(mathMixFVar, wiener_full_lpdf) { - using stan::math::var; - using stan::math::fvar; - fvar y = 1.0; - fvar a = 2.0; - fvar t0 = 0.2; - fvar w = 0.5; - fvar v = 1.5; - fvar sv = 0.2; - fvar sw = 0; - fvar st0 = 0.2; - stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); -} -*/ - -TEST(mathMixScalFun, wiener_full_lpdf) { - -/* auto f_y = [](const auto& a, const auto& t0, const auto& w, const auto& v, const auto& sv, const auto& sw, const auto& st0) { - return [&a, &t0, &w, &v, &sv, &sw, &st0](const auto& y) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; - - auto f_a = [](const auto& y, const auto& t0, const auto& w, const auto& v, const auto& sv, const auto& sw, const auto& st0) { - return [&y, &t0, &w, &v, &sv, &sw, &st0](const auto& a) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; - - auto f_t0 = [](const auto& y, const auto& a, const auto& w, const auto& v, const auto& sv, const auto& sw, const auto& st0) { - return [&y, &a, &w, &v, &sv, &sw, &st0](const auto& t0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; - - auto f_w = [](const auto& y, const auto& a, const auto& t0, const auto& v, const auto& sv, const auto& sw, const auto& st0) { - return [&y, &a, &t0, &v, &sv, &sw, &st0](const auto& w) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; - - auto f_v = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& sv, const auto& sw, const auto& st0) { - return [&y, &a, &t0, &w, &sv, &sw, &st0](const auto& v) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; - - auto f_sv = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v, const auto& sw, const auto& st0) { - return [&y, &a, &t0, &w, &v, &sw, &st0](const auto& sv) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; - - auto f_sw = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v, const auto& sv, const auto& st0) { - return [&y, &a, &t0, &w, &v, &sv, &st0](const auto& sw) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; - - auto f_st0 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v, const auto& sv, const auto& sw) { - return [&y, &a, &t0, &w, &v, &sv, &sw](const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; - - */ - auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { - return [&y, &a, &t0, &w, &v](const auto& sv, const auto& sw, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; - /* - auto f2 = [](const auto& y, const auto& a, const auto& sv, const auto& sw, const auto& st0) { - return [&y, &a, &sv, &sw, &st0](const auto& t0, const auto& w, const auto& v) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; - - auto f3 = [](const auto& w, const auto& v, const auto& sv, const auto& sw, const auto& st0) { - return [&w, &v, &sv, &sw, &st0](const auto& y, const auto& a, const auto& t0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; -*/ - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - - - - stan::test::expect_ad(f1(y, a, t0, w, v), sv, sw, st0); -// stan::test::expect_ad(f2(y, a, sv, sw, st0), t0, w, v); -// stan::test::expect_ad(f3(w, v, sv, sw, st0), y, a, t0); - - - - -// stan::test::expect_ad(f_y(a, t0, w, v, sv, sw, st0), y); -// stan::test::expect_ad(f_a(y, t0, w, v, sv, sw, st0), a); -// stan::test::expect_ad(f_t0(y, a, w, v, sv, sw, st0), t0); -// stan::test::expect_ad(f_w(y, a, t0, v, sv, sw, st0), w); -// stan::test::expect_ad(f_v(y, a, t0, w, sv, sw, st0), v); -// stan::test::expect_ad(f_sv(y, a, t0, w, v, sw, st0), sv); -// stan::test::expect_ad(f_sw(y, a, t0, w, v, sv, st0), sw); -// stan::test::expect_ad(f_st0(y, a, t0, w, v, sv, sw), st0); - - - -} - - - -TEST(mathMixScalFun_w_sw_st0, wiener_full_lpdf) { -auto f_w_sw_st0 = [](const auto& y, const auto& a, const auto& t0, const auto& v, const auto& sv) { - return [&y, &a, &t0, &v, &sv](const auto& w, const auto& sw, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - - stan::test::expect_ad(f_w_sw_st0(y, a, t0, v, sv), w, sw, st0); - } - - - -TEST(mathMixScalFun_v_sv_sw, wiener_full_lpdf) { -auto f_v_sv_sw = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& st0) { - return [&y, &a, &t0, &w, &st0](const auto& v, const auto& sv, const auto& sw) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - - stan::test::expect_ad(f_v_sv_sw(y, a, t0, w, st0), v, sv, sw); - } - - - -TEST(mathMixScalFun_v_sv_st0, wiener_full_lpdf) { -auto f_v_sv_st0 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& sw) { - return [&y, &a, &t0, &w, &sw](const auto& v, const auto& sv, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - - stan::test::expect_ad(f_v_sv_st0(y, a, t0, w, sw), v, sv, st0); - } - - - -TEST(mathMixScalFun_v_sw_st0, wiener_full_lpdf) { -auto f_v_sw_st0 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& sv) { - return [&y, &a, &t0, &w, &sv](const auto& v, const auto& sw, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - - stan::test::expect_ad(f_v_sw_st0(y, a, t0, w, sv), v, sw, st0); - } - - - -TEST(mathMixScalFun_sv_sw_st0, wiener_full_lpdf) { -auto f_sv_sw_st0 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { - return [&y, &a, &t0, &w, &v](const auto& sv, const auto& sw, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); - }; - }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - - stan::test::expect_ad(f_sv_sw_st0(y, a, t0, w, v), sv, sw, st0); - } - From ccd9d71a0e360d993d3ddd640fe0458918ee5a14 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 20 Oct 2023 20:54:48 +0200 Subject: [PATCH 113/179] mix tests for wiener5 --- .../math/mix/prob/wiener5_lpdf_0_test.cpp | 36 ++++++++ .../math/mix/prob/wiener5_lpdf_1_test.cpp | 87 +++++++++++++++++++ .../math/mix/prob/wiener5_lpdf_2_test.cpp | 87 +++++++++++++++++++ .../math/mix/prob/wiener5_lpdf_3_test.cpp | 87 +++++++++++++++++++ .../math/mix/prob/wiener5_lpdf_4_test.cpp | 87 +++++++++++++++++++ test/unit/math/mix/prob/wiener5_lpdf_test.cpp | 57 ------------ 6 files changed, 384 insertions(+), 57 deletions(-) create mode 100644 test/unit/math/mix/prob/wiener5_lpdf_0_test.cpp create mode 100644 test/unit/math/mix/prob/wiener5_lpdf_1_test.cpp create mode 100644 test/unit/math/mix/prob/wiener5_lpdf_2_test.cpp create mode 100644 test/unit/math/mix/prob/wiener5_lpdf_3_test.cpp create mode 100644 test/unit/math/mix/prob/wiener5_lpdf_4_test.cpp delete mode 100644 test/unit/math/mix/prob/wiener5_lpdf_test.cpp diff --git a/test/unit/math/mix/prob/wiener5_lpdf_0_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_0_test.cpp new file mode 100644 index 00000000000..dc4d5cf24f7 --- /dev/null +++ b/test/unit/math/mix/prob/wiener5_lpdf_0_test.cpp @@ -0,0 +1,36 @@ +#include +#include + +TEST(mathMixDouble, wiener5_lpdf) { + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 1.5; + double sv = 0.2; + stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); +} + +TEST(mathMixVar, wiener5_lpdf) { + using stan::math::var; + var y = 1.0; + var a = 2.0; + var t0 = 0.2; + var w = 0.5; + var v = 1.5; + var sv = 0.2; + stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); +} + +TEST(mathMixFVar, wiener5_lpdf) { + using stan::math::fvar; + using stan::math::var; + fvar y = 1.0; + fvar a = 2.0; + fvar t0 = 0.2; + fvar w = 0.5; + fvar v = 1.5; + fvar sv = 0.2; + double error = 1e-4; + stan::math::wiener5_lpdf(y, a, t0, w, v, sv, error); +} diff --git a/test/unit/math/mix/prob/wiener5_lpdf_1_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_1_test.cpp new file mode 100644 index 00000000000..e0883262018 --- /dev/null +++ b/test/unit/math/mix/prob/wiener5_lpdf_1_test.cpp @@ -0,0 +1,87 @@ +#include +#include + +TEST(mathMixScalFun_y_a_t0, wiener5_lpdf) { + auto f_y_a_t0 = [](const auto& w, const auto& v, const auto& sv) { + return [&w, &v, &sv](const auto& y, const auto& a, const auto& t0) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_y_a_t0(w, v, sv), y, a, t0); +} + +TEST(mathMixScalFun_y_a_w, wiener5_lpdf) { + auto f_y_a_w = [](const auto& t0, const auto& v, const auto& sv) { + return [&t0, &v, &sv](const auto& y, const auto& a, const auto& w) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_y_a_w(t0, v, sv), y, a, w); +} + +TEST(mathMixScalFun_y_a_v, wiener5_lpdf) { + auto f_y_a_v = [](const auto& t0, const auto& w, const auto& sv) { + return [&t0, &w, &sv](const auto& y, const auto& a, const auto& v) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_y_a_v(t0, w, sv), y, a, v); +} + +TEST(mathMixScalFun_y_a_sv, wiener5_lpdf) { + auto f_y_a_sv = [](const auto& t0, const auto& w, const auto& v) { + return [&t0, &w, &v](const auto& y, const auto& a, const auto& sv) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_y_a_sv(t0, w, v), y, a, sv); +} + +TEST(mathMixScalFun_y_t0_w, wiener5_lpdf) { + auto f_y_t0_w = [](const auto& a, const auto& v, const auto& sv) { + return [&a, &v, &sv](const auto& y, const auto& t0, const auto& w) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_y_t0_w(a, v, sv), y, t0, w); +} diff --git a/test/unit/math/mix/prob/wiener5_lpdf_2_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_2_test.cpp new file mode 100644 index 00000000000..0f58d804358 --- /dev/null +++ b/test/unit/math/mix/prob/wiener5_lpdf_2_test.cpp @@ -0,0 +1,87 @@ +#include +#include + +TEST(mathMixScalFun_y_t0_v, wiener5_lpdf) { + auto f_y_t0_v = [](const auto& a, const auto& w, const auto& sv) { + return [&a, &w, &sv](const auto& y, const auto& t0, const auto& v) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_y_t0_v(a, w, sv), y, t0, v); +} + +TEST(mathMixScalFun_y_t0_sv, wiener5_lpdf) { + auto f_y_t0_sv = [](const auto& a, const auto& w, const auto& v) { + return [&a, &w, &v](const auto& y, const auto& t0, const auto& sv) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_y_t0_sv(a, w, v), y, t0, sv); +} + +TEST(mathMixScalFun_y_w_v, wiener5_lpdf) { + auto f_y_w_v = [](const auto& a, const auto& t0, const auto& sv) { + return [&a, &t0, &sv](const auto& y, const auto& w, const auto& v) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_y_w_v(a, t0, sv), y, w, v); +} + +TEST(mathMixScalFun_y_w_sv, wiener5_lpdf) { + auto f_y_w_sv = [](const auto& a, const auto& t0, const auto& v) { + return [&a, &t0, &v](const auto& y, const auto& w, const auto& sv) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_y_w_sv(a, t0, v), y, w, sv); +} + +TEST(mathMixScalFun_y_v_sv, wiener5_lpdf) { + auto f_y_v_sv = [](const auto& a, const auto& t0, const auto& w) { + return [&a, &t0, &w](const auto& y, const auto& v, const auto& sv) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_y_v_sv(a, t0, w), y, v, sv); +} diff --git a/test/unit/math/mix/prob/wiener5_lpdf_3_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_3_test.cpp new file mode 100644 index 00000000000..8bc6cbd13c4 --- /dev/null +++ b/test/unit/math/mix/prob/wiener5_lpdf_3_test.cpp @@ -0,0 +1,87 @@ +#include +#include + +TEST(mathMixScalFun_a_t0_w, wiener5_lpdf) { + auto f_a_t0_w = [](const auto& y, const auto& v, const auto& sv) { + return [&y, &v, &sv](const auto& a, const auto& t0, const auto& w) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_a_t0_w(y, v, sv), a, t0, w); +} + +TEST(mathMixScalFun_a_t0_v, wiener5_lpdf) { + auto f_a_t0_v = [](const auto& y, const auto& w, const auto& sv) { + return [&y, &w, &sv](const auto& a, const auto& t0, const auto& v) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_a_t0_v(y, w, sv), a, t0, v); +} + +TEST(mathMixScalFun_a_t0_sv, wiener5_lpdf) { + auto f_a_t0_sv = [](const auto& y, const auto& w, const auto& v) { + return [&y, &w, &v](const auto& a, const auto& t0, const auto& sv) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_a_t0_sv(y, w, v), a, t0, sv); +} + +TEST(mathMixScalFun_a_w_v, wiener5_lpdf) { + auto f_a_w_v = [](const auto& y, const auto& t0, const auto& sv) { + return [&y, &t0, &sv](const auto& a, const auto& w, const auto& v) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_a_w_v(y, t0, sv), a, w, v); +} + +TEST(mathMixScalFun_a_w_sv, wiener5_lpdf) { + auto f_a_w_sv = [](const auto& y, const auto& t0, const auto& v) { + return [&y, &t0, &v](const auto& a, const auto& w, const auto& sv) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_a_w_sv(y, t0, v), a, w, sv); +} diff --git a/test/unit/math/mix/prob/wiener5_lpdf_4_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_4_test.cpp new file mode 100644 index 00000000000..345e6d1dec7 --- /dev/null +++ b/test/unit/math/mix/prob/wiener5_lpdf_4_test.cpp @@ -0,0 +1,87 @@ +#include +#include + +TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { + auto f_a_v_sv = [](const auto& y, const auto& t0, const auto& w) { + return [&y, &t0, &w](const auto& a, const auto& v, const auto& sv) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_a_v_sv(y, t0, w), a, v, sv); +} + +TEST(mathMixScalFun_t0_w_v, wiener5_lpdf) { + auto f_t0_w_v = [](const auto& y, const auto& a, const auto& sv) { + return [&y, &a, &sv](const auto& t0, const auto& w, const auto& v) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_t0_w_v(y, a, sv), t0, w, v); +} + +TEST(mathMixScalFun_t0_w_sv, wiener5_lpdf) { + auto f_t0_w_sv = [](const auto& y, const auto& a, const auto& v) { + return [&y, &a, &v](const auto& t0, const auto& w, const auto& sv) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_t0_w_sv(y, a, v), t0, w, sv); +} + +TEST(mathMixScalFun_t0_v_sv, wiener5_lpdf) { + auto f_t0_v_sv = [](const auto& y, const auto& a, const auto& w) { + return [&y, &a, &w](const auto& t0, const auto& v, const auto& sv) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_t0_v_sv(y, a, w), t0, v, sv); +} + +TEST(mathMixScalFun_w_v_sv, wiener5_lpdf) { + auto f_w_v_sv = [](const auto& y, const auto& a, const auto& t0) { + return [&y, &a, &t0](const auto& w, const auto& v, const auto& sv) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_w_v_sv(y, a, t0), w, v, sv); +} diff --git a/test/unit/math/mix/prob/wiener5_lpdf_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_test.cpp deleted file mode 100644 index b3b7f201680..00000000000 --- a/test/unit/math/mix/prob/wiener5_lpdf_test.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include - - -TEST(mathMixDouble, wiener5_lpdf) { - double y = 1.0; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 1.5; - double sv = 0.2; - stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); -} - - -TEST(mathMixVar, wiener5_lpdf) { - using stan::math::var; - var y = 1.0; - var a = 2.0; - var t0 = 0.2; - var w = 0.5; - var v = 1.5; - var sv = 0.2; - stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); -} - - -TEST(mathMixFVar, wiener5_lpdf) { - using stan::math::fvar; - using stan::math::var; - fvar y = 1.0; - fvar a = 2.0; - fvar t0 = 0.2; - fvar w = 0.5; - fvar v = 1.5; - fvar sv = 0.2; - double error = 1e-4; - stan::math::wiener5_lpdf(y, a, t0, w, v, sv, error); -} - - - -TEST(mathMixDouble1Fun, wiener5_lpdf) { - using stan::math::var; - double y = 1.0; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 1.5; - double sv = 0.2; - auto f1 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { - return [&y, &a, &t0, &w, &v](const auto& sv) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); - }; - }; - stan::test::expect_ad(f1(y, a, t0, w, v), sv); -} From 5da36e446fa3eeed74f2a81d98295ddd13bddf42 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 20 Oct 2023 21:01:43 +0200 Subject: [PATCH 114/179] new names mix tests --- ...0_test.cpp => wiener_full_lpdf_0_test.cpp} | 0 ..._test.cpp => wiener_full_lpdf_10_test.cpp} | 0 ..._test.cpp => wiener_full_lpdf_11_test.cpp} | 0 ...1_test.cpp => wiener_full_lpdf_1_test.cpp} | 0 ...2_test.cpp => wiener_full_lpdf_2_test.cpp} | 0 ...3_test.cpp => wiener_full_lpdf_3_test.cpp} | 0 ...4_test.cpp => wiener_full_lpdf_4_test.cpp} | 0 ...5_test.cpp => wiener_full_lpdf_5_test.cpp} | 0 ...6_test.cpp => wiener_full_lpdf_6_test.cpp} | 0 ...7_test.cpp => wiener_full_lpdf_7_test.cpp} | 0 ...8_test.cpp => wiener_full_lpdf_8_test.cpp} | 0 ...9_test.cpp => wiener_full_lpdf_9_test.cpp} | 0 test/unit/math/prim/prob/wiener_full_test.cpp | 311 ------------------ 13 files changed, 311 deletions(-) rename test/unit/math/mix/prob/{wiener_full_0_test.cpp => wiener_full_lpdf_0_test.cpp} (100%) rename test/unit/math/mix/prob/{wiener_full_10_test.cpp => wiener_full_lpdf_10_test.cpp} (100%) rename test/unit/math/mix/prob/{wiener_full_11_test.cpp => wiener_full_lpdf_11_test.cpp} (100%) rename test/unit/math/mix/prob/{wiener_full_1_test.cpp => wiener_full_lpdf_1_test.cpp} (100%) rename test/unit/math/mix/prob/{wiener_full_2_test.cpp => wiener_full_lpdf_2_test.cpp} (100%) rename test/unit/math/mix/prob/{wiener_full_3_test.cpp => wiener_full_lpdf_3_test.cpp} (100%) rename test/unit/math/mix/prob/{wiener_full_4_test.cpp => wiener_full_lpdf_4_test.cpp} (100%) rename test/unit/math/mix/prob/{wiener_full_5_test.cpp => wiener_full_lpdf_5_test.cpp} (100%) rename test/unit/math/mix/prob/{wiener_full_6_test.cpp => wiener_full_lpdf_6_test.cpp} (100%) rename test/unit/math/mix/prob/{wiener_full_7_test.cpp => wiener_full_lpdf_7_test.cpp} (100%) rename test/unit/math/mix/prob/{wiener_full_8_test.cpp => wiener_full_lpdf_8_test.cpp} (100%) rename test/unit/math/mix/prob/{wiener_full_9_test.cpp => wiener_full_lpdf_9_test.cpp} (100%) delete mode 100644 test/unit/math/prim/prob/wiener_full_test.cpp diff --git a/test/unit/math/mix/prob/wiener_full_0_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_0_test.cpp similarity index 100% rename from test/unit/math/mix/prob/wiener_full_0_test.cpp rename to test/unit/math/mix/prob/wiener_full_lpdf_0_test.cpp diff --git a/test/unit/math/mix/prob/wiener_full_10_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_10_test.cpp similarity index 100% rename from test/unit/math/mix/prob/wiener_full_10_test.cpp rename to test/unit/math/mix/prob/wiener_full_lpdf_10_test.cpp diff --git a/test/unit/math/mix/prob/wiener_full_11_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_11_test.cpp similarity index 100% rename from test/unit/math/mix/prob/wiener_full_11_test.cpp rename to test/unit/math/mix/prob/wiener_full_lpdf_11_test.cpp diff --git a/test/unit/math/mix/prob/wiener_full_1_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_1_test.cpp similarity index 100% rename from test/unit/math/mix/prob/wiener_full_1_test.cpp rename to test/unit/math/mix/prob/wiener_full_lpdf_1_test.cpp diff --git a/test/unit/math/mix/prob/wiener_full_2_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_2_test.cpp similarity index 100% rename from test/unit/math/mix/prob/wiener_full_2_test.cpp rename to test/unit/math/mix/prob/wiener_full_lpdf_2_test.cpp diff --git a/test/unit/math/mix/prob/wiener_full_3_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_3_test.cpp similarity index 100% rename from test/unit/math/mix/prob/wiener_full_3_test.cpp rename to test/unit/math/mix/prob/wiener_full_lpdf_3_test.cpp diff --git a/test/unit/math/mix/prob/wiener_full_4_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_4_test.cpp similarity index 100% rename from test/unit/math/mix/prob/wiener_full_4_test.cpp rename to test/unit/math/mix/prob/wiener_full_lpdf_4_test.cpp diff --git a/test/unit/math/mix/prob/wiener_full_5_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_5_test.cpp similarity index 100% rename from test/unit/math/mix/prob/wiener_full_5_test.cpp rename to test/unit/math/mix/prob/wiener_full_lpdf_5_test.cpp diff --git a/test/unit/math/mix/prob/wiener_full_6_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_6_test.cpp similarity index 100% rename from test/unit/math/mix/prob/wiener_full_6_test.cpp rename to test/unit/math/mix/prob/wiener_full_lpdf_6_test.cpp diff --git a/test/unit/math/mix/prob/wiener_full_7_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_7_test.cpp similarity index 100% rename from test/unit/math/mix/prob/wiener_full_7_test.cpp rename to test/unit/math/mix/prob/wiener_full_lpdf_7_test.cpp diff --git a/test/unit/math/mix/prob/wiener_full_8_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_8_test.cpp similarity index 100% rename from test/unit/math/mix/prob/wiener_full_8_test.cpp rename to test/unit/math/mix/prob/wiener_full_lpdf_8_test.cpp diff --git a/test/unit/math/mix/prob/wiener_full_9_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_9_test.cpp similarity index 100% rename from test/unit/math/mix/prob/wiener_full_9_test.cpp rename to test/unit/math/mix/prob/wiener_full_lpdf_9_test.cpp diff --git a/test/unit/math/prim/prob/wiener_full_test.cpp b/test/unit/math/prim/prob/wiener_full_test.cpp deleted file mode 100644 index 6f23c4d5f4f..00000000000 --- a/test/unit/math/prim/prob/wiener_full_test.cpp +++ /dev/null @@ -1,311 +0,0 @@ -#include -#include -#include -#include - -#include -#include - -TEST(mathPrimScalProbWienerFullScal, valid) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, - st0 = 0.1; - EXPECT_NO_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, st0)); - rt = 5; - a = 1; - v = 1; - w = 0.5; - t0 = 0.0; - sv = 0.0; - sw = 0.0; - st0 = 0.0; - EXPECT_NO_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, st0)); -} - -// rt -TEST(mathPrimScalProbWienerFullScal, invalid_rt) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(0, a, t0, w, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(-1, a, t0, w, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(INFTY, a, t0, w, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(-INFTY, a, t0, w, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(NAN, a, t0, w, v, sv, sw, st0), - std::domain_error); -} - -// a -TEST(mathPrimScalProbWienerFullScal, invalid_a) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double rt = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, 0, t0, w, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, -1, t0, w, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, INFTY, t0, w, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, -INFTY, t0, w, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, NAN, t0, w, v, sv, sw, st0), - std::domain_error); -} - -// v -TEST(mathPrimScalProbWienerFullScal, invalid_v) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, - st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, INFTY, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, -INFTY, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, NAN, sv, sw, st0), - std::domain_error); -} - -// w -TEST(mathPrimScalProbWienerFullScal, invalid_w) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double rt = 1, a = 1, v = -1, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, -0.1, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 1, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 1.1, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, INFTY, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, -INFTY, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, NAN, v, sv, sw, st0), - std::domain_error); -} - -// t0 -TEST(mathPrimScalProbWienerFullScal, invalid_t0) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, 2, w, v, sv, sw, st0), - std::domain_error); // rt must be greater than t0 - EXPECT_THROW(wiener_full_lpdf(rt, a, -1, w, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, INFTY, w, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, -INFTY, w, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, NAN, w, v, sv, sw, st0), - std::domain_error); -} - -// sv -TEST(mathPrimScalProbWienerFullScal, invalid_sv) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, -1, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, INFTY, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, -INFTY, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, NAN, sw, st0), - std::domain_error); -} - -// sw -TEST(mathPrimScalProbWienerFullScal, invalid_sw) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, -1, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0.8, v, sv, 0.5, st0), - std::domain_error); // sw must be smaller than 2*(1-w) - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0.3, v, sv, 0.7, st0), - std::domain_error); // sw must be smaller than 2*w - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, INFTY, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, -INFTY, st0), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, NAN, st0), - std::domain_error); -} - -// st0 -TEST(mathPrimScalProbWienerFullScal, invalid_st0) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, -1), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, INFTY), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, -INFTY), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, NAN), - std::domain_error); -} - -TEST(mathPrimScalProbWienerFullPrecScal, valid) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, - st0 = 0.1; - EXPECT_NO_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, st0, 1e-4)); - rt = 5; - a = 1; - v = 1; - w = 0.5; - t0 = 0.0; - sv = 0.0; - sw = 0.0; - st0 = 0.0; - EXPECT_NO_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, st0, 1e-4)); -} - -// rt -TEST(mathPrimScalProbWienerFullPrecScal, invalid_rt) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(0, a, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(-1, a, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(INFTY, a, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(-INFTY, a, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(NAN, a, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); -} - -// a -TEST(mathPrimScalProbWienerFullPrecScal, invalid_a) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double rt = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, 0, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, -1, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, INFTY, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, -INFTY, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, NAN, t0, w, v, sv, sw, st0, 1e-4), - std::domain_error); -} - -// v -TEST(mathPrimScalProbWienerFullPrecScal, invalid_v) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, - st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, INFTY, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, -INFTY, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, NAN, sv, sw, st0, 1e-4), - std::domain_error); -} - -// w -TEST(mathPrimScalProbWienerFullPrecScal, invalid_w) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double rt = 1, a = 1, v = -1, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, -0.1, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 1, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 1.1, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, INFTY, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, -INFTY, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, NAN, v, sv, sw, st0, 1e-4), - std::domain_error); -} - -// t0 -TEST(mathPrimScalProbWienerFullPrecScal, invalid_t0) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, 2, w, v, sv, sw, st0, 1e-4), - std::domain_error); // rt must be greater than t0 - EXPECT_THROW(wiener_full_lpdf(rt, a, -1, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, INFTY, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, -INFTY, w, v, sv, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, NAN, w, v, sv, sw, st0, 1e-4), - std::domain_error); -} - -// sv -TEST(mathPrimScalProbWienerFullPrecScal, invalid_sv) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, -1, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, INFTY, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, -INFTY, sw, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, NAN, sw, st0, 1e-4), - std::domain_error); -} - -// sw -TEST(mathPrimScalProbWienerFullPrecScal, invalid_sw) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, -1, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0.8, v, sv, 0.5, st0, 1e-4), - std::domain_error); // sw must be smaller than 2*(1-w) - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0.3, v, sv, 0.7, st0, 1e-4), - std::domain_error); // sw must be smaller than 2*w - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, INFTY, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, -INFTY, st0, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, NAN, st0, 1e-4), - std::domain_error); -} - -// st0 -TEST(mathPrimScalProbWienerFullPrecScal, invalid_st0) { - using stan::math::INFTY; - using stan::math::wiener_full_lpdf; - double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, -1, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, INFTY, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, -INFTY, 1e-4), - std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, NAN, 1e-4), - std::domain_error); -} From 641d5f19ad2e3518cc159387740efab4e125ebfe Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 20 Oct 2023 21:02:31 +0200 Subject: [PATCH 115/179] new name prob test --- .../math/prim/prob/wiener_full_lpdf_test.cpp | 311 ++++++++++++++++++ 1 file changed, 311 insertions(+) create mode 100644 test/unit/math/prim/prob/wiener_full_lpdf_test.cpp diff --git a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp new file mode 100644 index 00000000000..6f23c4d5f4f --- /dev/null +++ b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp @@ -0,0 +1,311 @@ +#include +#include +#include +#include + +#include +#include + +TEST(mathPrimScalProbWienerFullScal, valid) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, + st0 = 0.1; + EXPECT_NO_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, st0)); + rt = 5; + a = 1; + v = 1; + w = 0.5; + t0 = 0.0; + sv = 0.0; + sw = 0.0; + st0 = 0.0; + EXPECT_NO_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, st0)); +} + +// rt +TEST(mathPrimScalProbWienerFullScal, invalid_rt) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(0, a, t0, w, v, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(-1, a, t0, w, v, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(INFTY, a, t0, w, v, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(-INFTY, a, t0, w, v, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(NAN, a, t0, w, v, sv, sw, st0), + std::domain_error); +} + +// a +TEST(mathPrimScalProbWienerFullScal, invalid_a) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, 0, t0, w, v, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, -1, t0, w, v, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, INFTY, t0, w, v, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, -INFTY, t0, w, v, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, NAN, t0, w, v, sv, sw, st0), + std::domain_error); +} + +// v +TEST(mathPrimScalProbWienerFullScal, invalid_v) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, + st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, INFTY, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, -INFTY, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, NAN, sv, sw, st0), + std::domain_error); +} + +// w +TEST(mathPrimScalProbWienerFullScal, invalid_w) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, -0.1, v, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0, v, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 1, v, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 1.1, v, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, INFTY, v, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, -INFTY, v, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, NAN, v, sv, sw, st0), + std::domain_error); +} + +// t0 +TEST(mathPrimScalProbWienerFullScal, invalid_t0) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, 2, w, v, sv, sw, st0), + std::domain_error); // rt must be greater than t0 + EXPECT_THROW(wiener_full_lpdf(rt, a, -1, w, v, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, INFTY, w, v, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, -INFTY, w, v, sv, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, NAN, w, v, sv, sw, st0), + std::domain_error); +} + +// sv +TEST(mathPrimScalProbWienerFullScal, invalid_sv) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, -1, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, INFTY, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, -INFTY, sw, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, NAN, sw, st0), + std::domain_error); +} + +// sw +TEST(mathPrimScalProbWienerFullScal, invalid_sw) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, -1, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0.8, v, sv, 0.5, st0), + std::domain_error); // sw must be smaller than 2*(1-w) + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0.3, v, sv, 0.7, st0), + std::domain_error); // sw must be smaller than 2*w + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, INFTY, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, -INFTY, st0), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, NAN, st0), + std::domain_error); +} + +// st0 +TEST(mathPrimScalProbWienerFullScal, invalid_st0) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2; + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, -1), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, INFTY), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, -INFTY), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, NAN), + std::domain_error); +} + +TEST(mathPrimScalProbWienerFullPrecScal, valid) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, + st0 = 0.1; + EXPECT_NO_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, st0, 1e-4)); + rt = 5; + a = 1; + v = 1; + w = 0.5; + t0 = 0.0; + sv = 0.0; + sw = 0.0; + st0 = 0.0; + EXPECT_NO_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, st0, 1e-4)); +} + +// rt +TEST(mathPrimScalProbWienerFullPrecScal, invalid_rt) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(0, a, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(-1, a, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(INFTY, a, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(-INFTY, a, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(NAN, a, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); +} + +// a +TEST(mathPrimScalProbWienerFullPrecScal, invalid_a) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, 0, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, -1, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, INFTY, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, -INFTY, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, NAN, t0, w, v, sv, sw, st0, 1e-4), + std::domain_error); +} + +// v +TEST(mathPrimScalProbWienerFullPrecScal, invalid_v) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, + st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, INFTY, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, -INFTY, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, NAN, sv, sw, st0, 1e-4), + std::domain_error); +} + +// w +TEST(mathPrimScalProbWienerFullPrecScal, invalid_w) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, -0.1, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 1, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 1.1, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, INFTY, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, -INFTY, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, NAN, v, sv, sw, st0, 1e-4), + std::domain_error); +} + +// t0 +TEST(mathPrimScalProbWienerFullPrecScal, invalid_t0) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, sv = 0.2, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, 2, w, v, sv, sw, st0, 1e-4), + std::domain_error); // rt must be greater than t0 + EXPECT_THROW(wiener_full_lpdf(rt, a, -1, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, INFTY, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, -INFTY, w, v, sv, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, NAN, w, v, sv, sw, st0, 1e-4), + std::domain_error); +} + +// sv +TEST(mathPrimScalProbWienerFullPrecScal, invalid_sv) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sw = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, -1, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, INFTY, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, -INFTY, sw, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, NAN, sw, st0, 1e-4), + std::domain_error); +} + +// sw +TEST(mathPrimScalProbWienerFullPrecScal, invalid_sw) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, st0 = 0.1; + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, -1, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0.8, v, sv, 0.5, st0, 1e-4), + std::domain_error); // sw must be smaller than 2*(1-w) + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0.3, v, sv, 0.7, st0, 1e-4), + std::domain_error); // sw must be smaller than 2*w + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, INFTY, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, -INFTY, st0, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, NAN, st0, 1e-4), + std::domain_error); +} + +// st0 +TEST(mathPrimScalProbWienerFullPrecScal, invalid_st0) { + using stan::math::INFTY; + using stan::math::wiener_full_lpdf; + double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2; + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, -1, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, INFTY, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, -INFTY, 1e-4), + std::domain_error); + EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, NAN, 1e-4), + std::domain_error); +} From dc5e37a1eafdf8699790e1caf10c55ae9b2097e8 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 20 Oct 2023 21:14:18 +0200 Subject: [PATCH 116/179] prob test --- .../math/prim/prob/wiener_full_lpdf_test.cpp | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp index 6f23c4d5f4f..7498bb45338 100644 --- a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp @@ -309,3 +309,119 @@ TEST(mathPrimScalProbWienerFullPrecScal, invalid_st0) { EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, NAN, 1e-4), std::domain_error); } + + + +// CHECK THAT ALL VALID TYPES ARE ACCEPTED +template +void check_all_types(F& f, double value, double res, double deriv) { + // - f: Function with a single parameter exposed, all others have to be scalars + // - value: value to be used for the parameter + // - res: expected result of calling `f` with `value` + // - deriv: expected result of partial of f with respect to the parameter in `value` + // + // for testing vectors, `value` will be used twice, doubling the + // result and the derivative. + using stan::math::var; + double err_tol = 2e-6; + + // type double + EXPECT_NEAR(f(value), res, err_tol); + + +} + +TEST(ProbWienerFull, wiener_full_all) { + // tests all parameter types individually, with other parameters set to double + using stan::math::wiener_full_lpdf; +//Franzi: hier gibt es noch Probleme. Wenn die letzten beiden Spalten dabei sind, entsteht bei mir ein seg fault. Wenn die letzten beiden Spalten einzeln getestet werden (siehe unten), läuft der Test durch. + std::vector rt {1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector a {1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector v {1, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector w {0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; + std::vector t0 {0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0}; + std::vector sv {0.1, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0}; + std::vector sw {0.1, 0.1, 0, 0.1, 0, 0.1, 0, 0, 0}; + std::vector st0 {0.1, 0, 0.1, 0.1, 0, 0, 0.1, 0, 0}; +//Values for other parametrization with t0 as mean +/* std::vector result {-2.698058, -2.710348, -2.694359, -2.694535, -2.70665, -2.706812, -2.690835, -2.703112, -3.790072}; + std::vector drt {-5.436843, -5.436798, -5.436836, -5.434801, -5.436791, -5.434801, -5.434802, -5.434802, -5.434802}; + std::vector da { 6.350556, 6.395031, 6.349721, 6.352031, 6.394195, 6.396512, 6.351203, 6.395684, 8.369604}; + std::vector dv {-0.29233, -0.2967977, -0.2931514, -0.2946628, -0.297619, -0.2991696, -0.2954931, -0.3, -0.5}; + std::vector dw {-0.98876, -0.9887305, -0.9969633, -0.9916592, -0.9969335, -0.991674, -0.9998948, -0.9999097, -0.9999953}; + std::vector dt0 { 5.436843, 5.436798, 5.436836, 5.434801, 5.436791, 5.434801, 5.434802, 5.434802, 5.434802}; + std::vector dsv {-0.07021279, -0.07047449, -0.07024642, 0.0, -0.07050737, 0.0, 0.0, 0.0, 0.0}; + std::vector dsw {-0.07407336, -0.07407386, 0.0, -0.07410711, 0.0, -0.07410686, 0.0, 0.0, 0.0}; + std::vector dst0 { 0.2452021, 0.0, 0.2452016, 0.2449388, 0.0, 0.0, 0.244939, 0.0, 0.0}; + */ + std::vector result {-2.426204, -2.710348, -2.422505, -2.422795, -2.70665, -2.706812, -2.419095};//, -2.703112, -3.790072}; + std::vector drt {-5.437337, -5.436798, -5.437332, -5.434799, -5.436791, -5.434801, -5.434802, -5.434802, -5.434802}; + std::vector da { 5.857318, 6.395031, 5.856484, 5.858549, 6.394195, 6.396512, 5.857722, 6.395684, 8.369604}; + std::vector dv {-0.2428443, -0.2967977, -0.2436664, -0.2446629, -0.297619, -0.2991696, -0.2454931, -0.3, -0.5}; + std::vector dw {-0.9891369, -0.9887305, -0.9973428, -0.9915453, -0.9969335, -0.991674, -0.9997794, -0.9999097, -0.9999953}; + std::vector dt0 { 5.437337, 5.436798, 5.437332, 5.434799, 5.436791, 5.434801, 5.434802, 5.434802, 5.434802}; + std::vector dsv {-0.06793703, -0.07047449, -0.06797882, 0.0, -0.07050737, 0.0, 0.0, 0.0, 0.0}; + std::vector dsw {-0.07406705, -0.07407386, 0.0, -0.07410901, 0.0, -0.07410686, 0.0, 0.0, 0.0}; + std::vector dst0 { 2.963915, 0.0, 2.963912, 2.962338, 0.0, 0.0, 2.96234, 0.0, 0.0}; + + /* + //ohne diese letzten zwei Werte geht es oben und diese letzten zwei Werte allein gehen auch. Nur zusammen nicht ... + std::vector rt {1, 1}; + std::vector a {1, 1}; + std::vector v {1, 1}; + std::vector w {0.5, 0.5}; + std::vector t0 {0.2, 0}; + std::vector sv {0, 0}; + std::vector sw {0, 0}; + std::vector st0 {0, 0}; + + std::vector result {-2.703112, -3.790072}; + std::vector drt {-5.434802, -5.434802}; + std::vector da {6.395684, 8.369604}; + std::vector dv {-0.3, -0.5}; + std::vector dw {-0.9999097, -0.9999953}; + std::vector dt0 {5.434802, 5.434802}; + std::vector dsv {0.0, 0.0}; + std::vector dsw {0.0, 0.0}; + std::vector dst0 {0.0, 0.0}; + */ + + + for (int i = 0; i < result.size(); i++) { + // rt + auto f_rt = [=](auto value) {return wiener_full_lpdf(value, a[i], v[i], w[i], t0[i], sv[i], sw[i], st0[i]);}; + check_all_types(f_rt, rt[i], result[i], drt[i]); + EXPECT_NEAR(f_rt(rt[i]), result[i], err_tol); + + // type var with derivative + var value_var = value; + var result_var = f(value_var); + result_var.grad(); + EXPECT_NEAR(value_of(result_var), res, err_tol); + EXPECT_NEAR(value_var.adj(), deriv, err_tol); + // a + auto f_a = [=](auto value) {return wiener_full_lpdf(rt[i], value, v[i], w[i], t0[i], sv[i], sw[i], st0[i]);}; + check_all_types(f_a, a[i], result[i], da[i]); + // v + auto f_v = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], value, w[i], t0[i], sv[i], sw[i], st0[i]);}; + check_all_types(f_v, v[i], result[i], dv[i]); + // w + auto f_w = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], value, t0[i], sv[i], sw[i], st0[i]);}; + check_all_types(f_w, w[i], result[i], dw[i]); + // t0 + auto f_t0 = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], w[i], value, sv[i], sw[i], st0[i]);}; + check_all_types(f_t0, t0[i], result[i], dt0[i]); + // sv + auto f_sv = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], w[i], t0[i], value, sw[i], st0[i]);}; + check_all_types(f_sv, sv[i], result[i], dsv[i]); + // sw + auto f_sw = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], w[i], t0[i], sv[i], value, st0[i]);}; + check_all_types(f_sw, sw[i], result[i], dsw[i]); + // st0 + auto f_st0 = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], w[i], t0[i], sv[i], sw[i], value);}; + check_all_types(f_st0, st0[i], result[i], dst0[i]); + } + + + +} \ No newline at end of file From fe96d1863db9e4ba54bc8f1c1b7923021000978e Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 20 Oct 2023 22:17:35 +0200 Subject: [PATCH 117/179] expect_near in wiener_full --- .../math/prim/prob/wiener_full_lpdf_test.cpp | 207 ++++++++---------- 1 file changed, 96 insertions(+), 111 deletions(-) diff --git a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp index 7498bb45338..d777c810091 100644 --- a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp @@ -310,118 +310,103 @@ TEST(mathPrimScalProbWienerFullPrecScal, invalid_st0) { std::domain_error); } +TEST(mathPrimCorrectValues, wiener_full_lpdf) { + std::vector y_vec = {2, 3, 4, 5, 6, 7, 8, 8.85, 8.9, 9, 1}; + std::vector a_vec + = {2.0, 2.0, 10.0, 4.0, 10.0, 1.0, 3.0, 1.7, 2.4, 11.0, 1.5}; + std::vector v_vec + = {2.0, 2.0, 4.0, 3.0, -3.0, 1.0, -1.0, -7.3, -4.9, 4.5, 3}; + std::vector w_vec = {.1, 0.5, .8, 0.7, .1, .9, .7, .92, .9, .12, 0.5}; + std::vector t0_vec + = {1e-9, 0.01, .01, .01, .01, .01, .01, .01, .01, .01, 0.1}; + std::vector sv_vec = {0, 0.2, 0, 0, .2, .2, 0, .7, 0, .7, 0.5}; + std::vector sw_vec = {0, 0, .1, 0, .1, 0, .1, .01, 0, .1, 0.2}; + std::vector st0_vec + = {0, 0, 0, 0.007, 0, .007, .007, .009, .009, .009, 0}; + std::vector true_dens + = {-4.28564747866615, -7.52379235146909, -26.1551056209248, + -22.1939134892089, -50.0587553794834, -37.2817263586318, + -10.5428662079438, -61.5915905674246, -117.238967959795, + -12.5788594249676, -3.1448097740735}; + std::vector true_grad_y + = {-3.22509339523307, -2.91155058614589, -8.21331631900955, + -4.82948967379739, -1.50069056428102, -5.25831601347426, + -1.04831896413742, -2.67457492096193, -12.8617364931501, + -1.12047317491985, -5.68799957241344}; + std::vector true_grad_a = { + 3.25018678924105, 3.59980430191399, 0.876602303160642, 1.2215517888504, + -3.02928674030948, 67.0322498959921, 1.95334514374631, 16.4642201959135, + 5.02038145619773, 0.688439187670968, 2.63200041459657}; + std::vector true_grad_t0 + = {3.22509339523307, 2.91155058614589, 8.21331631900955, 4.82948967379739, + 1.50069056428102, 5.25831601347426, 1.04831896413742, 2.67457492096193, + 12.8617364931501, 1.12047317491985, 5.68799957241344}; + std::vector true_grad_w + = {5.67120184517318, -3.64396221090076, -38.7775057146792, + -14.1837930137393, -34.5869239580708, -10.4535345681946, + 0.679597983582904, -9.93144540834201, 2.09117200953597, + -6.0858540417876, -3.74870310978083}; + std::vector true_grad_v = { + -2.199999998, -4.44801714898178, -13.6940602985224, -13.7593709622169, + 21.5540563802381, -5.38233555673517, 8.88475440789056, 12.1280680728793, + 43.7785246930371, -5.68143495684294, -1.57639220567218}; + std::vector true_grad_sv = {0, + 3.42285198319565, + 0, + 0, + 91.9551438876654, + 4.70180879974639, + 0, + 101.80250964211, + 0, + 21.4332628706595, + 0.877556017134384}; + std::vector true_grad_sw = {0, + 0, + 10.1052188867058, + 0, + 8.72398, + 0, + -0.122807217815892, + -0.0506322723373748, + 0, + -0.0704990526706635, + 0.0827817310725268}; + std::vector true_grad_st0 = {0, + 0, + 0, + 2.42836139121338, + 0, + 2.64529825657625, + 0.524800556172613, + 1.34278261179603, + 6.55490874737353, + 0.561295838843035, + 0}; -// CHECK THAT ALL VALID TYPES ARE ACCEPTED -template -void check_all_types(F& f, double value, double res, double deriv) { - // - f: Function with a single parameter exposed, all others have to be scalars - // - value: value to be used for the parameter - // - res: expected result of calling `f` with `value` - // - deriv: expected result of partial of f with respect to the parameter in `value` - // - // for testing vectors, `value` will be used twice, doubling the - // result and the derivative. using stan::math::var; - double err_tol = 2e-6; - - // type double - EXPECT_NEAR(f(value), res, err_tol); - - -} - -TEST(ProbWienerFull, wiener_full_all) { - // tests all parameter types individually, with other parameters set to double - using stan::math::wiener_full_lpdf; -//Franzi: hier gibt es noch Probleme. Wenn die letzten beiden Spalten dabei sind, entsteht bei mir ein seg fault. Wenn die letzten beiden Spalten einzeln getestet werden (siehe unten), läuft der Test durch. - std::vector rt {1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector a {1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector v {1, 1, 1, 1, 1, 1, 1, 1, 1}; - std::vector w {0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; - std::vector t0 {0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0}; - std::vector sv {0.1, 0.1, 0.1, 0, 0.1, 0, 0, 0, 0}; - std::vector sw {0.1, 0.1, 0, 0.1, 0, 0.1, 0, 0, 0}; - std::vector st0 {0.1, 0, 0.1, 0.1, 0, 0, 0.1, 0, 0}; -//Values for other parametrization with t0 as mean -/* std::vector result {-2.698058, -2.710348, -2.694359, -2.694535, -2.70665, -2.706812, -2.690835, -2.703112, -3.790072}; - std::vector drt {-5.436843, -5.436798, -5.436836, -5.434801, -5.436791, -5.434801, -5.434802, -5.434802, -5.434802}; - std::vector da { 6.350556, 6.395031, 6.349721, 6.352031, 6.394195, 6.396512, 6.351203, 6.395684, 8.369604}; - std::vector dv {-0.29233, -0.2967977, -0.2931514, -0.2946628, -0.297619, -0.2991696, -0.2954931, -0.3, -0.5}; - std::vector dw {-0.98876, -0.9887305, -0.9969633, -0.9916592, -0.9969335, -0.991674, -0.9998948, -0.9999097, -0.9999953}; - std::vector dt0 { 5.436843, 5.436798, 5.436836, 5.434801, 5.436791, 5.434801, 5.434802, 5.434802, 5.434802}; - std::vector dsv {-0.07021279, -0.07047449, -0.07024642, 0.0, -0.07050737, 0.0, 0.0, 0.0, 0.0}; - std::vector dsw {-0.07407336, -0.07407386, 0.0, -0.07410711, 0.0, -0.07410686, 0.0, 0.0, 0.0}; - std::vector dst0 { 0.2452021, 0.0, 0.2452016, 0.2449388, 0.0, 0.0, 0.244939, 0.0, 0.0}; - */ - std::vector result {-2.426204, -2.710348, -2.422505, -2.422795, -2.70665, -2.706812, -2.419095};//, -2.703112, -3.790072}; - std::vector drt {-5.437337, -5.436798, -5.437332, -5.434799, -5.436791, -5.434801, -5.434802, -5.434802, -5.434802}; - std::vector da { 5.857318, 6.395031, 5.856484, 5.858549, 6.394195, 6.396512, 5.857722, 6.395684, 8.369604}; - std::vector dv {-0.2428443, -0.2967977, -0.2436664, -0.2446629, -0.297619, -0.2991696, -0.2454931, -0.3, -0.5}; - std::vector dw {-0.9891369, -0.9887305, -0.9973428, -0.9915453, -0.9969335, -0.991674, -0.9997794, -0.9999097, -0.9999953}; - std::vector dt0 { 5.437337, 5.436798, 5.437332, 5.434799, 5.436791, 5.434801, 5.434802, 5.434802, 5.434802}; - std::vector dsv {-0.06793703, -0.07047449, -0.06797882, 0.0, -0.07050737, 0.0, 0.0, 0.0, 0.0}; - std::vector dsw {-0.07406705, -0.07407386, 0.0, -0.07410901, 0.0, -0.07410686, 0.0, 0.0, 0.0}; - std::vector dst0 { 2.963915, 0.0, 2.963912, 2.962338, 0.0, 0.0, 2.96234, 0.0, 0.0}; - - /* - //ohne diese letzten zwei Werte geht es oben und diese letzten zwei Werte allein gehen auch. Nur zusammen nicht ... - std::vector rt {1, 1}; - std::vector a {1, 1}; - std::vector v {1, 1}; - std::vector w {0.5, 0.5}; - std::vector t0 {0.2, 0}; - std::vector sv {0, 0}; - std::vector sw {0, 0}; - std::vector st0 {0, 0}; - - std::vector result {-2.703112, -3.790072}; - std::vector drt {-5.434802, -5.434802}; - std::vector da {6.395684, 8.369604}; - std::vector dv {-0.3, -0.5}; - std::vector dw {-0.9999097, -0.9999953}; - std::vector dt0 {5.434802, 5.434802}; - std::vector dsv {0.0, 0.0}; - std::vector dsw {0.0, 0.0}; - std::vector dst0 {0.0, 0.0}; - */ - - - for (int i = 0; i < result.size(); i++) { - // rt - auto f_rt = [=](auto value) {return wiener_full_lpdf(value, a[i], v[i], w[i], t0[i], sv[i], sw[i], st0[i]);}; - check_all_types(f_rt, rt[i], result[i], drt[i]); - EXPECT_NEAR(f_rt(rt[i]), result[i], err_tol); - - // type var with derivative - var value_var = value; - var result_var = f(value_var); - result_var.grad(); - EXPECT_NEAR(value_of(result_var), res, err_tol); - EXPECT_NEAR(value_var.adj(), deriv, err_tol); - // a - auto f_a = [=](auto value) {return wiener_full_lpdf(rt[i], value, v[i], w[i], t0[i], sv[i], sw[i], st0[i]);}; - check_all_types(f_a, a[i], result[i], da[i]); - // v - auto f_v = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], value, w[i], t0[i], sv[i], sw[i], st0[i]);}; - check_all_types(f_v, v[i], result[i], dv[i]); - // w - auto f_w = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], value, t0[i], sv[i], sw[i], st0[i]);}; - check_all_types(f_w, w[i], result[i], dw[i]); - // t0 - auto f_t0 = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], w[i], value, sv[i], sw[i], st0[i]);}; - check_all_types(f_t0, t0[i], result[i], dt0[i]); - // sv - auto f_sv = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], w[i], t0[i], value, sw[i], st0[i]);}; - check_all_types(f_sv, sv[i], result[i], dsv[i]); - // sw - auto f_sw = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], w[i], t0[i], sv[i], value, st0[i]);}; - check_all_types(f_sw, sw[i], result[i], dsw[i]); - // st0 - auto f_st0 = [=](auto value) {return wiener_full_lpdf(rt[i], a[i], v[i], w[i], t0[i], sv[i], sw[i], value);}; - check_all_types(f_st0, st0[i], result[i], dst0[i]); + double err_tol_dens = 1e-6; + double err_tol = 1e-4; + for (int i = 0; i < y_vec.size(); i++) { + var y = y_vec[i]; + var a = a_vec[i]; + var t0 = t0_vec[i]; + var w = w_vec[i]; + var v = v_vec[i]; + var sv = sv_vec[i]; + var sw = sw_vec[i]; + var st0 = st0_vec[i]; + var dens = stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + dens.grad(); + EXPECT_NEAR(dens.val(), true_dens[i], err_tol_dens); + EXPECT_NEAR(y.adj(), true_grad_y[i], err_tol); + EXPECT_NEAR(a.adj(), true_grad_a[i], err_tol); + EXPECT_NEAR(t0.adj(), true_grad_t0[i], err_tol); + EXPECT_NEAR(w.adj(), true_grad_w[i], err_tol); + EXPECT_NEAR(v.adj(), true_grad_v[i], err_tol); + EXPECT_NEAR(sv.adj(), true_grad_sv[i], err_tol); + EXPECT_NEAR(sw.adj(), true_grad_sw[i], err_tol); + EXPECT_NEAR(st0.adj(), true_grad_st0[i], err_tol); } - - - -} \ No newline at end of file +} From 6e469ef910d76a60a3e357780824f0175a19711d Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Mon, 23 Oct 2023 09:23:02 +0200 Subject: [PATCH 118/179] test test --- .../mix/prob/wiener5_lpdf_x_test_test.cpp | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp diff --git a/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp new file mode 100644 index 00000000000..9ba4961ec5f --- /dev/null +++ b/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp @@ -0,0 +1,20 @@ +#include +#include + +TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { + auto f_a_v_sv = [](const auto& y, const auto& t0, const auto& w) { + return [&y, &t0, &w](const auto& a, const auto& v, const auto& sv) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_a_v_sv(y, t0, w), a, v, sv); +} + From f76d4cddd1f330ff690cd4a34013c9835f49a1d0 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Mon, 23 Oct 2023 09:27:19 +0200 Subject: [PATCH 119/179] test --- .../mix/prob/wiener5_lpdf_x_test_test.cpp | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp index 9ba4961ec5f..22d0b07a841 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp @@ -1,7 +1,7 @@ #include #include -TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { +/*TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { auto f_a_v_sv = [](const auto& y, const auto& t0, const auto& w) { return [&y, &t0, &w](const auto& a, const auto& v, const auto& sv) { return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); @@ -16,5 +16,23 @@ TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { double sv = 0.2; stan::test::expect_ad(f_a_v_sv(y, t0, w), a, v, sv); +}*/ + +TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { + auto f_a_v_sv = [](const auto& y, const auto& t0, const auto& w, const auto& sv) { + return [&y, &t0, &w, &sv](const auto& a, const auto& v) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_a_v_sv(y, t0, w, sv), a, v); } + From 141c044b7f907e2ad1e185fb6951e37e49eeb9af Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Mon, 23 Oct 2023 09:28:44 +0200 Subject: [PATCH 120/179] test --- .../mix/prob/wiener5_lpdf_x_test_test.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp index 22d0b07a841..41847cd465f 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp @@ -18,7 +18,7 @@ stan::test::expect_ad(f_a_v_sv(y, t0, w), a, v, sv); }*/ -TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { +/*TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { auto f_a_v_sv = [](const auto& y, const auto& t0, const auto& w, const auto& sv) { return [&y, &t0, &w, &sv](const auto& a, const auto& v) { return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); @@ -33,6 +33,23 @@ TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { double sv = 0.2; stan::test::expect_ad(f_a_v_sv(y, t0, w, sv), a, v); +}*/ + +TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { + auto f_a_v_sv = [](const auto& y, const auto& t0, const auto& w, const auto& v, const auto& sv) { + return [&y, &t0, &w, &v, &sv](const auto& a) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_a_v_sv(y, t0, w, v, sv), a); } From b6373e054adec4d11f79d858633eaf4ba823ea0a Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Mon, 23 Oct 2023 10:56:17 +0200 Subject: [PATCH 121/179] some changes --- stan/math/prim/prob/wiener5_lpdf.hpp | 199 +++++++++++------- .../mix/prob/wiener5_lpdf_x_test_test.cpp | 78 ++++++- 2 files changed, 190 insertions(+), 87 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 6eb0ff302cf..b6d7697e30d 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -17,9 +17,10 @@ namespace internal { * @param sv The inter-trial variability of the drift rate * @return 'error_term' term */ -template +template inline Scalar wiener5_compute_error_term(T_y&& y, T_a&& a, T_v&& v_value, - T_w&& w_value, T_sv&& sv) noexcept { + T_w&& w_value, T_sv&& sv) noexcept { const Scalar w = 1.0 - w_value; const Scalar v = -v_value; const Scalar sv_sqr = square(sv); @@ -49,9 +50,11 @@ inline Scalar wiener5_compute_error_term(T_y&& y, T_a&& a, T_v&& v_value, * @param sv The inter-trial variability of the drift rate * @return 'density_part_one' term */ -template +template inline Scalar wiener5_density_part_one(T_y&& y, T_a&& a, T_v_value&& v_value, - T_w_value&& w_value, T_sv&& sv) noexcept { + T_w_value&& w_value, + T_sv&& sv) noexcept { const Scalar w = 1.0 - w_value; const Scalar v = -v_value; const Scalar sv_sqr = square(sv); @@ -92,7 +95,8 @@ inline Scalar wiener5_density_part_one(T_y&& y, T_a&& a, T_v_value&& v_value, * @param error The error tolerance * @return 'n_terms_small_t' term */ -template +template inline Scalar wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, Scalar error) noexcept { const Scalar two_error = 2.0 * error; @@ -131,7 +135,8 @@ inline Scalar wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, * @param error The error tolerance * @return 'n_terms_large_t' term */ -template +template inline Scalar wiener5_n_terms_largel_t(T_y&& y, T_a&& a, T_w_value&& w_value, Scalar error) noexcept { const Scalar two_error = 2.0 * error; @@ -179,9 +184,9 @@ inline Scalar wiener5_n_terms_largel_t(T_y&& y, T_a&& a, T_w_value&& w_value, * @param n_terms_large_t The n_terms_large_t term * @return 'result' sum and its sign */ -template -inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, +template +inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, T_nsmall&& n_terms_small_t, T_nlarge&& n_terms_large_t) noexcept { const Scalar y_asq = y / square(a); @@ -200,7 +205,7 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, const Scalar mult = Density ? 1 : 3; const Scalar offset = GradW ? y_asq : 0; const Scalar sqrt_offset = sqrt(offset); - for (auto k = n_terms_small_t; k >= 1; k--) { + for (auto k = n_terms_small_t; k >= 1; k--) { const Scalar wp2k = w + 2.0 * k; const Scalar wm2k = w - 2.0 * k; int wp2k_sign = (wp2k > sqrt_offset) ? 1 : -1; @@ -221,7 +226,7 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, prev_sign = current_sign; } Scalar new_val = GradW ? log(fabs(square(w) - offset)) - square(w) * scaling - : mult * log(w) - square(w) * scaling; + : mult * log(w) - square(w) * scaling; int new_val_sign = GradW ? (w > sqrt_offset ? 1 : -1) : (new_val > 0 ? 1 : -1); int factor_sign = GradW ? 1 : -1; @@ -235,7 +240,7 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, } else if (GradW) { mult = 2; } - for (auto k = n_terms_large_t; k >= 1; k--) { + for (auto k = n_terms_large_t; k >= 1; k--) { const Scalar pi_k = k * pi(); const Scalar check = (GradW) ? cos(pi_k * w) : sin(pi_k * w); int check_sign = sign(check); @@ -264,9 +269,9 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, * @param err The log error tolerance * @return density */ -template -inline Scalar wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, +template +inline Scalar wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, const T_w& w_value, const T_sv& sv, Scalar err = log(1e-12)) noexcept { const Scalar error_term @@ -277,11 +282,12 @@ inline Scalar wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, const Scalar n_terms_large_t = wiener5_n_terms_largel_t(y, a, w_value, error); - auto res = wiener5_log_sum_exp(y, a, w_value, n_terms_small_t, - n_terms_large_t).first; + auto res = wiener5_log_sum_exp( + y, a, w_value, n_terms_small_t, n_terms_large_t) + .first; if (2 * n_terms_small_t <= n_terms_large_t) { Scalar log_density = error_term - 0.5 * LOG_TWO - LOG_SQRT_PI - - 1.5 * (log(y) - 2 * log(a)) + res; + - 1.5 * (log(y) - 2 * log(a)) + res; return NaturalScale ? exp(log_density) : log_density; } else { Scalar log_density = error_term + res + LOG_PI; @@ -307,13 +313,14 @@ inline Scalar wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, template inline Scalar wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, - const T_w& w_value, const T_sv& sv, Scalar err = log(1e-12)) noexcept { + const T_w& w_value, const T_sv& sv, + Scalar err = log(1e-12)) noexcept { const Scalar two_log_a = 2 * log(a); const Scalar log_y_asq = log(y) - two_log_a; const Scalar error_term = wiener5_compute_error_term(y, a, v_value, w_value, sv); - const Scalar density_part_one - = wiener5_density_part_one(y, a, v_value, w_value, sv); + const Scalar density_part_one = wiener5_density_part_one( + y, a, v_value, w_value, sv); const Scalar error = (err - error_term) + two_log_a; const Scalar n_terms_small_t @@ -322,13 +329,14 @@ inline Scalar wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, = wiener5_n_terms_largel_t(y, a, w_value, error); Scalar result; int newsign; - std::forward_as_tuple(result, newsign) = wiener5_log_sum_exp( - y, a, w_value, n_terms_small_t, n_terms_large_t); + std::forward_as_tuple(result, newsign) + = wiener5_log_sum_exp( + y, a, w_value, n_terms_small_t, n_terms_large_t); const Scalar error_log_density - = log(fmax(fabs(density_part_one - 1.5 / y), fabs(density_part_one))); - const Scalar log_density - = wiener5_density(y, a, v_value, w_value, sv, err - error_log_density); + = log(fmax(fabs(density_part_one - 1.5 / y), fabs(density_part_one))); + const Scalar log_density = wiener5_density( + y, a, v_value, w_value, sv, err - error_log_density); Scalar ans; if (2 * n_terms_small_t < n_terms_large_t) { ans = density_part_one - 1.5 / y @@ -362,13 +370,14 @@ inline Scalar wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, template inline Scalar wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, - const T_w& w_value, const T_sv& sv, Scalar err = log(1e-12)) noexcept { + const T_w& w_value, const T_sv& sv, + Scalar err = log(1e-12)) noexcept { const Scalar two_log_a = 2 * log(a); const Scalar log_y_asq = log(y) - two_log_a; const Scalar error_term = wiener5_compute_error_term(y, a, v_value, w_value, sv); - const Scalar density_part_one - = wiener5_density_part_one(y, a, v_value, w_value, sv); + const Scalar density_part_one = wiener5_density_part_one( + y, a, v_value, w_value, sv); const Scalar error = err - error_term + 3 * log(a) - log(y) - LOG_TWO; const Scalar n_terms_small_t @@ -377,13 +386,14 @@ inline Scalar wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, = wiener5_n_terms_largel_t(y, a, w_value, error); Scalar result; int newsign; - std::forward_as_tuple(result, newsign) = wiener5_log_sum_exp( - y, a, w_value, n_terms_small_t, n_terms_large_t); + std::forward_as_tuple(result, newsign) + = wiener5_log_sum_exp( + y, a, w_value, n_terms_small_t, n_terms_large_t); const Scalar error_log_density = log( - fmax(fabs(density_part_one + 1.0 / a), fabs(density_part_one - 2.0 / a))); - const Scalar log_density - = wiener5_density(y, a, v_value, w_value, sv, err - error_log_density); + fmax(fabs(density_part_one + 1.0 / a), fabs(density_part_one - 2.0 / a))); + const Scalar log_density = wiener5_density( + y, a, v_value, w_value, sv, err - error_log_density); Scalar ans; if (2 * n_terms_small_t < n_terms_large_t) { ans = density_part_one + 1.0 / a @@ -417,12 +427,15 @@ inline Scalar wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, template inline Scalar wiener5_grad_v(const T_y& y, const T_a& a, const T_v& v_value, - const T_w& w_value, const T_sv& sv, Scalar err = log(1e-12)) noexcept { + const T_w& w_value, const T_sv& sv, + Scalar err = log(1e-12)) noexcept { Scalar ans = (a * (1 - w_value) - v_value * y); if (sv != 0) { ans /= 1 + square(sv) * y; } - return WrtLog ? ans * wiener5_density(y, a, v_value, w_value, sv, err) + return WrtLog ? ans + * wiener5_density(y, a, v_value, w_value, + sv, err) : ans; } @@ -444,13 +457,15 @@ inline Scalar wiener5_grad_v(const T_y& y, const T_a& a, const T_v& v_value, template inline Scalar wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, - const T_w& w_value, const T_sv& sv, Scalar err = log(1e-12)) noexcept { + const T_w& w_value, const T_sv& sv, + Scalar err = log(1e-12)) noexcept { const Scalar two_log_a = 2 * log(a); const Scalar log_y_asq = log(y) - two_log_a; const Scalar error_term = wiener5_compute_error_term(y, a, v_value, w_value, sv); const Scalar density_part_one - = wiener5_density_part_one(y, a, v_value, w_value, sv); + = wiener5_density_part_one(y, a, v_value, w_value, + sv); const Scalar error = (err - error_term); const Scalar n_terms_small_t @@ -459,11 +474,12 @@ inline Scalar wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, = wiener5_n_terms_largel_t(y, a, w_value, error); Scalar result; int newsign; - std::forward_as_tuple(result, newsign) = wiener5_log_sum_exp( - y, a, w_value, n_terms_small_t, n_terms_large_t); + std::forward_as_tuple(result, newsign) + = wiener5_log_sum_exp(y, a, w_value, n_terms_small_t, + n_terms_large_t); - const Scalar log_density = wiener5_density(y, a, v_value, w_value, sv, - err - log(fabs(density_part_one))); + const Scalar log_density = wiener5_density( + y, a, v_value, w_value, sv, err - log(fabs(density_part_one))); Scalar ans; if (2 * n_terms_small_t < n_terms_large_t) { ans = -(density_part_one @@ -504,7 +520,9 @@ inline Scalar wiener5_grad_sv(const T_y& y, const T_a& a, const T_v& v_value, const Scalar t2 = (square(a * w) + 2 * a * v * w * y + square(v * y)) / square(one_plus_svsqr_y); const Scalar ans = sv * (t1 + t2); - return WrtLog ? ans * wiener5_density(y, a, v_value, w_value, sv, err) + return WrtLog ? ans + * wiener5_density(y, a, v_value, w_value, + sv, err) : ans; } @@ -541,14 +559,15 @@ inline void assign_err(std::tuple& args_tuple, Scalar err) { * @param args_tuple Tuple of arguments to pass to functor * @param log_result Whether the function result is already on the log-scale */ -template +template Scalar estimate_with_err_check(const F& functor, Scalar err, ArgsTupleT&&... args_tuple) { Scalar result = functor(args_tuple...); Scalar log_fabs_result = LogResult ? log(fabs(result)) : fabs(result); if (log_fabs_result < err) { - log_fabs_result = is_inf(log_fabs_result) ? 0 : log_fabs_result; + log_fabs_result = is_inf(log_fabs_result) ? 0 : log_fabs_result; auto err_args_tuple = std::make_tuple(args_tuple...); const Scalar new_error = GradW7 ? err + log_fabs_result + LOG_TWO : err + log_fabs_result; @@ -582,27 +601,26 @@ Scalar estimate_with_err_check(const F& functor, Scalar err, * the specified arguments for upper boundary responses */ template > + typename T_w, typename T_v, typename T_sv, + typename ReturnT = return_type_t> inline return_type_t wiener5_lpdf( const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, const T_sv& sv, const ReturnT& precision_derivatives) { + + using T_partials_return = partials_return_t; + + if (!include_summand::value) { + return static_cast(0.0); + } + using T_y_ref = ref_type_if_t::value, T_y>; using T_a_ref = ref_type_if_t::value, T_a>; using T_t0_ref = ref_type_if_t::value, T_t0>; using T_w_ref = ref_type_if_t::value, T_w>; using T_v_ref = ref_type_if_t::value, T_v>; using T_sv_ref = ref_type_if_t::value, T_sv>; - - using T_partials_return = partials_return_t; static constexpr const char* function_name = "wiener5_lpdf"; - if (size_zero(y, a, t0, w, v, sv)) { - return 0; - } - if (!include_summand::value) { - return 0; - } check_consistent_sizes(function_name, "Random variable", y, "Boundary separation", a, "Drift rate", v, @@ -615,7 +633,7 @@ inline return_type_t wiener5_lpdf( T_w_ref w_ref = w; T_v_ref v_ref = v; T_sv_ref sv_ref = sv; - + decltype(auto) y_val = to_ref(as_value_column_array_or_scalar(y_ref)); decltype(auto) a_val = to_ref(as_value_column_array_or_scalar(a_ref)); decltype(auto) v_val = to_ref(as_value_column_array_or_scalar(v_ref)); @@ -633,8 +651,6 @@ inline return_type_t wiener5_lpdf( sv_val); check_finite(function_name, "Inter-trial variability in drift rate", sv_val); - - check_positive_finite(function_name, "Random variable", value_of(y_ref)); check_positive_finite(function_name, "Boundary separation", value_of(a_ref)); check_nonnegative(function_name, "Nondecision time", value_of(t0_ref)); @@ -646,8 +662,14 @@ inline return_type_t wiener5_lpdf( value_of(sv_ref)); check_finite(function_name, "Inter-trial variability in drift rate", value_of(sv_ref)); - + + if (size_zero(y, a, t0, w, v, sv)) { + return 0; + } const size_t N = max_size(y, a, t0, w, v, sv); + if (!N) { + return 0; + } scalar_seq_view y_vec(y_ref); scalar_seq_view a_vec(a_ref); @@ -671,8 +693,8 @@ inline return_type_t wiener5_lpdf( const T_partials_return log_error_derivative = log(precision_derivatives); const T_partials_return log_error_absolute = log(1e-12); T_partials_return log_density = 0.0; - operands_and_partials - ops_partials(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref); + auto ops_partials = make_partials_propagator(y_ref, a_ref, t0_ref, w_ref, + v_ref, sv_ref); static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; @@ -688,48 +710,63 @@ inline return_type_t wiener5_lpdf( const T_partials_return v_value = v_vec.val(i); const T_partials_return sv_value = sv_vec.val(i); - T_partials_return l_density = internal::estimate_with_err_check( - [&](auto&&... args) { return internal::wiener5_density(args...); }, - log_error_density - LOG_TWO, y_value - t0_value, a_value, v_value, w_value, - sv_value, log_error_absolute); - - log_density += l_density; + T_partials_return l_density = internal::estimate_with_err_check< + T_partials_return, 5, false, 0, false>( + [&](auto&&... args) { + return internal::wiener5_density(args...); + }, + log_error_density - LOG_TWO, y_value - t0_value, a_value, v_value, + w_value, sv_value, log_error_absolute); + + log_density += l_density; - const T_partials_return new_est_err = l_density + log_error_derivative - LOG_FOUR; + const T_partials_return new_est_err + = l_density + log_error_derivative - LOG_FOUR; // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 - const T_partials_return deriv_y = internal::estimate_with_err_check( - [&](auto&&... args) { return internal::wiener5_grad_t(args...); }, + const T_partials_return deriv_y = internal::estimate_with_err_check< + T_partials_return, 5, false, 0, true>( + [&](auto&&... args) { + return internal::wiener5_grad_t(args...); + }, new_est_err, y_value - t0_value, a_value, v_value, w_value, sv_value, log_error_absolute); // computation of derivatives and precision checks if (!is_constant_all::value) { - ops_partials.edge1_.partials_[i] = deriv_y; + partials<0>(ops_partials)[i] = deriv_y; } if (!is_constant_all::value) { - ops_partials.edge2_.partials_[i] = internal::estimate_with_err_check( - [&](auto&&... args) { return internal::wiener5_grad_a(args...); }, + partials<1>(ops_partials)[i] = internal::estimate_with_err_check< + T_partials_return, 5, false, 0, true>( + [&](auto&&... args) { + return internal::wiener5_grad_a(args...); + }, new_est_err, y_value - t0_value, a_value, v_value, w_value, sv_value, log_error_absolute); } if (!is_constant_all::value) { - ops_partials.edge3_.partials_[i] = -deriv_y; + partials<2>(ops_partials)[i] = -deriv_y; } if (!is_constant_all::value) { - ops_partials.edge4_.partials_[i] = internal::estimate_with_err_check( - [&](auto&&... args) { return internal::wiener5_grad_w(args...); }, + partials<3>(ops_partials)[i] = internal::estimate_with_err_check< + T_partials_return, 5, false, 0, true>( + [&](auto&&... args) { + return internal::wiener5_grad_w(args...); + }, new_est_err, y_value - t0_value, a_value, v_value, w_value, sv_value, log_error_absolute); } if (!is_constant_all::value) { - ops_partials.edge5_.partials_[i] = internal::wiener5_grad_v( - y_value - t0_value, a_value, v_value, w_value, sv_value); + partials<4>(ops_partials)[i] + = internal::wiener5_grad_v( + y_value - t0_value, a_value, v_value, w_value, sv_value); } if (!is_constant_all::value) { - ops_partials.edge6_.partials_[i] = internal::wiener5_grad_sv( - y_value - t0_value, a_value, v_value, w_value, sv_value); + partials<5>(ops_partials)[i] + = internal::wiener5_grad_sv( + y_value - t0_value, a_value, v_value, w_value, sv_value); } } // end for loop return ops_partials.build(log_density); diff --git a/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp index 41847cd465f..8a367fcc4c7 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp @@ -1,7 +1,7 @@ #include #include -/*TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { +/*TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { // error with grad_hessian() auto f_a_v_sv = [](const auto& y, const auto& t0, const auto& w) { return [&y, &t0, &w](const auto& a, const auto& v, const auto& sv) { return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); @@ -18,7 +18,7 @@ stan::test::expect_ad(f_a_v_sv(y, t0, w), a, v, sv); }*/ -/*TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { +/*TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { // error with grad_hessian() auto f_a_v_sv = [](const auto& y, const auto& t0, const auto& w, const auto& sv) { return [&y, &t0, &w, &sv](const auto& a, const auto& v) { return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); @@ -35,9 +35,26 @@ stan::test::expect_ad(f_a_v_sv(y, t0, w, sv), a, v); }*/ -TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { - auto f_a_v_sv = [](const auto& y, const auto& t0, const auto& w, const auto& v, const auto& sv) { - return [&y, &t0, &w, &v, &sv](const auto& a) { +/*TEST(mathMixScalFun_sv, wiener5_lpdf) { // runs successfully + auto f_sv = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { + return [&y, &a, &t0, &w, &v](const auto& sv) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_sv(y, a, t0, w, v), sv); +}*/ + +/*TEST(mathMixScalFun_v, wiener5_lpdf) { // runs successfully + auto f_v = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& sv) { + return [&y, &a, &t0, &w, &sv](const auto& v) { return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; @@ -49,7 +66,56 @@ TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { double v = 2.0; double sv = 0.2; - stan::test::expect_ad(f_a_v_sv(y, t0, w, v, sv), a); + stan::test::expect_ad(f_v(y, a, t0, w, sv), v); +}*/ + + +TEST(mathMixScalFun_y, wiener5_lpdf) { // error with grad_hessian() + auto f_y = [](const auto& a, const auto& t0, const auto& w, const auto& v, const auto& sv) { + return [&a, &t0, &w, &v, &sv](const auto& y) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + stan::test::expect_ad(f_y(a, t0, w, v, sv), y); } +/*TEST(mathMixScalFun_a, wiener5_lpdf) { // error with grad_hessian() + auto f_a = [](const auto& y, const auto& t0, const auto& w, const auto& v, const auto& sv) { + return [&y, &t0, &w, &v, &sv](const auto& a) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + + stan::test::expect_ad(f_a(y, t0, w, v, sv), a); +}*/ + +/*TEST(mathMixScalFun_w, wiener5_lpdf) { + auto f_w = [](const auto& y, const auto& a, const auto& t0, const auto& v, const auto& sv) { + return [&y, &a, &t0, &v, &sv](const auto& w) { + return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + }; + }; + + double y = 1.0; + double a = 2.0; + double t0 = 0.2; + double w = 0.5; + double v = 2.0; + double sv = 0.2; + stan::test::expect_ad(f_w(y, a, t0, v, sv), w); +}*/ \ No newline at end of file From 853a46a4e17a64cdabc000d815e395b0940c9cba Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Mon, 23 Oct 2023 15:06:02 +0200 Subject: [PATCH 122/179] two small changes --- stan/math/prim/prob/wiener5_lpdf.hpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index b6d7697e30d..803e086ae32 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -610,7 +610,7 @@ inline return_type_t wiener5_lpdf( using T_partials_return = partials_return_t; if (!include_summand::value) { - return static_cast(0.0); + return 0; } using T_y_ref = ref_type_if_t::value, T_y>; @@ -650,18 +650,6 @@ inline return_type_t wiener5_lpdf( check_nonnegative(function_name, "Inter-trial variability in drift rate", sv_val); check_finite(function_name, "Inter-trial variability in drift rate", sv_val); - - check_positive_finite(function_name, "Random variable", value_of(y_ref)); - check_positive_finite(function_name, "Boundary separation", value_of(a_ref)); - check_nonnegative(function_name, "Nondecision time", value_of(t0_ref)); - check_finite(function_name, "Nondecision time", value_of(t0_ref)); - check_less(function_name, "A-priori bias", value_of(w_ref), 1); - check_greater(function_name, "A-priori bias", value_of(w_ref), 0); - check_finite(function_name, "Drift rate", value_of(v_ref)); - check_nonnegative(function_name, "Inter-trial variability in drift rate", - value_of(sv_ref)); - check_finite(function_name, "Inter-trial variability in drift rate", - value_of(sv_ref)); if (size_zero(y, a, t0, w, v, sv)) { return 0; From 99e9c708f5aed8bd5efe119c378566273e6e3594 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Mon, 23 Oct 2023 15:28:12 +0200 Subject: [PATCH 123/179] new comment --- test/unit/math/prim/prob/wiener_full_lpdf_test.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp index d777c810091..4243bd11f2c 100644 --- a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp @@ -311,6 +311,9 @@ TEST(mathPrimScalProbWienerFullPrecScal, invalid_st0) { } TEST(mathPrimCorrectValues, wiener_full_lpdf) { +/* Test concrete values. True values are computed in R using the R-package + * WienR and the function WienerPDF. + */ std::vector y_vec = {2, 3, 4, 5, 6, 7, 8, 8.85, 8.9, 9, 1}; std::vector a_vec = {2.0, 2.0, 10.0, 4.0, 10.0, 1.0, 3.0, 1.7, 2.4, 11.0, 1.5}; From a859ae7b2b55aad9b6a7b852529c0237845e2312 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 23 Oct 2023 10:01:39 -0400 Subject: [PATCH 124/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/functor/hcubature.hpp | 71 ++++---- stan/math/prim/prob/wiener5_lpdf.hpp | 11 +- stan/math/prim/prob/wiener_full_lpdf.hpp | 153 ++++++++++-------- .../mix/prob/wiener5_lpdf_x_test_test.cpp | 36 ++--- .../math/prim/prob/wiener_full_lpdf_test.cpp | 6 +- 5 files changed, 154 insertions(+), 123 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index dd97b92bbfa..1ee5f310d8e 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -71,8 +71,9 @@ static constexpr std::array gwd7{ * @param p number of elements * @param x x-th lexicographically ordered set */ -inline Eigen::Matrix combination(Eigen::Matrix& c, const int dim, - const int p, const int x) { +inline Eigen::Matrix combination(Eigen::Matrix& c, + const int dim, const int p, + const int x) { int r = 0; int k = 0; c[0] = 0; @@ -107,7 +108,8 @@ inline Eigen::Matrix combination(Eigen::Matrix& c, const * @param dim dimension */ template -inline Eigen::Matrix combos(const int k, const Scalar lambda, const int dim) { +inline Eigen::Matrix combos(const int k, const Scalar lambda, + const int dim) { Eigen::Matrix c(k); const auto choose_dimk = choose(dim, k); Eigen::Matrix p = Eigen::MatrixXd::Zero(dim, choose_dimk); @@ -131,13 +133,16 @@ inline Eigen::Matrix combos(const int k, const Scalar lambda, co * @param dim dimension */ template -inline Eigen::Matrix signcombos(const int k, const Scalar lambda, - const int dim) { -// Eigen::VectorXi c(k); +inline Eigen::Matrix signcombos(const int k, + const Scalar lambda, + const int dim) { + // Eigen::VectorXi c(k); Eigen::Matrix c(k); const auto choose_dimk = choose(dim, k); -// Eigen::MatrixXd p = Eigen::MatrixXd::Zero(dim, choose_dimk * std::pow(2, k)); - Eigen::Matrix p = Eigen::MatrixXd::Zero(dim, choose_dimk * std::pow(2, k)); + // Eigen::MatrixXd p = Eigen::MatrixXd::Zero(dim, choose_dimk * std::pow(2, + // k)); + Eigen::Matrix p + = Eigen::MatrixXd::Zero(dim, choose_dimk * std::pow(2, k)); int current_col = 0; for (int i = 1; i != choose_dimk + 1; i++) { c = combination(c, dim, k, i); @@ -239,8 +244,8 @@ std::pair gauss_kronrod(const F& integrand, const Scalar a, * @param dim dimension */ template -inline std::tuple>, Eigen::Matrix, - Eigen::Matrix> +inline std::tuple>, + Eigen::Matrix, Eigen::Matrix> make_GenzMalik(const int dim) { std::vector> points(4); Eigen::Matrix weights(5); @@ -287,10 +292,12 @@ make_GenzMalik(const int dim) { */ template std::tuple integrate_GenzMalik( - const F& integrand, const std::vector>& points, - const Eigen::Matrix& weights, const Eigen::Matrix& weights_low_deg, - const int dim, const Eigen::Matrix& a, const Eigen::Matrix& b, - const ParsTupleT& pars_tuple) { + const F& integrand, + const std::vector>& points, + const Eigen::Matrix& weights, + const Eigen::Matrix& weights_low_deg, const int dim, + const Eigen::Matrix& a, + const Eigen::Matrix& b, const ParsTupleT& pars_tuple) { using eig_vec = Eigen::Matrix; Eigen::Matrix c = Eigen::VectorXd::Zero(dim); for (auto i = 0; i != dim; i++) { @@ -482,9 +489,9 @@ struct Box { */ template Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, - const Eigen::Matrix& a, const Eigen::Matrix& b, - const int max_eval, const Scalar reqAbsError, - const Scalar reqRelError) { + const Eigen::Matrix& a, + const Eigen::Matrix& b, const int max_eval, + const Scalar reqAbsError, const Scalar reqRelError) { using eig_vec = Eigen::Matrix; const Scalar maxEval = max_eval <= 0 ? 1000000 : max_eval; Scalar result; @@ -527,39 +534,41 @@ Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, err_vec.push_back(err); while ((numevals < maxEval) && (error > fmax(reqRelError * fabs(val), reqAbsError)) - && fabs(val) < INFTY){ + && fabs(val) < INFTY) { auto err_idx = get_largest_box_idx(err_vec); auto&& box = ms[err_idx]; Scalar w = (box.b_[box.kdiv_] - box.a_[box.kdiv_]) / 2; - eig_vec ma - = Eigen::Map(box.a_.data(), box.a_.size()); + eig_vec ma = Eigen::Map(box.a_.data(), box.a_.size()); ma[box.kdiv_] += w; - eig_vec mb - = Eigen::Map(box.b_.data(), box.b_.size()); + eig_vec mb = Eigen::Map(box.b_.data(), box.b_.size()); mb[box.kdiv_] -= w; int kdivide_1{0}; int kdivide_2{0}; Scalar result_1; - Scalar result_2; - Scalar err_1; - Scalar err_2; + Scalar result_2; + Scalar err_1; + Scalar err_2; if (dim == 1) { std::tie(result_1, err_1) = internal::gauss_kronrod(integrand, ma[0], box.b_[0], pars); std::tie(result_2, err_2) = internal::gauss_kronrod(integrand, box.a_[0], mb[0], pars); } else { - std::tie(result_1, err_1, kdivide_1) = internal::integrate_GenzMalik( - integrand, p, w_five, wd_four, dim, ma, box.b_, pars); - std::tie(result_2, err_2, kdivide_2) = internal::integrate_GenzMalik( - integrand, p, w_five, wd_four, dim, box.a_, mb, pars); + std::tie(result_1, err_1, kdivide_1) + = internal::integrate_GenzMalik(integrand, p, w_five, wd_four, + dim, ma, box.b_, pars); + std::tie(result_2, err_2, kdivide_2) + = internal::integrate_GenzMalik(integrand, p, w_five, wd_four, + dim, box.a_, mb, pars); } - internal::Box box1(std::move(ma), std::move(box.b_), result_1, kdivide_1); - internal::Box box2(std::move(box.a_), std::move(mb), result_2, kdivide_2); + internal::Box box1(std::move(ma), std::move(box.b_), result_1, + kdivide_1); + internal::Box box2(std::move(box.a_), std::move(mb), result_2, + kdivide_2); result += result_1 + result_2 - box.I_; err += err_1 + err_2 - err_vec[err_idx]; ms[err_idx].I_ = 0; diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 803e086ae32..86ca5f6447d 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -606,13 +606,12 @@ template wiener5_lpdf( const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, const T_sv& sv, const ReturnT& precision_derivatives) { - using T_partials_return = partials_return_t; - + if (!include_summand::value) { return 0; } - + using T_y_ref = ref_type_if_t::value, T_y>; using T_a_ref = ref_type_if_t::value, T_a>; using T_t0_ref = ref_type_if_t::value, T_t0>; @@ -650,7 +649,7 @@ inline return_type_t wiener5_lpdf( check_nonnegative(function_name, "Inter-trial variability in drift rate", sv_val); check_finite(function_name, "Inter-trial variability in drift rate", sv_val); - + if (size_zero(y, a, t0, w, v, sv)) { return 0; } @@ -681,8 +680,8 @@ inline return_type_t wiener5_lpdf( const T_partials_return log_error_derivative = log(precision_derivatives); const T_partials_return log_error_absolute = log(1e-12); T_partials_return log_density = 0.0; - auto ops_partials = make_partials_propagator(y_ref, a_ref, t0_ref, w_ref, - v_ref, sv_ref); + auto ops_partials + = make_partials_propagator(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref); static constexpr double LOG_FOUR = LOG_TWO + LOG_TWO; diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 2cd296f043a..3d7f71da695 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -21,16 +21,19 @@ namespace internal { * @param log_error The log error tolerance * @return Gradient w.r.t. sw */ -template > -inline ReturnT wiener7_grad_sw(const T_y& y, const T_a& a, const T_v& v, const T_w& w, const T_sv& sv, - const T_sw& sw, Scalar log_error) { +template > +inline ReturnT wiener7_grad_sw(const T_y& y, const T_a& a, const T_v& v, + const T_w& w, const T_sv& sv, const T_sw& sw, + Scalar log_error) { Scalar low = w - sw / 2.0; low = (0 > low) ? 0 : low; Scalar high = w + sw / 2.0; high = (1 < high) ? 1 : high; - const Scalar lower_value = wiener5_density(y, a, v, low, sv, log_error); + const Scalar lower_value + = wiener5_density(y, a, v, low, sv, log_error); const Scalar upper_value = wiener5_density(y, a, v, high, sv, log_error); return 0.5 * (lower_value + upper_value) / sw; @@ -59,12 +62,13 @@ inline ReturnT wiener7_grad_sw(const T_y& y, const T_a& a, const T_v& v, const T * @param log_error The log error tolerance * @return Functor applied to arguments */ -template * = nullptr> +template * = nullptr> inline Scalar conditionally_grad_sw(const F& functor, Scalar y_diff, Scalar a, Scalar v, Scalar w, Scalar sv, Scalar sw, Scalar log_error) { return functor(y_diff, a, v, w, sv, log_error); -} +} /** * Helper function for agnostically calling wiener5 functions @@ -90,12 +94,13 @@ inline Scalar conditionally_grad_sw(const F& functor, Scalar y_diff, Scalar a, * @param log_error The log error tolerance * @return Functor applied to arguments */ -template * = nullptr> +template * = nullptr> inline Scalar conditionally_grad_sw(const F& functor, Scalar y_diff, Scalar a, Scalar v, Scalar w, Scalar sv, Scalar sw, Scalar log_error) { return functor(y_diff, a, v, w, sv, sw, log_error); -} +} /** * Implementation function for preparing arguments and functor to be passed @@ -112,30 +117,32 @@ inline Scalar conditionally_grad_sw(const F& functor, Scalar y_diff, Scalar a, * @param args Additional arguments to be passed to the hcubature function * @return Wiener7 density or gradient calculated by integration */ -template > +template > ReturnT wiener7_integrate(const Wiener7FunctorT& wiener7_functor, - Scalar hcubature_err, TArgs&&... args) { - const auto wiener7_integrand_impl - = [&](auto&& x, Scalar y, Scalar a, Scalar v, Scalar w, Scalar t0, - Scalar sv, Scalar sw, Scalar st0, Scalar log_error) { - scalar_seq_view x_vec(x); - const Scalar sw_val = GradSW ? 0 : sw; - const Scalar new_w = (sw_val!= 0) ? w + sw_val * (x_vec[0] - 0.5) : w; - const Scalar new_t0 = (sw_val!= 0) ? ((st0 != 0) ? t0 + st0 * x_vec[1] : t0) - : ((st0 != 0) ? t0 + st0 * x_vec[0] : t0); - if (y - new_t0 <= 0) { - return static_cast(0.0); - } else { - return conditionally_grad_sw(wiener7_functor, y - new_t0, a, - v, new_w, sv, sw, - log_error); - } - }; + Scalar hcubature_err, TArgs&&... args) { + const auto wiener7_integrand_impl = + [&](auto&& x, Scalar y, Scalar a, Scalar v, Scalar w, Scalar t0, + Scalar sv, Scalar sw, Scalar st0, Scalar log_error) { + scalar_seq_view x_vec(x); + const Scalar sw_val = GradSW ? 0 : sw; + const Scalar new_w = (sw_val != 0) ? w + sw_val * (x_vec[0] - 0.5) : w; + const Scalar new_t0 = (sw_val != 0) + ? ((st0 != 0) ? t0 + st0 * x_vec[1] : t0) + : ((st0 != 0) ? t0 + st0 * x_vec[0] : t0); + if (y - new_t0 <= 0) { + return static_cast(0.0); + } else { + return conditionally_grad_sw( + wiener7_functor, y - new_t0, a, v, new_w, sv, sw, log_error); + } + }; const auto functor = [&](auto&&... int_args) { return hcubature(wiener7_integrand_impl, int_args...); }; - return estimate_with_err_check(functor, hcubature_err, args...); + return estimate_with_err_check( + functor, hcubature_err, args...); } } // namespace internal @@ -306,8 +313,9 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, using T_sv_ref = ref_type_if_t::value, T_sv>; using T_sw_ref = ref_type_if_t::value, T_sw>; using T_st0_ref = ref_type_if_t::value, T_st0>; - - using T_partials_return = partials_return_t; + + using T_partials_return + = partials_return_t; static constexpr const char* function_name = "wiener_full_lpdf"; check_consistent_sizes(function_name, "Random variable", y, @@ -398,7 +406,8 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } } - const T_partials_return log_error_density = log(1e-6); // precision for density + const T_partials_return log_error_density + = log(1e-6); // precision for density const T_partials_return error_bound = precision_derivatives; // precision for // derivatives (controllable by user) const T_partials_return log_error_derivative = log(error_bound); @@ -416,8 +425,9 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, for (size_t i = 0; i < N; i++) { if (sw_vec[i] == 0 && st0_vec[i] == 0) { result - = result + wiener5_lpdf(y_vec[i], a_vec[i], t0_vec[i], w_vec[i], - v_vec[i], sv_vec[i], precision_derivatives); + = result + + wiener5_lpdf(y_vec[i], a_vec[i], t0_vec[i], w_vec[i], + v_vec[i], sv_vec[i], precision_derivatives); continue; } const T_partials_return y_value = y_vec.val(i); @@ -434,22 +444,26 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, "(Inter-trial variability in nondecision time)", dim); - Eigen::Matrix xmin = Eigen::VectorXd::Zero(dim); + Eigen::Matrix xmin = Eigen::VectorXd::Zero(dim); Eigen::Matrix xmax = Eigen::VectorXd::Ones(dim); if (st0_value != 0) { xmax[dim - 1] = fmin(1.0, (y_value - t0_value) / st0_value); } - - T_partials_return hcubature_err = log_error_absolute - log_error_density + LOG_TWO + 1; - const auto params - = std::make_tuple(y_value, a_value, v_value, w_value, t0_value, sv_value, sw_value, - st0_value, log_error_absolute - LOG_TWO); - T_partials_return density = internal::wiener7_integrate( - [&](auto&&... args) { - return internal::wiener5_density(args...); - }, - hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, - absolute_error_hcubature, relative_error_hcubature / 2); + + T_partials_return hcubature_err + = log_error_absolute - log_error_density + LOG_TWO + 1; + const auto params = std::make_tuple(y_value, a_value, v_value, w_value, + t0_value, sv_value, sw_value, st0_value, + log_error_absolute - LOG_TWO); + T_partials_return density + = internal::wiener7_integrate( + [&](auto&&... args) { + return internal::wiener5_density( + args...); + }, + hcubature_err, params, dim, xmin, xmax, + maximal_evaluations_hcubature, absolute_error_hcubature, + relative_error_hcubature / 2); log_density += log(density); hcubature_err = log_error_absolute - log_error_derivative @@ -476,8 +490,10 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, partials<1>(ops_partials)[i] = internal::wiener7_integrate( [&](auto&&... args) { - return internal::wiener5_grad_a(args...); + return internal::wiener5_grad_a< + true, T_partials_return, T_partials_return, + T_partials_return, T_partials_return, T_partials_return, + T_partials_return>(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, @@ -525,20 +541,23 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, partials<6>(ops_partials)[i] = 0; } else { if (st0_value == 0) { - derivative = internal::estimate_with_err_check( + derivative = internal::estimate_with_err_check( [&](auto&&... args) { return internal::wiener7_grad_sw(args...); }, - hcubature_err, y_value - t0_value, a_value, v_value, w_value, sv_value, - sw_value, log_error_absolute - LOG_TWO); + hcubature_err, y_value - t0_value, a_value, v_value, w_value, + sv_value, sw_value, log_error_absolute - LOG_TWO); } else { - derivative = internal::wiener7_integrate( - [&](auto&&... args) { - return internal::wiener7_grad_sw(args...); - }, - hcubature_err, params, 1, xmin, xmax, - maximal_evaluations_hcubature, absolute_error_hcubature, - relative_error_hcubature / 2); + derivative + = internal::wiener7_integrate( + [&](auto&&... args) { + return internal::wiener7_grad_sw( + args...); + }, + hcubature_err, params, 1, xmin, xmax, + maximal_evaluations_hcubature, absolute_error_hcubature, + relative_error_hcubature / 2); } partials<6>(ops_partials)[i] = derivative / density - 1 / sw_value; } @@ -552,19 +571,23 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } else { const T_partials_return t0_st0 = t0_value + st0_value; if (sw_value == 0) { - f = internal::estimate_with_err_check( + f = internal::estimate_with_err_check( [&](auto&&... args) { - return internal::wiener5_density(args...); + return internal::wiener5_density( + args...); }, - log_error_derivative + log(st0_value), y_value - t0_st0, a_value, v_value, - w_value, sv_value, log_error_absolute - LOG_TWO); + log_error_derivative + log(st0_value), y_value - t0_st0, a_value, + v_value, w_value, sv_value, log_error_absolute - LOG_TWO); } else { const T_partials_return new_error = log_error_absolute - LOG_TWO; - const auto& params_st = std::make_tuple( - y_value, a_value, v_value, w_value, t0_st0, sv_value, sw_value, 0, new_error); + const auto& params_st + = std::make_tuple(y_value, a_value, v_value, w_value, t0_st0, + sv_value, sw_value, 0, new_error); f = internal::wiener7_integrate( [&](auto&&... args) { - return internal::wiener5_density(args...); + return internal::wiener5_density( + args...); }, hcubature_err, params_st, 1, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, diff --git a/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp index 8a367fcc4c7..c3686d2eb98 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp @@ -19,9 +19,9 @@ }*/ /*TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { // error with grad_hessian() - auto f_a_v_sv = [](const auto& y, const auto& t0, const auto& w, const auto& sv) { - return [&y, &t0, &w, &sv](const auto& a, const auto& v) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + auto f_a_v_sv = [](const auto& y, const auto& t0, const auto& w, const auto& +sv) { return [&y, &t0, &w, &sv](const auto& a, const auto& v) { return +stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; @@ -36,9 +36,9 @@ }*/ /*TEST(mathMixScalFun_sv, wiener5_lpdf) { // runs successfully - auto f_sv = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { - return [&y, &a, &t0, &w, &v](const auto& sv) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + auto f_sv = [](const auto& y, const auto& a, const auto& t0, const auto& w, +const auto& v) { return [&y, &a, &t0, &w, &v](const auto& sv) { return +stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; @@ -53,9 +53,9 @@ }*/ /*TEST(mathMixScalFun_v, wiener5_lpdf) { // runs successfully - auto f_v = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& sv) { - return [&y, &a, &t0, &w, &sv](const auto& v) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + auto f_v = [](const auto& y, const auto& a, const auto& t0, const auto& w, +const auto& sv) { return [&y, &a, &t0, &w, &sv](const auto& v) { return +stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; @@ -69,9 +69,9 @@ stan::test::expect_ad(f_v(y, a, t0, w, sv), v); }*/ - -TEST(mathMixScalFun_y, wiener5_lpdf) { // error with grad_hessian() - auto f_y = [](const auto& a, const auto& t0, const auto& w, const auto& v, const auto& sv) { +TEST(mathMixScalFun_y, wiener5_lpdf) { // error with grad_hessian() + auto f_y = [](const auto& a, const auto& t0, const auto& w, const auto& v, + const auto& sv) { return [&a, &t0, &w, &v, &sv](const auto& y) { return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); }; @@ -87,9 +87,9 @@ TEST(mathMixScalFun_y, wiener5_lpdf) { // error with grad_hessian() } /*TEST(mathMixScalFun_a, wiener5_lpdf) { // error with grad_hessian() - auto f_a = [](const auto& y, const auto& t0, const auto& w, const auto& v, const auto& sv) { - return [&y, &t0, &w, &v, &sv](const auto& a) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + auto f_a = [](const auto& y, const auto& t0, const auto& w, const auto& v, +const auto& sv) { return [&y, &t0, &w, &v, &sv](const auto& a) { return +stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; @@ -104,9 +104,9 @@ TEST(mathMixScalFun_y, wiener5_lpdf) { // error with grad_hessian() }*/ /*TEST(mathMixScalFun_w, wiener5_lpdf) { - auto f_w = [](const auto& y, const auto& a, const auto& t0, const auto& v, const auto& sv) { - return [&y, &a, &t0, &v, &sv](const auto& w) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + auto f_w = [](const auto& y, const auto& a, const auto& t0, const auto& v, +const auto& sv) { return [&y, &a, &t0, &v, &sv](const auto& w) { return +stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; diff --git a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp index 4243bd11f2c..aa731db9924 100644 --- a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp @@ -311,9 +311,9 @@ TEST(mathPrimScalProbWienerFullPrecScal, invalid_st0) { } TEST(mathPrimCorrectValues, wiener_full_lpdf) { -/* Test concrete values. True values are computed in R using the R-package - * WienR and the function WienerPDF. - */ + /* Test concrete values. True values are computed in R using the R-package + * WienR and the function WienerPDF. + */ std::vector y_vec = {2, 3, 4, 5, 6, 7, 8, 8.85, 8.9, 9, 1}; std::vector a_vec = {2.0, 2.0, 10.0, 4.0, 10.0, 1.0, 3.0, 1.7, 2.4, 11.0, 1.5}; From 7f1b0a7a0095763b1e87452d6f378ad6e5a7d452 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Mon, 23 Oct 2023 16:12:02 +0200 Subject: [PATCH 125/179] add new line, delete test test --- .../mix/prob/wiener5_lpdf_x_test_test.cpp | 121 ------------------ .../math/mix/prob/wiener_full_lpdf_0_test.cpp | 2 +- 2 files changed, 1 insertion(+), 122 deletions(-) delete mode 100644 test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp diff --git a/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp deleted file mode 100644 index c3686d2eb98..00000000000 --- a/test/unit/math/mix/prob/wiener5_lpdf_x_test_test.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include -#include - -/*TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { // error with grad_hessian() - auto f_a_v_sv = [](const auto& y, const auto& t0, const auto& w) { - return [&y, &t0, &w](const auto& a, const auto& v, const auto& sv) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); - }; - }; - - double y = 1.0; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - - stan::test::expect_ad(f_a_v_sv(y, t0, w), a, v, sv); -}*/ - -/*TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { // error with grad_hessian() - auto f_a_v_sv = [](const auto& y, const auto& t0, const auto& w, const auto& -sv) { return [&y, &t0, &w, &sv](const auto& a, const auto& v) { return -stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); - }; - }; - - double y = 1.0; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - - stan::test::expect_ad(f_a_v_sv(y, t0, w, sv), a, v); -}*/ - -/*TEST(mathMixScalFun_sv, wiener5_lpdf) { // runs successfully - auto f_sv = [](const auto& y, const auto& a, const auto& t0, const auto& w, -const auto& v) { return [&y, &a, &t0, &w, &v](const auto& sv) { return -stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); - }; - }; - - double y = 1.0; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - - stan::test::expect_ad(f_sv(y, a, t0, w, v), sv); -}*/ - -/*TEST(mathMixScalFun_v, wiener5_lpdf) { // runs successfully - auto f_v = [](const auto& y, const auto& a, const auto& t0, const auto& w, -const auto& sv) { return [&y, &a, &t0, &w, &sv](const auto& v) { return -stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); - }; - }; - - double y = 1.0; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - - stan::test::expect_ad(f_v(y, a, t0, w, sv), v); -}*/ - -TEST(mathMixScalFun_y, wiener5_lpdf) { // error with grad_hessian() - auto f_y = [](const auto& a, const auto& t0, const auto& w, const auto& v, - const auto& sv) { - return [&a, &t0, &w, &v, &sv](const auto& y) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); - }; - }; - - double y = 1.0; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_y(a, t0, w, v, sv), y); -} - -/*TEST(mathMixScalFun_a, wiener5_lpdf) { // error with grad_hessian() - auto f_a = [](const auto& y, const auto& t0, const auto& w, const auto& v, -const auto& sv) { return [&y, &t0, &w, &v, &sv](const auto& a) { return -stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); - }; - }; - - double y = 1.0; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - - stan::test::expect_ad(f_a(y, t0, w, v, sv), a); -}*/ - -/*TEST(mathMixScalFun_w, wiener5_lpdf) { - auto f_w = [](const auto& y, const auto& a, const auto& t0, const auto& v, -const auto& sv) { return [&y, &a, &t0, &v, &sv](const auto& w) { return -stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); - }; - }; - - double y = 1.0; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - - stan::test::expect_ad(f_w(y, a, t0, v, sv), w); -}*/ \ No newline at end of file diff --git a/test/unit/math/mix/prob/wiener_full_lpdf_0_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_0_test.cpp index 6cc014138a3..d57a612173e 100644 --- a/test/unit/math/mix/prob/wiener_full_lpdf_0_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_lpdf_0_test.cpp @@ -59,4 +59,4 @@ TEST(mathMixScalFun_y_a_t0, wiener_full_lpdf) { double st0 = 0.3; stan::test::expect_ad(f_y_a_t0(w, v, sv, sw, st0), y, a, t0); -} \ No newline at end of file +} From 2adc7ac36bcef362271fbc82e355a0fbfd5c46fc Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Wed, 20 Dec 2023 13:45:12 +0100 Subject: [PATCH 126/179] all tests successful --- stan/math/prim/prob/wiener5_lpdf.hpp | 172 ++++++++++++------ .../math/mix/prob/wiener5_lpdf_1_test.cpp | 10 +- .../math/mix/prob/wiener5_lpdf_2_test.cpp | 10 +- .../math/mix/prob/wiener5_lpdf_3_test.cpp | 10 +- .../math/mix/prob/wiener5_lpdf_4_test.cpp | 10 +- 5 files changed, 133 insertions(+), 79 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 86ca5f6447d..59b6799d17a 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -115,10 +115,11 @@ inline Scalar wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_error)); } const Scalar arg_mult = (Density || GradW) ? 1 : 3; - const Scalar arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - + const Scalar arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + const Scalar n_2 = (arg > 0) ? GradW ? 0.5 * (sqrt(arg) + w) : 0.5 * (sqrt(arg) - w) : n_1; + return ceil(fmax(n_1, n_2)); } @@ -137,7 +138,7 @@ inline Scalar wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, */ template -inline Scalar wiener5_n_terms_largel_t(T_y&& y, T_a&& a, T_w_value&& w_value, +inline Scalar wiener5_n_terms_large_t(T_y&& y, T_a&& a, T_w_value&& w_value, Scalar error) noexcept { const Scalar two_error = 2.0 * error; const Scalar y_asq = y / square(a); @@ -189,68 +190,119 @@ template ; + ret_t current_val; + int current_sign; + if (small_n_terms_small_t) { + ret_t fplus = NEGATIVE_INFTY; + ret_t fminus = NEGATIVE_INFTY; + const auto mult = Density ? 1 : 3; + const auto offset = GradW ? y_asq : 0; + for (auto k = n_terms_small_t; k >= 1; k--) { - const Scalar wp2k = w + 2.0 * k; - const Scalar wm2k = w - 2.0 * k; - int wp2k_sign = (wp2k > sqrt_offset) ? 1 : -1; - int wm2k_sign = (wm2k > sqrt_offset) ? 1 : -1; - Scalar wp2k_quant - = GradW ? log(fabs((square(wp2k) - offset))) - square(wp2k) * scaling - : mult * log(wp2k_sign * wp2k) - square(wp2k) * scaling; - Scalar wm2k_quant - = GradW ? log(fabs((square(wm2k) - offset))) - square(wm2k) * scaling - : mult * log(wm2k_sign * wm2k) - square(wm2k) * scaling; - Scalar k_term; - int k_sign; - std::forward_as_tuple(k_term, k_sign) = log_sum_exp_signed( - wm2k_quant, -1 * wm2k_sign, wp2k_quant, wp2k_sign); - std::forward_as_tuple(current_val, current_sign) - = log_sum_exp_signed(k_term, k_sign, prev_val, prev_sign); - prev_val = current_val; - prev_sign = current_sign; + const auto wp2k = w + 2.0 * k; + const auto wm2k = w - 2.0 * k; + if (GradW) { + const auto sqwp2k_mo = square(wp2k) - offset; + if (sqwp2k_mo > 0) { + const auto wp2k_quant = log(sqwp2k_mo) - square(wp2k) * scaling; + fplus = log_sum_exp(fplus, wp2k_quant); + } else if (sqwp2k_mo < 0) { + const auto wp2k_quant = log(-sqwp2k_mo) - square(wp2k) * scaling; + fminus = log_sum_exp(fminus, wp2k_quant); + } + } else { + const auto wp2k_quant = mult * log(wp2k) - square(wp2k) * scaling; + fplus = log_sum_exp(fplus, wp2k_quant); + } + + if (GradW) { + const auto sqwm2k_mo = square(wm2k) - offset; + if (sqwm2k_mo > 0) { + const auto wm2k_quant = log(sqwm2k_mo) - square(wm2k) * scaling; + fplus = log_sum_exp(fplus, wm2k_quant); + } else if (sqwm2k_mo < 0) { + const auto wm2k_quant = log(-sqwm2k_mo) - square(wm2k) * scaling; + fminus = log_sum_exp(fminus, wm2k_quant); + } + } else { + const auto wm2k_quant = mult * log(-wm2k) - square(wm2k) * scaling; + if (fminus <= NEGATIVE_INFTY) { + fminus = wm2k_quant; + } else if (wm2k_quant <= NEGATIVE_INFTY) { + fminus = fminus; + } else if (fminus > wm2k_quant) { + fminus = fminus + log1p(exp(wm2k_quant - fminus)); + } else { + fminus = wm2k_quant + log1p(exp(fminus - wm2k_quant)); + } + } } - Scalar new_val = GradW ? log(fabs(square(w) - offset)) - square(w) * scaling - : mult * log(w) - square(w) * scaling; - int new_val_sign - = GradW ? (w > sqrt_offset ? 1 : -1) : (new_val > 0 ? 1 : -1); - int factor_sign = GradW ? 1 : -1; - std::forward_as_tuple(current_val, current_sign) - = log_sum_exp_signed(new_val, factor_sign * new_val_sign, current_val, - factor_sign * current_sign); - } else { - Scalar mult = 3; + + if (GradW) { + const auto sqw_mo = square(w) - offset; + if (sqw_mo > 0) { + const auto new_val = log(sqw_mo) - square(w) * scaling; + fplus = log_sum_exp(fplus, new_val); + } else if (sqw_mo < 0) { + const auto new_val = log(-sqw_mo) - square(w) * scaling; + fminus = log_sum_exp(fminus, new_val); + } + } else { + const auto new_val = mult * log(w) - square(w) * scaling; + fplus = log_sum_exp(fplus, new_val); + } + + if (fplus == NEGATIVE_INFTY) { + current_val = fminus; + } else if (fminus == NEGATIVE_INFTY) { + current_val = fplus; + } else if (fplus > fminus) { + current_val = log_diff_exp(fplus, fminus); + } else if (fplus < fminus) { + current_val = log_diff_exp(fminus, fplus); + } else { + current_val = NEGATIVE_INFTY; + } + current_sign = (fplus < fminus)? -1: 1; + + } else { // for large t + auto mult = 3; if (Density) { mult = 1; } else if (GradW) { mult = 2; } + ret_t fplus = NEGATIVE_INFTY; + ret_t fminus = NEGATIVE_INFTY; for (auto k = n_terms_large_t; k >= 1; k--) { - const Scalar pi_k = k * pi(); - const Scalar check = (GradW) ? cos(pi_k * w) : sin(pi_k * w); - int check_sign = sign(check); - Scalar n_terms_large_t_quant - = mult * log(k) - square(pi_k) * scaling + log(fabs(check)); - std::forward_as_tuple(current_val, current_sign) = log_sum_exp_signed( - prev_val, prev_sign, n_terms_large_t_quant, check_sign); - prev_val = current_val; - prev_sign = current_sign; - } + const auto pi_k = k * pi(); + const auto check = (GradW) ? cos(pi_k * w) : sin(pi_k * w); + if (check > 0) { + fplus = log_sum_exp(fplus, mult*log(k) - square(pi_k) * scaling + log(check)); + } else if ((GradW && check < 0) || !GradW) { + fminus = log_sum_exp(fminus, mult*log(k) - square(pi_k) * scaling + log(-check)); + } + } + if (fplus == NEGATIVE_INFTY) { + current_val = fminus; + } else if (fminus == NEGATIVE_INFTY) { + current_val = fplus; + } else if (fplus > fminus) { + current_val = log_diff_exp(fplus, fminus); + } else if (fplus < fminus) { + current_val = log_diff_exp(fminus, fplus); + } else { + current_val = NEGATIVE_INFTY; + } + current_sign = (fplus < fminus)? -1: 1; } return std::make_pair(current_val, current_sign); } @@ -280,7 +332,7 @@ inline Scalar wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, const Scalar n_terms_small_t = wiener5_n_terms_small_t(y, a, w_value, error); const Scalar n_terms_large_t - = wiener5_n_terms_largel_t(y, a, w_value, error); + = wiener5_n_terms_large_t(y, a, w_value, error); auto res = wiener5_log_sum_exp( y, a, w_value, n_terms_small_t, n_terms_large_t) @@ -326,7 +378,7 @@ inline Scalar wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, const Scalar n_terms_small_t = wiener5_n_terms_small_t(y, a, w_value, error); const Scalar n_terms_large_t - = wiener5_n_terms_largel_t(y, a, w_value, error); + = wiener5_n_terms_large_t(y, a, w_value, error); Scalar result; int newsign; std::forward_as_tuple(result, newsign) @@ -383,7 +435,7 @@ inline Scalar wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, const Scalar n_terms_small_t = wiener5_n_terms_small_t(y, a, w_value, error); const Scalar n_terms_large_t - = wiener5_n_terms_largel_t(y, a, w_value, error); + = wiener5_n_terms_large_t(y, a, w_value, error); Scalar result; int newsign; std::forward_as_tuple(result, newsign) @@ -471,7 +523,7 @@ inline Scalar wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, const Scalar n_terms_small_t = wiener5_n_terms_small_t(y, a, w_value, error); const Scalar n_terms_large_t - = wiener5_n_terms_largel_t(y, a, w_value, error); + = wiener5_n_terms_large_t(y, a, w_value, error); Scalar result; int newsign; std::forward_as_tuple(result, newsign) @@ -493,6 +545,7 @@ inline Scalar wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, return WrtLog ? ans * exp(log_density) : ans; } + /** * Calculate the derivative of the wiener5 density w.r.t. 'sv' * @@ -690,13 +743,14 @@ inline return_type_t wiener5_lpdf( // Calculate 4-parameter model without inter-trial variabilities (if // sv_vec[i] == 0) or 5-parameter model with inter-trial variability in // drift rate (if sv_vec[i] != 0) + const T_partials_return y_value = y_vec.val(i); const T_partials_return a_value = a_vec.val(i); const T_partials_return t0_value = t0_vec.val(i); const T_partials_return w_value = w_vec.val(i); const T_partials_return v_value = v_vec.val(i); const T_partials_return sv_value = sv_vec.val(i); - + T_partials_return l_density = internal::estimate_with_err_check< T_partials_return, 5, false, 0, false>( [&](auto&&... args) { diff --git a/test/unit/math/mix/prob/wiener5_lpdf_1_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_1_test.cpp index e0883262018..de915668db9 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_1_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_1_test.cpp @@ -9,7 +9,7 @@ TEST(mathMixScalFun_y_a_t0, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; @@ -26,7 +26,7 @@ TEST(mathMixScalFun_y_a_w, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; @@ -43,7 +43,7 @@ TEST(mathMixScalFun_y_a_v, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; @@ -60,7 +60,7 @@ TEST(mathMixScalFun_y_a_sv, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; @@ -77,7 +77,7 @@ TEST(mathMixScalFun_y_t0_w, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; diff --git a/test/unit/math/mix/prob/wiener5_lpdf_2_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_2_test.cpp index 0f58d804358..5684003bd52 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_2_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_2_test.cpp @@ -9,7 +9,7 @@ TEST(mathMixScalFun_y_t0_v, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; @@ -26,7 +26,7 @@ TEST(mathMixScalFun_y_t0_sv, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; @@ -43,7 +43,7 @@ TEST(mathMixScalFun_y_w_v, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; @@ -60,7 +60,7 @@ TEST(mathMixScalFun_y_w_sv, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; @@ -77,7 +77,7 @@ TEST(mathMixScalFun_y_v_sv, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; diff --git a/test/unit/math/mix/prob/wiener5_lpdf_3_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_3_test.cpp index 8bc6cbd13c4..9fb75a88bea 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_3_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_3_test.cpp @@ -9,7 +9,7 @@ TEST(mathMixScalFun_a_t0_w, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; @@ -26,7 +26,7 @@ TEST(mathMixScalFun_a_t0_v, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; @@ -43,7 +43,7 @@ TEST(mathMixScalFun_a_t0_sv, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; @@ -60,7 +60,7 @@ TEST(mathMixScalFun_a_w_v, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; @@ -77,7 +77,7 @@ TEST(mathMixScalFun_a_w_sv, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; diff --git a/test/unit/math/mix/prob/wiener5_lpdf_4_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_4_test.cpp index 345e6d1dec7..e24640d6a54 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_4_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_4_test.cpp @@ -9,7 +9,7 @@ TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; @@ -26,7 +26,7 @@ TEST(mathMixScalFun_t0_w_v, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; @@ -43,7 +43,7 @@ TEST(mathMixScalFun_t0_w_sv, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; @@ -60,7 +60,7 @@ TEST(mathMixScalFun_t0_v_sv, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; @@ -77,7 +77,7 @@ TEST(mathMixScalFun_w_v_sv, wiener5_lpdf) { }; double y = 1.0; - double a = 2.0; + double a = 2.5; double t0 = 0.2; double w = 0.5; double v = 2.0; From 940ce638158c614e21e38f66a04954e553b36b5c Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 20 Dec 2023 07:46:25 -0500 Subject: [PATCH 127/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 201 ++++++++++++++------------- 1 file changed, 101 insertions(+), 100 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 59b6799d17a..435c20969a2 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -115,8 +115,8 @@ inline Scalar wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_error)); } const Scalar arg_mult = (Density || GradW) ? 1 : 3; - const Scalar arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - + const Scalar arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + const Scalar n_2 = (arg > 0) ? GradW ? 0.5 * (sqrt(arg) + w) : 0.5 * (sqrt(arg) - w) : n_1; @@ -139,7 +139,7 @@ inline Scalar wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, template inline Scalar wiener5_n_terms_large_t(T_y&& y, T_a&& a, T_w_value&& w_value, - Scalar error) noexcept { + Scalar error) noexcept { const Scalar two_error = 2.0 * error; const Scalar y_asq = y / square(a); const Scalar two_log_a = 2 * log(a); @@ -197,112 +197,114 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, : (2 * n_terms_small_t < n_terms_large_t); const auto scaling = small_n_terms_small_t ? inv(2.0 * y_asq) : y_asq / 2.0; - using ret_t = return_type_t; - ret_t current_val; - int current_sign; - if (small_n_terms_small_t) { - ret_t fplus = NEGATIVE_INFTY; - ret_t fminus = NEGATIVE_INFTY; + using ret_t = return_type_t; + ret_t current_val; + int current_sign; + if (small_n_terms_small_t) { + ret_t fplus = NEGATIVE_INFTY; + ret_t fminus = NEGATIVE_INFTY; const auto mult = Density ? 1 : 3; const auto offset = GradW ? y_asq : 0; - + for (auto k = n_terms_small_t; k >= 1; k--) { - const auto wp2k = w + 2.0 * k; - const auto wm2k = w - 2.0 * k; - if (GradW) { - const auto sqwp2k_mo = square(wp2k) - offset; - if (sqwp2k_mo > 0) { - const auto wp2k_quant = log(sqwp2k_mo) - square(wp2k) * scaling; - fplus = log_sum_exp(fplus, wp2k_quant); - } else if (sqwp2k_mo < 0) { - const auto wp2k_quant = log(-sqwp2k_mo) - square(wp2k) * scaling; - fminus = log_sum_exp(fminus, wp2k_quant); - } - } else { - const auto wp2k_quant = mult * log(wp2k) - square(wp2k) * scaling; - fplus = log_sum_exp(fplus, wp2k_quant); - } - - if (GradW) { - const auto sqwm2k_mo = square(wm2k) - offset; - if (sqwm2k_mo > 0) { - const auto wm2k_quant = log(sqwm2k_mo) - square(wm2k) * scaling; - fplus = log_sum_exp(fplus, wm2k_quant); - } else if (sqwm2k_mo < 0) { - const auto wm2k_quant = log(-sqwm2k_mo) - square(wm2k) * scaling; - fminus = log_sum_exp(fminus, wm2k_quant); - } - } else { - const auto wm2k_quant = mult * log(-wm2k) - square(wm2k) * scaling; - if (fminus <= NEGATIVE_INFTY) { - fminus = wm2k_quant; - } else if (wm2k_quant <= NEGATIVE_INFTY) { - fminus = fminus; - } else if (fminus > wm2k_quant) { - fminus = fminus + log1p(exp(wm2k_quant - fminus)); - } else { - fminus = wm2k_quant + log1p(exp(fminus - wm2k_quant)); - } - } + const auto wp2k = w + 2.0 * k; + const auto wm2k = w - 2.0 * k; + if (GradW) { + const auto sqwp2k_mo = square(wp2k) - offset; + if (sqwp2k_mo > 0) { + const auto wp2k_quant = log(sqwp2k_mo) - square(wp2k) * scaling; + fplus = log_sum_exp(fplus, wp2k_quant); + } else if (sqwp2k_mo < 0) { + const auto wp2k_quant = log(-sqwp2k_mo) - square(wp2k) * scaling; + fminus = log_sum_exp(fminus, wp2k_quant); + } + } else { + const auto wp2k_quant = mult * log(wp2k) - square(wp2k) * scaling; + fplus = log_sum_exp(fplus, wp2k_quant); + } + + if (GradW) { + const auto sqwm2k_mo = square(wm2k) - offset; + if (sqwm2k_mo > 0) { + const auto wm2k_quant = log(sqwm2k_mo) - square(wm2k) * scaling; + fplus = log_sum_exp(fplus, wm2k_quant); + } else if (sqwm2k_mo < 0) { + const auto wm2k_quant = log(-sqwm2k_mo) - square(wm2k) * scaling; + fminus = log_sum_exp(fminus, wm2k_quant); + } + } else { + const auto wm2k_quant = mult * log(-wm2k) - square(wm2k) * scaling; + if (fminus <= NEGATIVE_INFTY) { + fminus = wm2k_quant; + } else if (wm2k_quant <= NEGATIVE_INFTY) { + fminus = fminus; + } else if (fminus > wm2k_quant) { + fminus = fminus + log1p(exp(wm2k_quant - fminus)); + } else { + fminus = wm2k_quant + log1p(exp(fminus - wm2k_quant)); + } + } + } + + if (GradW) { + const auto sqw_mo = square(w) - offset; + if (sqw_mo > 0) { + const auto new_val = log(sqw_mo) - square(w) * scaling; + fplus = log_sum_exp(fplus, new_val); + } else if (sqw_mo < 0) { + const auto new_val = log(-sqw_mo) - square(w) * scaling; + fminus = log_sum_exp(fminus, new_val); + } + } else { + const auto new_val = mult * log(w) - square(w) * scaling; + fplus = log_sum_exp(fplus, new_val); } - if (GradW) { - const auto sqw_mo = square(w) - offset; - if (sqw_mo > 0) { - const auto new_val = log(sqw_mo) - square(w) * scaling; - fplus = log_sum_exp(fplus, new_val); - } else if (sqw_mo < 0) { - const auto new_val = log(-sqw_mo) - square(w) * scaling; - fminus = log_sum_exp(fminus, new_val); - } - } else { - const auto new_val = mult * log(w) - square(w) * scaling; - fplus = log_sum_exp(fplus, new_val); - } - - if (fplus == NEGATIVE_INFTY) { - current_val = fminus; - } else if (fminus == NEGATIVE_INFTY) { - current_val = fplus; - } else if (fplus > fminus) { - current_val = log_diff_exp(fplus, fminus); - } else if (fplus < fminus) { - current_val = log_diff_exp(fminus, fplus); - } else { - current_val = NEGATIVE_INFTY; - } - current_sign = (fplus < fminus)? -1: 1; - - } else { // for large t + if (fplus == NEGATIVE_INFTY) { + current_val = fminus; + } else if (fminus == NEGATIVE_INFTY) { + current_val = fplus; + } else if (fplus > fminus) { + current_val = log_diff_exp(fplus, fminus); + } else if (fplus < fminus) { + current_val = log_diff_exp(fminus, fplus); + } else { + current_val = NEGATIVE_INFTY; + } + current_sign = (fplus < fminus) ? -1 : 1; + + } else { // for large t auto mult = 3; if (Density) { mult = 1; } else if (GradW) { mult = 2; } - ret_t fplus = NEGATIVE_INFTY; - ret_t fminus = NEGATIVE_INFTY; + ret_t fplus = NEGATIVE_INFTY; + ret_t fminus = NEGATIVE_INFTY; for (auto k = n_terms_large_t; k >= 1; k--) { - const auto pi_k = k * pi(); - const auto check = (GradW) ? cos(pi_k * w) : sin(pi_k * w); - if (check > 0) { - fplus = log_sum_exp(fplus, mult*log(k) - square(pi_k) * scaling + log(check)); - } else if ((GradW && check < 0) || !GradW) { - fminus = log_sum_exp(fminus, mult*log(k) - square(pi_k) * scaling + log(-check)); - } - } - if (fplus == NEGATIVE_INFTY) { - current_val = fminus; - } else if (fminus == NEGATIVE_INFTY) { - current_val = fplus; - } else if (fplus > fminus) { - current_val = log_diff_exp(fplus, fminus); - } else if (fplus < fminus) { - current_val = log_diff_exp(fminus, fplus); - } else { - current_val = NEGATIVE_INFTY; - } - current_sign = (fplus < fminus)? -1: 1; + const auto pi_k = k * pi(); + const auto check = (GradW) ? cos(pi_k * w) : sin(pi_k * w); + if (check > 0) { + fplus = log_sum_exp( + fplus, mult * log(k) - square(pi_k) * scaling + log(check)); + } else if ((GradW && check < 0) || !GradW) { + fminus = log_sum_exp( + fminus, mult * log(k) - square(pi_k) * scaling + log(-check)); + } + } + if (fplus == NEGATIVE_INFTY) { + current_val = fminus; + } else if (fminus == NEGATIVE_INFTY) { + current_val = fplus; + } else if (fplus > fminus) { + current_val = log_diff_exp(fplus, fminus); + } else if (fplus < fminus) { + current_val = log_diff_exp(fminus, fplus); + } else { + current_val = NEGATIVE_INFTY; + } + current_sign = (fplus < fminus) ? -1 : 1; } return std::make_pair(current_val, current_sign); } @@ -545,7 +547,6 @@ inline Scalar wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, return WrtLog ? ans * exp(log_density) : ans; } - /** * Calculate the derivative of the wiener5 density w.r.t. 'sv' * @@ -743,14 +744,14 @@ inline return_type_t wiener5_lpdf( // Calculate 4-parameter model without inter-trial variabilities (if // sv_vec[i] == 0) or 5-parameter model with inter-trial variability in // drift rate (if sv_vec[i] != 0) - + const T_partials_return y_value = y_vec.val(i); const T_partials_return a_value = a_vec.val(i); const T_partials_return t0_value = t0_vec.val(i); const T_partials_return w_value = w_vec.val(i); const T_partials_return v_value = v_vec.val(i); const T_partials_return sv_value = sv_vec.val(i); - + T_partials_return l_density = internal::estimate_with_err_check< T_partials_return, 5, false, 0, false>( [&](auto&&... args) { From 501c8d4b21c50bae6337cf40520a5c52965f2e65 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 8 Jan 2024 17:47:07 -0500 Subject: [PATCH 128/179] cleaning up hcubature --- stan/math/prim/functor/apply.hpp | 20 +- stan/math/prim/functor/hcubature.hpp | 237 +++++++----------- .../unit/math/prim/functor/hcubature_test.cpp | 47 ++-- 3 files changed, 130 insertions(+), 174 deletions(-) diff --git a/stan/math/prim/functor/apply.hpp b/stan/math/prim/functor/apply.hpp index 48673e5b98a..f0b006cc1cb 100644 --- a/stan/math/prim/functor/apply.hpp +++ b/stan/math/prim/functor/apply.hpp @@ -10,20 +10,23 @@ namespace math { namespace internal { /* * Invoke the functor f with arguments given in t and indexed in the index - * sequence I + * sequence I with other arguments possibly before or after * * @tparam F Type of functor * @tparam Tuple Type of tuple containing arguments + * @tparam PreArgs Parameter pack of arguments before the tuple * @tparam I Parameter pack of an index sequence going from 0 to * std::tuple_size::value - 1 inclusive * @param f functor callable * @param t tuple of arguments * @param i placeholder variable for index sequence + * @param pre_args parameter pack of arguments to place before elements in tuple. */ -template +template constexpr decltype(auto) apply_impl(F&& f, Tuple&& t, - std::index_sequence i) { - return f(std::forward(t))>(std::get(t))...); + std::index_sequence i, + PreArgs&&... pre_args) { + return std::forward(f)(std::forward(pre_args)..., std::forward(t))>(std::get(t))...); } } // namespace internal @@ -36,15 +39,18 @@ constexpr decltype(auto) apply_impl(F&& f, Tuple&& t, * * @tparam F Type of functor * @tparam Tuple Type of tuple containing arguments + * @tparam PreArgs Parameter pack of arguments before the tuple * @param f functor callable * @param t tuple of arguments + * @param pre_args parameter pack of arguments to place before elements in tuple. */ -template -constexpr decltype(auto) apply(F&& f, Tuple&& t) { +template +constexpr decltype(auto) apply(F&& f, Tuple&& t, PreArgs&&... pre_args) { return internal::apply_impl( std::forward(f), std::forward(t), std::make_index_sequence< - std::tuple_size>{}>{}); + std::tuple_size>{}>{}, + std::forward(pre_args)...); } } // namespace math diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 1ee5f310d8e..b1f5bf2bda8 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -33,6 +33,7 @@ namespace math { namespace internal { +// Why are there 8 things in xd7? 8th element never used static constexpr std::array xd7{ -9.9145537112081263920685469752598e-01, -9.4910791234275852452618968404809e-01, @@ -71,7 +72,7 @@ static constexpr std::array gwd7{ * @param p number of elements * @param x x-th lexicographically ordered set */ -inline Eigen::Matrix combination(Eigen::Matrix& c, +inline void combination(Eigen::Matrix& c, const int dim, const int p, const int x) { int r = 0; @@ -95,7 +96,6 @@ inline Eigen::Matrix combination(Eigen::Matrix& c, } else { c[0] = x; } - return std::move(c); } /** @@ -108,13 +108,13 @@ inline Eigen::Matrix combination(Eigen::Matrix& c, * @param dim dimension */ template -inline Eigen::Matrix combos(const int k, const Scalar lambda, +inline Eigen::Matrix combos(const int k, const Scalar lambda, const int dim) { - Eigen::Matrix c(k); + Eigen::Matrix c(k); const auto choose_dimk = choose(dim, k); - Eigen::Matrix p = Eigen::MatrixXd::Zero(dim, choose_dimk); + Eigen::Matrix p = Eigen::MatrixXd::Zero(dim, choose_dimk); for (size_t i = 0; i < choose_dimk; i++) { - c = combination(c, dim, k, i + 1); + combination(c, dim, k, i + 1); for (size_t j = 0; j < k; j++) { p.coeffRef(c.coeff(j) - 1, i) = lambda; } @@ -133,54 +133,41 @@ inline Eigen::Matrix combos(const int k, const Scalar lambda, * @param dim dimension */ template -inline Eigen::Matrix signcombos(const int k, +inline Eigen::Matrix signcombos(const int k, const Scalar lambda, const int dim) { - // Eigen::VectorXi c(k); - Eigen::Matrix c(k); + Eigen::Matrix c(k); const auto choose_dimk = choose(dim, k); - // Eigen::MatrixXd p = Eigen::MatrixXd::Zero(dim, choose_dimk * std::pow(2, - // k)); - Eigen::Matrix p + Eigen::Matrix p = Eigen::MatrixXd::Zero(dim, choose_dimk * std::pow(2, k)); int current_col = 0; + const auto inner_iter_len = std::pow(2, k); + std::vector index; + index.reserve(inner_iter_len * (choose_dimk + 1)); for (int i = 1; i != choose_dimk + 1; i++) { - c = combination(c, dim, k, i); - std::vector index; - for (int j = 0; j != std::pow(2, k); j++) { - int prev_col = (j == 0) ? current_col : current_col - 1; - p.col(current_col) = p.col(prev_col); - - if (index.size() == 0) { - index.push_back(false); - for (int h = 0; h != k; h++) { - p.col(current_col)[c[h] - 1] = lambda; - } + combination(c, dim, k, i); + index.push_back(false); + p(c.array() - 1.0, current_col).setConstant(lambda); + current_col += 1; + for (int j = 1; j != inner_iter_len; j++, current_col++) { + p.col(current_col) = p.col(current_col - 1); + int first_zero = std::distance(std::begin(index), + std::find(std::begin(index), + std::end(index), false)); + const std::size_t index_size = index.size(); + if (first_zero == index_size) { + index.flip(); + p(c.segment(0, index.size()).array() - 1, current_col).array() *= -1; + index.push_back(true); + p(c[index.size() - 1] - 1, current_col) = -lambda; } else { - int first_zero = 0; - while ((first_zero < index.size()) && index[first_zero]) { - first_zero++; - } - if (first_zero == index.size()) { - index.flip(); - for (int h = 0; h != index.size(); h++) { - p.col(current_col)[c[h] - 1] *= -1; - } - index.push_back(true); - p.col(current_col)[c[index.size() - 1] - 1] = -lambda; - } else { - for (int h = 0; h != first_zero + 1; h++) { - if (index[h]) { - index[h] = 0; - } else { - index[h] = 1; - } - p.col(current_col)[c[h] - 1] *= -1; - } + for (int h = 0; h != first_zero + 1; h++) { + index[h].flip(); } + p(c.segment(0, first_zero + 1).array() - 1, current_col).array() *= -1; } - current_col += 1; } + index.clear(); } return p; } @@ -201,27 +188,27 @@ template std::pair gauss_kronrod(const F& integrand, const Scalar a, const Scalar b, const ParsPairT& pars_pair) { - Eigen::Matrix c{{0.5 * (a + b)}}; - Eigen::Matrix cp(1); - Eigen::Matrix cm(1); - - Scalar delta = 0.5 * (b - a); + const Scalar c = 0.5 * (a + b); + const Scalar delta = 0.5 * (b - a); Scalar f0 = math::apply( - [&integrand, &c](auto&&... args) { return integrand(c, args...); }, - pars_pair); + [](auto&& integrand, auto&& c, auto&&... args) { return integrand(c, args...); }, + pars_pair, integrand, c); Scalar I = f0 * wd7[7]; Scalar Idash = f0 * gwd7[3]; + std::array deltax; + for (int i = 0; i < 7; ++i) { + deltax[i] = delta * xd7[i]; + } for (auto i = 0; i != 7; i++) { - Scalar deltax = delta * xd7[i]; - cp[0] = c[0] + deltax; - cm[0] = c[0] - deltax; + const Scalar cp = c + deltax[i]; + const Scalar cm = c - deltax[i]; Scalar fx = math::apply( - [&integrand, &cp](auto&&... args) { return integrand(cp, args...); }, - pars_pair); + [](auto&& integrand, auto&& cp, auto&&... args) { return integrand(cp, args...); }, + pars_pair, integrand, cp); Scalar temp = math::apply( - [&integrand, &cm](auto&&... args) { return integrand(cm, args...); }, - pars_pair); + [](auto&& integrand, auto&& cm, auto&&... args) { return integrand(cm, args...); }, + pars_pair, integrand, cm); fx += temp; I += fx * wd7[i]; if (i % 2 == 1) { @@ -244,25 +231,24 @@ std::pair gauss_kronrod(const F& integrand, const Scalar a, * @param dim dimension */ template -inline std::tuple>, - Eigen::Matrix, Eigen::Matrix> +inline std::tuple>, + Eigen::Matrix, Eigen::Matrix> make_GenzMalik(const int dim) { - std::vector> points(4); - Eigen::Matrix weights(5); - Eigen::Matrix weights_low_deg(4); - Scalar l4 = std::sqrt(9 * 1.0 / 10); - Scalar l2 = std::sqrt(9 * 1.0 / 70); + std::vector> points(4); + Eigen::Matrix weights(5); + Eigen::Matrix weights_low_deg(4); + Scalar l4 = std::sqrt(9.0 * 1.0 / 10.0); + Scalar l2 = std::sqrt(9.0 * 1.0 / 70.0); Scalar l3 = l4; - Scalar l5 = std::sqrt(9 * 1.0 / 19); - + Scalar l5 = std::sqrt(9.0 * 1.0 / 19.0); Scalar twopn = std::pow(2, dim); - weights[0] = twopn * ((12824 - 9120 * dim + 400 * dim * dim) * 1.0 / 19683); - weights[1] = twopn * (980.0 / 6561); - weights[2] = twopn * ((1820 - 400 * dim) * 1.0 / 19683); - weights[3] = twopn * (200.0 / 19683); - weights[4] = 6859.0 / 19683; - weights_low_deg[3] = twopn * (25.0 / 729); - weights_low_deg[2] = twopn * ((265 - 100 * dim) * 1.0 / 1458); + weights[0] = twopn * ((12824.0 - 9120.0 * dim + 400.0 * dim * dim) * 1.0 / 19683.0); + weights[1] = twopn * (980.0 / 6561.0); + weights[2] = twopn * ((1820.0 - 400.0 * dim) * 1.0 / 19683.0); + weights[3] = twopn * (200.0 / 19683.0); + weights[4] = 6859.0 / 19683.0; + weights_low_deg[3] = twopn * (25.0 / 729.0); + weights_low_deg[2] = twopn * ((265.0 - 100.0 * dim) * 1.0 / 1458.0); weights_low_deg[1] = twopn * (245.0 / 486); weights_low_deg[0] = twopn * ((729 - 950 * dim + 50 * dim * dim) * 1.0 / 729); points[0] = combos(1, l2, dim); @@ -293,104 +279,73 @@ make_GenzMalik(const int dim) { template std::tuple integrate_GenzMalik( const F& integrand, - const std::vector>& points, - const Eigen::Matrix& weights, - const Eigen::Matrix& weights_low_deg, const int dim, - const Eigen::Matrix& a, - const Eigen::Matrix& b, const ParsTupleT& pars_tuple) { - using eig_vec = Eigen::Matrix; - Eigen::Matrix c = Eigen::VectorXd::Zero(dim); + const std::vector>& points, + const Eigen::Matrix& weights, + const Eigen::Matrix& weights_low_deg, const int dim, + const Eigen::Matrix& a, + const Eigen::Matrix& b, const ParsTupleT& pars_tuple) { + using eig_vec = Eigen::Matrix; + eig_vec c(dim); + eig_vec deltac(dim); for (auto i = 0; i != dim; i++) { if (a[i] == b[i]) { return std::make_tuple(0.0, 0.0, 0); } c[i] = (a[i] + b[i]) / 2; + deltac[i] = (b[i] - a[i]) / 2.0; } - eig_vec deltac = ((b - a).array() / 2.0).matrix(); Scalar v = 1.0; for (std::size_t i = 0; i != dim; i++) { v *= deltac[i]; } Scalar f1 = math::apply( - [&integrand, &c](auto&&... args) { return integrand(c, args...); }, - pars_tuple); + [](auto&& integrand, auto&& c, auto&&... args) { return integrand(c, args...); }, + pars_tuple, integrand, c); + Scalar twelvef1 = 12.0 * f1; Scalar f2 = 0.0; Scalar f3 = 0.0; - Scalar twelvef1 = 12 * f1; - Scalar maxdivdiff = 0.0; eig_vec divdiff(dim); - eig_vec p2(dim); - eig_vec p3(dim); +// eig_vec p2(dim); +// eig_vec p3(dim); eig_vec cc(dim); for (auto i = 0; i != dim; i++) { - for (auto j = 0; j != dim; j++) { - p2[j] = deltac[j] * points[0](j, i); - } - - for (auto j = 0; j != dim; j++) { - cc[j] = c[j] + p2[j]; - } + auto p2 = deltac.cwiseProduct(points[0].col(i)); Scalar f2i = math::apply( - [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, - pars_tuple); - for (auto j = 0; j != dim; j++) { - cc[j] = c[j] - p2[j]; - } + [](auto&& integrand, auto&& cc, auto&&... args) { return integrand(cc, args...); }, + pars_tuple, integrand, c + p2); Scalar temp = math::apply( - [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, - pars_tuple); + [](auto&& integrand, auto&& cc, auto&&... args) { return integrand(cc, args...); }, + pars_tuple, integrand, c - p2); f2i += temp; - - for (auto j = 0; j != dim; j++) { - p3[j] = deltac[j] * points[1](j, i); - } - for (auto j = 0; j != dim; j++) { - cc[j] = c[j] + p3[j]; - } + auto p3 = deltac.cwiseProduct(points[1].col(i)); Scalar f3i = math::apply( - [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, - pars_tuple); - for (auto j = 0; j != dim; j++) { - cc[j] = c[j] - p3[j]; - } + [](auto&& integrand, auto&& cc, auto&&... args) { return integrand(cc, args...); }, + pars_tuple, integrand, c + p3); temp = math::apply( - [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, - pars_tuple); + [](auto&& integrand, auto&& cc, auto&&... args) { return integrand(cc, args...); }, + pars_tuple, integrand, c - p3); f3i += temp; f2 += f2i; f3 += f3i; divdiff[i] = fabs(f3i + twelvef1 - 7 * f2i); } - eig_vec p4(dim); +// eig_vec p4(dim); Scalar f4 = 0.0; for (auto i = 0; i != points[2].cols(); i++) { - for (auto j = 0; j != dim; j++) { - p4[j] = deltac[j] * points[2](j, i); - } - for (auto j = 0; j != dim; j++) { - cc[j] = c[j] + p4[j]; - } Scalar temp = math::apply( - [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, - pars_tuple); + [](auto&& integrand, auto&& cc, auto&&... args) { return integrand(cc, args...); }, + pars_tuple, integrand, c + deltac.cwiseProduct(points[2].col(i))); f4 += temp; } Scalar f5 = 0.0; - eig_vec p5(dim); +// eig_vec p5(dim); for (auto i = 0; i != points[3].cols(); i++) { - for (auto j = 0; j != dim; j++) { - p5[j] = deltac[j] * points[3](j, i); - } - - for (auto j = 0; j != dim; j++) { - cc[j] = c[j] + p5[j]; - } Scalar temp = math::apply( - [&integrand, &cc](auto&&... args) { return integrand(cc, args...); }, - pars_tuple); + [](auto&& integrand, auto&& cc, auto&&... args) { return integrand(cc, args...); }, + pars_tuple, integrand, c + deltac.cwiseProduct(points[3].col(i))); f5 += temp; } @@ -435,8 +390,8 @@ struct Box { b_(std::forward(b)), I_(I), kdiv_(kdivide) {} - Eigen::Matrix a_; - Eigen::Matrix b_; + Eigen::Matrix a_; + Eigen::Matrix b_; Scalar I_; int kdiv_; }; @@ -489,16 +444,16 @@ struct Box { */ template Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, - const Eigen::Matrix& a, - const Eigen::Matrix& b, const int max_eval, + const Eigen::Matrix& a, + const Eigen::Matrix& b, const int max_eval, const Scalar reqAbsError, const Scalar reqRelError) { - using eig_vec = Eigen::Matrix; + using eig_vec = Eigen::Matrix; const Scalar maxEval = max_eval <= 0 ? 1000000 : max_eval; Scalar result; Scalar err; auto kdivide = 0; - std::vector> p(4); + std::vector> p(4); eig_vec w_five(5); eig_vec wd_four(4); diff --git a/test/unit/math/prim/functor/hcubature_test.cpp b/test/unit/math/prim/functor/hcubature_test.cpp index 774b1464a56..d8325a41c92 100644 --- a/test/unit/math/prim/functor/hcubature_test.cpp +++ b/test/unit/math/prim/functor/hcubature_test.cpp @@ -7,58 +7,53 @@ namespace hcubature_test { template -stan::return_type_t f1(const T_x& x) { +inline auto f1(const T_x& x) { return stan::math::sum(stan::math::cos(x)); } template -stan::return_type_t f2(const T_x& x) { +inline auto f2(const T_x& x) { return stan::math::prod(stan::math::cos(x)); } template -stan::return_type_t f3(const T_x& x, double radius) { +inline auto f3(const T_x& x, double radius) { using stan::math::square; - - if (stan::math::sum(square(x)) < square(radius)) { - return 1; - } else { - return 0; - } + return stan::return_type_t(stan::math::sum(square(x)) < square(radius)); } template -stan::return_type_t f4(const T_x& x, double sigma) { +inline auto f4(const T_x& x, double sigma) { using stan::math::as_array_or_scalar; using stan::math::square; using stan::math::sum; using stan::math::TWO_OVER_SQRT_PI; - double numerator = sum(square(as_array_or_scalar(x) - 0.5)); + auto numerator = sum(square(as_array_or_scalar(x) - 0.5)); return square(TWO_OVER_SQRT_PI / (2.0 * sigma)) * exp(-numerator / square(sigma)); } template -stan::return_type_t f5(const T_x& x) { +inline auto f5(const T_x& x) { using stan::math::prod; using stan::math::square; using stan::math::TWO_OVER_SQRT_PI; const auto& x_arr = stan::math::as_array_or_scalar(x); - double val = stan::math::sum(square((1 - x_arr) / x_arr)); - double scale = prod(TWO_OVER_SQRT_PI / square(x_arr)); + auto val = stan::math::sum(square((1 - x_arr) / x_arr)); + auto scale = prod(TWO_OVER_SQRT_PI / square(x_arr)); return exp(-val) * scale; } template -stan::return_type_t f6(const T_x& x) { +inline auto f6(const T_x& x) { const auto& x_arr = stan::math::as_array_or_scalar(x); return stan::math::prod(2 * x_arr); } template -stan::return_type_t f7(const T_x& x, double a) { +inline auto f7(const T_x& x, double a) { const auto& x_arr = stan::math::as_array_or_scalar(x); return stan::math::prod(a / (a + 1) * stan::math::square((a + 1) / (a + x_arr))); @@ -103,11 +98,11 @@ stan::return_type_t f7(const T_x& x, double a) { * @param val correct value of integral */ -template +template void test_integration(const F& f, const ArgsTupleT& pars, int dim, - const Eigen::VectorXd& a, const Eigen::VectorXd& b, + const T_a& a, const T_b& b, int maxEval, double reqAbsError, - const Eigen::VectorXd& reqRelError, double val) { + const T_relerr& reqRelError, double val) { using stan::math::hcubature; for (auto tolerance : reqRelError) { @@ -125,22 +120,22 @@ TEST(StanMath_hcubature_prim, test1) { const Eigen::VectorXd a{{0.0}}; const Eigen::VectorXd b{{1.0}}; const Eigen::VectorXd reqRelError{{1e-4, 1e-6, 1e-7}}; - test_integration(hcubature_test::f1, std::make_tuple(), + test_integration([](auto&& x) { return hcubature_test::f1(x);}, std::make_tuple(), dim, a, b, 6000, 0.0, reqRelError, 0.841471); dim = 2; const Eigen::VectorXd a_2{{0.0, 0.0}}; const Eigen::VectorXd b_2{{1.0, 1.0}}; - test_integration(hcubature_test::f2, std::make_tuple(), + test_integration([](auto&& x) { return hcubature_test::f2(x);}, std::make_tuple(), dim, a_2, b_2, 6000, 0.0, reqRelError, 0.7080734); const Eigen::VectorXd reqRelError_2{{1e-4}}; - test_integration(hcubature_test::f3, + test_integration([](auto&& x, auto&& radius) { return hcubature_test::f3(x, radius);}, std::make_tuple(0.50124145262344534123412), dim, a_2, b_2, 10000, 0.0, reqRelError_2, 0.1972807); // (Gaussian centered at 1/2) - test_integration(hcubature_test::f4, + test_integration([](auto&& x, auto&& sigma) { return hcubature_test::f4(x, sigma);}, std::make_tuple(0.1), dim, a_2, b_2, 6000, 0.0, reqRelError, 1); @@ -148,18 +143,18 @@ TEST(StanMath_hcubature_prim, test1) { const Eigen::VectorXd a_3{{0.0, 0.0, 0.0}}; const Eigen::VectorXd b_3{{1.0, 1.0, 1.0}}; const Eigen::VectorXd reqRelError_3{{1e-4, 1e-6}}; - test_integration(hcubature_test::f5, std::make_tuple(), + test_integration([](auto&& x) { return hcubature_test::f5(x);}, std::make_tuple(), dim, a_3, b_3, 6000, 0.0, reqRelError_3, 1.00001); const Eigen::VectorXd reqRelError_4{{1e-4, 1e-6, 1e-8}}; - test_integration(hcubature_test::f6, std::make_tuple(), + test_integration([](auto&& x) { return hcubature_test::f6(x);}, std::make_tuple(), dim, a_3, b_3, 6000, 0.0, reqRelError_4, 1); // (Tsuda's example) dim = 4; const Eigen::VectorXd a_4{{0.0, 0.0, 0.0, 0.0}}; const Eigen::VectorXd b_4{{1.0, 1.0, 1.0, 1.0}}; - test_integration(hcubature_test::f7, + test_integration([](auto&& x, auto&& a) { return hcubature_test::f7(x, a);}, std::make_tuple((1 + sqrt(10.0)) / 9.0), dim, a_4, b_4, 20000, 0.0, reqRelError_3, 0.999998); } From 967280421e14751abb43af61992590fcf56965e0 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 9 Jan 2024 18:06:11 -0500 Subject: [PATCH 129/179] remove Scalar template parameter from wiener5 --- stan/math/prim/functor/hcubature.hpp | 282 ++++++------- stan/math/prim/meta/return_type.hpp | 31 +- stan/math/prim/prob/wiener5_lpdf.hpp | 512 ++++++++++------------- stan/math/prim/prob/wiener_full_lpdf.hpp | 67 ++- 4 files changed, 408 insertions(+), 484 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index b1f5bf2bda8..16b9ba21d10 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -72,30 +72,24 @@ static constexpr std::array gwd7{ * @param p number of elements * @param x x-th lexicographically ordered set */ -inline void combination(Eigen::Matrix& c, - const int dim, const int p, - const int x) { +inline void combination(Eigen::Matrix& c, const int dim, + const int p, const int x) { int r = 0; int k = 0; c[0] = 0; - for (; k < x; k = k + r) { + for (; k < x; r = choose(dim - c[0], p - 1), k = k + r) { c[0]++; - r = choose(dim - c[0], p - 1); } k = k - r; for (int i = 1; i < p - 1; i++) { c[i] = c[i - 1]; - for (; k < x; k = k + r) { + for (; k < x; r = choose(dim - c[i], p - (i + 1)), k = k + r) { c[i]++; - r = choose(dim - c[i], p - (i + 1)); } k = k - r; } - if (p > 1) { - c[p - 1] = c[p - 2] + x - k; - } else { - c[0] = x; - } + // Assumes p cannot be 0 + c[p - 1] = (p > 1) ? c[p - 2] + x - k : x; } /** @@ -108,11 +102,12 @@ inline void combination(Eigen::Matrix& c, * @param dim dimension */ template -inline Eigen::Matrix combos(const int k, const Scalar lambda, - const int dim) { +inline Eigen::Matrix combos( + const int k, const Scalar lambda, const int dim) { Eigen::Matrix c(k); const auto choose_dimk = choose(dim, k); - Eigen::Matrix p = Eigen::MatrixXd::Zero(dim, choose_dimk); + Eigen::Matrix p + = Eigen::MatrixXd::Zero(dim, choose_dimk); for (size_t i = 0; i < choose_dimk; i++) { combination(c, dim, k, i + 1); for (size_t j = 0; j < k; j++) { @@ -133,9 +128,8 @@ inline Eigen::Matrix combos(const int k, * @param dim dimension */ template -inline Eigen::Matrix signcombos(const int k, - const Scalar lambda, - const int dim) { +inline Eigen::Matrix signcombos( + const int k, const Scalar lambda, const int dim) { Eigen::Matrix c(k); const auto choose_dimk = choose(dim, k); Eigen::Matrix p @@ -151,9 +145,9 @@ inline Eigen::Matrix signcombos(const in current_col += 1; for (int j = 1; j != inner_iter_len; j++, current_col++) { p.col(current_col) = p.col(current_col - 1); - int first_zero = std::distance(std::begin(index), - std::find(std::begin(index), - std::end(index), false)); + int first_zero + = std::distance(std::begin(index), + std::find(std::begin(index), std::end(index), false)); const std::size_t index_size = index.size(); if (first_zero == index_size) { index.flip(); @@ -184,38 +178,37 @@ inline Eigen::Matrix signcombos(const in * @param pars_pair Pair of parameters for the integrand * @return numeric integral of the integrand and error */ -template -std::pair gauss_kronrod(const F& integrand, const Scalar a, - const Scalar b, +template +auto gauss_kronrod(const F& integrand, const T_a a, + const T_b b, const ParsPairT& pars_pair) { - const Scalar c = 0.5 * (a + b); - const Scalar delta = 0.5 * (b - a); - Scalar f0 = math::apply( - [](auto&& integrand, auto&& c, auto&&... args) { return integrand(c, args...); }, - pars_pair, integrand, c); + using delta_t = return_type_t; + const delta_t c = 0.5 * (a + b); + const delta_t delta = 0.5 * (b - a); + auto f0 = math::apply([](auto&& integrand, auto&& c, + auto&&... args) { return integrand(c, args...); }, + pars_pair, integrand, c); - Scalar I = f0 * wd7[7]; - Scalar Idash = f0 * gwd7[3]; - std::array deltax; + auto I = f0 * wd7[7]; + auto Idash = f0 * gwd7[3]; + std::array deltax; for (int i = 0; i < 7; ++i) { deltax[i] = delta * xd7[i]; } for (auto i = 0; i != 7; i++) { - const Scalar cp = c + deltax[i]; - const Scalar cm = c - deltax[i]; - Scalar fx = math::apply( - [](auto&& integrand, auto&& cp, auto&&... args) { return integrand(cp, args...); }, - pars_pair, integrand, cp); - Scalar temp = math::apply( - [](auto&& integrand, auto&& cm, auto&&... args) { return integrand(cm, args...); }, - pars_pair, integrand, cm); - fx += temp; + auto fx + = math::apply([](auto&& integrand, auto&& c, auto&& delta, + auto&&... args) { + return integrand(c + delta, args...) + + integrand(c - delta, args...); + }, + pars_pair, integrand, c, deltax[i]); I += fx * wd7[i]; if (i % 2 == 1) { Idash += fx * gwd7[i / 2]; } } - Scalar V = fabs(delta); + delta_t V = fabs(delta); I *= V; Idash *= V; return std::make_pair(I, fabs(I - Idash)); @@ -230,31 +223,30 @@ std::pair gauss_kronrod(const F& integrand, const Scalar a, * @param[in,out] weights_low_deg weights for the embedded lower-degree rule * @param dim dimension */ -template -inline std::tuple>, - Eigen::Matrix, Eigen::Matrix> + +inline std::tuple< + std::array, 4>, + Eigen::Matrix, Eigen::Matrix> make_GenzMalik(const int dim) { - std::vector> points(4); - Eigen::Matrix weights(5); - Eigen::Matrix weights_low_deg(4); - Scalar l4 = std::sqrt(9.0 * 1.0 / 10.0); - Scalar l2 = std::sqrt(9.0 * 1.0 / 70.0); - Scalar l3 = l4; - Scalar l5 = std::sqrt(9.0 * 1.0 / 19.0); - Scalar twopn = std::pow(2, dim); - weights[0] = twopn * ((12824.0 - 9120.0 * dim + 400.0 * dim * dim) * 1.0 / 19683.0); + std::array, 4> points; + Eigen::Matrix weights; + Eigen::Matrix weights_low_deg; + double twopn = std::pow(2, dim); + weights[0] + = twopn * ((12824.0 - 9120.0 * dim + 400.0 * dim * dim) * 1.0 / 19683.0); weights[1] = twopn * (980.0 / 6561.0); weights[2] = twopn * ((1820.0 - 400.0 * dim) * 1.0 / 19683.0); weights[3] = twopn * (200.0 / 19683.0); weights[4] = 6859.0 / 19683.0; - weights_low_deg[3] = twopn * (25.0 / 729.0); - weights_low_deg[2] = twopn * ((265.0 - 100.0 * dim) * 1.0 / 1458.0); - weights_low_deg[1] = twopn * (245.0 / 486); weights_low_deg[0] = twopn * ((729 - 950 * dim + 50 * dim * dim) * 1.0 / 729); - points[0] = combos(1, l2, dim); + weights_low_deg[1] = twopn * (245.0 / 486); + weights_low_deg[2] = twopn * ((265.0 - 100.0 * dim) * 1.0 / 1458.0); + weights_low_deg[3] = twopn * (25.0 / 729.0); + points[0] = combos(1, std::sqrt(9.0 * 1.0 / 70.0), dim); + double l3 = std::sqrt(9.0 * 1.0 / 10.0); points[1] = combos(1, l3, dim); - points[2] = signcombos(2, l4, dim); - points[3] = signcombos(dim, l5, dim); + points[2] = signcombos(2, l3, dim); + points[3] = signcombos(dim, std::sqrt(9.0 * 1.0 / 19.0), dim); return std::make_tuple(std::move(points), std::move(weights), std::move(weights_low_deg)); } @@ -276,89 +268,76 @@ make_GenzMalik(const int dim) { * @return numeric integral of the integrand, error, and suggested coordinate to * subdivide next */ -template -std::tuple integrate_GenzMalik( +template +auto integrate_GenzMalik( const F& integrand, - const std::vector>& points, - const Eigen::Matrix& weights, - const Eigen::Matrix& weights_low_deg, const int dim, - const Eigen::Matrix& a, - const Eigen::Matrix& b, const ParsTupleT& pars_tuple) { - using eig_vec = Eigen::Matrix; - eig_vec c(dim); - eig_vec deltac(dim); + const GenzMalik& genz_malik, const int dim, + const Eigen::Matrix& a, + const Eigen::Matrix& b, + const ParsTupleT& pars_tuple) { + auto&& points = std::get<0>(genz_malik); + auto&& weights = std::get<1>(genz_malik); + auto&& weights_low_deg = std::get<2>(genz_malik); + using delta_t = return_type_t; + Eigen::Matrix c(dim); + Eigen::Matrix deltac(dim); + using Scalar = return_type_t; for (auto i = 0; i != dim; i++) { if (a[i] == b[i]) { - return std::make_tuple(0.0, 0.0, 0); + return std::make_tuple(Scalar(0.0), Scalar(0.0), 0); } c[i] = (a[i] + b[i]) / 2; deltac[i] = (b[i] - a[i]) / 2.0; } - Scalar v = 1.0; + delta_t v = 1.0; for (std::size_t i = 0; i != dim; i++) { v *= deltac[i]; } - - Scalar f1 = math::apply( - [](auto&& integrand, auto&& c, auto&&... args) { return integrand(c, args...); }, - pars_tuple, integrand, c); - Scalar twelvef1 = 12.0 * f1; - Scalar f2 = 0.0; - Scalar f3 = 0.0; - Scalar maxdivdiff = 0.0; - eig_vec divdiff(dim); -// eig_vec p2(dim); -// eig_vec p3(dim); - eig_vec cc(dim); - + Eigen::Matrix f = Eigen::Matrix::Zero(); + f.coeffRef(0) + = math::apply([](auto&& integrand, auto&& c, + auto&&... args) { return integrand(c, args...); }, + pars_tuple, integrand, c); + Eigen::Matrix divdiff(dim); for (auto i = 0; i != dim; i++) { auto p2 = deltac.cwiseProduct(points[0].col(i)); - Scalar f2i = math::apply( - [](auto&& integrand, auto&& cc, auto&&... args) { return integrand(cc, args...); }, - pars_tuple, integrand, c + p2); - Scalar temp = math::apply( - [](auto&& integrand, auto&& cc, auto&&... args) { return integrand(cc, args...); }, - pars_tuple, integrand, c - p2); - f2i += temp; + auto f2i = math::apply( + [](auto&& integrand, auto&& c, auto&& p2, auto&&... args) { + return integrand(c + p2, args...) + integrand(c - p2, args...); + }, + pars_tuple, integrand, c, p2); auto p3 = deltac.cwiseProduct(points[1].col(i)); - Scalar f3i = math::apply( - [](auto&& integrand, auto&& cc, auto&&... args) { return integrand(cc, args...); }, - pars_tuple, integrand, c + p3); - temp = math::apply( - [](auto&& integrand, auto&& cc, auto&&... args) { return integrand(cc, args...); }, - pars_tuple, integrand, c - p3); - f3i += temp; - f2 += f2i; - f3 += f3i; - divdiff[i] = fabs(f3i + twelvef1 - 7 * f2i); + auto f3i = math::apply( + [](auto&& integrand, auto&& c, auto&& p3, auto&&... args) { + return integrand(c + p3, args...) + integrand(c - p3, args...); + }, + pars_tuple, integrand, c, p3); + f.coeffRef(1) += f2i; + f.coeffRef(2) += f3i; + divdiff[i] = fabs(f3i + 12.0 * f.coeff(0) - 7.0 * f2i); } -// eig_vec p4(dim); - Scalar f4 = 0.0; for (auto i = 0; i != points[2].cols(); i++) { - Scalar temp = math::apply( - [](auto&& integrand, auto&& cc, auto&&... args) { return integrand(cc, args...); }, + f.coeffRef(3) += math::apply( + [](auto&& integrand, auto&& cc, auto&&... args) { + return integrand(cc, args...); + }, pars_tuple, integrand, c + deltac.cwiseProduct(points[2].col(i))); - f4 += temp; } - Scalar f5 = 0.0; -// eig_vec p5(dim); for (auto i = 0; i != points[3].cols(); i++) { - Scalar temp = math::apply( - [](auto&& integrand, auto&& cc, auto&&... args) { return integrand(cc, args...); }, + f.coeffRef(4) += math::apply( + [](auto&& integrand, auto&& cc, auto&&... args) { + return integrand(cc, args...); + }, pars_tuple, integrand, c + deltac.cwiseProduct(points[3].col(i))); - f5 += temp; } - Scalar I = v - * (weights[0] * f1 + weights[1] * f2 + weights[2] * f3 - + weights[3] * f4 + weights[4] * f5); - Scalar Idash = v - * (weights_low_deg[0] * f1 + weights_low_deg[1] * f2 - + weights_low_deg[2] * f3 + weights_low_deg[3] * f4); + Scalar I = v * weights.dot(f); + Scalar Idash = v * weights_low_deg.dot(f.template head<4>()); Scalar E = fabs(I - Idash); int kdivide = 0; Scalar deltaf = E / (std::pow(10, dim) * v); + Scalar maxdivdiff = 0.0; for (auto i = 0; i != dim; i++) { Scalar delta = divdiff[i] - maxdivdiff; if (delta > deltaf) { @@ -382,17 +361,17 @@ std::tuple integrate_GenzMalik( * @param I value of the integral * @param kdivide number of subdividing the integration volume */ -template +template struct Box { template - Box(Vec1&& a, Vec2&& b, Scalar I, int kdivide) + Box(Vec1&& a, Vec2&& b, return_type_t I, int kdivide) : a_(std::forward(a)), b_(std::forward(b)), I_(I), kdiv_(kdivide) {} - Eigen::Matrix a_; - Eigen::Matrix b_; - Scalar I_; + Eigen::Matrix a_; + Eigen::Matrix b_; + return_type_t I_; int kdiv_; }; @@ -442,28 +421,28 @@ struct Box { \f$b\f$. * @throw std::domain_error no errors will be thrown. */ -template +template Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, - const Eigen::Matrix& a, - const Eigen::Matrix& b, const int max_eval, - const Scalar reqAbsError, const Scalar reqRelError) { - using eig_vec = Eigen::Matrix; - const Scalar maxEval = max_eval <= 0 ? 1000000 : max_eval; + const Eigen::Matrix& a, + const Eigen::Matrix& b, + const int max_eval, const Scalar reqAbsError, + const Scalar reqRelError) { + using eig_vec_a = Eigen::Matrix; + using eig_vec_b = Eigen::Matrix; + const int maxEval = max_eval <= 0 ? 1000000 : max_eval; Scalar result; Scalar err; auto kdivide = 0; - - std::vector> p(4); - eig_vec w_five(5); - eig_vec wd_four(4); - + std::tuple, 4>, + Eigen::Matrix, + Eigen::Matrix> genz_malik; if (dim == 1) { std::tie(result, err) - = internal::gauss_kronrod(integrand, a[0], b[0], pars); + = internal::gauss_kronrod(integrand, a[0], b[0], pars); } else { - std::tie(p, w_five, wd_four) = internal::make_GenzMalik(dim); - std::tie(result, err, kdivide) = internal::integrate_GenzMalik( - integrand, p, w_five, wd_four, dim, a, b, pars); + genz_malik = internal::make_GenzMalik(dim); + std::tie(result, err, kdivide) = internal::integrate_GenzMalik( + integrand, genz_malik, dim, a, b, pars); } auto numevals = (dim == 1) ? 15 : 1 + 4 * dim + 2 * dim * (dim - 1) + std::pow(2, dim); @@ -477,7 +456,8 @@ Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, return result; } numevals += 2 * evals_per_box; - std::vector> ms; + using box_t = internal::Box; + std::vector ms; ms.reserve(numevals); ms.emplace_back(std::move(a), std::move(b), result, kdivide); auto get_largest_box_idx = [](auto&& box_vec) { @@ -492,38 +472,32 @@ Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, && fabs(val) < INFTY) { auto err_idx = get_largest_box_idx(err_vec); auto&& box = ms[err_idx]; - - Scalar w = (box.b_[box.kdiv_] - box.a_[box.kdiv_]) / 2; - eig_vec ma = Eigen::Map(box.a_.data(), box.a_.size()); - + auto w = (box.b_[box.kdiv_] - box.a_[box.kdiv_]) / 2; + eig_vec_a ma = Eigen::Map(box.a_.data(), box.a_.size()); ma[box.kdiv_] += w; - eig_vec mb = Eigen::Map(box.b_.data(), box.b_.size()); + eig_vec_b mb = Eigen::Map(box.b_.data(), box.b_.size()); mb[box.kdiv_] -= w; - int kdivide_1{0}; int kdivide_2{0}; - Scalar result_1; Scalar result_2; Scalar err_1; Scalar err_2; if (dim == 1) { std::tie(result_1, err_1) - = internal::gauss_kronrod(integrand, ma[0], box.b_[0], pars); + = internal::gauss_kronrod(integrand, ma[0], box.b_[0], pars); std::tie(result_2, err_2) - = internal::gauss_kronrod(integrand, box.a_[0], mb[0], pars); + = internal::gauss_kronrod(integrand, box.a_[0], mb[0], pars); } else { std::tie(result_1, err_1, kdivide_1) - = internal::integrate_GenzMalik(integrand, p, w_five, wd_four, + = internal::integrate_GenzMalik(integrand, genz_malik, dim, ma, box.b_, pars); std::tie(result_2, err_2, kdivide_2) - = internal::integrate_GenzMalik(integrand, p, w_five, wd_four, + = internal::integrate_GenzMalik(integrand, genz_malik, dim, box.a_, mb, pars); } - internal::Box box1(std::move(ma), std::move(box.b_), result_1, - kdivide_1); - internal::Box box2(std::move(box.a_), std::move(mb), result_2, - kdivide_2); + box_t box1(std::move(ma), std::move(box.b_), result_1, kdivide_1); + box_t box2(std::move(box.a_), std::move(mb), result_2, kdivide_2); result += result_1 + result_2 - box.I_; err += err_1 + err_2 - err_vec[err_idx]; ms[err_idx].I_ = 0; diff --git a/stan/math/prim/meta/return_type.hpp b/stan/math/prim/meta/return_type.hpp index 79ef5816a9a..1ad0dd51c91 100644 --- a/stan/math/prim/meta/return_type.hpp +++ b/stan/math/prim/meta/return_type.hpp @@ -146,6 +146,26 @@ struct scalar_lub, std::complex> { template using scalar_lub_t = typename scalar_lub::type; +namespace internal { + template +struct return_type_impl { + using type = double; +}; + +template +struct return_type_impl { + using type + = scalar_lub_t, typename return_type_impl::type>; +}; + +template +struct return_type_impl, Ts...> { + using type + = scalar_lub_t::type, typename return_type_impl::type>; +}; + +} + /** * Template metaprogram to calculate the base scalar return type * resulting from promoting all the scalar types of the template @@ -184,15 +204,10 @@ using scalar_lub_t = typename scalar_lub::type; * @ingroup type_trait */ template -struct return_type { - using type = double; -}; +struct return_type : internal::return_type_impl...> {}; + + -template -struct return_type { - using type - = scalar_lub_t, typename return_type::type>; -}; /** * Convenience type for the return type of the specified template diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 435c20969a2..902e1afd9e1 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -17,23 +17,19 @@ namespace internal { * @param sv The inter-trial variability of the drift rate * @return 'error_term' term */ -template -inline Scalar wiener5_compute_error_term(T_y&& y, T_a&& a, T_v&& v_value, +inline auto wiener5_compute_error_term(T_y&& y, T_a&& a, T_v&& v_value, T_w&& w_value, T_sv&& sv) noexcept { - const Scalar w = 1.0 - w_value; - const Scalar v = -v_value; - const Scalar sv_sqr = square(sv); - const Scalar one_plus_svsqr_y = 1 + sv_sqr * y; - const Scalar two_avw = 2 * a * v * w; - const Scalar two_log_a = 2 * log(a); - if (sv != 0) { - return stan::math::eval((sv_sqr * square(a * w) - two_avw - square(v) * y) - / 2.0 / one_plus_svsqr_y - - two_log_a - 0.5 * log(one_plus_svsqr_y)); - } else { - return stan::math::eval((-two_avw - square(v) * y) / 2.0 - two_log_a); - } + const auto w = 1.0 - w_value; + const auto v = -v_value; + const auto sv_sqr = square(sv); + const auto one_plus_svsqr_y = 1 + sv_sqr * y; + const auto two_avw = 2.0 * a * v * w; + const auto two_log_a = 2.0 * log(a); + return stan::math::eval((sv_sqr * square(a * w) - two_avw - square(v) * y) + / 2.0 / one_plus_svsqr_y + - two_log_a - 0.5 * log(one_plus_svsqr_y)); } /** @@ -50,36 +46,28 @@ inline Scalar wiener5_compute_error_term(T_y&& y, T_a&& a, T_v&& v_value, * @param sv The inter-trial variability of the drift rate * @return 'density_part_one' term */ -template -inline Scalar wiener5_density_part_one(T_y&& y, T_a&& a, T_v_value&& v_value, +inline auto wiener5_density_part_one(T_y&& y, T_a&& a, T_v_value&& v_value, T_w_value&& w_value, T_sv&& sv) noexcept { - const Scalar w = 1.0 - w_value; - const Scalar v = -v_value; - const Scalar sv_sqr = square(sv); - const Scalar one_plus_svsqr_y = 1 + sv_sqr * y; - const Scalar two_avw = 2 * a * v * w; - - const Scalar var_a = GradA ? w : a; - const Scalar var_b = GradA ? a : w; - + const auto w = 1.0 - w_value; + const auto v = -v_value; + const auto sv_sqr = square(sv); + const auto one_plus_svsqr_y = 1 + sv_sqr * y; if (GradT) { - if (sv != 0) { return -0.5 - * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - two_avw) + * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - (2.0 * a * v * w)) + square(v)) / square(one_plus_svsqr_y); + } else { + if (GradA) { + return (-v * w + sv_sqr * square(w) * a) / one_plus_svsqr_y; } else { - return -0.5 * square(v); + return (-v * a + sv_sqr * square(a) * w) / one_plus_svsqr_y; } } - if (sv != 0) { - return (-v * var_a + sv_sqr * square(var_a) * var_b) / one_plus_svsqr_y; - } else { - return -v * var_a; - } } /** @@ -136,39 +124,35 @@ inline Scalar wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, * @param error The error tolerance * @return 'n_terms_large_t' term */ -template -inline Scalar wiener5_n_terms_large_t(T_y&& y, T_a&& a, T_w_value&& w_value, - Scalar error) noexcept { - const Scalar two_error = 2.0 * error; - const Scalar y_asq = y / square(a); - const Scalar two_log_a = 2 * log(a); - const Scalar log_y_asq = log(y) - two_log_a; - const Scalar w = 1.0 - w_value; - - const Scalar n_1_factor = GradW ? 2 : 3; +template +inline auto wiener5_n_terms_large_t(T_y&& y, T_a&& a, T_w_value&& w_value, + T_err error) noexcept { + const auto y_asq = y / square(a); + const auto log_y_asq = log(y) - 2 * log(a); static constexpr double PI_SQUARED = pi() * pi(); - - Scalar n_1; - Scalar n_2; if (Density) { - n_1 = 1.0 / (pi() * sqrt(y_asq)); - const Scalar two_log_piy = -2.0 * (LOG_PI + log_y_asq + error); - n_2 = (two_log_piy >= 0) ? sqrt(two_log_piy / (PI_SQUARED * y_asq)) : 0.0; + auto n_1 = 1.0 / (pi() * sqrt(y_asq)); + const auto two_log_piy = -2.0 * (LOG_PI + log_y_asq + error); + auto n_2 = (two_log_piy >= 0) ? sqrt(two_log_piy / (PI_SQUARED * y_asq)) : 0.0; + return ceil(fmax(n_1, n_2)); } else { - n_1 = sqrt(n_1_factor / y_asq) / pi(); - const Scalar u_eps_arg + const auto n_1_factor = GradW ? 2 : 3; + auto n_1 = sqrt(n_1_factor / y_asq) / pi(); + const auto two_error = 2.0 * error; + const auto u_eps_arg = GradW ? log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_error : log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + error; - const Scalar u_eps = fmin(-1, u_eps_arg); - const Scalar arg_mult = GradW ? 1 : (2.0 / PI_SQUARED / y_asq); - const Scalar arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - n_2 = GradW ? (arg > 0) ? sqrt(arg / y_asq) / pi() : n_1 - : (arg > 0) ? sqrt(arg) : n_1; + const auto u_eps = fmin(-1, u_eps_arg); + const auto arg_mult = GradW ? 1 : (2.0 / PI_SQUARED / y_asq); + const auto arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + auto n_2 = GradW ? + ((arg > 0) ? sqrt(arg / y_asq) / pi() : n_1) + : ((arg > 0) ? sqrt(arg) : n_1); + return ceil(fmax(n_1, n_2)); } - return ceil(fmax(n_1, n_2)); } /** @@ -185,7 +169,7 @@ inline Scalar wiener5_n_terms_large_t(T_y&& y, T_a&& a, T_w_value&& w_value, * @param n_terms_large_t The n_terms_large_t term * @return 'result' sum and its sign */ -template inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, T_nsmall&& n_terms_small_t, @@ -196,20 +180,17 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, = Density ? (2 * n_terms_small_t <= n_terms_large_t) : (2 * n_terms_small_t < n_terms_large_t); const auto scaling = small_n_terms_small_t ? inv(2.0 * y_asq) : y_asq / 2.0; - - using ret_t = return_type_t; - ret_t current_val; + using ret_t = return_type_t; + ret_t fplus = NEGATIVE_INFTY; + ret_t fminus = NEGATIVE_INFTY; int current_sign; if (small_n_terms_small_t) { - ret_t fplus = NEGATIVE_INFTY; - ret_t fminus = NEGATIVE_INFTY; - const auto mult = Density ? 1 : 3; - const auto offset = GradW ? y_asq : 0; - - for (auto k = n_terms_small_t; k >= 1; k--) { - const auto wp2k = w + 2.0 * k; - const auto wm2k = w - 2.0 * k; - if (GradW) { + constexpr double mult = Density ? 1.0 : 3.0; + if (GradW) { + const auto offset = y_asq; + for (auto k = n_terms_small_t; k >= 1; k--) { + const auto wp2k = w + 2.0 * k; + const auto wm2k = w - 2.0 * k; const auto sqwp2k_mo = square(wp2k) - offset; if (sqwp2k_mo > 0) { const auto wp2k_quant = log(sqwp2k_mo) - square(wp2k) * scaling; @@ -218,12 +199,6 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, const auto wp2k_quant = log(-sqwp2k_mo) - square(wp2k) * scaling; fminus = log_sum_exp(fminus, wp2k_quant); } - } else { - const auto wp2k_quant = mult * log(wp2k) - square(wp2k) * scaling; - fplus = log_sum_exp(fplus, wp2k_quant); - } - - if (GradW) { const auto sqwm2k_mo = square(wm2k) - offset; if (sqwm2k_mo > 0) { const auto wm2k_quant = log(sqwm2k_mo) - square(wm2k) * scaling; @@ -232,21 +207,7 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, const auto wm2k_quant = log(-sqwm2k_mo) - square(wm2k) * scaling; fminus = log_sum_exp(fminus, wm2k_quant); } - } else { - const auto wm2k_quant = mult * log(-wm2k) - square(wm2k) * scaling; - if (fminus <= NEGATIVE_INFTY) { - fminus = wm2k_quant; - } else if (wm2k_quant <= NEGATIVE_INFTY) { - fminus = fminus; - } else if (fminus > wm2k_quant) { - fminus = fminus + log1p(exp(wm2k_quant - fminus)); - } else { - fminus = wm2k_quant + log1p(exp(fminus - wm2k_quant)); - } } - } - - if (GradW) { const auto sqw_mo = square(w) - offset; if (sqw_mo > 0) { const auto new_val = log(sqw_mo) - square(w) * scaling; @@ -256,32 +217,27 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, fminus = log_sum_exp(fminus, new_val); } } else { + for (auto k = n_terms_small_t; k >= 1; k--) { + const auto wp2k = w + 2.0 * k; + const auto wm2k = w - 2.0 * k; + const auto wp2k_quant = mult * log(wp2k) - square(wp2k) * scaling; + fplus = log_sum_exp(fplus, wp2k_quant); + const auto wm2k_quant = mult * log(-wm2k) - square(wm2k) * scaling; + if (fminus <= NEGATIVE_INFTY) { + fminus = wm2k_quant; + } else if (wm2k_quant <= NEGATIVE_INFTY) { + continue; + } else if (fminus > wm2k_quant) { + fminus = fminus + log1p(exp(wm2k_quant - fminus)); + } else { + fminus = wm2k_quant + log1p(exp(fminus - wm2k_quant)); + } + } const auto new_val = mult * log(w) - square(w) * scaling; fplus = log_sum_exp(fplus, new_val); } - - if (fplus == NEGATIVE_INFTY) { - current_val = fminus; - } else if (fminus == NEGATIVE_INFTY) { - current_val = fplus; - } else if (fplus > fminus) { - current_val = log_diff_exp(fplus, fminus); - } else if (fplus < fminus) { - current_val = log_diff_exp(fminus, fplus); - } else { - current_val = NEGATIVE_INFTY; - } - current_sign = (fplus < fminus) ? -1 : 1; - } else { // for large t - auto mult = 3; - if (Density) { - mult = 1; - } else if (GradW) { - mult = 2; - } - ret_t fplus = NEGATIVE_INFTY; - ret_t fminus = NEGATIVE_INFTY; + constexpr double mult = (Density ? 1 : (GradW ? 2 : 3)); for (auto k = n_terms_large_t; k >= 1; k--) { const auto pi_k = k * pi(); const auto check = (GradW) ? cos(pi_k * w) : sin(pi_k * w); @@ -293,20 +249,19 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, fminus, mult * log(k) - square(pi_k) * scaling + log(-check)); } } - if (fplus == NEGATIVE_INFTY) { - current_val = fminus; - } else if (fminus == NEGATIVE_INFTY) { - current_val = fplus; - } else if (fplus > fminus) { - current_val = log_diff_exp(fplus, fminus); - } else if (fplus < fminus) { - current_val = log_diff_exp(fminus, fplus); - } else { - current_val = NEGATIVE_INFTY; - } - current_sign = (fplus < fminus) ? -1 : 1; } - return std::make_pair(current_val, current_sign); + current_sign = (fplus < fminus) ? -1 : 1; + if (fplus == NEGATIVE_INFTY) { + return std::make_pair(fminus, current_sign); + } else if (fminus == NEGATIVE_INFTY) { + return std::make_pair(fplus, current_sign); + } else if (fplus > fminus) { + return std::make_pair(log_diff_exp(fplus, fminus), current_sign); + } else if (fplus < fminus) { + return std::make_pair(log_diff_exp(fminus, fplus), current_sign); + } else { + return std::make_pair(ret_t(NEGATIVE_INFTY), current_sign); + } } /** @@ -323,28 +278,28 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, * @param err The log error tolerance * @return density */ -template -inline Scalar wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, +template +inline auto wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, const T_w& w_value, const T_sv& sv, - Scalar err = log(1e-12)) noexcept { - const Scalar error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); - const Scalar error = (err - error_term); - const Scalar n_terms_small_t - = wiener5_n_terms_small_t(y, a, w_value, error); - const Scalar n_terms_large_t - = wiener5_n_terms_large_t(y, a, w_value, error); - - auto res = wiener5_log_sum_exp( + T_err err = log(1e-12)) noexcept { + const auto error_term + = wiener5_compute_error_term(y, a, v_value, w_value, sv); + const auto error = (err - error_term); + const auto n_terms_small_t + = wiener5_n_terms_small_t(y, a, w_value, error); + const auto n_terms_large_t + = wiener5_n_terms_large_t(y, a, w_value, error); + + auto res = wiener5_log_sum_exp( y, a, w_value, n_terms_small_t, n_terms_large_t) .first; if (2 * n_terms_small_t <= n_terms_large_t) { - Scalar log_density = error_term - 0.5 * LOG_TWO - LOG_SQRT_PI + auto log_density = error_term - 0.5 * LOG_TWO - LOG_SQRT_PI - 1.5 * (log(y) - 2 * log(a)) + res; return NaturalScale ? exp(log_density) : log_density; } else { - Scalar log_density = error_term + res + LOG_PI; + auto log_density = error_term + res + LOG_PI; return NaturalScale ? exp(log_density) : log_density; } } @@ -364,46 +319,43 @@ inline Scalar wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, * @param err The log error tolerance * @return Gradient w.r.t. t */ -template -inline Scalar wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, +template +inline auto wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, const T_w& w_value, const T_sv& sv, - Scalar err = log(1e-12)) noexcept { - const Scalar two_log_a = 2 * log(a); - const Scalar log_y_asq = log(y) - two_log_a; - const Scalar error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); - const Scalar density_part_one = wiener5_density_part_one( + T_err err = log(1e-12)) noexcept { + const auto two_log_a = 2 * log(a); + const auto log_y_asq = log(y) - two_log_a; + const auto error_term + = wiener5_compute_error_term(y, a, v_value, w_value, sv); + const auto density_part_one = wiener5_density_part_one( y, a, v_value, w_value, sv); - const Scalar error = (err - error_term) + two_log_a; - - const Scalar n_terms_small_t - = wiener5_n_terms_small_t(y, a, w_value, error); - const Scalar n_terms_large_t - = wiener5_n_terms_large_t(y, a, w_value, error); - Scalar result; - int newsign; - std::forward_as_tuple(result, newsign) - = wiener5_log_sum_exp( + const auto error = (err - error_term) + two_log_a; + const auto n_terms_small_t + = wiener5_n_terms_small_t(y, a, w_value, error); + const auto n_terms_large_t + = wiener5_n_terms_large_t(y, a, w_value, error); + auto wiener_res = wiener5_log_sum_exp( y, a, w_value, n_terms_small_t, n_terms_large_t); - - const Scalar error_log_density + auto&& result = wiener_res.first; + auto&& newsign = wiener_res.second; + const auto error_log_density = log(fmax(fabs(density_part_one - 1.5 / y), fabs(density_part_one))); - const Scalar log_density = wiener5_density( + const auto log_density = wiener5_density( y, a, v_value, w_value, sv, err - error_log_density); - Scalar ans; if (2 * n_terms_small_t < n_terms_large_t) { - ans = density_part_one - 1.5 / y + auto ans = density_part_one - 1.5 / y + newsign * exp(error_term - two_log_a - 1.5 * LOG_TWO - LOG_SQRT_PI - 3.5 * log_y_asq + result - log_density); - } else { - ans = density_part_one + return WrtLog ? ans * exp(log_density) : ans; +} else { + auto ans = density_part_one - newsign * exp(error_term - two_log_a + 3.0 * LOG_PI - LOG_TWO + result - log_density); - } return WrtLog ? ans * exp(log_density) : ans; + } } /** @@ -421,46 +373,44 @@ inline Scalar wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, * @param err The log error tolerance * @return Gradient w.r.t. a */ -template -inline Scalar wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, +template +inline auto wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, const T_w& w_value, const T_sv& sv, - Scalar err = log(1e-12)) noexcept { - const Scalar two_log_a = 2 * log(a); - const Scalar log_y_asq = log(y) - two_log_a; - const Scalar error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); - const Scalar density_part_one = wiener5_density_part_one( + T_err err = log(1e-12)) noexcept { + const auto two_log_a = 2 * log(a); + const auto log_y_asq = log(y) - two_log_a; + const auto error_term + = wiener5_compute_error_term(y, a, v_value, w_value, sv); + const auto density_part_one = wiener5_density_part_one( y, a, v_value, w_value, sv); - const Scalar error = err - error_term + 3 * log(a) - log(y) - LOG_TWO; - - const Scalar n_terms_small_t - = wiener5_n_terms_small_t(y, a, w_value, error); - const Scalar n_terms_large_t - = wiener5_n_terms_large_t(y, a, w_value, error); - Scalar result; - int newsign; - std::forward_as_tuple(result, newsign) - = wiener5_log_sum_exp( - y, a, w_value, n_terms_small_t, n_terms_large_t); + const auto error = err - error_term + 3 * log(a) - log(y) - LOG_TWO; - const Scalar error_log_density = log( + const auto n_terms_small_t + = wiener5_n_terms_small_t(y, a, w_value, error); + const auto n_terms_large_t + = wiener5_n_terms_large_t(y, a, w_value, error); + auto wiener_res = wiener5_log_sum_exp( + y, a, w_value, n_terms_small_t, n_terms_large_t); + auto&& result = wiener_res.first; + auto&& newsign = wiener_res.second; + const auto error_log_density = log( fmax(fabs(density_part_one + 1.0 / a), fabs(density_part_one - 2.0 / a))); - const Scalar log_density = wiener5_density( + const auto log_density = wiener5_density( y, a, v_value, w_value, sv, err - error_log_density); - Scalar ans; if (2 * n_terms_small_t < n_terms_large_t) { - ans = density_part_one + 1.0 / a + auto ans = density_part_one + 1.0 / a - newsign * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * log(y) + 2.0 * two_log_a + error_term + result - log_density); + return WrtLog ? ans * exp(log_density) : ans; } else { - ans = density_part_one - 2.0 / a + auto ans = density_part_one - 2.0 / a + newsign * exp(log(y) + error_term - 3 * (log(a) - LOG_PI) + result - log_density); + return WrtLog ? ans * exp(log_density) : ans; } - return WrtLog ? ans * exp(log_density) : ans; } /** @@ -478,19 +428,17 @@ inline Scalar wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, * @param err The log error tolerance * @return Gradient w.r.t. v */ -template -inline Scalar wiener5_grad_v(const T_y& y, const T_a& a, const T_v& v_value, +template +inline auto wiener5_grad_v(const T_y& y, const T_a& a, const T_v& v_value, const T_w& w_value, const T_sv& sv, - Scalar err = log(1e-12)) noexcept { - Scalar ans = (a * (1 - w_value) - v_value * y); - if (sv != 0) { - ans /= 1 + square(sv) * y; + T_err err = log(1e-12)) noexcept { + auto ans = (a * (1 - w_value) - v_value * y) / (1.0 + square(sv) * y); + if (WrtLog) { + return ans * wiener5_density(y, a, v_value, w_value, sv, err); + } else { + return ans; } - return WrtLog ? ans - * wiener5_density(y, a, v_value, w_value, - sv, err) - : ans; } /** @@ -508,43 +456,42 @@ inline Scalar wiener5_grad_v(const T_y& y, const T_a& a, const T_v& v_value, * @param err The log error tolerance * @return Gradient w.r.t. w */ -template -inline Scalar wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, +template +inline auto wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, const T_w& w_value, const T_sv& sv, - Scalar err = log(1e-12)) noexcept { - const Scalar two_log_a = 2 * log(a); - const Scalar log_y_asq = log(y) - two_log_a; - const Scalar error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); - const Scalar density_part_one - = wiener5_density_part_one(y, a, v_value, w_value, + T_err err = log(1e-12)) noexcept { + const auto two_log_a = 2 * log(a); + const auto log_y_asq = log(y) - two_log_a; + const auto error_term + = wiener5_compute_error_term(y, a, v_value, w_value, sv); + const auto density_part_one + = wiener5_density_part_one(y, a, v_value, w_value, sv); - const Scalar error = (err - error_term); - - const Scalar n_terms_small_t - = wiener5_n_terms_small_t(y, a, w_value, error); - const Scalar n_terms_large_t - = wiener5_n_terms_large_t(y, a, w_value, error); - Scalar result; - int newsign; - std::forward_as_tuple(result, newsign) - = wiener5_log_sum_exp(y, a, w_value, n_terms_small_t, + const auto error = (err - error_term); + + const auto n_terms_small_t + = wiener5_n_terms_small_t(y, a, w_value, error); + const auto n_terms_large_t + = wiener5_n_terms_large_t(y, a, w_value, error); + auto wiener_res + = wiener5_log_sum_exp(y, a, w_value, n_terms_small_t, n_terms_large_t); - - const Scalar log_density = wiener5_density( + auto&& result = wiener_res.first; + auto&& newsign = wiener_res.second; + const auto log_density = wiener5_density( y, a, v_value, w_value, sv, err - log(fabs(density_part_one))); - Scalar ans; if (2 * n_terms_small_t < n_terms_large_t) { - ans = -(density_part_one + auto ans = -(density_part_one - newsign * exp(result - (log_density - error_term) - 2.5 * log_y_asq - 0.5 * LOG_TWO - 0.5 * LOG_PI)); + return WrtLog ? ans * exp(log_density) : ans; } else { - ans = -(density_part_one + auto ans = -(density_part_one + newsign * exp(result - (log_density - error_term) + 2 * LOG_PI)); + return WrtLog ? ans * exp(log_density) : ans; } - return WrtLog ? ans * exp(log_density) : ans; } /** @@ -562,20 +509,20 @@ inline Scalar wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, * @param err The log error tolerance * @return Gradient w.r.t. sv */ -template -inline Scalar wiener5_grad_sv(const T_y& y, const T_a& a, const T_v& v_value, +template +inline auto wiener5_grad_sv(const T_y& y, const T_a& a, const T_v& v_value, const T_w& w_value, const T_sv& sv, - Scalar err = log(1e-12)) noexcept { - const Scalar one_plus_svsqr_y = 1 + square(sv) * y; - const Scalar w = 1.0 - w_value; - const Scalar v = -v_value; - const Scalar t1 = -y / one_plus_svsqr_y; - const Scalar t2 = (square(a * w) + 2 * a * v * w * y + square(v * y)) + T_err err = log(1e-12)) noexcept { + const auto one_plus_svsqr_y = 1 + square(sv) * y; + const auto w = 1.0 - w_value; + const auto v = -v_value; + const auto t1 = -y / one_plus_svsqr_y; + const auto t2 = (square(a * w) + 2 * a * v * w * y + square(v * y)) / square(one_plus_svsqr_y); - const Scalar ans = sv * (t1 + t2); + const auto ans = sv * (t1 + t2); return WrtLog ? ans - * wiener5_density(y, a, v_value, w_value, + * wiener5_density(y, a, v_value, w_value, sv, err) : ans; } @@ -583,8 +530,8 @@ inline Scalar wiener5_grad_sv(const T_y& y, const T_a& a, const T_v& v_value, /** * Utility function for replacing a value with a specified error value */ -template -inline void assign_err(Scalar arg, Scalar err) { +template +inline void assign_err(Scalar1 arg, Scalar2 err) { arg = err; } @@ -613,17 +560,17 @@ inline void assign_err(std::tuple& args_tuple, Scalar err) { * @param args_tuple Tuple of arguments to pass to functor * @param log_result Whether the function result is already on the log-scale */ -template -Scalar estimate_with_err_check(const F& functor, Scalar err, +inline auto estimate_with_err_check(const F& functor, T_err err, ArgsTupleT&&... args_tuple) { - Scalar result = functor(args_tuple...); - Scalar log_fabs_result = LogResult ? log(fabs(result)) : fabs(result); + auto result = functor(args_tuple...); + auto log_fabs_result = LogResult ? log(fabs(result)) : fabs(result); if (log_fabs_result < err) { log_fabs_result = is_inf(log_fabs_result) ? 0 : log_fabs_result; auto err_args_tuple = std::make_tuple(args_tuple...); - const Scalar new_error + const auto new_error = GradW7 ? err + log_fabs_result + LOG_TWO : err + log_fabs_result; assign_err(std::get(err_args_tuple), new_error); result = math::apply([&](auto&&... args) { return functor(args...); }, @@ -656,14 +603,14 @@ Scalar estimate_with_err_check(const F& functor, Scalar err, */ template > -inline return_type_t wiener5_lpdf( + typename T_precision> +inline auto wiener5_lpdf( const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, - const T_sv& sv, const ReturnT& precision_derivatives) { + const T_sv& sv, const T_precision& precision_derivatives) { using T_partials_return = partials_return_t; - + using ret_t = return_type_t; if (!include_summand::value) { - return 0; + return ret_t(0.0); } using T_y_ref = ref_type_if_t::value, T_y>; @@ -705,11 +652,11 @@ inline return_type_t wiener5_lpdf( check_finite(function_name, "Inter-trial variability in drift rate", sv_val); if (size_zero(y, a, t0, w, v, sv)) { - return 0; + return ret_t(0.0); } const size_t N = max_size(y, a, t0, w, v, sv); if (!N) { - return 0; + return ret_t(0.0); } scalar_seq_view y_vec(y_ref); @@ -730,9 +677,10 @@ inline return_type_t wiener5_lpdf( } } - const T_partials_return log_error_density = log(1e-6); - const T_partials_return log_error_derivative = log(precision_derivatives); - const T_partials_return log_error_absolute = log(1e-12); + const auto log_error_density = log(1e-6); + const auto log_error_derivative = log(precision_derivatives); + const double log_error_absolute_val = log(1e-12); + const T_partials_return log_error_absolute = log_error_absolute_val; T_partials_return log_density = 0.0; auto ops_partials = make_partials_propagator(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref); @@ -745,32 +693,30 @@ inline return_type_t wiener5_lpdf( // sv_vec[i] == 0) or 5-parameter model with inter-trial variability in // drift rate (if sv_vec[i] != 0) - const T_partials_return y_value = y_vec.val(i); - const T_partials_return a_value = a_vec.val(i); - const T_partials_return t0_value = t0_vec.val(i); - const T_partials_return w_value = w_vec.val(i); - const T_partials_return v_value = v_vec.val(i); - const T_partials_return sv_value = sv_vec.val(i); + const auto y_value = y_vec.val(i); + const auto a_value = a_vec.val(i); + const auto t0_value = t0_vec.val(i); + const auto w_value = w_vec.val(i); + const auto v_value = v_vec.val(i); + const auto sv_value = sv_vec.val(i); - T_partials_return l_density = internal::estimate_with_err_check< - T_partials_return, 5, false, 0, false>( + auto l_density = internal::estimate_with_err_check<5, false, 0, false>( [&](auto&&... args) { - return internal::wiener5_density(args...); + return internal::wiener5_density(args...); }, log_error_density - LOG_TWO, y_value - t0_value, a_value, v_value, w_value, sv_value, log_error_absolute); log_density += l_density; - const T_partials_return new_est_err + const auto new_est_err = l_density + log_error_derivative - LOG_FOUR; // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 - const T_partials_return deriv_y = internal::estimate_with_err_check< - T_partials_return, 5, false, 0, true>( + const auto deriv_y = internal::estimate_with_err_check<5, false, 0, true>( [&](auto&&... args) { - return internal::wiener5_grad_t(args...); + return internal::wiener5_grad_t(args...); }, new_est_err, y_value - t0_value, a_value, v_value, w_value, sv_value, log_error_absolute); @@ -780,10 +726,9 @@ inline return_type_t wiener5_lpdf( partials<0>(ops_partials)[i] = deriv_y; } if (!is_constant_all::value) { - partials<1>(ops_partials)[i] = internal::estimate_with_err_check< - T_partials_return, 5, false, 0, true>( + partials<1>(ops_partials)[i] = internal::estimate_with_err_check<5, false, 0, true>( [&](auto&&... args) { - return internal::wiener5_grad_a(args...); + return internal::wiener5_grad_a(args...); }, new_est_err, y_value - t0_value, a_value, v_value, w_value, sv_value, log_error_absolute); @@ -792,23 +737,22 @@ inline return_type_t wiener5_lpdf( partials<2>(ops_partials)[i] = -deriv_y; } if (!is_constant_all::value) { - partials<3>(ops_partials)[i] = internal::estimate_with_err_check< - T_partials_return, 5, false, 0, true>( + partials<3>(ops_partials)[i] = internal::estimate_with_err_check<5, false, 0, true>( [&](auto&&... args) { - return internal::wiener5_grad_w(args...); + return internal::wiener5_grad_w(args...); }, new_est_err, y_value - t0_value, a_value, v_value, w_value, sv_value, log_error_absolute); } if (!is_constant_all::value) { partials<4>(ops_partials)[i] - = internal::wiener5_grad_v( - y_value - t0_value, a_value, v_value, w_value, sv_value); + = internal::wiener5_grad_v( + y_value - t0_value, a_value, v_value, w_value, sv_value, log_error_absolute_val); } if (!is_constant_all::value) { partials<5>(ops_partials)[i] - = internal::wiener5_grad_sv( - y_value - t0_value, a_value, v_value, w_value, sv_value); + = internal::wiener5_grad_sv( + y_value - t0_value, a_value, v_value, w_value, sv_value, log_error_absolute_val); } } // end for loop return ops_partials.build(log_density); diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 3d7f71da695..7f299be99de 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -21,21 +21,20 @@ namespace internal { * @param log_error The log error tolerance * @return Gradient w.r.t. sw */ -template > -inline ReturnT wiener7_grad_sw(const T_y& y, const T_a& a, const T_v& v, +template +inline auto wiener7_grad_sw(const T_y& y, const T_a& a, const T_v& v, const T_w& w, const T_sv& sv, const T_sw& sw, - Scalar log_error) { - Scalar low = w - sw / 2.0; + T_err log_error) { + auto low = w - sw / 2.0; low = (0 > low) ? 0 : low; - Scalar high = w + sw / 2.0; + auto high = w + sw / 2.0; high = (1 < high) ? 1 : high; - const Scalar lower_value - = wiener5_density(y, a, v, low, sv, log_error); - const Scalar upper_value - = wiener5_density(y, a, v, high, sv, log_error); + const auto lower_value + = wiener5_density(y, a, v, low, sv, log_error); + const auto upper_value + = wiener5_density(y, a, v, high, sv, log_error); return 0.5 * (lower_value + upper_value) / sw; } @@ -141,7 +140,7 @@ ReturnT wiener7_integrate(const Wiener7FunctorT& wiener7_functor, const auto functor = [&](auto&&... int_args) { return hcubature(wiener7_integrand_impl, int_args...); }; - return estimate_with_err_check( + return estimate_with_err_check<0, GradW7, 8, true>( functor, hcubature_err, args...); } } // namespace internal @@ -293,16 +292,15 @@ ReturnT wiener7_integrate(const Wiener7FunctorT& wiener7_functor, */ template > -inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, + typename T_st0> +inline auto wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, const T_sv& sv, const T_sw& sw, const T_st0& st0, const double& precision_derivatives = 1e-4) { + using ret_t = return_type_t; if (!include_summand::value) { - return 0; + return ret_t(0); } using T_y_ref = ref_type_if_t::value, T_y>; @@ -360,11 +358,11 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, st0_val); if (size_zero(y, a, v, w, t0) || size_zero(sv, sw, st0)) { - return 0; + return ret_t(0); } const size_t N = max_size(y, a, v, w, t0, sv, sw, st0); if (!N) { - return 0; + return ret_t(0); } scalar_seq_view y_vec(y_ref); scalar_seq_view a_vec(a_ref); @@ -408,9 +406,9 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_partials_return log_error_density = log(1e-6); // precision for density - const T_partials_return error_bound = precision_derivatives; // precision for + const auto error_bound = precision_derivatives; // precision for // derivatives (controllable by user) - const T_partials_return log_error_derivative = log(error_bound); + const auto log_error_derivative = log(error_bound); const T_partials_return absolute_error_hcubature = 0.0; const T_partials_return relative_error_hcubature = .9 * error_bound; // eps_rel(Integration) @@ -419,14 +417,12 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, T_partials_return log_density = 0.0; auto ops_partials = make_partials_propagator(y_ref, a_ref, t0_ref, w_ref, v_ref, sv_ref, sw_ref, st0_ref); - ReturnT result = 0; + ret_t result = 0; // calculate density and partials for (size_t i = 0; i < N; i++) { if (sw_vec[i] == 0 && st0_vec[i] == 0) { - result - = result - + wiener5_lpdf(y_vec[i], a_vec[i], t0_vec[i], w_vec[i], + result += wiener5_lpdf(y_vec[i], a_vec[i], t0_vec[i], w_vec[i], v_vec[i], sv_vec[i], precision_derivatives); continue; } @@ -458,7 +454,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, T_partials_return density = internal::wiener7_integrate( [&](auto&&... args) { - return internal::wiener5_density( + return internal::wiener5_density( args...); }, hcubature_err, params, dim, xmin, xmax, @@ -490,10 +486,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, partials<1>(ops_partials)[i] = internal::wiener7_integrate( [&](auto&&... args) { - return internal::wiener5_grad_a< - true, T_partials_return, T_partials_return, - T_partials_return, T_partials_return, T_partials_return, - T_partials_return>(args...); + return internal::wiener5_grad_a(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, @@ -541,10 +534,9 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, partials<6>(ops_partials)[i] = 0; } else { if (st0_value == 0) { - derivative = internal::estimate_with_err_check( + derivative = internal::estimate_with_err_check<6, false, 0, true>( [&](auto&&... args) { - return internal::wiener7_grad_sw(args...); + return internal::wiener7_grad_sw(args...); }, hcubature_err, y_value - t0_value, a_value, v_value, w_value, sv_value, sw_value, log_error_absolute - LOG_TWO); @@ -552,7 +544,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, derivative = internal::wiener7_integrate( [&](auto&&... args) { - return internal::wiener7_grad_sw( + return internal::wiener7_grad_sw( args...); }, hcubature_err, params, 1, xmin, xmax, @@ -571,10 +563,9 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } else { const T_partials_return t0_st0 = t0_value + st0_value; if (sw_value == 0) { - f = internal::estimate_with_err_check( + f = internal::estimate_with_err_check<5, false, 0, true>( [&](auto&&... args) { - return internal::wiener5_density( + return internal::wiener5_density( args...); }, log_error_derivative + log(st0_value), y_value - t0_st0, a_value, @@ -586,7 +577,7 @@ inline ReturnT wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, sv_value, sw_value, 0, new_error); f = internal::wiener7_integrate( [&](auto&&... args) { - return internal::wiener5_density( + return internal::wiener5_density( args...); }, hcubature_err, params_st, 1, xmin, xmax, From 96ad22de4811058844e9f161281f78db5557d6cc Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 10 Jan 2024 15:41:39 -0500 Subject: [PATCH 130/179] update inline and run clang-format --- stan/math/prim/functor/hcubature.hpp | 70 ++-- stan/math/prim/prob.hpp | 4 +- stan/math/prim/prob/wiener5_lpdf.hpp | 316 +++++++++--------- stan/math/prim/prob/wiener_full_lpdf.hpp | 215 ++++++------ test/unit/math/mix/prob/util.hpp | 36 ++ .../math/mix/prob/wiener5_lpdf_0_test.cpp | 12 +- .../math/mix/prob/wiener5_lpdf_1_test.cpp | 61 +--- .../math/mix/prob/wiener5_lpdf_2_test.cpp | 61 +--- .../math/mix/prob/wiener5_lpdf_3_test.cpp | 61 +--- .../math/mix/prob/wiener5_lpdf_4_test.cpp | 61 +--- .../math/mix/prob/wiener_full_lpdf_0_test.cpp | 27 +- .../mix/prob/wiener_full_lpdf_10_test.cpp | 71 +--- .../mix/prob/wiener_full_lpdf_11_test.cpp | 71 +--- .../math/mix/prob/wiener_full_lpdf_1_test.cpp | 71 +--- .../math/mix/prob/wiener_full_lpdf_2_test.cpp | 71 +--- .../math/mix/prob/wiener_full_lpdf_3_test.cpp | 71 +--- .../math/mix/prob/wiener_full_lpdf_4_test.cpp | 71 +--- .../math/mix/prob/wiener_full_lpdf_5_test.cpp | 71 +--- .../math/mix/prob/wiener_full_lpdf_6_test.cpp | 71 +--- .../math/mix/prob/wiener_full_lpdf_7_test.cpp | 71 +--- .../math/mix/prob/wiener_full_lpdf_8_test.cpp | 71 +--- .../math/mix/prob/wiener_full_lpdf_9_test.cpp | 71 +--- 22 files changed, 525 insertions(+), 1180 deletions(-) create mode 100644 test/unit/math/mix/prob/util.hpp diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 16b9ba21d10..db04c7a117f 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -179,15 +179,14 @@ inline Eigen::Matrix signcombos( * @return numeric integral of the integrand and error */ template -auto gauss_kronrod(const F& integrand, const T_a a, - const T_b b, - const ParsPairT& pars_pair) { +inline auto gauss_kronrod(const F& integrand, const T_a a, const T_b b, + const ParsPairT& pars_pair) { using delta_t = return_type_t; const delta_t c = 0.5 * (a + b); const delta_t delta = 0.5 * (b - a); auto f0 = math::apply([](auto&& integrand, auto&& c, - auto&&... args) { return integrand(c, args...); }, - pars_pair, integrand, c); + auto&&... args) { return integrand(c, args...); }, + pars_pair, integrand, c); auto I = f0 * wd7[7]; auto Idash = f0 * gwd7[3]; @@ -196,13 +195,11 @@ auto gauss_kronrod(const F& integrand, const T_a a, deltax[i] = delta * xd7[i]; } for (auto i = 0; i != 7; i++) { - auto fx - = math::apply([](auto&& integrand, auto&& c, auto&& delta, - auto&&... args) { - return integrand(c + delta, args...) + - integrand(c - delta, args...); - }, - pars_pair, integrand, c, deltax[i]); + auto fx = math::apply( + [](auto&& integrand, auto&& c, auto&& delta, auto&&... args) { + return integrand(c + delta, args...) + integrand(c - delta, args...); + }, + pars_pair, integrand, c, deltax[i]); I += fx * wd7[i]; if (i % 2 == 1) { Idash += fx * gwd7[i / 2]; @@ -268,13 +265,13 @@ make_GenzMalik(const int dim) { * @return numeric integral of the integrand, error, and suggested coordinate to * subdivide next */ -template -auto integrate_GenzMalik( - const F& integrand, - const GenzMalik& genz_malik, const int dim, - const Eigen::Matrix& a, - const Eigen::Matrix& b, - const ParsTupleT& pars_tuple) { +template +inline auto integrate_GenzMalik(const F& integrand, const GenzMalik& genz_malik, + const int dim, + const Eigen::Matrix& a, + const Eigen::Matrix& b, + const ParsTupleT& pars_tuple) { auto&& points = std::get<0>(genz_malik); auto&& weights = std::get<1>(genz_malik); auto&& weights_low_deg = std::get<2>(genz_malik); @@ -421,28 +418,31 @@ struct Box { \f$b\f$. * @throw std::domain_error no errors will be thrown. */ -template -Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, - const Eigen::Matrix& a, - const Eigen::Matrix& b, - const int max_eval, const Scalar reqAbsError, - const Scalar reqRelError) { +template +inline Scalar hcubature(const F& integrand, const ParsTuple& pars, + const int dim, + const Eigen::Matrix& a, + const Eigen::Matrix& b, + const int max_eval, const Scalar reqAbsError, + const Scalar reqRelError) { using eig_vec_a = Eigen::Matrix; using eig_vec_b = Eigen::Matrix; const int maxEval = max_eval <= 0 ? 1000000 : max_eval; Scalar result; Scalar err; auto kdivide = 0; - std::tuple, 4>, - Eigen::Matrix, - Eigen::Matrix> genz_malik; + std::tuple< + std::array, 4>, + Eigen::Matrix, Eigen::Matrix> + genz_malik; if (dim == 1) { std::tie(result, err) = internal::gauss_kronrod(integrand, a[0], b[0], pars); } else { genz_malik = internal::make_GenzMalik(dim); - std::tie(result, err, kdivide) = internal::integrate_GenzMalik( - integrand, genz_malik, dim, a, b, pars); + std::tie(result, err, kdivide) + = internal::integrate_GenzMalik(integrand, genz_malik, dim, a, b, pars); } auto numevals = (dim == 1) ? 15 : 1 + 4 * dim + 2 * dim * (dim - 1) + std::pow(2, dim); @@ -489,12 +489,10 @@ Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, std::tie(result_2, err_2) = internal::gauss_kronrod(integrand, box.a_[0], mb[0], pars); } else { - std::tie(result_1, err_1, kdivide_1) - = internal::integrate_GenzMalik(integrand, genz_malik, - dim, ma, box.b_, pars); - std::tie(result_2, err_2, kdivide_2) - = internal::integrate_GenzMalik(integrand, genz_malik, - dim, box.a_, mb, pars); + std::tie(result_1, err_1, kdivide_1) = internal::integrate_GenzMalik( + integrand, genz_malik, dim, ma, box.b_, pars); + std::tie(result_2, err_2, kdivide_2) = internal::integrate_GenzMalik( + integrand, genz_malik, dim, box.a_, mb, pars); } box_t box1(std::move(ma), std::move(box.b_), result_1, kdivide_1); box_t box2(std::move(box.a_), std::move(mb), result_2, kdivide_2); diff --git a/stan/math/prim/prob.hpp b/stan/math/prim/prob.hpp index 36c65ec84a4..598663b71e2 100644 --- a/stan/math/prim/prob.hpp +++ b/stan/math/prim/prob.hpp @@ -370,9 +370,9 @@ #include #include #include -#include -#include #include +#include +#include #include #include #include diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 902e1afd9e1..314269d8eae 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -7,6 +7,8 @@ namespace stan { namespace math { namespace internal { +enum GradientCalc { OFF = 0, ON = 1 }; + /** * Calculate the 'error_term' term for a wiener5 density or gradient * @@ -17,10 +19,9 @@ namespace internal { * @param sv The inter-trial variability of the drift rate * @return 'error_term' term */ -template +template inline auto wiener5_compute_error_term(T_y&& y, T_a&& a, T_v&& v_value, - T_w&& w_value, T_sv&& sv) noexcept { + T_w&& w_value, T_sv&& sv) noexcept { const auto w = 1.0 - w_value; const auto v = -v_value; const auto sv_sqr = square(sv); @@ -46,20 +47,19 @@ inline auto wiener5_compute_error_term(T_y&& y, T_a&& a, T_v&& v_value, * @param sv The inter-trial variability of the drift rate * @return 'density_part_one' term */ -template inline auto wiener5_density_part_one(T_y&& y, T_a&& a, T_v_value&& v_value, - T_w_value&& w_value, - T_sv&& sv) noexcept { + T_w_value&& w_value, T_sv&& sv) noexcept { const auto w = 1.0 - w_value; const auto v = -v_value; const auto sv_sqr = square(sv); const auto one_plus_svsqr_y = 1 + sv_sqr * y; if (GradT) { - return -0.5 - * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - (2.0 * a * v * w)) - + square(v)) - / square(one_plus_svsqr_y); + return -0.5 + * (square(sv_sqr) * (y + square(a * w)) + + sv_sqr * (1 - (2.0 * a * v * w)) + square(v)) + / square(one_plus_svsqr_y); } else { if (GradA) { return (-v * w + sv_sqr * square(w) * a) / one_plus_svsqr_y; @@ -67,7 +67,6 @@ inline auto wiener5_density_part_one(T_y&& y, T_a&& a, T_v_value&& v_value, return (-v * a + sv_sqr * square(a) * w) / one_plus_svsqr_y; } } - } /** @@ -83,29 +82,26 @@ inline auto wiener5_density_part_one(T_y&& y, T_a&& a, T_v_value&& v_value, * @param error The error tolerance * @return 'n_terms_small_t' term */ -template -inline Scalar wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, - Scalar error) noexcept { - const Scalar two_error = 2.0 * error; - const Scalar y_asq = y / square(a); - const Scalar two_log_a = 2 * log(a); - const Scalar log_y_asq = log(y) - two_log_a; - const Scalar w = 1.0 - w_value; - - const Scalar n_1_factor = Density ? 2 : 3; - const Scalar n_1 = (sqrt(n_1_factor * y_asq) + w) / 2.0; - Scalar u_eps; - if (Density || GradW) { - u_eps = fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log_y_asq + two_error); - } else { - u_eps = fmin(-3.0, - (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + two_error)); - } - const Scalar arg_mult = (Density || GradW) ? 1 : 3; - const Scalar arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); +template +inline auto wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, + T_err&& error) noexcept { + const auto two_error = 2.0 * error; + const auto y_asq = y / square(a); + const auto two_log_a = 2 * log(a); + const auto log_y_asq = log(y) - two_log_a; + const auto w = 1.0 - w_value; + + const auto n_1_factor = Density ? 2 : 3; + const auto n_1 = (sqrt(n_1_factor * y_asq) + w) / 2.0; + auto u_eps = (Density || GradW) + ? fmin(-1.0, LOG_TWO + LOG_PI + 2.0 * log_y_asq + two_error) + : fmin(-3.0, (log(8.0) - log(27.0) + LOG_PI + 4.0 * log_y_asq + + two_error)); + const auto arg_mult = (Density || GradW) ? 1 : 3; + const auto arg = -arg_mult * y_asq * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - const Scalar n_2 + const auto n_2 = (arg > 0) ? GradW ? 0.5 * (sqrt(arg) + w) : 0.5 * (sqrt(arg) - w) : n_1; return ceil(fmax(n_1, n_2)); @@ -124,17 +120,18 @@ inline Scalar wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, * @param error The error tolerance * @return 'n_terms_large_t' term */ -template inline auto wiener5_n_terms_large_t(T_y&& y, T_a&& a, T_w_value&& w_value, - T_err error) noexcept { + T_err&& error) noexcept { const auto y_asq = y / square(a); const auto log_y_asq = log(y) - 2 * log(a); static constexpr double PI_SQUARED = pi() * pi(); if (Density) { auto n_1 = 1.0 / (pi() * sqrt(y_asq)); const auto two_log_piy = -2.0 * (LOG_PI + log_y_asq + error); - auto n_2 = (two_log_piy >= 0) ? sqrt(two_log_piy / (PI_SQUARED * y_asq)) : 0.0; + auto n_2 + = (two_log_piy >= 0) ? sqrt(two_log_piy / (PI_SQUARED * y_asq)) : 0.0; return ceil(fmax(n_1, n_2)); } else { const auto n_1_factor = GradW ? 2 : 3; @@ -147,12 +144,10 @@ inline auto wiener5_n_terms_large_t(T_y&& y, T_a&& a, T_w_value&& w_value, const auto u_eps = fmin(-1, u_eps_arg); const auto arg_mult = GradW ? 1 : (2.0 / PI_SQUARED / y_asq); const auto arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - auto n_2 = GradW ? - ((arg > 0) ? sqrt(arg / y_asq) / pi() : n_1) - : ((arg > 0) ? sqrt(arg) : n_1); + auto n_2 = GradW ? ((arg > 0) ? sqrt(arg / y_asq) / pi() : n_1) + : ((arg > 0) ? sqrt(arg) : n_1); return ceil(fmax(n_1, n_2)); } - } /** @@ -169,7 +164,7 @@ inline auto wiener5_n_terms_large_t(T_y&& y, T_a&& a, T_w_value&& w_value, * @param n_terms_large_t The n_terms_large_t term * @return 'result' sum and its sign */ -template inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, T_nsmall&& n_terms_small_t, @@ -278,25 +273,27 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, * @param err The log error tolerance * @return density */ -template +template inline auto wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, - const T_w& w_value, const T_sv& sv, - T_err err = log(1e-12)) noexcept { + const T_w& w_value, const T_sv& sv, + T_err&& err = log(1e-12)) noexcept { const auto error_term = wiener5_compute_error_term(y, a, v_value, w_value, sv); const auto error = (err - error_term); const auto n_terms_small_t - = wiener5_n_terms_small_t(y, a, w_value, error); + = wiener5_n_terms_small_t( + y, a, w_value, error); const auto n_terms_large_t - = wiener5_n_terms_large_t(y, a, w_value, error); + = wiener5_n_terms_large_t( + y, a, w_value, error); - auto res = wiener5_log_sum_exp( + auto res = wiener5_log_sum_exp( y, a, w_value, n_terms_small_t, n_terms_large_t) .first; if (2 * n_terms_small_t <= n_terms_large_t) { auto log_density = error_term - 0.5 * LOG_TWO - LOG_SQRT_PI - - 1.5 * (log(y) - 2 * log(a)) + res; + - 1.5 * (log(y) - 2 * log(a)) + res; return NaturalScale ? exp(log_density) : log_density; } else { auto log_density = error_term + res + LOG_PI; @@ -319,42 +316,45 @@ inline auto wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, * @param err The log error tolerance * @return Gradient w.r.t. t */ -template +template inline auto wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, - const T_w& w_value, const T_sv& sv, - T_err err = log(1e-12)) noexcept { + const T_w& w_value, const T_sv& sv, + T_err&& err = log(1e-12)) noexcept { const auto two_log_a = 2 * log(a); const auto log_y_asq = log(y) - two_log_a; const auto error_term = wiener5_compute_error_term(y, a, v_value, w_value, sv); - const auto density_part_one = wiener5_density_part_one( - y, a, v_value, w_value, sv); + const auto density_part_one + = wiener5_density_part_one( + y, a, v_value, w_value, sv); const auto error = (err - error_term) + two_log_a; const auto n_terms_small_t - = wiener5_n_terms_small_t(y, a, w_value, error); + = wiener5_n_terms_small_t( + y, a, w_value, error); const auto n_terms_large_t - = wiener5_n_terms_large_t(y, a, w_value, error); - auto wiener_res = wiener5_log_sum_exp( - y, a, w_value, n_terms_small_t, n_terms_large_t); + = wiener5_n_terms_large_t( + y, a, w_value, error); + auto wiener_res = wiener5_log_sum_exp( + y, a, w_value, n_terms_small_t, n_terms_large_t); auto&& result = wiener_res.first; auto&& newsign = wiener_res.second; const auto error_log_density = log(fmax(fabs(density_part_one - 1.5 / y), fabs(density_part_one))); - const auto log_density = wiener5_density( + const auto log_density = wiener5_density( y, a, v_value, w_value, sv, err - error_log_density); if (2 * n_terms_small_t < n_terms_large_t) { - auto ans = density_part_one - 1.5 / y - + newsign - * exp(error_term - two_log_a - 1.5 * LOG_TWO - LOG_SQRT_PI - - 3.5 * log_y_asq + result - log_density); - return WrtLog ? ans * exp(log_density) : ans; -} else { - auto ans = density_part_one - - newsign - * exp(error_term - two_log_a + 3.0 * LOG_PI - LOG_TWO + result - - log_density); - return WrtLog ? ans * exp(log_density) : ans; + auto ans = density_part_one - 1.5 / y + + newsign + * exp(error_term - two_log_a - 1.5 * LOG_TWO - LOG_SQRT_PI + - 3.5 * log_y_asq + result - log_density); + return WrtLog ? ans * exp(log_density) : ans; + } else { + auto ans = density_part_one + - newsign + * exp(error_term - two_log_a + 3.0 * LOG_PI - LOG_TWO + + result - log_density); + return WrtLog ? ans * exp(log_density) : ans; } } @@ -373,42 +373,46 @@ inline auto wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, * @param err The log error tolerance * @return Gradient w.r.t. a */ -template +template inline auto wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, - const T_w& w_value, const T_sv& sv, - T_err err = log(1e-12)) noexcept { + const T_w& w_value, const T_sv& sv, + T_err&& err = log(1e-12)) noexcept { const auto two_log_a = 2 * log(a); const auto log_y_asq = log(y) - two_log_a; const auto error_term = wiener5_compute_error_term(y, a, v_value, w_value, sv); - const auto density_part_one = wiener5_density_part_one( - y, a, v_value, w_value, sv); + const auto density_part_one + = wiener5_density_part_one( + y, a, v_value, w_value, sv); const auto error = err - error_term + 3 * log(a) - log(y) - LOG_TWO; const auto n_terms_small_t - = wiener5_n_terms_small_t(y, a, w_value, error); + = wiener5_n_terms_small_t( + y, a, w_value, error); const auto n_terms_large_t - = wiener5_n_terms_large_t(y, a, w_value, error); - auto wiener_res = wiener5_log_sum_exp( - y, a, w_value, n_terms_small_t, n_terms_large_t); + = wiener5_n_terms_large_t( + y, a, w_value, error); + auto wiener_res = wiener5_log_sum_exp( + y, a, w_value, n_terms_small_t, n_terms_large_t); auto&& result = wiener_res.first; auto&& newsign = wiener_res.second; const auto error_log_density = log( fmax(fabs(density_part_one + 1.0 / a), fabs(density_part_one - 2.0 / a))); - const auto log_density = wiener5_density( + const auto log_density = wiener5_density( y, a, v_value, w_value, sv, err - error_log_density); if (2 * n_terms_small_t < n_terms_large_t) { - auto ans = density_part_one + 1.0 / a + auto ans + = density_part_one + 1.0 / a - newsign * exp(-0.5 * LOG_TWO - LOG_SQRT_PI - 2.5 * log(y) + 2.0 * two_log_a + error_term + result - log_density); return WrtLog ? ans * exp(log_density) : ans; } else { auto ans = density_part_one - 2.0 / a - + newsign - * exp(log(y) + error_term - 3 * (log(a) - LOG_PI) + result - - log_density); + + newsign + * exp(log(y) + error_term - 3 * (log(a) - LOG_PI) + result + - log_density); return WrtLog ? ans * exp(log_density) : ans; } } @@ -428,11 +432,11 @@ inline auto wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, * @param err The log error tolerance * @return Gradient w.r.t. v */ -template +template inline auto wiener5_grad_v(const T_y& y, const T_a& a, const T_v& v_value, - const T_w& w_value, const T_sv& sv, - T_err err = log(1e-12)) noexcept { + const T_w& w_value, const T_sv& sv, + T_err&& err = log(1e-12)) noexcept { auto ans = (a * (1 - w_value) - v_value * y) / (1.0 + square(sv) * y); if (WrtLog) { return ans * wiener5_density(y, a, v_value, w_value, sv, err); @@ -456,39 +460,41 @@ inline auto wiener5_grad_v(const T_y& y, const T_a& a, const T_v& v_value, * @param err The log error tolerance * @return Gradient w.r.t. w */ -template +template inline auto wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, - const T_w& w_value, const T_sv& sv, - T_err err = log(1e-12)) noexcept { + const T_w& w_value, const T_sv& sv, + T_err&& err = log(1e-12)) noexcept { const auto two_log_a = 2 * log(a); const auto log_y_asq = log(y) - two_log_a; const auto error_term = wiener5_compute_error_term(y, a, v_value, w_value, sv); const auto density_part_one - = wiener5_density_part_one(y, a, v_value, w_value, - sv); + = wiener5_density_part_one( + y, a, v_value, w_value, sv); const auto error = (err - error_term); const auto n_terms_small_t - = wiener5_n_terms_small_t(y, a, w_value, error); + = wiener5_n_terms_small_t( + y, a, w_value, error); const auto n_terms_large_t - = wiener5_n_terms_large_t(y, a, w_value, error); - auto wiener_res - = wiener5_log_sum_exp(y, a, w_value, n_terms_small_t, - n_terms_large_t); + = wiener5_n_terms_large_t( + y, a, w_value, error); + auto wiener_res = wiener5_log_sum_exp( + y, a, w_value, n_terms_small_t, n_terms_large_t); auto&& result = wiener_res.first; auto&& newsign = wiener_res.second; - const auto log_density = wiener5_density( + const auto log_density = wiener5_density( y, a, v_value, w_value, sv, err - log(fabs(density_part_one))); if (2 * n_terms_small_t < n_terms_large_t) { auto ans = -(density_part_one - - newsign - * exp(result - (log_density - error_term) - 2.5 * log_y_asq - - 0.5 * LOG_TWO - 0.5 * LOG_PI)); + - newsign + * exp(result - (log_density - error_term) + - 2.5 * log_y_asq - 0.5 * LOG_TWO - 0.5 * LOG_PI)); return WrtLog ? ans * exp(log_density) : ans; } else { - auto ans = -(density_part_one + auto ans + = -(density_part_one + newsign * exp(result - (log_density - error_term) + 2 * LOG_PI)); return WrtLog ? ans * exp(log_density) : ans; } @@ -509,21 +515,19 @@ inline auto wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, * @param err The log error tolerance * @return Gradient w.r.t. sv */ -template +template inline auto wiener5_grad_sv(const T_y& y, const T_a& a, const T_v& v_value, - const T_w& w_value, const T_sv& sv, - T_err err = log(1e-12)) noexcept { + const T_w& w_value, const T_sv& sv, + T_err&& err = log(1e-12)) noexcept { const auto one_plus_svsqr_y = 1 + square(sv) * y; const auto w = 1.0 - w_value; const auto v = -v_value; const auto t1 = -y / one_plus_svsqr_y; const auto t2 = (square(a * w) + 2 * a * v * w * y + square(v * y)) - / square(one_plus_svsqr_y); + / square(one_plus_svsqr_y); const auto ans = sv * (t1 + t2); - return WrtLog ? ans - * wiener5_density(y, a, v_value, w_value, - sv, err) + return WrtLog ? ans * wiener5_density(y, a, v_value, w_value, sv, err) : ans; } @@ -560,11 +564,11 @@ inline void assign_err(std::tuple& args_tuple, Scalar err) { * @param args_tuple Tuple of arguments to pass to functor * @param log_result Whether the function result is already on the log-scale */ -template -inline auto estimate_with_err_check(const F& functor, T_err err, - ArgsTupleT&&... args_tuple) { +template +inline auto estimate_with_err_check(F&& functor, T_err&& err, + ArgsTupleT&&... args_tuple) { auto result = functor(args_tuple...); auto log_fabs_result = LogResult ? log(fabs(result)) : fabs(result); if (log_fabs_result < err) { @@ -573,8 +577,9 @@ inline auto estimate_with_err_check(const F& functor, T_err err, const auto new_error = GradW7 ? err + log_fabs_result + LOG_TWO : err + log_fabs_result; assign_err(std::get(err_args_tuple), new_error); - result = math::apply([&](auto&&... args) { return functor(args...); }, - err_args_tuple); + result + = math::apply([](auto&& func, auto&&... args) { return func(args...); }, + err_args_tuple, functor); } return result; } @@ -582,7 +587,7 @@ inline auto estimate_with_err_check(const F& functor, T_err err, /** * Log-density function for the 5-parameter Wiener density. - * See 'wiener_full_lpdf' for more comprehensive documentation + * See 'wiener_lpdf' for more comprehensive documentation * * @tparam T_y type of scalar * @tparam T_a type of boundary @@ -602,17 +607,15 @@ inline auto estimate_with_err_check(const F& functor, T_err err, * the specified arguments for upper boundary responses */ template -inline auto wiener5_lpdf( - const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, - const T_sv& sv, const T_precision& precision_derivatives) { + typename T_w, typename T_v, typename T_sv, typename T_precision> +inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, + const T_w& w, const T_v& v, const T_sv& sv, + const T_precision& precision_derivatives) { using T_partials_return = partials_return_t; using ret_t = return_type_t; if (!include_summand::value) { return ret_t(0.0); } - using T_y_ref = ref_type_if_t::value, T_y>; using T_a_ref = ref_type_if_t::value, T_a>; using T_t0_ref = ref_type_if_t::value, T_t0>; @@ -699,24 +702,25 @@ inline auto wiener5_lpdf( const auto w_value = w_vec.val(i); const auto v_value = v_vec.val(i); const auto sv_value = sv_vec.val(i); - - auto l_density = internal::estimate_with_err_check<5, false, 0, false>( - [&](auto&&... args) { - return internal::wiener5_density(args...); + using internal::GradientCalc; + auto l_density = internal::estimate_with_err_check<5, GradientCalc::OFF, 0, + GradientCalc::OFF>( + [](auto&&... args) { + return internal::wiener5_density(args...); }, log_error_density - LOG_TWO, y_value - t0_value, a_value, v_value, w_value, sv_value, log_error_absolute); log_density += l_density; - const auto new_est_err - = l_density + log_error_derivative - LOG_FOUR; + const auto new_est_err = l_density + log_error_derivative - LOG_FOUR; // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 - const auto deriv_y = internal::estimate_with_err_check<5, false, 0, true>( - [&](auto&&... args) { - return internal::wiener5_grad_t(args...); + const auto deriv_y = internal::estimate_with_err_check<5, GradientCalc::OFF, + 0, GradientCalc::ON>( + [](auto&&... args) { + return internal::wiener5_grad_t(args...); }, new_est_err, y_value - t0_value, a_value, v_value, w_value, sv_value, log_error_absolute); @@ -726,33 +730,39 @@ inline auto wiener5_lpdf( partials<0>(ops_partials)[i] = deriv_y; } if (!is_constant_all::value) { - partials<1>(ops_partials)[i] = internal::estimate_with_err_check<5, false, 0, true>( - [&](auto&&... args) { - return internal::wiener5_grad_a(args...); - }, - new_est_err, y_value - t0_value, a_value, v_value, w_value, sv_value, - log_error_absolute); + partials<1>(ops_partials)[i] + = internal::estimate_with_err_check<5, GradientCalc::OFF, 0, + GradientCalc::ON>( + [](auto&&... args) { + return internal::wiener5_grad_a(args...); + }, + new_est_err, y_value - t0_value, a_value, v_value, w_value, + sv_value, log_error_absolute); } if (!is_constant_all::value) { partials<2>(ops_partials)[i] = -deriv_y; } if (!is_constant_all::value) { - partials<3>(ops_partials)[i] = internal::estimate_with_err_check<5, false, 0, true>( - [&](auto&&... args) { - return internal::wiener5_grad_w(args...); - }, - new_est_err, y_value - t0_value, a_value, v_value, w_value, sv_value, - log_error_absolute); + partials<3>(ops_partials)[i] + = internal::estimate_with_err_check<5, GradientCalc::OFF, 0, + GradientCalc::ON>( + [](auto&&... args) { + return internal::wiener5_grad_w(args...); + }, + new_est_err, y_value - t0_value, a_value, v_value, w_value, + sv_value, log_error_absolute); } if (!is_constant_all::value) { partials<4>(ops_partials)[i] - = internal::wiener5_grad_v( - y_value - t0_value, a_value, v_value, w_value, sv_value, log_error_absolute_val); + = internal::wiener5_grad_v( + y_value - t0_value, a_value, v_value, w_value, sv_value, + log_error_absolute_val); } if (!is_constant_all::value) { partials<5>(ops_partials)[i] - = internal::wiener5_grad_sv( - y_value - t0_value, a_value, v_value, w_value, sv_value, log_error_absolute_val); + = internal::wiener5_grad_sv( + y_value - t0_value, a_value, v_value, w_value, sv_value, + log_error_absolute_val); } } // end for loop return ops_partials.build(log_density); diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 7f299be99de..2492473deb5 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -21,20 +21,19 @@ namespace internal { * @param log_error The log error tolerance * @return Gradient w.r.t. sw */ -template +template inline auto wiener7_grad_sw(const T_y& y, const T_a& a, const T_v& v, - const T_w& w, const T_sv& sv, const T_sw& sw, - T_err log_error) { + const T_w& w, const T_sv& sv, const T_sw& sw, + T_err log_error) { auto low = w - sw / 2.0; low = (0 > low) ? 0 : low; + const auto lower_value + = wiener5_density(y, a, v, low, sv, log_error); auto high = w + sw / 2.0; high = (1 < high) ? 1 : high; - - const auto lower_value - = wiener5_density(y, a, v, low, sv, log_error); const auto upper_value - = wiener5_density(y, a, v, high, sv, log_error); + = wiener5_density(y, a, v, high, sv, log_error); return 0.5 * (lower_value + upper_value) / sw; } @@ -61,11 +60,12 @@ inline auto wiener7_grad_sw(const T_y& y, const T_a& a, const T_v& v, * @param log_error The log error tolerance * @return Functor applied to arguments */ -template * = nullptr> -inline Scalar conditionally_grad_sw(const F& functor, Scalar y_diff, Scalar a, - Scalar v, Scalar w, Scalar sv, Scalar sw, - Scalar log_error) { +inline auto conditionally_grad_sw(F&& functor, T_y&& y_diff, T_a&& a, T_v&& v, + T_w&& w, T_sv&& sv, T_sw&& sw, + T_err&& log_error) { return functor(y_diff, a, v, w, sv, log_error); } @@ -93,11 +93,12 @@ inline Scalar conditionally_grad_sw(const F& functor, Scalar y_diff, Scalar a, * @param log_error The log error tolerance * @return Functor applied to arguments */ -template * = nullptr> -inline Scalar conditionally_grad_sw(const F& functor, Scalar y_diff, Scalar a, - Scalar v, Scalar w, Scalar sv, Scalar sw, - Scalar log_error) { +inline auto conditionally_grad_sw(F&& functor, T_y&& y_diff, T_a&& a, T_v&& v, + T_w&& w, T_sv&& sv, T_sw&& sw, + T_err&& log_error) { return functor(y_diff, a, v, w, sv, sw, log_error); } @@ -116,31 +117,35 @@ inline Scalar conditionally_grad_sw(const F& functor, Scalar y_diff, Scalar a, * @param args Additional arguments to be passed to the hcubature function * @return Wiener7 density or gradient calculated by integration */ -template > -ReturnT wiener7_integrate(const Wiener7FunctorT& wiener7_functor, - Scalar hcubature_err, TArgs&&... args) { +template +inline auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, + T_err&& hcubature_err, TArgs&&... args) { const auto wiener7_integrand_impl = - [&](auto&& x, Scalar y, Scalar a, Scalar v, Scalar w, Scalar t0, - Scalar sv, Scalar sw, Scalar st0, Scalar log_error) { + [&wiener7_functor](auto&& x, auto&& y, auto&& a, auto&& v, auto&& w, + auto&& t0, auto&& sv, auto&& sw, auto&& st0, + auto&& log_error) { + using ret_t + = return_type_t; scalar_seq_view x_vec(x); - const Scalar sw_val = GradSW ? 0 : sw; - const Scalar new_w = (sw_val != 0) ? w + sw_val * (x_vec[0] - 0.5) : w; - const Scalar new_t0 = (sw_val != 0) - ? ((st0 != 0) ? t0 + st0 * x_vec[1] : t0) - : ((st0 != 0) ? t0 + st0 * x_vec[0] : t0); + const auto sw_val = GradSW ? 0 : sw; + const auto new_w = w + sw_val * (x_vec[0] - 0.5); + const auto new_t0 = (sw_val != 0) + ? ((st0 != 0) ? t0 + st0 * x_vec[1] : t0) + : ((st0 != 0) ? t0 + st0 * x_vec[0] : t0); if (y - new_t0 <= 0) { - return static_cast(0.0); + return ret_t(0.0); } else { - return conditionally_grad_sw( - wiener7_functor, y - new_t0, a, v, new_w, sv, sw, log_error); + return ret_t(conditionally_grad_sw( + wiener7_functor, y - new_t0, a, v, new_w, sv, sw, log_error)); } }; - const auto functor = [&](auto&&... int_args) { + const auto functor = [&wiener7_integrand_impl](auto&&... int_args) { return hcubature(wiener7_integrand_impl, int_args...); }; - return estimate_with_err_check<0, GradW7, 8, true>( + return estimate_with_err_check<0, GradW7, 8, GradientCalc::ON>( functor, hcubature_err, args...); } } // namespace internal @@ -191,7 +196,7 @@ ReturnT wiener7_integrate(const Wiener7FunctorT& wiener7_functor, * \c t0 is the lower bound of the variability interval; * \c w is the mean of the variability interval. * - * See \b Details below for more details on how to use \c wiener_full_lpdf(). + * See \b Details below for more details on how to use \c wiener_lpdf(). * * @tparam T_y type of scalar * @tparam T_a type of boundary separation @@ -225,14 +230,14 @@ ReturnT wiener7_integrate(const Wiener7FunctorT& wiener7_functor, * * The function can be called by @code - target += wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + target += wiener_lpdf(y, a, t0, w, v, sv, sw, st0); @endcode * or @code y ~ wiener_full(a, t0, w, v, sv, sw, st0); @endcode * - * By default \c wiener_full_lpdf() gives the log of the + * By default \c wiener_lpdf() gives the log of the * Wiener first-passage time probability density function for the \e upper response * boundary. To use the \e lower response boundary \c v and \c w must be changed @@ -247,21 +252,21 @@ ReturnT wiener7_integrate(const Wiener7FunctorT& wiener7_functor, * variability for the relative starting point is needed one can write something like: @code - target += wiener_full_lpdf(y, a, t0, w, v, sv, 0, st0) + target += wiener_lpdf(y, a, t0, w, v, sv, 0, st0) @endcode * If no inter-trial variability is needed at all one can write something like: @code - target += wiener_full_lpdf(y, a, t0, w, v, 0, 0, 0) + target += wiener_lpdf(y, a, t0, w, v, 0, 0, 0) @endcode * If for some reason no non-decision time is assumed one can write something like: @code - target += wiener_full_lpdf(y, a, 0, w, v, sv, sw, 0) + target += wiener_lpdf(y, a, 0, w, v, sv, sw, 0) @endcode * * To also control the precision in the estimation of the partial derivatives: @code - target += wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0, precision); + target += wiener_lpdf(y, a, t0, w, v, sv, sw, st0, precision); @endcode * * @@ -293,10 +298,10 @@ ReturnT wiener7_integrate(const Wiener7FunctorT& wiener7_functor, template -inline auto wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, - const T_w& w, const T_v& v, const T_sv& sv, - const T_sw& sw, const T_st0& st0, - const double& precision_derivatives = 1e-4) { +inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, + const T_w& w, const T_v& v, const T_sv& sv, + const T_sw& sw, const T_st0& st0, + const double& precision_derivatives = 1e-4) { using ret_t = return_type_t; if (!include_summand::value) { @@ -315,7 +320,7 @@ inline auto wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, using T_partials_return = partials_return_t; - static constexpr const char* function_name = "wiener_full_lpdf"; + static constexpr const char* function_name = "wiener_lpdf"; check_consistent_sizes(function_name, "Random variable", y, "Boundary separation", a, "Drift rate", v, "A-priori bias", w, "Nondecision time", t0, @@ -386,26 +391,31 @@ inline auto wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, size_t N_beta_sw = max_size(w, sw); for (size_t i = 0; i < N_beta_sw; ++i) { if (unlikely(w_vec[i] - .5 * sw_vec[i] <= 0)) { - std::stringstream msg; - msg << ", but must be smaller than 2*(A-priori bias) = " << 2 * w_vec[i]; - std::string msg_str(msg.str()); - throw_domain_error(function_name, - "Inter-trial variability in A-priori bias", sw_vec[i], - " = ", msg_str.c_str()); + [&]() STAN_COLD_PATH { + std::stringstream msg; + msg << ", but must be smaller than 2*(A-priori bias) = " + << 2 * w_vec[i]; + std::string msg_str(msg.str()); + throw_domain_error(function_name, + "Inter-trial variability in A-priori bias", + sw_vec[i], " = ", msg_str.c_str()); + }(); } if (unlikely(w_vec[i] + .5 * sw_vec[i] >= 1)) { - std::stringstream msg; - msg << ", but must be smaller than 2*(1-A-priori bias) = " - << 2 * (1 - w_vec[i]); - std::string msg_str(msg.str()); - throw_domain_error(function_name, - "Inter-trial variability in A-priori bias", sw_vec[i], - " = ", msg_str.c_str()); + [&]() STAN_COLD_PATH { + std::stringstream msg; + msg << ", but must be smaller than 2*(1-A-priori bias) = " + << 2 * (1 - w_vec[i]); + std::string msg_str(msg.str()); + throw_domain_error(function_name, + "Inter-trial variability in A-priori bias", + sw_vec[i], " = ", msg_str.c_str()); + }(); } } const T_partials_return log_error_density - = log(1e-6); // precision for density + = log(1e-6); // precision for density const auto error_bound = precision_derivatives; // precision for // derivatives (controllable by user) const auto log_error_derivative = log(error_bound); @@ -422,8 +432,8 @@ inline auto wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, // calculate density and partials for (size_t i = 0; i < N; i++) { if (sw_vec[i] == 0 && st0_vec[i] == 0) { - result += wiener5_lpdf(y_vec[i], a_vec[i], t0_vec[i], w_vec[i], - v_vec[i], sv_vec[i], precision_derivatives); + result += wiener_lpdf(y_vec[i], a_vec[i], t0_vec[i], w_vec[i], + v_vec[i], sv_vec[i], precision_derivatives); continue; } const T_partials_return y_value = y_vec.val(i); @@ -448,14 +458,14 @@ inline auto wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, T_partials_return hcubature_err = log_error_absolute - log_error_density + LOG_TWO + 1; + using internal::GradientCalc; const auto params = std::make_tuple(y_value, a_value, v_value, w_value, t0_value, sv_value, sw_value, st0_value, log_error_absolute - LOG_TWO); T_partials_return density - = internal::wiener7_integrate( - [&](auto&&... args) { - return internal::wiener5_density( - args...); + = internal::wiener7_integrate( + [](auto&&... args) { + return internal::wiener5_density(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, @@ -468,9 +478,9 @@ inline auto wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, // computation of derivative for t and precision check in order to give // the value as deriv_t to edge1 and as -deriv_t to edge5 const T_partials_return deriv_t_7 - = internal::wiener7_integrate( - [&](auto&&... args) { - return internal::wiener5_grad_t(args...); + = internal::wiener7_integrate( + [](auto&&... args) { + return internal::wiener5_grad_t(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, @@ -484,9 +494,9 @@ inline auto wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } if (!is_constant_all::value) { partials<1>(ops_partials)[i] - = internal::wiener7_integrate( - [&](auto&&... args) { - return internal::wiener5_grad_a(args...); + = internal::wiener7_integrate( + [](auto&&... args) { + return internal::wiener5_grad_a(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, @@ -498,9 +508,9 @@ inline auto wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } if (!is_constant_all::value) { partials<3>(ops_partials)[i] - = internal::wiener7_integrate( - [&](auto&&... args) { - return internal::wiener5_grad_w(args...); + = internal::wiener7_integrate( + [](auto&&... args) { + return internal::wiener5_grad_w(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, @@ -509,9 +519,9 @@ inline auto wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } if (!is_constant_all::value) { partials<4>(ops_partials)[i] - = internal::wiener7_integrate( - [&](auto&&... args) { - return internal::wiener5_grad_v(args...); + = internal::wiener7_integrate( + [](auto&&... args) { + return internal::wiener5_grad_v(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, @@ -520,9 +530,9 @@ inline auto wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } if (!is_constant_all::value) { partials<5>(ops_partials)[i] - = internal::wiener7_integrate( - [&](auto&&... args) { - return internal::wiener5_grad_sv(args...); + = internal::wiener7_integrate( + [](auto&&... args) { + return internal::wiener5_grad_sv(args...); }, hcubature_err, params, dim, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, @@ -534,24 +544,20 @@ inline auto wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, partials<6>(ops_partials)[i] = 0; } else { if (st0_value == 0) { - derivative = internal::estimate_with_err_check<6, false, 0, true>( - [&](auto&&... args) { - return internal::wiener7_grad_sw(args...); - }, + derivative = internal::estimate_with_err_check<6, GradientCalc::OFF, + 0, GradientCalc::ON>( + [](auto&&... args) { return internal::wiener7_grad_sw(args...); }, hcubature_err, y_value - t0_value, a_value, v_value, w_value, sv_value, sw_value, log_error_absolute - LOG_TWO); } else { - derivative - = internal::wiener7_integrate( - [&](auto&&... args) { - return internal::wiener7_grad_sw( - args...); - }, - hcubature_err, params, 1, xmin, xmax, - maximal_evaluations_hcubature, absolute_error_hcubature, - relative_error_hcubature / 2); + derivative = internal::wiener7_integrate( + [](auto&&... args) { return internal::wiener7_grad_sw(args...); }, + hcubature_err, params, 1, xmin, xmax, + maximal_evaluations_hcubature, absolute_error_hcubature, + relative_error_hcubature / 2); } - partials<6>(ops_partials)[i] = derivative / density - 1 / sw_value; + partials<6>(ops_partials)[i] = derivative / density - 1.0 / sw_value; } } if (!is_constant_all::value) { @@ -563,26 +569,25 @@ inline auto wiener_full_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } else { const T_partials_return t0_st0 = t0_value + st0_value; if (sw_value == 0) { - f = internal::estimate_with_err_check<5, false, 0, true>( - [&](auto&&... args) { - return internal::wiener5_density( - args...); + f = internal::estimate_with_err_check<5, GradientCalc::OFF, 0, + GradientCalc::ON>( + [](auto&&... args) { + return internal::wiener5_density(args...); }, log_error_derivative + log(st0_value), y_value - t0_st0, a_value, v_value, w_value, sv_value, log_error_absolute - LOG_TWO); } else { const T_partials_return new_error = log_error_absolute - LOG_TWO; - const auto& params_st + auto params_st = std::make_tuple(y_value, a_value, v_value, w_value, t0_st0, - sv_value, sw_value, 0, new_error); - f = internal::wiener7_integrate( - [&](auto&&... args) { - return internal::wiener5_density( - args...); + sv_value, sw_value, 0.0, new_error); + f = internal::wiener7_integrate( + [](auto&&... args) { + return internal::wiener5_density(args...); }, hcubature_err, params_st, 1, xmin, xmax, maximal_evaluations_hcubature, absolute_error_hcubature, - relative_error_hcubature / 2); + relative_error_hcubature / 2.0); } partials<7>(ops_partials)[i] = -1 / st0_value + f / st0_value / density; } diff --git a/test/unit/math/mix/prob/util.hpp b/test/unit/math/mix/prob/util.hpp new file mode 100644 index 00000000000..426975aa15b --- /dev/null +++ b/test/unit/math/mix/prob/util.hpp @@ -0,0 +1,36 @@ +#ifndef STAN_TEST_UNIT_MATH_MIX_PROB_UTIL_HPP +#define STAN_TEST_UNIT_MATH_MIX_PROB_UTIL_HPP + +#include + +class Wiener7MixArgs : public ::testing::Test { + public: + const char* function = "function"; + void SetUp() {} + + Eigen::VectorXd y{{0.1, 0.3}}; + Eigen::VectorXd a{{2.0, 2.5}}; + Eigen::VectorXd t0{{0.2, 0.1}}; + Eigen::VectorXd w{{0.5, 0.2}}; + Eigen::VectorXd v{{2.0, 0.8}}; + Eigen::VectorXd sv{{0.2, 0.1}}; + Eigen::VectorXd sw{{0.1, .99}}; + Eigen::VectorXd st0{{0.3, .8}}; + +}; + +class Wiener5MixArgs : public ::testing::Test { + public: + const char* function = "function"; + void SetUp() {} + + Eigen::VectorXd y{{1.0, 0.1, 0.3}}; + Eigen::VectorXd a{{2.5, 2.0, 2.5}}; + Eigen::VectorXd t0{{0.2, 0.2, 0.1}}; + Eigen::VectorXd w{{0.5, 0.5, 0.2}}; + Eigen::VectorXd v{{2.0, 2.0, 0.8}}; + Eigen::VectorXd sv{{0.2, 0.2, 0.1}}; + +}; + +#endif \ No newline at end of file diff --git a/test/unit/math/mix/prob/wiener5_lpdf_0_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_0_test.cpp index dc4d5cf24f7..672a18afb88 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_0_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_0_test.cpp @@ -1,17 +1,17 @@ #include #include -TEST(mathMixDouble, wiener5_lpdf) { +TEST(mathMixDouble, wiener_lpdf) { double y = 1.0; double a = 2.0; double t0 = 0.2; double w = 0.5; double v = 1.5; double sv = 0.2; - stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); } -TEST(mathMixVar, wiener5_lpdf) { +TEST(mathMixVar, wiener_lpdf) { using stan::math::var; var y = 1.0; var a = 2.0; @@ -19,10 +19,10 @@ TEST(mathMixVar, wiener5_lpdf) { var w = 0.5; var v = 1.5; var sv = 0.2; - stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); } -TEST(mathMixFVar, wiener5_lpdf) { +TEST(mathMixFVar, wiener_lpdf) { using stan::math::fvar; using stan::math::var; fvar y = 1.0; @@ -32,5 +32,5 @@ TEST(mathMixFVar, wiener5_lpdf) { fvar v = 1.5; fvar sv = 0.2; double error = 1e-4; - stan::math::wiener5_lpdf(y, a, t0, w, v, sv, error); + stan::math::wiener_lpdf(y, a, t0, w, v, sv, error); } diff --git a/test/unit/math/mix/prob/wiener5_lpdf_1_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_1_test.cpp index de915668db9..c516f0fdda7 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_1_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_1_test.cpp @@ -1,87 +1,48 @@ #include #include +#include -TEST(mathMixScalFun_y_a_t0, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_y_a_t0) { auto f_y_a_t0 = [](const auto& w, const auto& v, const auto& sv) { return [&w, &v, &sv](const auto& y, const auto& a, const auto& t0) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_y_a_t0(w, v, sv), y, a, t0); } -TEST(mathMixScalFun_y_a_w, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_y_a_w) { auto f_y_a_w = [](const auto& t0, const auto& v, const auto& sv) { return [&t0, &v, &sv](const auto& y, const auto& a, const auto& w) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_y_a_w(t0, v, sv), y, a, w); } -TEST(mathMixScalFun_y_a_v, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_y_a_v) { auto f_y_a_v = [](const auto& t0, const auto& w, const auto& sv) { return [&t0, &w, &sv](const auto& y, const auto& a, const auto& v) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_y_a_v(t0, w, sv), y, a, v); } -TEST(mathMixScalFun_y_a_sv, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_y_a_sv) { auto f_y_a_sv = [](const auto& t0, const auto& w, const auto& v) { return [&t0, &w, &v](const auto& y, const auto& a, const auto& sv) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_y_a_sv(t0, w, v), y, a, sv); } -TEST(mathMixScalFun_y_t0_w, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_y_t0_w) { auto f_y_t0_w = [](const auto& a, const auto& v, const auto& sv) { return [&a, &v, &sv](const auto& y, const auto& t0, const auto& w) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_y_t0_w(a, v, sv), y, t0, w); } diff --git a/test/unit/math/mix/prob/wiener5_lpdf_2_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_2_test.cpp index 5684003bd52..b2d6acf2a3c 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_2_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_2_test.cpp @@ -1,87 +1,48 @@ #include #include +#include -TEST(mathMixScalFun_y_t0_v, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_y_t0_v) { auto f_y_t0_v = [](const auto& a, const auto& w, const auto& sv) { return [&a, &w, &sv](const auto& y, const auto& t0, const auto& v) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_y_t0_v(a, w, sv), y, t0, v); } -TEST(mathMixScalFun_y_t0_sv, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_y_t0_sv) { auto f_y_t0_sv = [](const auto& a, const auto& w, const auto& v) { return [&a, &w, &v](const auto& y, const auto& t0, const auto& sv) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_y_t0_sv(a, w, v), y, t0, sv); } -TEST(mathMixScalFun_y_w_v, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_y_w_v) { auto f_y_w_v = [](const auto& a, const auto& t0, const auto& sv) { return [&a, &t0, &sv](const auto& y, const auto& w, const auto& v) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_y_w_v(a, t0, sv), y, w, v); } -TEST(mathMixScalFun_y_w_sv, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_y_w_sv) { auto f_y_w_sv = [](const auto& a, const auto& t0, const auto& v) { return [&a, &t0, &v](const auto& y, const auto& w, const auto& sv) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_y_w_sv(a, t0, v), y, w, sv); } -TEST(mathMixScalFun_y_v_sv, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_y_v_sv) { auto f_y_v_sv = [](const auto& a, const auto& t0, const auto& w) { return [&a, &t0, &w](const auto& y, const auto& v, const auto& sv) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_y_v_sv(a, t0, w), y, v, sv); } diff --git a/test/unit/math/mix/prob/wiener5_lpdf_3_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_3_test.cpp index 9fb75a88bea..d16285a95b3 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_3_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_3_test.cpp @@ -1,87 +1,48 @@ #include #include +#include -TEST(mathMixScalFun_a_t0_w, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_a_t0_w) { auto f_a_t0_w = [](const auto& y, const auto& v, const auto& sv) { return [&y, &v, &sv](const auto& a, const auto& t0, const auto& w) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_a_t0_w(y, v, sv), a, t0, w); } -TEST(mathMixScalFun_a_t0_v, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_a_t0_v) { auto f_a_t0_v = [](const auto& y, const auto& w, const auto& sv) { return [&y, &w, &sv](const auto& a, const auto& t0, const auto& v) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_a_t0_v(y, w, sv), a, t0, v); } -TEST(mathMixScalFun_a_t0_sv, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_a_t0_sv) { auto f_a_t0_sv = [](const auto& y, const auto& w, const auto& v) { return [&y, &w, &v](const auto& a, const auto& t0, const auto& sv) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_a_t0_sv(y, w, v), a, t0, sv); } -TEST(mathMixScalFun_a_w_v, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_a_w_v) { auto f_a_w_v = [](const auto& y, const auto& t0, const auto& sv) { return [&y, &t0, &sv](const auto& a, const auto& w, const auto& v) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_a_w_v(y, t0, sv), a, w, v); } -TEST(mathMixScalFun_a_w_sv, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_a_w_sv) { auto f_a_w_sv = [](const auto& y, const auto& t0, const auto& v) { return [&y, &t0, &v](const auto& a, const auto& w, const auto& sv) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_a_w_sv(y, t0, v), a, w, sv); } diff --git a/test/unit/math/mix/prob/wiener5_lpdf_4_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_4_test.cpp index e24640d6a54..cb0423b9dbb 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_4_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_4_test.cpp @@ -1,87 +1,48 @@ #include #include +#include -TEST(mathMixScalFun_a_v_sv, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_a_v_sv) { auto f_a_v_sv = [](const auto& y, const auto& t0, const auto& w) { return [&y, &t0, &w](const auto& a, const auto& v, const auto& sv) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_a_v_sv(y, t0, w), a, v, sv); } -TEST(mathMixScalFun_t0_w_v, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_t0_w_v) { auto f_t0_w_v = [](const auto& y, const auto& a, const auto& sv) { return [&y, &a, &sv](const auto& t0, const auto& w, const auto& v) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_t0_w_v(y, a, sv), t0, w, v); } -TEST(mathMixScalFun_t0_w_sv, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_t0_w_sv) { auto f_t0_w_sv = [](const auto& y, const auto& a, const auto& v) { return [&y, &a, &v](const auto& t0, const auto& w, const auto& sv) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_t0_w_sv(y, a, v), t0, w, sv); } -TEST(mathMixScalFun_t0_v_sv, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_t0_v_sv) { auto f_t0_v_sv = [](const auto& y, const auto& a, const auto& w) { return [&y, &a, &w](const auto& t0, const auto& v, const auto& sv) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_t0_v_sv(y, a, w), t0, v, sv); } -TEST(mathMixScalFun_w_v_sv, wiener5_lpdf) { +TEST_F(Wiener5MixArgs, wiener_lpdf_w_v_sv) { auto f_w_v_sv = [](const auto& y, const auto& a, const auto& t0) { return [&y, &a, &t0](const auto& w, const auto& v, const auto& sv) { - return stan::math::wiener5_lpdf(y, a, t0, w, v, sv, 1e-4); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); }; }; - - double y = 1.0; - double a = 2.5; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - stan::test::expect_ad(f_w_v_sv(y, a, t0), w, v, sv); } diff --git a/test/unit/math/mix/prob/wiener_full_lpdf_0_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_0_test.cpp index d57a612173e..23871b5d28d 100644 --- a/test/unit/math/mix/prob/wiener_full_lpdf_0_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_lpdf_0_test.cpp @@ -1,7 +1,8 @@ #include #include +#include -TEST(mathMixDouble, wiener_full_lpdf) { +TEST(mathMixDouble, wiener_lpdf) { double y = 1.0; double a = 2.0; double t0 = 0.2; @@ -10,10 +11,10 @@ TEST(mathMixDouble, wiener_full_lpdf) { double sv = 0.2; double sw = 0.2; double st0 = 0.2; - stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0, 1e-4); + stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0, 1e-4); } -TEST(mathMixVar, wiener_full_lpdf) { +TEST(mathMixVar, wiener_lpdf) { using stan::math::var; var y = 1.0; var a = 2.0; @@ -23,10 +24,10 @@ TEST(mathMixVar, wiener_full_lpdf) { var sv = 0.2; var sw = 0; var st0 = 0.2; - stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); } -TEST(mathMixFVar, wiener_full_lpdf) { +TEST(mathMixFVar, wiener_lpdf) { using stan::math::fvar; using stan::math::var; fvar y = 1.0; @@ -37,26 +38,16 @@ TEST(mathMixFVar, wiener_full_lpdf) { fvar sv = 0.2; fvar sw = 0; fvar st0 = 0.2; - stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); } -TEST(mathMixScalFun_y_a_t0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_a_t0) { auto f_y_a_t0 = [](const auto& w, const auto& v, const auto& sv, const auto& sw, const auto& st0) { return [&w, &v, &sv, &sw, &st0](const auto& y, const auto& a, const auto& t0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_a_t0(w, v, sv, sw, st0), y, a, t0); } diff --git a/test/unit/math/mix/prob/wiener_full_lpdf_10_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_10_test.cpp index f38a2d274fa..fb3c9537ec9 100644 --- a/test/unit/math/mix/prob/wiener_full_lpdf_10_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_lpdf_10_test.cpp @@ -1,107 +1,58 @@ #include #include +#include -TEST(mathMixScalFun_w_v_sv, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_w_v_sv) { auto f_w_v_sv = [](const auto& y, const auto& a, const auto& t0, const auto& sw, const auto& st0) { return [&y, &a, &t0, &sw, &st0](const auto& w, const auto& v, const auto& sv) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_w_v_sv(y, a, t0, sw, st0), w, v, sv); } -TEST(mathMixScalFun_w_v_sw, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_w_v_sw) { auto f_w_v_sw = [](const auto& y, const auto& a, const auto& t0, const auto& sv, const auto& st0) { return [&y, &a, &t0, &sv, &st0](const auto& w, const auto& v, const auto& sw) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_w_v_sw(y, a, t0, sv, st0), w, v, sw); } -TEST(mathMixScalFun_w_v_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_w_v_st0) { auto f_w_v_st0 = [](const auto& y, const auto& a, const auto& t0, const auto& sv, const auto& sw) { return [&y, &a, &t0, &sv, &sw](const auto& w, const auto& v, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_w_v_st0(y, a, t0, sv, sw), w, v, st0); } -TEST(mathMixScalFun_w_sv_sw, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_w_sv_sw) { auto f_w_sv_sw = [](const auto& y, const auto& a, const auto& t0, const auto& v, const auto& st0) { return [&y, &a, &t0, &v, &st0](const auto& w, const auto& sv, const auto& sw) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_w_sv_sw(y, a, t0, v, st0), w, sv, sw); } -TEST(mathMixScalFun_w_sv_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_w_sv_st0) { auto f_w_sv_st0 = [](const auto& y, const auto& a, const auto& t0, const auto& v, const auto& sw) { return [&y, &a, &t0, &v, &sw](const auto& w, const auto& sv, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_w_sv_st0(y, a, t0, v, sw), w, sv, st0); } diff --git a/test/unit/math/mix/prob/wiener_full_lpdf_11_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_11_test.cpp index f1bc94e22f3..d5a11e954d6 100644 --- a/test/unit/math/mix/prob/wiener_full_lpdf_11_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_lpdf_11_test.cpp @@ -1,107 +1,58 @@ #include #include +#include -TEST(mathMixScalFun_w_sw_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_w_sw_st0) { auto f_w_sw_st0 = [](const auto& y, const auto& a, const auto& t0, const auto& v, const auto& sv) { return [&y, &a, &t0, &v, &sv](const auto& w, const auto& sw, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_w_sw_st0(y, a, t0, v, sv), w, sw, st0); } -TEST(mathMixScalFun_v_sv_sw, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_v_sv_sw) { auto f_v_sv_sw = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& st0) { return [&y, &a, &t0, &w, &st0](const auto& v, const auto& sv, const auto& sw) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_v_sv_sw(y, a, t0, w, st0), v, sv, sw); } -TEST(mathMixScalFun_v_sv_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_v_sv_st0) { auto f_v_sv_st0 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& sw) { return [&y, &a, &t0, &w, &sw](const auto& v, const auto& sv, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_v_sv_st0(y, a, t0, w, sw), v, sv, st0); } -TEST(mathMixScalFun_v_sw_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_v_sw_st0) { auto f_v_sw_st0 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& sv) { return [&y, &a, &t0, &w, &sv](const auto& v, const auto& sw, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_v_sw_st0(y, a, t0, w, sv), v, sw, st0); } -TEST(mathMixScalFun_sv_sw_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_sv_sw_st0) { auto f_sv_sw_st0 = [](const auto& y, const auto& a, const auto& t0, const auto& w, const auto& v) { return [&y, &a, &t0, &w, &v](const auto& sv, const auto& sw, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_sv_sw_st0(y, a, t0, w, v), sv, sw, st0); } diff --git a/test/unit/math/mix/prob/wiener_full_lpdf_1_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_1_test.cpp index 075435ba4ae..3bc1985fc14 100644 --- a/test/unit/math/mix/prob/wiener_full_lpdf_1_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_lpdf_1_test.cpp @@ -1,107 +1,58 @@ #include #include +#include -TEST(mathMixScalFun_y_a_w, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_a_w) { auto f_y_a_w = [](const auto& t0, const auto& v, const auto& sv, const auto& sw, const auto& st0) { return [&t0, &v, &sv, &sw, &st0](const auto& y, const auto& a, const auto& w) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_a_w(t0, v, sv, sw, st0), y, a, w); } -TEST(mathMixScalFun_y_a_v, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_a_v) { auto f_y_a_v = [](const auto& t0, const auto& w, const auto& sv, const auto& sw, const auto& st0) { return [&t0, &w, &sv, &sw, &st0](const auto& y, const auto& a, const auto& v) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_a_v(t0, w, sv, sw, st0), y, a, v); } -TEST(mathMixScalFun_y_a_sv, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_a_sv) { auto f_y_a_sv = [](const auto& t0, const auto& w, const auto& v, const auto& sw, const auto& st0) { return [&t0, &w, &v, &sw, &st0](const auto& y, const auto& a, const auto& sv) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_a_sv(t0, w, v, sw, st0), y, a, sv); } -TEST(mathMixScalFun_y_a_sw, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_a_sw) { auto f_y_a_sw = [](const auto& t0, const auto& w, const auto& v, const auto& sv, const auto& st0) { return [&t0, &w, &v, &sv, &st0](const auto& y, const auto& a, const auto& sw) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_a_sw(t0, w, v, sv, st0), y, a, sw); } -TEST(mathMixScalFun_y_a_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_a_st0) { auto f_y_a_st0 = [](const auto& t0, const auto& w, const auto& v, const auto& sv, const auto& sw) { return [&t0, &w, &v, &sv, &sw](const auto& y, const auto& a, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_a_st0(t0, w, v, sv, sw), y, a, st0); } diff --git a/test/unit/math/mix/prob/wiener_full_lpdf_2_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_2_test.cpp index 816a97d5539..531940c6922 100644 --- a/test/unit/math/mix/prob/wiener_full_lpdf_2_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_lpdf_2_test.cpp @@ -1,107 +1,58 @@ #include #include +#include -TEST(mathMixScalFun_y_t0_w, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_t0_w) { auto f_y_t0_w = [](const auto& a, const auto& v, const auto& sv, const auto& sw, const auto& st0) { return [&a, &v, &sv, &sw, &st0](const auto& y, const auto& t0, const auto& w) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_t0_w(a, v, sv, sw, st0), y, t0, w); } -TEST(mathMixScalFun_y_t0_v, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_t0_v) { auto f_y_t0_v = [](const auto& a, const auto& w, const auto& sv, const auto& sw, const auto& st0) { return [&a, &w, &sv, &sw, &st0](const auto& y, const auto& t0, const auto& v) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_t0_v(a, w, sv, sw, st0), y, t0, v); } -TEST(mathMixScalFun_y_t0_sv, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_t0_sv) { auto f_y_t0_sv = [](const auto& a, const auto& w, const auto& v, const auto& sw, const auto& st0) { return [&a, &w, &v, &sw, &st0](const auto& y, const auto& t0, const auto& sv) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_t0_sv(a, w, v, sw, st0), y, t0, sv); } -TEST(mathMixScalFun_y_t0_sw, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_t0_sw) { auto f_y_t0_sw = [](const auto& a, const auto& w, const auto& v, const auto& sv, const auto& st0) { return [&a, &w, &v, &sv, &st0](const auto& y, const auto& t0, const auto& sw) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_t0_sw(a, w, v, sv, st0), y, t0, sw); } -TEST(mathMixScalFun_y_t0_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_t0_st0) { auto f_y_t0_st0 = [](const auto& a, const auto& w, const auto& v, const auto& sv, const auto& sw) { return [&a, &w, &v, &sv, &sw](const auto& y, const auto& t0, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_t0_st0(a, w, v, sv, sw), y, t0, st0); } diff --git a/test/unit/math/mix/prob/wiener_full_lpdf_3_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_3_test.cpp index ee4fc356b91..6342b2a945c 100644 --- a/test/unit/math/mix/prob/wiener_full_lpdf_3_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_lpdf_3_test.cpp @@ -1,107 +1,58 @@ #include #include +#include -TEST(mathMixScalFun_y_w_v, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_w_v) { auto f_y_w_v = [](const auto& a, const auto& t0, const auto& sv, const auto& sw, const auto& st0) { return [&a, &t0, &sv, &sw, &st0](const auto& y, const auto& w, const auto& v) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_w_v(a, t0, sv, sw, st0), y, w, v); } -TEST(mathMixScalFun_y_w_sv, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_w_sv) { auto f_y_w_sv = [](const auto& a, const auto& t0, const auto& v, const auto& sw, const auto& st0) { return [&a, &t0, &v, &sw, &st0](const auto& y, const auto& w, const auto& sv) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_w_sv(a, t0, v, sw, st0), y, w, sv); } -TEST(mathMixScalFun_y_w_sw, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_w_sw) { auto f_y_w_sw = [](const auto& a, const auto& t0, const auto& v, const auto& sv, const auto& st0) { return [&a, &t0, &v, &sv, &st0](const auto& y, const auto& w, const auto& sw) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_w_sw(a, t0, v, sv, st0), y, w, sw); } -TEST(mathMixScalFun_y_w_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_w_st0) { auto f_y_w_st0 = [](const auto& a, const auto& t0, const auto& v, const auto& sv, const auto& sw) { return [&a, &t0, &v, &sv, &sw](const auto& y, const auto& w, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_w_st0(a, t0, v, sv, sw), y, w, st0); } -TEST(mathMixScalFun_y_v_sv, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_v_sv) { auto f_y_v_sv = [](const auto& a, const auto& t0, const auto& w, const auto& sw, const auto& st0) { return [&a, &t0, &w, &sw, &st0](const auto& y, const auto& v, const auto& sv) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_v_sv(a, t0, w, sw, st0), y, v, sv); } diff --git a/test/unit/math/mix/prob/wiener_full_lpdf_4_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_4_test.cpp index 0abdaeafc0b..c7462a99ca7 100644 --- a/test/unit/math/mix/prob/wiener_full_lpdf_4_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_lpdf_4_test.cpp @@ -1,107 +1,58 @@ #include #include +#include -TEST(mathMixScalFun_y_v_sw, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_v_sw) { auto f_y_v_sw = [](const auto& a, const auto& t0, const auto& w, const auto& sv, const auto& st0) { return [&a, &t0, &w, &sv, &st0](const auto& y, const auto& v, const auto& sw) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_v_sw(a, t0, w, sv, st0), y, v, sw); } -TEST(mathMixScalFun_y_v_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_v_st0) { auto f_y_v_st0 = [](const auto& a, const auto& t0, const auto& w, const auto& sv, const auto& sw) { return [&a, &t0, &w, &sv, &sw](const auto& y, const auto& v, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_v_st0(a, t0, w, sv, sw), y, v, st0); } -TEST(mathMixScalFun_y_sv_sw, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_sv_sw) { auto f_y_sv_sw = [](const auto& a, const auto& t0, const auto& w, const auto& v, const auto& st0) { return [&a, &t0, &w, &v, &st0](const auto& y, const auto& sv, const auto& sw) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_sv_sw(a, t0, w, v, st0), y, sv, sw); } -TEST(mathMixScalFun_y_sv_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_sv_st0) { auto f_y_sv_st0 = [](const auto& a, const auto& t0, const auto& w, const auto& v, const auto& sw) { return [&a, &t0, &w, &v, &sw](const auto& y, const auto& sv, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_sv_st0(a, t0, w, v, sw), y, sv, st0); } -TEST(mathMixScalFun_y_sw_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_y_sw_st0) { auto f_y_sw_st0 = [](const auto& a, const auto& t0, const auto& w, const auto& v, const auto& sv) { return [&a, &t0, &w, &v, &sv](const auto& y, const auto& sw, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_y_sw_st0(a, t0, w, v, sv), y, sw, st0); } diff --git a/test/unit/math/mix/prob/wiener_full_lpdf_5_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_5_test.cpp index 3fd64d52a70..6e26a4d9b5d 100644 --- a/test/unit/math/mix/prob/wiener_full_lpdf_5_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_lpdf_5_test.cpp @@ -1,107 +1,58 @@ #include #include +#include -TEST(mathMixScalFun_a_t0_w, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_a_t0_w) { auto f_a_t0_w = [](const auto& y, const auto& v, const auto& sv, const auto& sw, const auto& st0) { return [&y, &v, &sv, &sw, &st0](const auto& a, const auto& t0, const auto& w) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_a_t0_w(y, v, sv, sw, st0), a, t0, w); } -TEST(mathMixScalFun_a_t0_v, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_a_t0_v) { auto f_a_t0_v = [](const auto& y, const auto& w, const auto& sv, const auto& sw, const auto& st0) { return [&y, &w, &sv, &sw, &st0](const auto& a, const auto& t0, const auto& v) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_a_t0_v(y, w, sv, sw, st0), a, t0, v); } -TEST(mathMixScalFun_a_t0_sv, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_a_t0_sv) { auto f_a_t0_sv = [](const auto& y, const auto& w, const auto& v, const auto& sw, const auto& st0) { return [&y, &w, &v, &sw, &st0](const auto& a, const auto& t0, const auto& sv) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_a_t0_sv(y, w, v, sw, st0), a, t0, sv); } -TEST(mathMixScalFun_a_t0_sw, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_a_t0_sw) { auto f_a_t0_sw = [](const auto& y, const auto& w, const auto& v, const auto& sv, const auto& st0) { return [&y, &w, &v, &sv, &st0](const auto& a, const auto& t0, const auto& sw) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_a_t0_sw(y, w, v, sv, st0), a, t0, sw); } -TEST(mathMixScalFun_a_t0_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_a_t0_st0) { auto f_a_t0_st0 = [](const auto& y, const auto& w, const auto& v, const auto& sv, const auto& sw) { return [&y, &w, &v, &sv, &sw](const auto& a, const auto& t0, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_a_t0_st0(y, w, v, sv, sw), a, t0, st0); } diff --git a/test/unit/math/mix/prob/wiener_full_lpdf_6_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_6_test.cpp index 45fe9a52b90..60e5cdc1c61 100644 --- a/test/unit/math/mix/prob/wiener_full_lpdf_6_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_lpdf_6_test.cpp @@ -1,107 +1,58 @@ #include #include +#include -TEST(mathMixScalFun_a_w_v, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_a_w_v) { auto f_a_w_v = [](const auto& y, const auto& t0, const auto& sv, const auto& sw, const auto& st0) { return [&y, &t0, &sv, &sw, &st0](const auto& a, const auto& w, const auto& v) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_a_w_v(y, t0, sv, sw, st0), a, w, v); } -TEST(mathMixScalFun_a_w_sv, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_a_w_sv) { auto f_a_w_sv = [](const auto& y, const auto& t0, const auto& v, const auto& sw, const auto& st0) { return [&y, &t0, &v, &sw, &st0](const auto& a, const auto& w, const auto& sv) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_a_w_sv(y, t0, v, sw, st0), a, w, sv); } -TEST(mathMixScalFun_a_w_sw, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_a_w_sw) { auto f_a_w_sw = [](const auto& y, const auto& t0, const auto& v, const auto& sv, const auto& st0) { return [&y, &t0, &v, &sv, &st0](const auto& a, const auto& w, const auto& sw) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_a_w_sw(y, t0, v, sv, st0), a, w, sw); } -TEST(mathMixScalFun_a_w_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_a_w_st0) { auto f_a_w_st0 = [](const auto& y, const auto& t0, const auto& v, const auto& sv, const auto& sw) { return [&y, &t0, &v, &sv, &sw](const auto& a, const auto& w, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_a_w_st0(y, t0, v, sv, sw), a, w, st0); } -TEST(mathMixScalFun_a_v_sv, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_a_v_sv) { auto f_a_v_sv = [](const auto& y, const auto& t0, const auto& w, const auto& sw, const auto& st0) { return [&y, &t0, &w, &sw, &st0](const auto& a, const auto& v, const auto& sv) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_a_v_sv(y, t0, w, sw, st0), a, v, sv); } diff --git a/test/unit/math/mix/prob/wiener_full_lpdf_7_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_7_test.cpp index 13fe6364be0..d74690692f0 100644 --- a/test/unit/math/mix/prob/wiener_full_lpdf_7_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_lpdf_7_test.cpp @@ -1,107 +1,58 @@ #include #include +#include -TEST(mathMixScalFun_a_v_sw, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_a_v_sw) { auto f_a_v_sw = [](const auto& y, const auto& t0, const auto& w, const auto& sv, const auto& st0) { return [&y, &t0, &w, &sv, &st0](const auto& a, const auto& v, const auto& sw) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_a_v_sw(y, t0, w, sv, st0), a, v, sw); } -TEST(mathMixScalFun_a_v_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_a_v_st0) { auto f_a_v_st0 = [](const auto& y, const auto& t0, const auto& w, const auto& sv, const auto& sw) { return [&y, &t0, &w, &sv, &sw](const auto& a, const auto& v, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_a_v_st0(y, t0, w, sv, sw), a, v, st0); } -TEST(mathMixScalFun_a_sv_sw, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_a_sv_sw) { auto f_a_sv_sw = [](const auto& y, const auto& t0, const auto& w, const auto& v, const auto& st0) { return [&y, &t0, &w, &v, &st0](const auto& a, const auto& sv, const auto& sw) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_a_sv_sw(y, t0, w, v, st0), a, sv, sw); } -TEST(mathMixScalFun_a_sv_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_a_sv_st0) { auto f_a_sv_st0 = [](const auto& y, const auto& t0, const auto& w, const auto& v, const auto& sw) { return [&y, &t0, &w, &v, &sw](const auto& a, const auto& sv, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_a_sv_st0(y, t0, w, v, sw), a, sv, st0); } -TEST(mathMixScalFun_a_sw_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_a_sw_st0) { auto f_a_sw_st0 = [](const auto& y, const auto& t0, const auto& w, const auto& v, const auto& sv) { return [&y, &t0, &w, &v, &sv](const auto& a, const auto& sw, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_a_sw_st0(y, t0, w, v, sv), a, sw, st0); } diff --git a/test/unit/math/mix/prob/wiener_full_lpdf_8_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_8_test.cpp index e40ac07b781..ace6b36c254 100644 --- a/test/unit/math/mix/prob/wiener_full_lpdf_8_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_lpdf_8_test.cpp @@ -1,107 +1,58 @@ #include #include +#include -TEST(mathMixScalFun_t0_w_v, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_t0_w_v) { auto f_t0_w_v = [](const auto& y, const auto& a, const auto& sv, const auto& sw, const auto& st0) { return [&y, &a, &sv, &sw, &st0](const auto& t0, const auto& w, const auto& v) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_t0_w_v(y, a, sv, sw, st0), t0, w, v); } -TEST(mathMixScalFun_t0_w_sv, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_t0_w_sv) { auto f_t0_w_sv = [](const auto& y, const auto& a, const auto& v, const auto& sw, const auto& st0) { return [&y, &a, &v, &sw, &st0](const auto& t0, const auto& w, const auto& sv) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_t0_w_sv(y, a, v, sw, st0), t0, w, sv); } -TEST(mathMixScalFun_t0_w_sw, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_t0_w_sw) { auto f_t0_w_sw = [](const auto& y, const auto& a, const auto& v, const auto& sv, const auto& st0) { return [&y, &a, &v, &sv, &st0](const auto& t0, const auto& w, const auto& sw) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_t0_w_sw(y, a, v, sv, st0), t0, w, sw); } -TEST(mathMixScalFun_t0_w_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_t0_w_st0) { auto f_t0_w_st0 = [](const auto& y, const auto& a, const auto& v, const auto& sv, const auto& sw) { return [&y, &a, &v, &sv, &sw](const auto& t0, const auto& w, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_t0_w_st0(y, a, v, sv, sw), t0, w, st0); } -TEST(mathMixScalFun_t0_v_sv, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_t0_v_sv) { auto f_t0_v_sv = [](const auto& y, const auto& a, const auto& w, const auto& sw, const auto& st0) { return [&y, &a, &w, &sw, &st0](const auto& t0, const auto& v, const auto& sv) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_t0_v_sv(y, a, w, sw, st0), t0, v, sv); } diff --git a/test/unit/math/mix/prob/wiener_full_lpdf_9_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_9_test.cpp index b41b7e30274..91faeb42eba 100644 --- a/test/unit/math/mix/prob/wiener_full_lpdf_9_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_lpdf_9_test.cpp @@ -1,107 +1,58 @@ #include #include +#include -TEST(mathMixScalFun_t0_v_sw, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_t0_v_sw) { auto f_t0_v_sw = [](const auto& y, const auto& a, const auto& w, const auto& sv, const auto& st0) { return [&y, &a, &w, &sv, &st0](const auto& t0, const auto& v, const auto& sw) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_t0_v_sw(y, a, w, sv, st0), t0, v, sw); } -TEST(mathMixScalFun_t0_v_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_t0_v_st0) { auto f_t0_v_st0 = [](const auto& y, const auto& a, const auto& w, const auto& sv, const auto& sw) { return [&y, &a, &w, &sv, &sw](const auto& t0, const auto& v, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_t0_v_st0(y, a, w, sv, sw), t0, v, st0); } -TEST(mathMixScalFun_t0_sv_sw, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_t0_sv_sw) { auto f_t0_sv_sw = [](const auto& y, const auto& a, const auto& w, const auto& v, const auto& st0) { return [&y, &a, &w, &v, &st0](const auto& t0, const auto& sv, const auto& sw) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_t0_sv_sw(y, a, w, v, st0), t0, sv, sw); } -TEST(mathMixScalFun_t0_sv_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_t0_sv_st0) { auto f_t0_sv_st0 = [](const auto& y, const auto& a, const auto& w, const auto& v, const auto& sw) { return [&y, &a, &w, &v, &sw](const auto& t0, const auto& sv, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_t0_sv_st0(y, a, w, v, sw), t0, sv, st0); } -TEST(mathMixScalFun_t0_sw_st0, wiener_full_lpdf) { +TEST_F(Wiener7MixArgs, wiener_lpdf_t0_sw_st0) { auto f_t0_sw_st0 = [](const auto& y, const auto& a, const auto& w, const auto& v, const auto& sv) { return [&y, &a, &w, &v, &sv](const auto& t0, const auto& sw, const auto& st0) { - return stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + return stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); }; }; - - double y = 0.1; - double a = 2.0; - double t0 = 0.2; - double w = 0.5; - double v = 2.0; - double sv = 0.2; - double sw = 0.1; - double st0 = 0.3; - stan::test::expect_ad(f_t0_sw_st0(y, a, w, v, sv), t0, sw, st0); } From b7291b54b827fa6af6f3a33c24022dfc76bd4eb4 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 11 Jan 2024 04:54:37 -0500 Subject: [PATCH 131/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/functor/apply.hpp | 12 ++++-- stan/math/prim/meta/return_type.hpp | 11 ++--- test/unit/math/mix/prob/util.hpp | 2 - .../unit/math/prim/functor/hcubature_test.cpp | 43 +++++++++++-------- 4 files changed, 36 insertions(+), 32 deletions(-) diff --git a/stan/math/prim/functor/apply.hpp b/stan/math/prim/functor/apply.hpp index f0b006cc1cb..e0c1c7c73bf 100644 --- a/stan/math/prim/functor/apply.hpp +++ b/stan/math/prim/functor/apply.hpp @@ -20,13 +20,16 @@ namespace internal { * @param f functor callable * @param t tuple of arguments * @param i placeholder variable for index sequence - * @param pre_args parameter pack of arguments to place before elements in tuple. + * @param pre_args parameter pack of arguments to place before elements in + * tuple. */ template constexpr decltype(auto) apply_impl(F&& f, Tuple&& t, std::index_sequence i, PreArgs&&... pre_args) { - return std::forward(f)(std::forward(pre_args)..., std::forward(t))>(std::get(t))...); + return std::forward(f)( + std::forward(pre_args)..., + std::forward(t))>(std::get(t))...); } } // namespace internal @@ -42,7 +45,8 @@ constexpr decltype(auto) apply_impl(F&& f, Tuple&& t, * @tparam PreArgs Parameter pack of arguments before the tuple * @param f functor callable * @param t tuple of arguments - * @param pre_args parameter pack of arguments to place before elements in tuple. + * @param pre_args parameter pack of arguments to place before elements in + * tuple. */ template constexpr decltype(auto) apply(F&& f, Tuple&& t, PreArgs&&... pre_args) { @@ -50,7 +54,7 @@ constexpr decltype(auto) apply(F&& f, Tuple&& t, PreArgs&&... pre_args) { std::forward(f), std::forward(t), std::make_index_sequence< std::tuple_size>{}>{}, - std::forward(pre_args)...); + std::forward(pre_args)...); } } // namespace math diff --git a/stan/math/prim/meta/return_type.hpp b/stan/math/prim/meta/return_type.hpp index 1ad0dd51c91..e4204343011 100644 --- a/stan/math/prim/meta/return_type.hpp +++ b/stan/math/prim/meta/return_type.hpp @@ -147,7 +147,7 @@ template using scalar_lub_t = typename scalar_lub::type; namespace internal { - template +template struct return_type_impl { using type = double; }; @@ -160,11 +160,11 @@ struct return_type_impl { template struct return_type_impl, Ts...> { - using type - = scalar_lub_t::type, typename return_type_impl::type>; + using type = scalar_lub_t::type, + typename return_type_impl::type>; }; -} +} // namespace internal /** * Template metaprogram to calculate the base scalar return type @@ -206,9 +206,6 @@ struct return_type_impl, Ts...> { template struct return_type : internal::return_type_impl...> {}; - - - /** * Convenience type for the return type of the specified template * parameters. diff --git a/test/unit/math/mix/prob/util.hpp b/test/unit/math/mix/prob/util.hpp index 426975aa15b..ae354299afa 100644 --- a/test/unit/math/mix/prob/util.hpp +++ b/test/unit/math/mix/prob/util.hpp @@ -16,7 +16,6 @@ class Wiener7MixArgs : public ::testing::Test { Eigen::VectorXd sv{{0.2, 0.1}}; Eigen::VectorXd sw{{0.1, .99}}; Eigen::VectorXd st0{{0.3, .8}}; - }; class Wiener5MixArgs : public ::testing::Test { @@ -30,7 +29,6 @@ class Wiener5MixArgs : public ::testing::Test { Eigen::VectorXd w{{0.5, 0.5, 0.2}}; Eigen::VectorXd v{{2.0, 2.0, 0.8}}; Eigen::VectorXd sv{{0.2, 0.2, 0.1}}; - }; #endif \ No newline at end of file diff --git a/test/unit/math/prim/functor/hcubature_test.cpp b/test/unit/math/prim/functor/hcubature_test.cpp index d8325a41c92..ae19259e4be 100644 --- a/test/unit/math/prim/functor/hcubature_test.cpp +++ b/test/unit/math/prim/functor/hcubature_test.cpp @@ -98,10 +98,10 @@ inline auto f7(const T_x& x, double a) { * @param val correct value of integral */ -template -void test_integration(const F& f, const ArgsTupleT& pars, int dim, - const T_a& a, const T_b& b, - int maxEval, double reqAbsError, +template +void test_integration(const F& f, const ArgsTupleT& pars, int dim, const T_a& a, + const T_b& b, int maxEval, double reqAbsError, const T_relerr& reqRelError, double val) { using stan::math::hcubature; @@ -120,41 +120,46 @@ TEST(StanMath_hcubature_prim, test1) { const Eigen::VectorXd a{{0.0}}; const Eigen::VectorXd b{{1.0}}; const Eigen::VectorXd reqRelError{{1e-4, 1e-6, 1e-7}}; - test_integration([](auto&& x) { return hcubature_test::f1(x);}, std::make_tuple(), - dim, a, b, 6000, 0.0, reqRelError, 0.841471); + test_integration([](auto&& x) { return hcubature_test::f1(x); }, + std::make_tuple(), dim, a, b, 6000, 0.0, reqRelError, + 0.841471); dim = 2; const Eigen::VectorXd a_2{{0.0, 0.0}}; const Eigen::VectorXd b_2{{1.0, 1.0}}; - test_integration([](auto&& x) { return hcubature_test::f2(x);}, std::make_tuple(), - dim, a_2, b_2, 6000, 0.0, reqRelError, 0.7080734); + test_integration([](auto&& x) { return hcubature_test::f2(x); }, + std::make_tuple(), dim, a_2, b_2, 6000, 0.0, reqRelError, + 0.7080734); const Eigen::VectorXd reqRelError_2{{1e-4}}; - test_integration([](auto&& x, auto&& radius) { return hcubature_test::f3(x, radius);}, - std::make_tuple(0.50124145262344534123412), dim, a_2, b_2, - 10000, 0.0, reqRelError_2, 0.1972807); + test_integration( + [](auto&& x, auto&& radius) { return hcubature_test::f3(x, radius); }, + std::make_tuple(0.50124145262344534123412), dim, a_2, b_2, 10000, 0.0, + reqRelError_2, 0.1972807); // (Gaussian centered at 1/2) - test_integration([](auto&& x, auto&& sigma) { return hcubature_test::f4(x, sigma);}, - std::make_tuple(0.1), dim, a_2, b_2, 6000, 0.0, reqRelError, - 1); + test_integration( + [](auto&& x, auto&& sigma) { return hcubature_test::f4(x, sigma); }, + std::make_tuple(0.1), dim, a_2, b_2, 6000, 0.0, reqRelError, 1); dim = 3; const Eigen::VectorXd a_3{{0.0, 0.0, 0.0}}; const Eigen::VectorXd b_3{{1.0, 1.0, 1.0}}; const Eigen::VectorXd reqRelError_3{{1e-4, 1e-6}}; - test_integration([](auto&& x) { return hcubature_test::f5(x);}, std::make_tuple(), - dim, a_3, b_3, 6000, 0.0, reqRelError_3, 1.00001); + test_integration([](auto&& x) { return hcubature_test::f5(x); }, + std::make_tuple(), dim, a_3, b_3, 6000, 0.0, reqRelError_3, + 1.00001); const Eigen::VectorXd reqRelError_4{{1e-4, 1e-6, 1e-8}}; - test_integration([](auto&& x) { return hcubature_test::f6(x);}, std::make_tuple(), - dim, a_3, b_3, 6000, 0.0, reqRelError_4, 1); + test_integration([](auto&& x) { return hcubature_test::f6(x); }, + std::make_tuple(), dim, a_3, b_3, 6000, 0.0, reqRelError_4, + 1); // (Tsuda's example) dim = 4; const Eigen::VectorXd a_4{{0.0, 0.0, 0.0, 0.0}}; const Eigen::VectorXd b_4{{1.0, 1.0, 1.0, 1.0}}; - test_integration([](auto&& x, auto&& a) { return hcubature_test::f7(x, a);}, + test_integration([](auto&& x, auto&& a) { return hcubature_test::f7(x, a); }, std::make_tuple((1 + sqrt(10.0)) / 9.0), dim, a_4, b_4, 20000, 0.0, reqRelError_3, 0.999998); } From b1eabb431aea49bcfff96e66ccf3edf0ecc7d749 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Thu, 11 Jan 2024 11:00:59 +0100 Subject: [PATCH 132/179] add newline in util.hpp --- test/unit/math/mix/prob/util.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/math/mix/prob/util.hpp b/test/unit/math/mix/prob/util.hpp index ae354299afa..d0ffbcefa5f 100644 --- a/test/unit/math/mix/prob/util.hpp +++ b/test/unit/math/mix/prob/util.hpp @@ -31,4 +31,4 @@ class Wiener5MixArgs : public ::testing::Test { Eigen::VectorXd sv{{0.2, 0.2, 0.1}}; }; -#endif \ No newline at end of file +#endif From c2cfef50bf183dd5e2e126e5e6dca937b256edb7 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Thu, 11 Jan 2024 11:22:48 +0100 Subject: [PATCH 133/179] unique test names --- test/unit/math/mix/prob/wiener5_lpdf_0_test.cpp | 6 +++--- test/unit/math/mix/prob/wiener_full_lpdf_0_test.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/unit/math/mix/prob/wiener5_lpdf_0_test.cpp b/test/unit/math/mix/prob/wiener5_lpdf_0_test.cpp index 672a18afb88..24901ac760b 100644 --- a/test/unit/math/mix/prob/wiener5_lpdf_0_test.cpp +++ b/test/unit/math/mix/prob/wiener5_lpdf_0_test.cpp @@ -1,7 +1,7 @@ #include #include -TEST(mathMixDouble, wiener_lpdf) { +TEST(mathMixDouble5, wiener_lpdf) { double y = 1.0; double a = 2.0; double t0 = 0.2; @@ -11,7 +11,7 @@ TEST(mathMixDouble, wiener_lpdf) { stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); } -TEST(mathMixVar, wiener_lpdf) { +TEST(mathMixVar5, wiener_lpdf) { using stan::math::var; var y = 1.0; var a = 2.0; @@ -22,7 +22,7 @@ TEST(mathMixVar, wiener_lpdf) { stan::math::wiener_lpdf(y, a, t0, w, v, sv, 1e-4); } -TEST(mathMixFVar, wiener_lpdf) { +TEST(mathMixFVar5, wiener_lpdf) { using stan::math::fvar; using stan::math::var; fvar y = 1.0; diff --git a/test/unit/math/mix/prob/wiener_full_lpdf_0_test.cpp b/test/unit/math/mix/prob/wiener_full_lpdf_0_test.cpp index 23871b5d28d..374b2ed0083 100644 --- a/test/unit/math/mix/prob/wiener_full_lpdf_0_test.cpp +++ b/test/unit/math/mix/prob/wiener_full_lpdf_0_test.cpp @@ -2,7 +2,7 @@ #include #include -TEST(mathMixDouble, wiener_lpdf) { +TEST(mathMixDouble7, wiener_lpdf) { double y = 1.0; double a = 2.0; double t0 = 0.2; @@ -14,7 +14,7 @@ TEST(mathMixDouble, wiener_lpdf) { stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0, 1e-4); } -TEST(mathMixVar, wiener_lpdf) { +TEST(mathMixVar7, wiener_lpdf) { using stan::math::var; var y = 1.0; var a = 2.0; @@ -27,7 +27,7 @@ TEST(mathMixVar, wiener_lpdf) { stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); } -TEST(mathMixFVar, wiener_lpdf) { +TEST(mathMixFVar7, wiener_lpdf) { using stan::math::fvar; using stan::math::var; fvar y = 1.0; From fc41c9a0a824c7564874b42ea1c46abadcd7c8fa Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Thu, 11 Jan 2024 11:39:12 +0100 Subject: [PATCH 134/179] correct names in prob test --- .../math/prim/prob/wiener_full_lpdf_test.cpp | 204 +++++++++--------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp index aa731db9924..942bf05b257 100644 --- a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp @@ -8,10 +8,10 @@ TEST(mathPrimScalProbWienerFullScal, valid) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_NO_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, st0)); + EXPECT_NO_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, st0)); rt = 5; a = 1; v = 1; @@ -20,150 +20,150 @@ TEST(mathPrimScalProbWienerFullScal, valid) { sv = 0.0; sw = 0.0; st0 = 0.0; - EXPECT_NO_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, st0)); + EXPECT_NO_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, st0)); } // rt TEST(mathPrimScalProbWienerFullScal, invalid_rt) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(0, a, t0, w, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(0, a, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(-1, a, t0, w, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(-1, a, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(INFTY, a, t0, w, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(INFTY, a, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(-INFTY, a, t0, w, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(-INFTY, a, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(NAN, a, t0, w, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(NAN, a, t0, w, v, sv, sw, st0), std::domain_error); } // a TEST(mathPrimScalProbWienerFullScal, invalid_a) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double rt = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, 0, t0, w, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, 0, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, -1, t0, w, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, -1, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, INFTY, t0, w, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, INFTY, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, -INFTY, t0, w, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, -INFTY, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, NAN, t0, w, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, NAN, t0, w, v, sv, sw, st0), std::domain_error); } // v TEST(mathPrimScalProbWienerFullScal, invalid_v) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, INFTY, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, INFTY, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, -INFTY, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, -INFTY, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, NAN, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, NAN, sv, sw, st0), std::domain_error); } // w TEST(mathPrimScalProbWienerFullScal, invalid_w) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, -0.1, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, -0.1, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, 0, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 1, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, 1, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 1.1, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, 1.1, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, INFTY, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, INFTY, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, -INFTY, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, -INFTY, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, NAN, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, NAN, v, sv, sw, st0), std::domain_error); } // t0 TEST(mathPrimScalProbWienerFullScal, invalid_t0) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, 2, w, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, 2, w, v, sv, sw, st0), std::domain_error); // rt must be greater than t0 - EXPECT_THROW(wiener_full_lpdf(rt, a, -1, w, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, -1, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, INFTY, w, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, INFTY, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, -INFTY, w, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, -INFTY, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, NAN, w, v, sv, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, NAN, w, v, sv, sw, st0), std::domain_error); } // sv TEST(mathPrimScalProbWienerFullScal, invalid_sv) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, -1, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, -1, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, INFTY, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, INFTY, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, -INFTY, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, -INFTY, sw, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, NAN, sw, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, NAN, sw, st0), std::domain_error); } // sw TEST(mathPrimScalProbWienerFullScal, invalid_sw) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, -1, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, -1, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0.8, v, sv, 0.5, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, 0.8, v, sv, 0.5, st0), std::domain_error); // sw must be smaller than 2*(1-w) - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0.3, v, sv, 0.7, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, 0.3, v, sv, 0.7, st0), std::domain_error); // sw must be smaller than 2*w - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, INFTY, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, INFTY, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, -INFTY, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, -INFTY, st0), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, NAN, st0), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, NAN, st0), std::domain_error); } // st0 TEST(mathPrimScalProbWienerFullScal, invalid_st0) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, -1), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, -1), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, INFTY), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, INFTY), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, -INFTY), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, -INFTY), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, NAN), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, NAN), std::domain_error); } TEST(mathPrimScalProbWienerFullPrecScal, valid) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_NO_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, st0, 1e-4)); + EXPECT_NO_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, st0, 1e-4)); rt = 5; a = 1; v = 1; @@ -172,145 +172,145 @@ TEST(mathPrimScalProbWienerFullPrecScal, valid) { sv = 0.0; sw = 0.0; st0 = 0.0; - EXPECT_NO_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, st0, 1e-4)); + EXPECT_NO_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, st0, 1e-4)); } // rt TEST(mathPrimScalProbWienerFullPrecScal, invalid_rt) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(0, a, t0, w, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(0, a, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(-1, a, t0, w, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(-1, a, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(INFTY, a, t0, w, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(INFTY, a, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(-INFTY, a, t0, w, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(-INFTY, a, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(NAN, a, t0, w, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(NAN, a, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); } // a TEST(mathPrimScalProbWienerFullPrecScal, invalid_a) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double rt = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, 0, t0, w, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, 0, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, -1, t0, w, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, -1, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, INFTY, t0, w, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, INFTY, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, -INFTY, t0, w, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, -INFTY, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, NAN, t0, w, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, NAN, t0, w, v, sv, sw, st0, 1e-4), std::domain_error); } // v TEST(mathPrimScalProbWienerFullPrecScal, invalid_v) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, INFTY, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, INFTY, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, -INFTY, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, -INFTY, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, NAN, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, NAN, sv, sw, st0, 1e-4), std::domain_error); } // w TEST(mathPrimScalProbWienerFullPrecScal, invalid_w) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, -0.1, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, -0.1, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, 0, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 1, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, 1, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 1.1, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, 1.1, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, INFTY, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, INFTY, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, -INFTY, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, -INFTY, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, NAN, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, NAN, v, sv, sw, st0, 1e-4), std::domain_error); } // t0 TEST(mathPrimScalProbWienerFullPrecScal, invalid_t0) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, 2, w, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, 2, w, v, sv, sw, st0, 1e-4), std::domain_error); // rt must be greater than t0 - EXPECT_THROW(wiener_full_lpdf(rt, a, -1, w, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, -1, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, INFTY, w, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, INFTY, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, -INFTY, w, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, -INFTY, w, v, sv, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, NAN, w, v, sv, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, NAN, w, v, sv, sw, st0, 1e-4), std::domain_error); } // sv TEST(mathPrimScalProbWienerFullPrecScal, invalid_sv) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, -1, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, -1, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, INFTY, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, INFTY, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, -INFTY, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, -INFTY, sw, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, NAN, sw, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, NAN, sw, st0, 1e-4), std::domain_error); } // sw TEST(mathPrimScalProbWienerFullPrecScal, invalid_sw) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, -1, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, -1, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0.8, v, sv, 0.5, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, 0.8, v, sv, 0.5, st0, 1e-4), std::domain_error); // sw must be smaller than 2*(1-w) - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, 0.3, v, sv, 0.7, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, 0.3, v, sv, 0.7, st0, 1e-4), std::domain_error); // sw must be smaller than 2*w - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, INFTY, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, INFTY, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, -INFTY, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, -INFTY, st0, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, NAN, st0, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, NAN, st0, 1e-4), std::domain_error); } // st0 TEST(mathPrimScalProbWienerFullPrecScal, invalid_st0) { using stan::math::INFTY; - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2; - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, -1, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, -1, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, INFTY, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, INFTY, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, -INFTY, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, -INFTY, 1e-4), std::domain_error); - EXPECT_THROW(wiener_full_lpdf(rt, a, t0, w, v, sv, sw, NAN, 1e-4), + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, NAN, 1e-4), std::domain_error); } -TEST(mathPrimCorrectValues, wiener_full_lpdf) { +TEST(mathPrimCorrectValues, wiener_lpdf) { /* Test concrete values. True values are computed in R using the R-package * WienR and the function WienerPDF. */ @@ -400,7 +400,7 @@ TEST(mathPrimCorrectValues, wiener_full_lpdf) { var sv = sv_vec[i]; var sw = sw_vec[i]; var st0 = st0_vec[i]; - var dens = stan::math::wiener_full_lpdf(y, a, t0, w, v, sv, sw, st0); + var dens = stan::math::wiener_lpdf(y, a, t0, w, v, sv, sw, st0); dens.grad(); EXPECT_NEAR(dens.val(), true_dens[i], err_tol_dens); EXPECT_NEAR(y.adj(), true_grad_y[i], err_tol); From 517c3cb9f8e0a22d5f490bf138d2313fbc4c1a76 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 11 Jan 2024 05:40:22 -0500 Subject: [PATCH 135/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- .../math/prim/prob/wiener_full_lpdf_test.cpp | 78 +++++++------------ 1 file changed, 26 insertions(+), 52 deletions(-) diff --git a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp index 942bf05b257..2773267b218 100644 --- a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp @@ -28,16 +28,12 @@ TEST(mathPrimScalProbWienerFullScal, invalid_rt) { using stan::math::INFTY; using stan::math::wiener_lpdf; double a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_lpdf(0, a, t0, w, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_lpdf(-1, a, t0, w, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_lpdf(INFTY, a, t0, w, v, sv, sw, st0), - std::domain_error); + EXPECT_THROW(wiener_lpdf(0, a, t0, w, v, sv, sw, st0), std::domain_error); + EXPECT_THROW(wiener_lpdf(-1, a, t0, w, v, sv, sw, st0), std::domain_error); + EXPECT_THROW(wiener_lpdf(INFTY, a, t0, w, v, sv, sw, st0), std::domain_error); EXPECT_THROW(wiener_lpdf(-INFTY, a, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_lpdf(NAN, a, t0, w, v, sv, sw, st0), - std::domain_error); + EXPECT_THROW(wiener_lpdf(NAN, a, t0, w, v, sv, sw, st0), std::domain_error); } // a @@ -45,16 +41,13 @@ TEST(mathPrimScalProbWienerFullScal, invalid_a) { using stan::math::INFTY; using stan::math::wiener_lpdf; double rt = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_lpdf(rt, 0, t0, w, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_lpdf(rt, -1, t0, w, v, sv, sw, st0), - std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, 0, t0, w, v, sv, sw, st0), std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, -1, t0, w, v, sv, sw, st0), std::domain_error); EXPECT_THROW(wiener_lpdf(rt, INFTY, t0, w, v, sv, sw, st0), std::domain_error); EXPECT_THROW(wiener_lpdf(rt, -INFTY, t0, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_lpdf(rt, NAN, t0, w, v, sv, sw, st0), - std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, NAN, t0, w, v, sv, sw, st0), std::domain_error); } // v @@ -67,8 +60,7 @@ TEST(mathPrimScalProbWienerFullScal, invalid_v) { std::domain_error); EXPECT_THROW(wiener_lpdf(rt, a, t0, w, -INFTY, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_lpdf(rt, a, t0, w, NAN, sv, sw, st0), - std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, NAN, sv, sw, st0), std::domain_error); } // w @@ -76,20 +68,15 @@ TEST(mathPrimScalProbWienerFullScal, invalid_w) { using stan::math::INFTY; using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, t0 = 0.1, sv = 0.2, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_lpdf(rt, a, t0, -0.1, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_lpdf(rt, a, t0, 0, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_lpdf(rt, a, t0, 1, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_lpdf(rt, a, t0, 1.1, v, sv, sw, st0), - std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, t0, -0.1, v, sv, sw, st0), std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, t0, 0, v, sv, sw, st0), std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, t0, 1, v, sv, sw, st0), std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, t0, 1.1, v, sv, sw, st0), std::domain_error); EXPECT_THROW(wiener_lpdf(rt, a, t0, INFTY, v, sv, sw, st0), std::domain_error); EXPECT_THROW(wiener_lpdf(rt, a, t0, -INFTY, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_lpdf(rt, a, t0, NAN, v, sv, sw, st0), - std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, t0, NAN, v, sv, sw, st0), std::domain_error); } // t0 @@ -99,14 +86,11 @@ TEST(mathPrimScalProbWienerFullScal, invalid_t0) { double rt = 1, a = 1, v = -1, w = 0.5, sv = 0.2, sw = 0.2, st0 = 0.1; EXPECT_THROW(wiener_lpdf(rt, a, 2, w, v, sv, sw, st0), std::domain_error); // rt must be greater than t0 - EXPECT_THROW(wiener_lpdf(rt, a, -1, w, v, sv, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_lpdf(rt, a, INFTY, w, v, sv, sw, st0), - std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, -1, w, v, sv, sw, st0), std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, INFTY, w, v, sv, sw, st0), std::domain_error); EXPECT_THROW(wiener_lpdf(rt, a, -INFTY, w, v, sv, sw, st0), std::domain_error); - EXPECT_THROW(wiener_lpdf(rt, a, NAN, w, v, sv, sw, st0), - std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, NAN, w, v, sv, sw, st0), std::domain_error); } // sv @@ -114,14 +98,11 @@ TEST(mathPrimScalProbWienerFullScal, invalid_sv) { using stan::math::INFTY; using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sw = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, -1, sw, st0), - std::domain_error); - EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, INFTY, sw, st0), - std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, -1, sw, st0), std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, INFTY, sw, st0), std::domain_error); EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, -INFTY, sw, st0), std::domain_error); - EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, NAN, sw, st0), - std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, NAN, sw, st0), std::domain_error); } // sw @@ -129,18 +110,15 @@ TEST(mathPrimScalProbWienerFullScal, invalid_sw) { using stan::math::INFTY; using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, st0 = 0.1; - EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, -1, st0), - std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, -1, st0), std::domain_error); EXPECT_THROW(wiener_lpdf(rt, a, t0, 0.8, v, sv, 0.5, st0), std::domain_error); // sw must be smaller than 2*(1-w) EXPECT_THROW(wiener_lpdf(rt, a, t0, 0.3, v, sv, 0.7, st0), std::domain_error); // sw must be smaller than 2*w - EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, INFTY, st0), - std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, INFTY, st0), std::domain_error); EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, -INFTY, st0), std::domain_error); - EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, NAN, st0), - std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, NAN, st0), std::domain_error); } // st0 @@ -148,14 +126,10 @@ TEST(mathPrimScalProbWienerFullScal, invalid_st0) { using stan::math::INFTY; using stan::math::wiener_lpdf; double rt = 1, a = 1, v = -1, w = 0.5, t0 = 0.1, sv = 0.2, sw = 0.2; - EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, -1), - std::domain_error); - EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, INFTY), - std::domain_error); - EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, -INFTY), - std::domain_error); - EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, NAN), - std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, -1), std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, INFTY), std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, -INFTY), std::domain_error); + EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, NAN), std::domain_error); } TEST(mathPrimScalProbWienerFullPrecScal, valid) { From cda357b735e53144d30d25ee84b0ec0ffbaf734a Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Thu, 11 Jan 2024 13:05:44 +0100 Subject: [PATCH 136/179] docs --- stan/math/prim/functor/hcubature.hpp | 44 ++++-------- stan/math/prim/prob/wiener5_lpdf.hpp | 91 ++++++++++++++++++++---- stan/math/prim/prob/wiener_full_lpdf.hpp | 48 +++++++++---- 3 files changed, 127 insertions(+), 56 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index db04c7a117f..11996bf46d9 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -171,6 +171,8 @@ inline Eigen::Matrix signcombos( * for one dimension. * * @tparam F type of the integrand + * @tparam T_a type of lower limit of integration + * @tparam T_b type of upper limit of integration * @tparam ParsPairT type of the pair of parameters for the integrand * @param integrand function to be integrated * @param a lower limit of integration @@ -253,11 +255,12 @@ make_GenzMalik(const int dim) { * for more than one dimensions. * * @tparam F type of the integrand + * @tparam GenzMalik type of ----- + * @tparam T_a type of lower limit of integration + * @tparam T_b type of upper limit of integration * @tparam ParsTupleT type of the tuple of parameters for the integrand * @param[out] integrand function to be integrated - * @param[in] points points for the last 4 GenzMalik weights - * @param[in] weights weights for the 5 terms in the GenzMalik rule - * @param[in] weights_low_deg weights for the embedded lower-degree rule + * @param[in] genz_malik tuple of GenzMalik weights * @param dim dimension of the multidimensional integral * @param a lower limit of integration * @param b upper limit of integration @@ -351,6 +354,8 @@ inline auto integrate_GenzMalik(const F& integrand, const GenzMalik& genz_malik, * Compute the integral of the function to be integrated (integrand) from a to b * for more than one dimensions. * + * @tparam T_a Type of return_type_t 1 + * @tparam T_b Type of return_type_t 2 * @tparam Vec1 Type of vector 1 * @tparam Vec2 Type of vector 2 * @param a lower bounds of the integral @@ -375,46 +380,27 @@ struct Box { } // namespace internal /** - * Compute the dim-dimensional integral of the function \f$f\f$ from \f$a\f$ to + * Compute the [dim]-dimensional integral of the function \f$f\f$ from \f$a\f$ to \f$b\f$ within * specified relative and absolute tolerances or maximum number of evaluations. * \f$a\f$ and \f$b\f$ can be finite or infinite and should be given as vectors. * - * The prototype for \f$f\f$ is: - \verbatim - template - stan::return_type_t f(const T_x& x, const T_p& p) { - using T_x_ref = stan::ref_type_t; - T_x_ref x_ref = x; - stan::scalar_seq_view x_vec(x_ref); - my_params* pars = static_cast(p); - type_1 var_1 = (pars->par_1); - return ; - } - \endverbatim - * - * The parameters can be handed over to f as a struct: - \verbatim - struct my_params { - type_1 par_1; - type_2 par_2; - }; - \endverbatim - * + * @tparam Scalar Type of scalars * @tparam F Type of f - * @tparam T_pars Type of paramete-struct + * @tparam T_a Type of lower limit of integration + * @tparam T_b Type of upper limit of integration + * @tparam ParsTuple Type of parameter-tuple * * @param integrand a functor with signature given above - * @param pars parameters to be passed to f as a struct + * @param pars parameters to be passed to f as a tuple * @param dim dimension of the integral * @param a lower limit of integration as vector * @param b upper limit of integration as vector * @param max_eval maximal number of evaluations * @param reqAbsError absolute error * @param reqRelError relative error as vector - * @param val correct value of integral * - * @return The value of the dim-dimensional integral of \f$f\f$ from \f$a\f$ to + * @return The value of the [dim]-dimensional integral of \f$f\f$ from \f$a\f$ to \f$b\f$. * @throw std::domain_error no errors will be thrown. */ diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 314269d8eae..c67ecfe84a1 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -12,6 +12,12 @@ enum GradientCalc { OFF = 0, ON = 1 }; /** * Calculate the 'error_term' term for a wiener5 density or gradient * + * @tparam T_y type of scalar variable + * @tparam T_a type of boundary separation + * @tparam T_v type of drift rate + * @tparam T_w type of relative starting point + * @tparam T_sv type of inter-trial variability in v + * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation * @param v_value The drift rate @@ -38,7 +44,11 @@ inline auto wiener5_compute_error_term(T_y&& y, T_a&& a, T_v&& v_value, * * @tparam GradA Whether the calculation is for gradient w.r.t. 'a' * @tparam GradT Whether the calculation is for gradient w.r.t. 't' - * @tparam Scalar type of scalars + * @tparam T_y type of scalar variable + * @tparam T_a type of boundary separation + * @tparam T_v_value type of drift rate + * @tparam T_w_value type of relative starting point + * @tparam T_sv type of inter-trial variability in v * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -74,7 +84,10 @@ inline auto wiener5_density_part_one(T_y&& y, T_a&& a, T_v_value&& v_value, * * @tparam Density Whether the calculation is for the density * @tparam GradW Whether the calculation is for gradient w.r.t. 'w' - * @tparam Scalar type of scalars + * @tparam T_y type of scalar variable + * @tparam T_a type of boundary separation + * @tparam T_w_value type of relative starting point + * @tparam T_err type of error * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -111,8 +124,11 @@ inline auto wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, * Calculate the 'n_terms_small_t' term for a wiener5 density or gradient * * @tparam Density Whether the calculation is for the density - * @tparam GradT Whether the calculation is for gradient w.r.t. 't' - * @tparam Scalar type of scalars + * @tparam GradW Whether the calculation is for gradient w.r.t. 't' + * @tparam T_y type of scalar variable + * @tparam T_a type of boundary separation + * @tparam T_w_value type of relative starting point + * @tparam T_err type of error * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -155,7 +171,11 @@ inline auto wiener5_n_terms_large_t(T_y&& y, T_a&& a, T_w_value&& w_value, * * @tparam Density Whether the calculation is for the density * @tparam GradW Whether the calculation is for gradient w.r.t. 'w' - * @tparam Scalar type of scalars + * @tparam T_y type of scalar variable + * @tparam T_a type of boundary separation + * @tparam T_w type of relative starting point + * @tparam T_nsmall type of term number_small_terms + * @tparam T_nlarge type of term number_large_terms * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -264,6 +284,12 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, * * @tparam NaturalScale Whether to return the density on natural (true) or * log-scale (false) + * @tparam T_y type of scalar variable + * @tparam T_a type of boundary separation + * @tparam T_w type of relative starting point + * @tparam T_v type of drift rate + * @tparam T_sv type of inter-trial variability in v + * @tparam T_err type of log error * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -306,7 +332,12 @@ inline auto wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, * * @tparam WrtLog Whether to return the derivative w.r.t. * the natural (true) or log-scale (false) density - * @tparam Scalar type of scalars + * @tparam T_y type of scalar variable + * @tparam T_a type of boundary separation + * @tparam T_v type of drift rate + * @tparam T_w type of relative starting point + * @tparam T_sv type of inter-trial variability in v + * @tparam T_err type of log error * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -363,7 +394,12 @@ inline auto wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, * * @tparam WrtLog Whether to return the derivative w.r.t. * the natural (true) or log-scale (false) density - * @tparam Scalar type of scalars + * @tparam T_y type of scalar variable + * @tparam T_a type of boundary separation + * @tparam T_v type of drift rate + * @tparam T_w type of relative starting point + * @tparam T_sv type of inter-trial variability in v + * @tparam T_err type of log error * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -422,7 +458,12 @@ inline auto wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, * * @tparam WrtLog Whether to return the derivative w.r.t. * the natural (true) or log-scale (false) density - * @tparam Scalar type of scalars + * @tparam T_y type of scalar variable + * @tparam T_a type of boundary separation + * @tparam T_v type of drift rate + * @tparam T_w type of relative starting point + * @tparam T_sv type of inter-trial variability in v + * @tparam T_err type of log error * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -450,7 +491,12 @@ inline auto wiener5_grad_v(const T_y& y, const T_a& a, const T_v& v_value, * * @tparam WrtLog Whether to return the derivative w.r.t. * the natural (true) or log-scale (false) density - * @tparam Scalar type of scalars + * @tparam T_y type of scalar variable + * @tparam T_a type of boundary separation + * @tparam T_v type of drift rate + * @tparam T_w type of relative starting point + * @tparam T_sv type of inter-trial variability in v + * @tparam T_err type of log error * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -505,7 +551,12 @@ inline auto wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, * * @tparam WrtLog Whether to return the derivative w.r.t. * the natural (true) or log-scale (false) density - * @tparam Scalar type of scalars + * @tparam T_y type of scalar variable + * @tparam T_a type of boundary separation + * @tparam T_v type of drift rate + * @tparam T_w type of relative starting point + * @tparam T_sv type of inter-trial variability in v + * @tparam T_err type of log error * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -533,6 +584,13 @@ inline auto wiener5_grad_sv(const T_y& y, const T_a& a, const T_v& v_value, /** * Utility function for replacing a value with a specified error value + * + * @tparam NestedIndex index of error position in tuple + * @tparam Scalar1 type of argument to be replaced + * @tparam Scalar2 type of error to replace + * + * @param arg argument to be replaced + * @param err argument to replace */ template inline void assign_err(Scalar1 arg, Scalar2 err) { @@ -542,6 +600,13 @@ inline void assign_err(Scalar1 arg, Scalar2 err) { /** * Utility function for replacing a value with a specified error value, * overload for use when the value is stored within a tuple. + * + * @tparam NestedIndex index of error position in tuple + * @tparam Scalar1 type of argument to be replaced + * @tparam Scalar2 type of error to replace + * + * @param arg argument to be replaced + * @param err argument to replace */ template inline void assign_err(std::tuple& args_tuple, Scalar err) { @@ -553,16 +618,17 @@ inline void assign_err(std::tuple& args_tuple, Scalar err) { * checking the result against a provided error tolerance, and re-estimating * the function with the increased error if it fails. * - * @tparam Scalar type of scalars * @tparam ErrIndex Position of the error argument in the provided arguments + * @tparam GradW7 Whether the gradient of w is computed * @tparam NestedIndex Nested position if the error argument is within a tuple + * @tparam LogResult Whether result is on log- or on natural-scale * @tparam F Type of functor + * @tparam T_err type of error * @tparam ArgsTupleT Type of tuple of arguments for functor * * @param functor Function to apply * @param err Error value to check against * @param args_tuple Tuple of arguments to pass to functor - * @param log_result Whether the function result is already on the log-scale */ template Date: Thu, 11 Jan 2024 07:06:57 -0500 Subject: [PATCH 137/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/functor/hcubature.hpp | 10 +++++----- stan/math/prim/prob/wiener5_lpdf.hpp | 4 ++-- stan/math/prim/prob/wiener_full_lpdf.hpp | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 11996bf46d9..6162917131c 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -380,14 +380,14 @@ struct Box { } // namespace internal /** - * Compute the [dim]-dimensional integral of the function \f$f\f$ from \f$a\f$ to - \f$b\f$ within + * Compute the [dim]-dimensional integral of the function \f$f\f$ from \f$a\f$ + to \f$b\f$ within * specified relative and absolute tolerances or maximum number of evaluations. * \f$a\f$ and \f$b\f$ can be finite or infinite and should be given as vectors. * * @tparam Scalar Type of scalars * @tparam F Type of f - * @tparam T_a Type of lower limit of integration + * @tparam T_a Type of lower limit of integration * @tparam T_b Type of upper limit of integration * @tparam ParsTuple Type of parameter-tuple * @@ -400,8 +400,8 @@ struct Box { * @param reqAbsError absolute error * @param reqRelError relative error as vector * - * @return The value of the [dim]-dimensional integral of \f$f\f$ from \f$a\f$ to - \f$b\f$. + * @return The value of the [dim]-dimensional integral of \f$f\f$ from \f$a\f$ + to \f$b\f$. * @throw std::domain_error no errors will be thrown. */ template & args_tuple, Scalar err) { * @tparam NestedIndex Nested position if the error argument is within a tuple * @tparam LogResult Whether result is on log- or on natural-scale * @tparam F Type of functor - * @tparam T_err type of error + * @tparam T_err type of error * @tparam ArgsTupleT Type of tuple of arguments for functor * * @param functor Function to apply diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index cc2d0c7d797..d37bd8e45e9 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -18,7 +18,7 @@ namespace internal { * @tparam T_w type of relative starting point * @tparam T_sv type of inter-trial variability in v * @tparam T_sw type of inter-trial variability in w - * @tparam T_err type of log error tolerance + * @tparam T_err type of log error tolerance * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation @@ -60,10 +60,10 @@ inline auto wiener7_grad_sw(const T_y& y, const T_a& a, const T_v& v, * @tparam T_w type of relative starting point * @tparam T_sv type of inter-trial variability in v * @tparam T_sw type of inter-trial variability in w - * @tparam T_err type of log error tolerance + * @tparam T_err type of log error tolerance * * @param functor Gradient/density functor to apply - * @param y_diff A scalar variable; the reaction time in seconds without + * @param y_diff A scalar variable; the reaction time in seconds without * non-decision time * @param a The boundary separation * @param v The drift rate @@ -97,10 +97,10 @@ inline auto conditionally_grad_sw(F&& functor, T_y&& y_diff, T_a&& a, T_v&& v, * @tparam T_w type of relative starting point * @tparam T_sv type of inter-trial variability in v * @tparam T_sw type of inter-trial variability in w - * @tparam T_err type of log error tolerance + * @tparam T_err type of log error tolerance * * @param functor Gradient/density functor to apply - * @param y_diff A scalar variable; the reaction time in seconds without + * @param y_diff A scalar variable; the reaction time in seconds without * non-decision time * @param a The boundary separation * @param v The drift rate @@ -223,7 +223,7 @@ inline auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, * @tparam T_v type of drift rate * @tparam T_sv type of inter-trial variability of drift rate * @tparam T_sw type of inter-trial variability of relative starting point - * @tparam T_st0 type of inter-trial variability of non-decision time + * @tparam T_st0 type of inter-trial variability of non-decision time * * @param y A scalar variable; the reaction time in seconds * @param a The boundary separation From 45adcdbb418cdb3e5a7587289f05b0398357cece Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Thu, 11 Jan 2024 13:22:14 +0100 Subject: [PATCH 138/179] correct docs --- stan/math/prim/prob/wiener5_lpdf.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 0cedf49a62d..e2ec6d2a993 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -601,11 +601,11 @@ inline void assign_err(Scalar1 arg, Scalar2 err) { * Utility function for replacing a value with a specified error value, * overload for use when the value is stored within a tuple. * - * @tparam NestedIndex index of error position in tuple - * @tparam Scalar1 type of argument to be replaced - * @tparam Scalar2 type of error to replace + * @tparam NestedIndex index of element in tuple to be replaced + * @tparam Scalar type of error to replace + * @tparam TArgs type of arguments to be replaced * - * @param arg argument to be replaced + * @param args_tuple argument tuple to be replaced * @param err argument to replace */ template From c68aba3d74b6032b61cf96c1828f97e43f8bdd8f Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 11 Jan 2024 07:23:16 -0500 Subject: [PATCH 139/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index e2ec6d2a993..d0ca0caf20f 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -602,7 +602,7 @@ inline void assign_err(Scalar1 arg, Scalar2 err) { * overload for use when the value is stored within a tuple. * * @tparam NestedIndex index of element in tuple to be replaced - * @tparam Scalar type of error to replace + * @tparam Scalar type of error to replace * @tparam TArgs type of arguments to be replaced * * @param args_tuple argument tuple to be replaced From 3eb95613f47dfcff250c7ffeb379eb9161e009a0 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Thu, 11 Jan 2024 13:48:51 +0100 Subject: [PATCH 140/179] correct function name in rev --- test/unit/math/rev/prob/wiener_full_test.cpp | 54 ++++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/test/unit/math/rev/prob/wiener_full_test.cpp b/test/unit/math/rev/prob/wiener_full_test.cpp index 96f9abe7f1a..131fc89449e 100644 --- a/test/unit/math/rev/prob/wiener_full_test.cpp +++ b/test/unit/math/rev/prob/wiener_full_test.cpp @@ -32,7 +32,7 @@ void check_scalar_types(F& f, double value, double res, double deriv) { TEST(ProbWienerFull, wiener_full_all_scalar) { // tests all parameter types individually, with other // parameters set to double - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; std::vector rt{1, 1, 1, 1, 1, 1, 1, 1, 1}; std::vector a{1, 1, 1, 1, 1, 1, 1, 1, 1}; @@ -69,49 +69,49 @@ TEST(ProbWienerFull, wiener_full_all_scalar) { for (int i = 0; i < result.size(); i++) { // rt auto f_rt = [&](auto value) { - return wiener_full_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], + return wiener_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_rt, rt[i], result[i], drt[i]); // a auto f_a = [&](auto value) { - return wiener_full_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], + return wiener_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_a, a[i], result[i], da[i]); // v auto f_v = [&](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], + return wiener_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], st0[i]); }; check_scalar_types(f_v, v[i], result[i], dv[i]); // w auto f_w = [&](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], + return wiener_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_w, w[i], result[i], dw[i]); // t0 auto f_t0 = [&](auto value) { - return wiener_full_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], + return wiener_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_t0, t0[i], result[i], dt0[i]); // sv auto f_sv = [&](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], + return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], st0[i]); }; check_scalar_types(f_sv, sv[i], result[i], dsv[i]); // sw auto f_sw = [&](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, + return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, st0[i]); }; check_scalar_types(f_sw, sw[i], result[i], dsw[i]); // st0 auto f_st0 = [&](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], + return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], value); }; check_scalar_types(f_st0, st0[i], result[i], dst0[i]); @@ -121,7 +121,7 @@ TEST(ProbWienerFull, wiener_full_all_scalar) { TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { // tests all parameter types individually, with other parameters // set to double - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; double err_tol = 2e-6; std::vector rt{1, 1, 1, 1, 1, 1, 1, 1, 1}; @@ -159,49 +159,49 @@ TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { for (int i = 0; i < result.size(); i++) { // rt auto f_rt = [&](auto value) { - return wiener_full_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], + return wiener_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types(f_rt, rt[i], result[i], drt[i]); // a auto f_a = [&](auto value) { - return wiener_full_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], + return wiener_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types(f_a, a[i], result[i], da[i]); // v auto f_v = [&](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], + return wiener_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types(f_v, v[i], result[i], dv[i]); // w auto f_w = [&](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], + return wiener_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types(f_w, w[i], result[i], dw[i]); // t0 auto f_t0 = [&](auto value) { - return wiener_full_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], + return wiener_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], st0[i], 1e-6); }; check_scalar_types(f_t0, t0[i], result[i], dt0[i]); // sv auto f_sv = [&](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], + return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], st0[i], 1e-6); }; check_scalar_types(f_sv, sv[i], result[i], dsv[i]); // sw auto f_sw = [&](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, + return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, st0[i], 1e-6); }; check_scalar_types(f_sw, sw[i], result[i], dsw[i]); // st0 auto f_st0 = [&](auto value) { - return wiener_full_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], + return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], value, 1e-6); }; check_scalar_types(f_st0, st0[i], result[i], dst0[i]); @@ -231,7 +231,7 @@ void check_vector_types(F& f, std::vector value, double res) { TEST(ProbWienerFull, wiener_full_all_vector) { // tests all parameter types individually, with other // parameters set to std::vector - using stan::math::wiener_full_lpdf; + using stan::math::wiener_lpdf; std::vector rt{1, 1, 1, 1, 1, 1, 1, 1, 1}; std::vector a{1, 1, 1, 1, 1, 1, 1, 1, 1}; @@ -246,42 +246,42 @@ TEST(ProbWienerFull, wiener_full_all_vector) { // rt auto f_rt = [&](auto value) { - return wiener_full_lpdf(value, a, t0, w, v, sv, sw, st0); + return wiener_lpdf(value, a, t0, w, v, sv, sw, st0); }; check_vector_types(f_rt, rt, result); // a auto f_a = [&](auto value) { - return wiener_full_lpdf(rt, value, t0, w, v, sv, sw, st0); + return wiener_lpdf(rt, value, t0, w, v, sv, sw, st0); }; check_vector_types(f_a, a, result); // v auto f_v = [&](auto value) { - return wiener_full_lpdf(rt, a, t0, w, value, sv, sw, st0); + return wiener_lpdf(rt, a, t0, w, value, sv, sw, st0); }; check_vector_types(f_v, v, result); // w auto f_w = [&](auto value) { - return wiener_full_lpdf(rt, a, t0, value, v, sv, sw, st0); + return wiener_lpdf(rt, a, t0, value, v, sv, sw, st0); }; check_vector_types(f_w, w, result); // t0 auto f_t0 = [&](auto value) { - return wiener_full_lpdf(rt, a, value, w, v, sv, sw, st0); + return wiener_lpdf(rt, a, value, w, v, sv, sw, st0); }; check_vector_types(f_t0, t0, result); // sv auto f_sv = [&](auto value) { - return wiener_full_lpdf(rt, a, t0, w, v, value, sw, st0); + return wiener_lpdf(rt, a, t0, w, v, value, sw, st0); }; check_vector_types(f_sv, sv, result); // sw auto f_sw = [&](auto value) { - return wiener_full_lpdf(rt, a, t0, w, v, sv, value, st0); + return wiener_lpdf(rt, a, t0, w, v, sv, value, st0); }; check_vector_types(f_sw, sw, result); // st0 auto f_st0 = [&](auto value) { - return wiener_full_lpdf(rt, a, t0, w, v, sv, sw, value); + return wiener_lpdf(rt, a, t0, w, v, sv, sw, value); }; check_vector_types(f_st0, st0, result); } From 2c5eb794c8a958630583f5c9c34ac47f9cbac744 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 11 Jan 2024 07:49:57 -0500 Subject: [PATCH 141/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- test/unit/math/rev/prob/wiener_full_test.cpp | 61 +++++++++----------- 1 file changed, 26 insertions(+), 35 deletions(-) diff --git a/test/unit/math/rev/prob/wiener_full_test.cpp b/test/unit/math/rev/prob/wiener_full_test.cpp index 131fc89449e..bc36395489b 100644 --- a/test/unit/math/rev/prob/wiener_full_test.cpp +++ b/test/unit/math/rev/prob/wiener_full_test.cpp @@ -69,50 +69,42 @@ TEST(ProbWienerFull, wiener_full_all_scalar) { for (int i = 0; i < result.size(); i++) { // rt auto f_rt = [&](auto value) { - return wiener_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], - st0[i]); + return wiener_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_rt, rt[i], result[i], drt[i]); // a auto f_a = [&](auto value) { - return wiener_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], - st0[i]); + return wiener_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_a, a[i], result[i], da[i]); // v auto f_v = [&](auto value) { - return wiener_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], - st0[i]); + return wiener_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], st0[i]); }; check_scalar_types(f_v, v[i], result[i], dv[i]); // w auto f_w = [&](auto value) { - return wiener_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], - st0[i]); + return wiener_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_w, w[i], result[i], dw[i]); // t0 auto f_t0 = [&](auto value) { - return wiener_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], - st0[i]); + return wiener_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], st0[i]); }; check_scalar_types(f_t0, t0[i], result[i], dt0[i]); // sv auto f_sv = [&](auto value) { - return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], - st0[i]); + return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], st0[i]); }; check_scalar_types(f_sv, sv[i], result[i], dsv[i]); // sw auto f_sw = [&](auto value) { - return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, - st0[i]); + return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, st0[i]); }; check_scalar_types(f_sw, sw[i], result[i], dsw[i]); // st0 auto f_st0 = [&](auto value) { - return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], - value); + return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], value); }; check_scalar_types(f_st0, st0[i], result[i], dst0[i]); } @@ -159,50 +151,50 @@ TEST(ProbWienerFullPrec, wiener_full_prec_all_scalar) { for (int i = 0; i < result.size(); i++) { // rt auto f_rt = [&](auto value) { - return wiener_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], - st0[i], 1e-6); + return wiener_lpdf(value, a[i], t0[i], w[i], v[i], sv[i], sw[i], st0[i], + 1e-6); }; check_scalar_types(f_rt, rt[i], result[i], drt[i]); // a auto f_a = [&](auto value) { - return wiener_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], - st0[i], 1e-6); + return wiener_lpdf(rt[i], value, t0[i], w[i], v[i], sv[i], sw[i], st0[i], + 1e-6); }; check_scalar_types(f_a, a[i], result[i], da[i]); // v auto f_v = [&](auto value) { - return wiener_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], - st0[i], 1e-6); + return wiener_lpdf(rt[i], a[i], t0[i], w[i], value, sv[i], sw[i], st0[i], + 1e-6); }; check_scalar_types(f_v, v[i], result[i], dv[i]); // w auto f_w = [&](auto value) { - return wiener_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], - st0[i], 1e-6); + return wiener_lpdf(rt[i], a[i], t0[i], value, v[i], sv[i], sw[i], st0[i], + 1e-6); }; check_scalar_types(f_w, w[i], result[i], dw[i]); // t0 auto f_t0 = [&](auto value) { - return wiener_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], - st0[i], 1e-6); + return wiener_lpdf(rt[i], a[i], value, w[i], v[i], sv[i], sw[i], st0[i], + 1e-6); }; check_scalar_types(f_t0, t0[i], result[i], dt0[i]); // sv auto f_sv = [&](auto value) { - return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], - st0[i], 1e-6); + return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], value, sw[i], st0[i], + 1e-6); }; check_scalar_types(f_sv, sv[i], result[i], dsv[i]); // sw auto f_sw = [&](auto value) { - return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, - st0[i], 1e-6); + return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], value, st0[i], + 1e-6); }; check_scalar_types(f_sw, sw[i], result[i], dsw[i]); // st0 auto f_st0 = [&](auto value) { - return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], - value, 1e-6); + return wiener_lpdf(rt[i], a[i], t0[i], w[i], v[i], sv[i], sw[i], value, + 1e-6); }; check_scalar_types(f_st0, st0[i], result[i], dst0[i]); } @@ -280,8 +272,7 @@ TEST(ProbWienerFull, wiener_full_all_vector) { }; check_vector_types(f_sw, sw, result); // st0 - auto f_st0 = [&](auto value) { - return wiener_lpdf(rt, a, t0, w, v, sv, sw, value); - }; + auto f_st0 + = [&](auto value) { return wiener_lpdf(rt, a, t0, w, v, sv, sw, value); }; check_vector_types(f_st0, st0, result); } From 24e435063b12b301908a9a05d0ae441797f9e824 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Thu, 11 Jan 2024 17:08:07 +0100 Subject: [PATCH 142/179] mix test values in util --- test/unit/math/mix/prob/util.hpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test/unit/math/mix/prob/util.hpp b/test/unit/math/mix/prob/util.hpp index d0ffbcefa5f..6579a329768 100644 --- a/test/unit/math/mix/prob/util.hpp +++ b/test/unit/math/mix/prob/util.hpp @@ -8,14 +8,14 @@ class Wiener7MixArgs : public ::testing::Test { const char* function = "function"; void SetUp() {} - Eigen::VectorXd y{{0.1, 0.3}}; - Eigen::VectorXd a{{2.0, 2.5}}; - Eigen::VectorXd t0{{0.2, 0.1}}; - Eigen::VectorXd w{{0.5, 0.2}}; - Eigen::VectorXd v{{2.0, 0.8}}; - Eigen::VectorXd sv{{0.2, 0.1}}; - Eigen::VectorXd sw{{0.1, .99}}; - Eigen::VectorXd st0{{0.3, .8}}; + Eigen::VectorXd y {{1.0, 0.05, 3.0, 1.0, 1.0 , 2.0 , 1.0 , 1.0 , 1.0 , 1.0, 1.0 , 1.0, 1.0 , 1.0, 1.0 , 1.0 , 1.0, 1.0, 1.0}}; + Eigen::VectorXd a {{2.5, 2.5 , 2.5, 0.2, 15.0, 2.5 , 2.5 , 2.5 , 2.5 , 2.5, 2.5 , 2.5, 2.5 , 2.5, 2.5 , 2.5 , 2.5, 2.5, 2.5}}; + Eigen::VectorXd t0 {{2.2, 0.01, 2.2, 0.2, 0.2 , 1.99, 0.01, 0.2 , 0.2 , 0.2, 0.2 , 0.2, 0.2 , 0.2, 0.2 , 0.2 , 0.2, 0.2 , 0.2}}; + Eigen::VectorXd w {{0.5, 0.5 , 0.5, 0.5, 0.5 , 0.5 , 0.5 , 0.01, 0.99, 0.5, 0.5 , 0.5, 0.5 , 0.5, 0.5 , 0.5 , 0.5, 0.5 , 0.5}}; + Eigen::VectorXd v {{2.0, 2.0 , 2.0, 2.0, 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 0.0, -5.0, 8.0, 2.0 , 2.0, 2.0 , 2.0 , 2.0, 2.0 , 2.0}}; + Eigen::VectorXd sv {{0.2, 0.2 , 0.2, 0.2, 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2, 0.2 , 0.2, 0.02, 9.0, 0.01, 0.2 , 0.2, 0.2 , 0.2}}; + Eigen::VectorXd sw {{0.1, 0.1 , 0.1, 0.1, 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1, 0.1 , 0.1, 0.1 , 0.1, 0.1 , 0.02, 0.4, 0.1 , 0.1}}; + Eigen::VectorXd st0{{0.3, 0.3 , 0.3, 0.3, 0.3 , 0.3 , 0.3 , 0.3 , 0.3 , 0.3, 0.3 , 0.3, 0.3 , 0.3, 0.3 , 0.3 , 0.3, 0.02, 5.0}}; }; class Wiener5MixArgs : public ::testing::Test { @@ -23,12 +23,12 @@ class Wiener5MixArgs : public ::testing::Test { const char* function = "function"; void SetUp() {} - Eigen::VectorXd y{{1.0, 0.1, 0.3}}; - Eigen::VectorXd a{{2.5, 2.0, 2.5}}; - Eigen::VectorXd t0{{0.2, 0.2, 0.1}}; - Eigen::VectorXd w{{0.5, 0.5, 0.2}}; - Eigen::VectorXd v{{2.0, 2.0, 0.8}}; - Eigen::VectorXd sv{{0.2, 0.2, 0.1}}; + Eigen::VectorXd y {{1.0, 0.05, 3.0, 1.0, 1.0 , 2.0 , 1.0 , 1.0 , 1.0 , 1.0, 1.0 , 1.0, 1.0 , 1.0, 1.0}}; + Eigen::VectorXd a {{2.5, 2.5 , 2.5, 0.2, 15.0, 2.5 , 2.5 , 2.5 , 2.5 , 2.5, 2.5 , 2.5, 2.5 , 2.5, 2.5}}; + Eigen::VectorXd t0{{2.2, 0.01, 2.2, 0.2, 0.2 , 1.99, 0.01, 0.2 , 0.2 , 0.2, 0.2 , 0.2, 0.2 , 0.2, 0.2}}; + Eigen::VectorXd w {{0.5, 0.5 , 0.5, 0.5, 0.5 , 0.5 , 0.5 , 0.01, 0.99, 0.5, 0.5 , 0.5, 0.5 , 0.5, 0.5}}; + Eigen::VectorXd v {{2.0, 2.0 , 2.0, 2.0, 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 0.0, -5.0, 8.0, 2.0 , 2.0, 2.0}}; + Eigen::VectorXd sv{{0.2, 0.2 , 0.2, 0.2, 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2, 0.2 , 0.2, 0.02, 9.0, 0.01}}; }; #endif From c2c816d6004c8eac1d612fe85dc8c657b8c2af26 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 11 Jan 2024 11:09:27 -0500 Subject: [PATCH 143/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- test/unit/math/mix/prob/util.hpp | 42 +++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/test/unit/math/mix/prob/util.hpp b/test/unit/math/mix/prob/util.hpp index 6579a329768..6081c0721df 100644 --- a/test/unit/math/mix/prob/util.hpp +++ b/test/unit/math/mix/prob/util.hpp @@ -8,14 +8,22 @@ class Wiener7MixArgs : public ::testing::Test { const char* function = "function"; void SetUp() {} - Eigen::VectorXd y {{1.0, 0.05, 3.0, 1.0, 1.0 , 2.0 , 1.0 , 1.0 , 1.0 , 1.0, 1.0 , 1.0, 1.0 , 1.0, 1.0 , 1.0 , 1.0, 1.0, 1.0}}; - Eigen::VectorXd a {{2.5, 2.5 , 2.5, 0.2, 15.0, 2.5 , 2.5 , 2.5 , 2.5 , 2.5, 2.5 , 2.5, 2.5 , 2.5, 2.5 , 2.5 , 2.5, 2.5, 2.5}}; - Eigen::VectorXd t0 {{2.2, 0.01, 2.2, 0.2, 0.2 , 1.99, 0.01, 0.2 , 0.2 , 0.2, 0.2 , 0.2, 0.2 , 0.2, 0.2 , 0.2 , 0.2, 0.2 , 0.2}}; - Eigen::VectorXd w {{0.5, 0.5 , 0.5, 0.5, 0.5 , 0.5 , 0.5 , 0.01, 0.99, 0.5, 0.5 , 0.5, 0.5 , 0.5, 0.5 , 0.5 , 0.5, 0.5 , 0.5}}; - Eigen::VectorXd v {{2.0, 2.0 , 2.0, 2.0, 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 0.0, -5.0, 8.0, 2.0 , 2.0, 2.0 , 2.0 , 2.0, 2.0 , 2.0}}; - Eigen::VectorXd sv {{0.2, 0.2 , 0.2, 0.2, 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2, 0.2 , 0.2, 0.02, 9.0, 0.01, 0.2 , 0.2, 0.2 , 0.2}}; - Eigen::VectorXd sw {{0.1, 0.1 , 0.1, 0.1, 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1, 0.1 , 0.1, 0.1 , 0.1, 0.1 , 0.02, 0.4, 0.1 , 0.1}}; - Eigen::VectorXd st0{{0.3, 0.3 , 0.3, 0.3, 0.3 , 0.3 , 0.3 , 0.3 , 0.3 , 0.3, 0.3 , 0.3, 0.3 , 0.3, 0.3 , 0.3 , 0.3, 0.02, 5.0}}; + Eigen::VectorXd y{{1.0, 0.05, 3.0, 1.0, 1.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}}; + Eigen::VectorXd a{{2.5, 2.5, 2.5, 0.2, 15.0, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5}}; + Eigen::VectorXd t0{{2.2, 0.01, 2.2, 0.2, 0.2, 1.99, 0.01, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2}}; + Eigen::VectorXd w{{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.01, 0.99, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}}; + Eigen::VectorXd v{{2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 0.0, -5.0, + 8.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0}}; + Eigen::VectorXd sv{{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.02, 9.0, 0.01, 0.2, 0.2, 0.2, 0.2}}; + Eigen::VectorXd sw{{0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1, 0.1, 0.1, 0.02, 0.4, 0.1, 0.1}}; + Eigen::VectorXd st0{{0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, + 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.02, 5.0}}; }; class Wiener5MixArgs : public ::testing::Test { @@ -23,12 +31,18 @@ class Wiener5MixArgs : public ::testing::Test { const char* function = "function"; void SetUp() {} - Eigen::VectorXd y {{1.0, 0.05, 3.0, 1.0, 1.0 , 2.0 , 1.0 , 1.0 , 1.0 , 1.0, 1.0 , 1.0, 1.0 , 1.0, 1.0}}; - Eigen::VectorXd a {{2.5, 2.5 , 2.5, 0.2, 15.0, 2.5 , 2.5 , 2.5 , 2.5 , 2.5, 2.5 , 2.5, 2.5 , 2.5, 2.5}}; - Eigen::VectorXd t0{{2.2, 0.01, 2.2, 0.2, 0.2 , 1.99, 0.01, 0.2 , 0.2 , 0.2, 0.2 , 0.2, 0.2 , 0.2, 0.2}}; - Eigen::VectorXd w {{0.5, 0.5 , 0.5, 0.5, 0.5 , 0.5 , 0.5 , 0.01, 0.99, 0.5, 0.5 , 0.5, 0.5 , 0.5, 0.5}}; - Eigen::VectorXd v {{2.0, 2.0 , 2.0, 2.0, 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 0.0, -5.0, 8.0, 2.0 , 2.0, 2.0}}; - Eigen::VectorXd sv{{0.2, 0.2 , 0.2, 0.2, 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2, 0.2 , 0.2, 0.02, 9.0, 0.01}}; + Eigen::VectorXd y{{1.0, 0.05, 3.0, 1.0, 1.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0}}; + Eigen::VectorXd a{{2.5, 2.5, 2.5, 0.2, 15.0, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5, 2.5, 2.5}}; + Eigen::VectorXd t0{{2.2, 0.01, 2.2, 0.2, 0.2, 1.99, 0.01, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2, 0.2}}; + Eigen::VectorXd w{{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.01, 0.99, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5}}; + Eigen::VectorXd v{{2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 0.0, -5.0, + 8.0, 2.0, 2.0, 2.0}}; + Eigen::VectorXd sv{{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.02, 9.0, 0.01}}; }; #endif From 29e3ec9c22b2d7f9d816581cbcb5d276de31cd7a Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 16 Jan 2024 11:20:59 +0100 Subject: [PATCH 144/179] different names, requested changes --- stan/math/prim/functor/hcubature.hpp | 9 +--- stan/math/prim/prob/wiener5_lpdf.hpp | 62 ++++++++++++++-------------- 2 files changed, 33 insertions(+), 38 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 6162917131c..eed77692c35 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -33,7 +33,6 @@ namespace math { namespace internal { -// Why are there 8 things in xd7? 8th element never used static constexpr std::array xd7{ -9.9145537112081263920685469752598e-01, -9.4910791234275852452618968404809e-01, @@ -41,8 +40,7 @@ static constexpr std::array xd7{ -7.415311855993944398638647732811e-01, -5.8608723546769113029414483825842e-01, -4.0584515137739716690660641207707e-01, - -2.0778495500789846760068940377309e-01, - 0.0}; + -2.0778495500789846760068940377309e-01}; static constexpr std::array wd7{ 2.2935322010529224963732008059913e-02, @@ -88,7 +86,6 @@ inline void combination(Eigen::Matrix& c, const int dim, } k = k - r; } - // Assumes p cannot be 0 c[p - 1] = (p > 1) ? c[p - 2] + x - k : x; } @@ -356,8 +353,6 @@ inline auto integrate_GenzMalik(const F& integrand, const GenzMalik& genz_malik, * * @tparam T_a Type of return_type_t 1 * @tparam T_b Type of return_type_t 2 - * @tparam Vec1 Type of vector 1 - * @tparam Vec2 Type of vector 2 * @param a lower bounds of the integral * @param b upper bounds of the integral * @param I value of the integral @@ -445,7 +440,7 @@ inline Scalar hcubature(const F& integrand, const ParsTuple& pars, using box_t = internal::Box; std::vector ms; ms.reserve(numevals); - ms.emplace_back(std::move(a), std::move(b), result, kdivide); + ms.emplace_back(a, b, result, kdivide); auto get_largest_box_idx = [](auto&& box_vec) { auto max_it = std::max_element(box_vec.begin(), box_vec.end()); return std::distance(box_vec.begin(), max_it); diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index d0ca0caf20f..d97f8ee0f01 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -204,48 +204,48 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, if (GradW) { const auto offset = y_asq; for (auto k = n_terms_small_t; k >= 1; k--) { - const auto wp2k = w + 2.0 * k; - const auto wm2k = w - 2.0 * k; - const auto sqwp2k_mo = square(wp2k) - offset; - if (sqwp2k_mo > 0) { - const auto wp2k_quant = log(sqwp2k_mo) - square(wp2k) * scaling; - fplus = log_sum_exp(fplus, wp2k_quant); - } else if (sqwp2k_mo < 0) { - const auto wp2k_quant = log(-sqwp2k_mo) - square(wp2k) * scaling; - fminus = log_sum_exp(fminus, wp2k_quant); + const auto w_plus_2_k = w + 2.0 * k; + const auto w_minus_2_k = w - 2.0 * k; + const auto square_w_plus_2_k_minus_offset = square(w_plus_2_k) - offset; + if (square_w_plus_2_k_minus_offset > 0) { + const auto summand_plus = log(square_w_plus_2_k_minus_offset) - square(w_plus_2_k) * scaling; + fplus = log_sum_exp(fplus, summand_plus); + } else if (square_w_plus_2_k_minus_offset < 0) { + const auto summand_plus = log(-square_w_plus_2_k_minus_offset) - square(w_plus_2_k) * scaling; + fminus = log_sum_exp(fminus, summand_plus); } - const auto sqwm2k_mo = square(wm2k) - offset; - if (sqwm2k_mo > 0) { - const auto wm2k_quant = log(sqwm2k_mo) - square(wm2k) * scaling; - fplus = log_sum_exp(fplus, wm2k_quant); - } else if (sqwm2k_mo < 0) { - const auto wm2k_quant = log(-sqwm2k_mo) - square(wm2k) * scaling; - fminus = log_sum_exp(fminus, wm2k_quant); + const auto square_w_minus_2_k_minus_offset = square(w_minus_2_k) - offset; + if (square_w_minus_2_k_minus_offset > 0) { + const auto summand_minus = log(square_w_minus_2_k_minus_offset) - square(w_minus_2_k) * scaling; + fplus = log_sum_exp(fplus, summand_minus); + } else if (square_w_minus_2_k_minus_offset < 0) { + const auto summand_minus = log(-square_w_minus_2_k_minus_offset) - square(w_minus_2_k) * scaling; + fminus = log_sum_exp(fminus, summand_minus); } } - const auto sqw_mo = square(w) - offset; - if (sqw_mo > 0) { - const auto new_val = log(sqw_mo) - square(w) * scaling; + const auto square_w_minus_offset = square(w) - offset; + if (square_w_minus_offset > 0) { + const auto new_val = log(square_w_minus_offset) - square(w) * scaling; fplus = log_sum_exp(fplus, new_val); - } else if (sqw_mo < 0) { - const auto new_val = log(-sqw_mo) - square(w) * scaling; + } else if (square_w_minus_offset < 0) { + const auto new_val = log(-square_w_minus_offset) - square(w) * scaling; fminus = log_sum_exp(fminus, new_val); } } else { for (auto k = n_terms_small_t; k >= 1; k--) { - const auto wp2k = w + 2.0 * k; - const auto wm2k = w - 2.0 * k; - const auto wp2k_quant = mult * log(wp2k) - square(wp2k) * scaling; - fplus = log_sum_exp(fplus, wp2k_quant); - const auto wm2k_quant = mult * log(-wm2k) - square(wm2k) * scaling; + const auto w_plus_2_k = w + 2.0 * k; + const auto w_minus_2_k = w - 2.0 * k; + const auto summand_plus = mult * log(w_plus_2_k) - square(w_plus_2_k) * scaling; + fplus = log_sum_exp(fplus, summand_plus); + const auto summand_minus = mult * log(-w_minus_2_k) - square(w_minus_2_k) * scaling; if (fminus <= NEGATIVE_INFTY) { - fminus = wm2k_quant; - } else if (wm2k_quant <= NEGATIVE_INFTY) { + fminus = summand_minus; + } else if (summand_minus <= NEGATIVE_INFTY) { continue; - } else if (fminus > wm2k_quant) { - fminus = fminus + log1p(exp(wm2k_quant - fminus)); + } else if (fminus > summand_minus) { + fminus = fminus + log1p(exp(summand_minus - fminus)); } else { - fminus = wm2k_quant + log1p(exp(fminus - wm2k_quant)); + fminus = summand_minus + log1p(exp(fminus - summand_minus)); } } const auto new_val = mult * log(w) - square(w) * scaling; From c624381c03034836e9e7884988a5860bdb23178b Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 16 Jan 2024 05:22:08 -0500 Subject: [PATCH 145/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index d97f8ee0f01..8fe91c8145a 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -208,18 +208,23 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, const auto w_minus_2_k = w - 2.0 * k; const auto square_w_plus_2_k_minus_offset = square(w_plus_2_k) - offset; if (square_w_plus_2_k_minus_offset > 0) { - const auto summand_plus = log(square_w_plus_2_k_minus_offset) - square(w_plus_2_k) * scaling; + const auto summand_plus = log(square_w_plus_2_k_minus_offset) + - square(w_plus_2_k) * scaling; fplus = log_sum_exp(fplus, summand_plus); } else if (square_w_plus_2_k_minus_offset < 0) { - const auto summand_plus = log(-square_w_plus_2_k_minus_offset) - square(w_plus_2_k) * scaling; + const auto summand_plus = log(-square_w_plus_2_k_minus_offset) + - square(w_plus_2_k) * scaling; fminus = log_sum_exp(fminus, summand_plus); } - const auto square_w_minus_2_k_minus_offset = square(w_minus_2_k) - offset; + const auto square_w_minus_2_k_minus_offset + = square(w_minus_2_k) - offset; if (square_w_minus_2_k_minus_offset > 0) { - const auto summand_minus = log(square_w_minus_2_k_minus_offset) - square(w_minus_2_k) * scaling; + const auto summand_minus = log(square_w_minus_2_k_minus_offset) + - square(w_minus_2_k) * scaling; fplus = log_sum_exp(fplus, summand_minus); } else if (square_w_minus_2_k_minus_offset < 0) { - const auto summand_minus = log(-square_w_minus_2_k_minus_offset) - square(w_minus_2_k) * scaling; + const auto summand_minus = log(-square_w_minus_2_k_minus_offset) + - square(w_minus_2_k) * scaling; fminus = log_sum_exp(fminus, summand_minus); } } @@ -235,9 +240,11 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, for (auto k = n_terms_small_t; k >= 1; k--) { const auto w_plus_2_k = w + 2.0 * k; const auto w_minus_2_k = w - 2.0 * k; - const auto summand_plus = mult * log(w_plus_2_k) - square(w_plus_2_k) * scaling; + const auto summand_plus + = mult * log(w_plus_2_k) - square(w_plus_2_k) * scaling; fplus = log_sum_exp(fplus, summand_plus); - const auto summand_minus = mult * log(-w_minus_2_k) - square(w_minus_2_k) * scaling; + const auto summand_minus + = mult * log(-w_minus_2_k) - square(w_minus_2_k) * scaling; if (fminus <= NEGATIVE_INFTY) { fminus = summand_minus; } else if (summand_minus <= NEGATIVE_INFTY) { From 4fe653b2a942f1de1921e39ea5325c5ea1afc4f5 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 16 Jan 2024 11:24:02 +0100 Subject: [PATCH 146/179] signature hcubature --- stan/math/prim/functor/hcubature.hpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index eed77692c35..c9ccdb1868e 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -380,11 +380,12 @@ struct Box { * specified relative and absolute tolerances or maximum number of evaluations. * \f$a\f$ and \f$b\f$ can be finite or infinite and should be given as vectors. * - * @tparam Scalar Type of scalars * @tparam F Type of f * @tparam T_a Type of lower limit of integration * @tparam T_b Type of upper limit of integration * @tparam ParsTuple Type of parameter-tuple + * @tparam TAbsErr Type of absolute error + * @tparam TRelErr Type of relative error * * @param integrand a functor with signature given above * @param pars parameters to be passed to f as a tuple @@ -399,14 +400,15 @@ struct Box { to \f$b\f$. * @throw std::domain_error no errors will be thrown. */ -template +template inline Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, const Eigen::Matrix& a, const Eigen::Matrix& b, - const int max_eval, const Scalar reqAbsError, - const Scalar reqRelError) { + const int max_eval, const TAbsErr reqAbsError, + const TRelErr reqRelError) { + using Scalar = return_type_t; using eig_vec_a = Eigen::Matrix; using eig_vec_b = Eigen::Matrix; const int maxEval = max_eval <= 0 ? 1000000 : max_eval; From a723270afbd4e80d78a1e1d75554f3ba34d1568f Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 16 Jan 2024 05:25:08 -0500 Subject: [PATCH 147/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/functor/hcubature.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index c9ccdb1868e..622f21606e0 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -400,8 +400,8 @@ struct Box { to \f$b\f$. * @throw std::domain_error no errors will be thrown. */ -template +template inline Scalar hcubature(const F& integrand, const ParsTuple& pars, const int dim, const Eigen::Matrix& a, From 6fb66ef120d1e6fbdd94ef4fcfdf669c4ca2d7f9 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Wed, 17 Jan 2024 11:53:09 +0100 Subject: [PATCH 148/179] hcubature auto --- stan/math/prim/functor/hcubature.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 622f21606e0..d6c3636ab56 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -402,7 +402,7 @@ struct Box { */ template -inline Scalar hcubature(const F& integrand, const ParsTuple& pars, +inline auto hcubature(const F& integrand, const ParsTuple& pars, const int dim, const Eigen::Matrix& a, const Eigen::Matrix& b, From 0de5b43a309ae3585329e0595d204991bc0eea51 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 17 Jan 2024 05:54:13 -0500 Subject: [PATCH 149/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/functor/hcubature.hpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index d6c3636ab56..49a7709b939 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -402,12 +402,11 @@ struct Box { */ template -inline auto hcubature(const F& integrand, const ParsTuple& pars, - const int dim, - const Eigen::Matrix& a, - const Eigen::Matrix& b, - const int max_eval, const TAbsErr reqAbsError, - const TRelErr reqRelError) { +inline auto hcubature(const F& integrand, const ParsTuple& pars, const int dim, + const Eigen::Matrix& a, + const Eigen::Matrix& b, + const int max_eval, const TAbsErr reqAbsError, + const TRelErr reqRelError) { using Scalar = return_type_t; using eig_vec_a = Eigen::Matrix; using eig_vec_b = Eigen::Matrix; From 1d75a3987699714d932b4739e6a93d71dcf20d2b Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Thu, 18 Jan 2024 09:42:57 +0100 Subject: [PATCH 150/179] hcubature with boost::gauss_kronrod --- stan/math/prim/functor/hcubature.hpp | 98 ++++++---------------------- 1 file changed, 21 insertions(+), 77 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 49a7709b939..82b203596f4 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -28,35 +28,14 @@ #include #include +#include +//#include + namespace stan { namespace math { namespace internal { -static constexpr std::array xd7{ - -9.9145537112081263920685469752598e-01, - -9.4910791234275852452618968404809e-01, - -8.6486442335976907278971278864098e-01, - -7.415311855993944398638647732811e-01, - -5.8608723546769113029414483825842e-01, - -4.0584515137739716690660641207707e-01, - -2.0778495500789846760068940377309e-01}; - -static constexpr std::array wd7{ - 2.2935322010529224963732008059913e-02, - 6.3092092629978553290700663189093e-02, - 1.0479001032225018383987632254189e-01, - 1.4065325971552591874518959051021e-01, - 1.6900472663926790282658342659795e-01, - 1.9035057806478540991325640242055e-01, - 2.0443294007529889241416199923466e-01, - 2.0948214108472782801299917489173e-01}; - -static constexpr std::array gwd7{ - 1.2948496616886969327061143267787e-01, 2.797053914892766679014677714229e-01, - 3.8183005050511894495036977548818e-01, - 4.1795918367346938775510204081658e-01}; - /** * Get the [x]-th lexicographically ordered set of [p] elements in [dim] * output is in [c], and should be sizeof(int)*[p] @@ -163,53 +142,6 @@ inline Eigen::Matrix signcombos( return p; } -/** - * Compute the integral of the function to be integrated (integrand) from a to b - * for one dimension. - * - * @tparam F type of the integrand - * @tparam T_a type of lower limit of integration - * @tparam T_b type of upper limit of integration - * @tparam ParsPairT type of the pair of parameters for the integrand - * @param integrand function to be integrated - * @param a lower limit of integration - * @param b upper limit of integration - * @param pars_pair Pair of parameters for the integrand - * @return numeric integral of the integrand and error - */ -template -inline auto gauss_kronrod(const F& integrand, const T_a a, const T_b b, - const ParsPairT& pars_pair) { - using delta_t = return_type_t; - const delta_t c = 0.5 * (a + b); - const delta_t delta = 0.5 * (b - a); - auto f0 = math::apply([](auto&& integrand, auto&& c, - auto&&... args) { return integrand(c, args...); }, - pars_pair, integrand, c); - - auto I = f0 * wd7[7]; - auto Idash = f0 * gwd7[3]; - std::array deltax; - for (int i = 0; i < 7; ++i) { - deltax[i] = delta * xd7[i]; - } - for (auto i = 0; i != 7; i++) { - auto fx = math::apply( - [](auto&& integrand, auto&& c, auto&& delta, auto&&... args) { - return integrand(c + delta, args...) + integrand(c - delta, args...); - }, - pars_pair, integrand, c, deltax[i]); - I += fx * wd7[i]; - if (i % 2 == 1) { - Idash += fx * gwd7[i / 2]; - } - } - delta_t V = fabs(delta); - I *= V; - Idash *= V; - return std::make_pair(I, fabs(I - Idash)); -} - /** * Compute the points and weights corresponding to a [dim]-dimensional * Genz-Malik cubature rule @@ -410,6 +342,8 @@ inline auto hcubature(const F& integrand, const ParsTuple& pars, const int dim, using Scalar = return_type_t; using eig_vec_a = Eigen::Matrix; using eig_vec_b = Eigen::Matrix; + using namespace boost::math::quadrature; + const int maxEval = max_eval <= 0 ? 1000000 : max_eval; Scalar result; Scalar err; @@ -418,9 +352,19 @@ inline auto hcubature(const F& integrand, const ParsTuple& pars, const int dim, std::array, 4>, Eigen::Matrix, Eigen::Matrix> genz_malik; + + auto gk_lambda = [&integrand, &pars](auto&& c) { + return stan::math::apply( + [](auto&& integrand, auto&& c, auto&&... args) { + return integrand(c, args...); + }, + pars, integrand, c); + }; + if (dim == 1) { - std::tie(result, err) - = internal::gauss_kronrod(integrand, a[0], b[0], pars); + result = gauss_kronrod::integrate(gk_lambda, a[0], b[0], 15, 0, + &err); + } else { genz_malik = internal::make_GenzMalik(dim); std::tie(result, err, kdivide) @@ -466,10 +410,10 @@ inline auto hcubature(const F& integrand, const ParsTuple& pars, const int dim, Scalar err_1; Scalar err_2; if (dim == 1) { - std::tie(result_1, err_1) - = internal::gauss_kronrod(integrand, ma[0], box.b_[0], pars); - std::tie(result_2, err_2) - = internal::gauss_kronrod(integrand, box.a_[0], mb[0], pars); + result_1 = gauss_kronrod::integrate(gk_lambda, ma[0], + box.b_[0], 15, 0, &err_1); + result_2 = gauss_kronrod::integrate(gk_lambda, box.a_[0], + mb[0], 15, 0, &err_2); } else { std::tie(result_1, err_1, kdivide_1) = internal::integrate_GenzMalik( integrand, genz_malik, dim, ma, box.b_, pars); From 0292edeee434085f0745dc59db8b4ddb6b591215 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Thu, 18 Jan 2024 09:52:51 +0100 Subject: [PATCH 151/179] clean includes --- stan/math/prim/functor/hcubature.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index 82b203596f4..a0c591c000a 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -27,9 +27,7 @@ #include #include #include - #include -//#include namespace stan { namespace math { From e3715bfd9f63799895a6643761704810a595535c Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 31 Jan 2024 15:04:15 -0500 Subject: [PATCH 152/179] merge develop and revert hcubature to use internal gauss kronrod --- stan/math/prim/functor/hcubature.hpp | 85 +++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 7 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index a0c591c000a..ff5ab5ca81b 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -34,6 +35,30 @@ namespace math { namespace internal { + static constexpr std::array xd7{ + -9.9145537112081263920685469752598e-01, + -9.4910791234275852452618968404809e-01, + -8.6486442335976907278971278864098e-01, + -7.415311855993944398638647732811e-01, + -5.8608723546769113029414483825842e-01, + -4.0584515137739716690660641207707e-01, + -2.0778495500789846760068940377309e-01}; + +static constexpr std::array wd7{ + 2.2935322010529224963732008059913e-02, + 6.3092092629978553290700663189093e-02, + 1.0479001032225018383987632254189e-01, + 1.4065325971552591874518959051021e-01, + 1.6900472663926790282658342659795e-01, + 1.9035057806478540991325640242055e-01, + 2.0443294007529889241416199923466e-01, + 2.0948214108472782801299917489173e-01}; + +static constexpr std::array gwd7{ + 1.2948496616886969327061143267787e-01, 2.797053914892766679014677714229e-01, + 3.8183005050511894495036977548818e-01, + 4.1795918367346938775510204081658e-01}; + /** * Get the [x]-th lexicographically ordered set of [p] elements in [dim] * output is in [c], and should be sizeof(int)*[p] @@ -177,6 +202,53 @@ make_GenzMalik(const int dim) { std::move(weights_low_deg)); } +/** + * Compute the integral of the function to be integrated (integrand) from a to b + * for one dimension. + * + * @tparam F type of the integrand + * @tparam T_a type of lower limit of integration + * @tparam T_b type of upper limit of integration + * @tparam ParsPairT type of the pair of parameters for the integrand + * @param integrand function to be integrated + * @param a lower limit of integration + * @param b upper limit of integration + * @param pars_pair Pair of parameters for the integrand + * @return numeric integral of the integrand and error + */ +template +inline auto gauss_kronrod(const F& integrand, const T_a a, const T_b b, + const ParsPairT& pars_pair) { + using delta_t = return_type_t; + const delta_t c = 0.5 * (a + b); + const delta_t delta = 0.5 * (b - a); + auto f0 = math::apply([](auto&& integrand, auto&& c, + auto&&... args) { return integrand(c, args...); }, + pars_pair, integrand, c); + + auto I = f0 * wd7[7]; + auto Idash = f0 * gwd7[3]; + std::array deltax; + for (int i = 0; i < 7; ++i) { + deltax[i] = delta * xd7[i]; + } + for (auto i = 0; i != 7; i++) { + auto fx = math::apply( + [](auto&& integrand, auto&& c, auto&& delta, auto&&... args) { + return integrand(c + delta, args...) + integrand(c - delta, args...); + }, + pars_pair, integrand, c, deltax[i]); + I += fx * wd7[i]; + if (i % 2 == 1) { + Idash += fx * gwd7[i / 2]; + } + } + delta_t V = fabs(delta); + I *= V; + Idash *= V; + return std::make_pair(I, fabs(I - Idash)); +} + /** * Compute the integral of the function to be integrated (integrand) from a to b * for more than one dimensions. @@ -360,9 +432,8 @@ inline auto hcubature(const F& integrand, const ParsTuple& pars, const int dim, }; if (dim == 1) { - result = gauss_kronrod::integrate(gk_lambda, a[0], b[0], 15, 0, - &err); - + std::tie(result, err) + = internal::gauss_kronrod(integrand, a[0], b[0], pars); } else { genz_malik = internal::make_GenzMalik(dim); std::tie(result, err, kdivide) @@ -408,10 +479,10 @@ inline auto hcubature(const F& integrand, const ParsTuple& pars, const int dim, Scalar err_1; Scalar err_2; if (dim == 1) { - result_1 = gauss_kronrod::integrate(gk_lambda, ma[0], - box.b_[0], 15, 0, &err_1); - result_2 = gauss_kronrod::integrate(gk_lambda, box.a_[0], - mb[0], 15, 0, &err_2); + std::tie(result_1, err_1) + = internal::gauss_kronrod(integrand, ma[0], box.b_[0], pars); + std::tie(result_2, err_2) + = internal::gauss_kronrod(integrand, box.a_[0], mb[0], pars); } else { std::tie(result_1, err_1, kdivide_1) = internal::integrate_GenzMalik( integrand, genz_malik, dim, ma, box.b_, pars); From 9f835520bb3ee387c5d2d8841a5b90d399589b35 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 31 Jan 2024 15:08:19 -0500 Subject: [PATCH 153/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/functor/hcubature.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index ff5ab5ca81b..da5acfd73ff 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -35,7 +35,7 @@ namespace math { namespace internal { - static constexpr std::array xd7{ +static constexpr std::array xd7{ -9.9145537112081263920685469752598e-01, -9.4910791234275852452618968404809e-01, -8.6486442335976907278971278864098e-01, From 70bda5748842650a423c736b0307c4e17838e817 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 31 Jan 2024 16:32:46 -0500 Subject: [PATCH 154/179] update tests for more extreme values --- stan/math/prim/prob/wiener_full_lpdf.hpp | 2 + test/unit/math/mix/prob/util.hpp | 48 ++++++++++++------------ 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index d37bd8e45e9..6f1362791b5 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -399,11 +399,13 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, for (size_t i = 0; i < N_y_t0; ++i) { if (y_vec[i] <= t0_vec[i]) { + [&]() STAN_COLD_PATH { std::stringstream msg; msg << ", but must be greater than nondecision time = " << t0_vec[i]; std::string msg_str(msg.str()); throw_domain_error(function_name, "Random variable", y_vec[i], " = ", msg_str.c_str()); + }(); } } size_t N_beta_sw = max_size(w, sw); diff --git a/test/unit/math/mix/prob/util.hpp b/test/unit/math/mix/prob/util.hpp index 6081c0721df..028af6fee7c 100644 --- a/test/unit/math/mix/prob/util.hpp +++ b/test/unit/math/mix/prob/util.hpp @@ -8,21 +8,21 @@ class Wiener7MixArgs : public ::testing::Test { const char* function = "function"; void SetUp() {} - Eigen::VectorXd y{{1.0, 0.05, 3.0, 1.0, 1.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}}; - Eigen::VectorXd a{{2.5, 2.5, 2.5, 0.2, 15.0, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + Eigen::VectorXd y{{1.0, 0.05, 3.0, 1.0, 1.0, 2.0, 1.0, 1e-14, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 100.0, 1e10}}; + Eigen::VectorXd a{{2.5, 2.5, 2.5, 0.2, 15.0, 1e-13, 2.5e10, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5}}; - Eigen::VectorXd t0{{2.2, 0.01, 2.2, 0.2, 0.2, 1.99, 0.01, 0.2, 0.2, 0.2, 0.2, - 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2}}; - Eigen::VectorXd w{{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.01, 0.99, 0.5, 0.5, + Eigen::VectorXd t0{{2.2, 0.01, 2.2, 0.2, 0.2, 1.99, 1e-13, 0.0, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2, 0.2, 0.2, 1e13, 0.2, 0.2}}; + Eigen::VectorXd w{{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1e-13, 0.999999999999, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}}; - Eigen::VectorXd v{{2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 0.0, -5.0, - 8.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0}}; - Eigen::VectorXd sv{{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2, 0.02, 9.0, 0.01, 0.2, 0.2, 0.2, 0.2}}; - Eigen::VectorXd sw{{0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + Eigen::VectorXd v{{2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 1e-12, 0.0, 2.0, 0.0, -5.0, + 8.0, 2.0, 2.0, 2.0, 2.0, 2.0, 4e10, -4e10}}; + Eigen::VectorXd sv{{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 1e-14, 0.2, 0.2, + 0.2, 0.02, 9.0, 0.01, 0.2, 4, 0.2, 1e14}}; + Eigen::VectorXd sw{{0.1, 1e-13, 0.9999999999, 0.1, 0.4, 0.1, 0.1, 0.8, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.02, 0.4, 0.1, 0.1}}; - Eigen::VectorXd st0{{0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, + Eigen::VectorXd st0{{0.0, 1e-13, 1e16, 0.3, 0.3, 0.3, 1, 10, 100, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.02, 5.0}}; }; @@ -31,18 +31,18 @@ class Wiener5MixArgs : public ::testing::Test { const char* function = "function"; void SetUp() {} - Eigen::VectorXd y{{1.0, 0.05, 3.0, 1.0, 1.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0}}; - Eigen::VectorXd a{{2.5, 2.5, 2.5, 0.2, 15.0, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, - 2.5, 2.5, 2.5, 2.5}}; - Eigen::VectorXd t0{{2.2, 0.01, 2.2, 0.2, 0.2, 1.99, 0.01, 0.2, 0.2, 0.2, 0.2, - 0.2, 0.2, 0.2, 0.2}}; - Eigen::VectorXd w{{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.01, 0.99, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5}}; - Eigen::VectorXd v{{2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 0.0, -5.0, - 8.0, 2.0, 2.0, 2.0}}; - Eigen::VectorXd sv{{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2, 0.02, 9.0, 0.01}}; + Eigen::VectorXd y{{1.0, 0.05, 3.0, 1.0, 1.0, 2.0, 1.0, 1e-14, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 100.0, 1e10}}; + Eigen::VectorXd a{{2.5, 2.5, 2.5, 0.2, 15.0, 1e-13, 2.5e10, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5}}; + Eigen::VectorXd t0{{2.2, 0.01, 2.2, 0.2, 0.2, 1.99, 1e-13, 0.0, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2, 0.2, 0.2, 1e13, 0.2, 0.2}}; + Eigen::VectorXd w{{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1e-13, 0.999999999999, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}}; + Eigen::VectorXd v{{2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 1e-12, 0.0, 2.0, 0.0, -5.0, + 8.0, 2.0, 2.0, 2.0, 2.0, 2.0, 4e10, -4e10}}; + Eigen::VectorXd sv{{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 1e-14, 0.2, 0.2, + 0.2, 0.02, 9.0, 0.01, 0.2, 4, 0.2, 1e14}}; }; #endif From 5200f9f9a6038ec9f971175b4436adf706ebc8b0 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 31 Jan 2024 17:23:15 -0500 Subject: [PATCH 155/179] make wiener7_integrate lambdas more locally scoped. Add more extreme values to tests --- stan/math/prim/prob/wiener_full_lpdf.hpp | 67 +++++++++++------------- test/unit/math/mix/prob/util.hpp | 4 +- 2 files changed, 33 insertions(+), 38 deletions(-) diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 6f1362791b5..ff030cdffd1 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -73,7 +73,7 @@ inline auto wiener7_grad_sw(const T_y& y, const T_a& a, const T_v& v, * @param log_error The log error tolerance * @return Functor applied to arguments */ -template * = nullptr> inline auto conditionally_grad_sw(F&& functor, T_y&& y_diff, T_a&& a, T_v&& v, @@ -110,7 +110,7 @@ inline auto conditionally_grad_sw(F&& functor, T_y&& y_diff, T_a&& a, T_v&& v, * @param log_error The log error tolerance * @return Functor applied to arguments */ -template * = nullptr> inline auto conditionally_grad_sw(F&& functor, T_y&& y_diff, T_a&& a, T_v&& v, @@ -135,33 +135,29 @@ inline auto conditionally_grad_sw(F&& functor, T_y&& y_diff, T_a&& a, T_v&& v, * @param args Additional arguments to be passed to the hcubature function * @return Wiener7 density or gradient calculated by integration */ -template inline auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, T_err&& hcubature_err, TArgs&&... args) { - const auto wiener7_integrand_impl = - [&wiener7_functor](auto&& x, auto&& y, auto&& a, auto&& v, auto&& w, - auto&& t0, auto&& sv, auto&& sw, auto&& st0, - auto&& log_error) { - using ret_t - = return_type_t; - scalar_seq_view x_vec(x); - const auto sw_val = GradSW ? 0 : sw; - const auto new_w = w + sw_val * (x_vec[0] - 0.5); - const auto new_t0 = (sw_val != 0) - ? ((st0 != 0) ? t0 + st0 * x_vec[1] : t0) - : ((st0 != 0) ? t0 + st0 * x_vec[0] : t0); - if (y - new_t0 <= 0) { - return ret_t(0.0); - } else { - return ret_t(conditionally_grad_sw( - wiener7_functor, y - new_t0, a, v, new_w, sv, sw, log_error)); - } - }; - const auto functor = [&wiener7_integrand_impl](auto&&... int_args) { - return hcubature(wiener7_integrand_impl, int_args...); + const auto functor = [&wiener7_functor](auto&&... integration_args) { + return hcubature([&wiener7_functor](auto&& x, auto&& y, auto&& a, auto&& v, auto&& w, + auto&& t0, auto&& sv, auto&& sw, auto&& st0, + auto&& log_error) { + using ret_t + = return_type_t; + scalar_seq_view x_vec(x); + const auto sw_val = GradSW ? 0 : sw; + const auto new_t0 = t0 + st0 * x_vec[(sw_val != 0) ? 1 : 0]; + if (y - new_t0 <= 0) { + return ret_t(0.0); + } else { + const auto new_w = w + sw_val * (x_vec[0] - 0.5); + return ret_t(conditionally_grad_sw( + wiener7_functor, y - new_t0, a, v, new_w, sv, sw, log_error)); + } + }, integration_args...); }; return estimate_with_err_check<0, GradW7, 8, GradientCalc::ON>( functor, hcubature_err, args...); @@ -433,15 +429,14 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, }(); } } - - const T_partials_return log_error_density - = log(1e-6); // precision for density - const auto error_bound = precision_derivatives; // precision for - // derivatives (controllable by user) + // precision for density + const T_partials_return log_error_density = log(1e-6); + // precision for derivatives (controllable by user) + const auto error_bound = precision_derivatives; const auto log_error_derivative = log(error_bound); const T_partials_return absolute_error_hcubature = 0.0; - const T_partials_return relative_error_hcubature - = .9 * error_bound; // eps_rel(Integration) + // eps_rel(Integration) + const T_partials_return relative_error_hcubature = .9 * error_bound; const T_partials_return log_error_absolute = log(1e-12); const int maximal_evaluations_hcubature = 6000; T_partials_return log_density = 0.0; @@ -479,9 +474,10 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, T_partials_return hcubature_err = log_error_absolute - log_error_density + LOG_TWO + 1; using internal::GradientCalc; - const auto params = std::make_tuple(y_value, a_value, v_value, w_value, + auto log_err_abs = log_error_absolute - LOG_TWO; + const auto params = std::forward_as_tuple(y_value, a_value, v_value, w_value, t0_value, sv_value, sw_value, st0_value, - log_error_absolute - LOG_TWO); + log_err_abs); T_partials_return density = internal::wiener7_integrate( [](auto&&... args) { @@ -491,7 +487,6 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, maximal_evaluations_hcubature, absolute_error_hcubature, relative_error_hcubature / 2); log_density += log(density); - hcubature_err = log_error_absolute - log_error_derivative + log(fabs(density)) + LOG_TWO + 1; diff --git a/test/unit/math/mix/prob/util.hpp b/test/unit/math/mix/prob/util.hpp index 028af6fee7c..369a24d0411 100644 --- a/test/unit/math/mix/prob/util.hpp +++ b/test/unit/math/mix/prob/util.hpp @@ -14,13 +14,13 @@ class Wiener7MixArgs : public ::testing::Test { 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5}}; Eigen::VectorXd t0{{2.2, 0.01, 2.2, 0.2, 0.2, 1.99, 1e-13, 0.0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 1e13, 0.2, 0.2}}; - Eigen::VectorXd w{{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1e-13, 0.999999999999, 0.5, 0.5, + Eigen::VectorXd w{{1e-13, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1e-13, 0.999999999999, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}}; Eigen::VectorXd v{{2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 1e-12, 0.0, 2.0, 0.0, -5.0, 8.0, 2.0, 2.0, 2.0, 2.0, 2.0, 4e10, -4e10}}; Eigen::VectorXd sv{{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 1e-14, 0.2, 0.2, 0.2, 0.02, 9.0, 0.01, 0.2, 4, 0.2, 1e14}}; - Eigen::VectorXd sw{{0.1, 1e-13, 0.9999999999, 0.1, 0.4, 0.1, 0.1, 0.8, 0.1, 0.1, 0.1, + Eigen::VectorXd sw{{1, 1e-13, 0.9999999999, 0.1, 0.4, 0.1, 0.1, 0.8, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.02, 0.4, 0.1, 0.1}}; Eigen::VectorXd st0{{0.0, 1e-13, 1e16, 0.3, 0.3, 0.3, 1, 10, 100, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.02, 5.0}}; From bd563cc78097dce6fd8c078ae5c4a654bc2cb32a Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 31 Jan 2024 17:24:37 -0500 Subject: [PATCH 156/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener_full_lpdf.hpp | 70 ++++++++++++------------ test/unit/math/mix/prob/util.hpp | 28 +++++----- 2 files changed, 50 insertions(+), 48 deletions(-) diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index ff030cdffd1..795f60e2a1b 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -73,9 +73,9 @@ inline auto wiener7_grad_sw(const T_y& y, const T_a& a, const T_v& v, * @param log_error The log error tolerance * @return Functor applied to arguments */ -template * = nullptr> +template * = nullptr> inline auto conditionally_grad_sw(F&& functor, T_y&& y_diff, T_a&& a, T_v&& v, T_w&& w, T_sv&& sv, T_sw&& sw, T_err&& log_error) { @@ -110,9 +110,9 @@ inline auto conditionally_grad_sw(F&& functor, T_y&& y_diff, T_a&& a, T_v&& v, * @param log_error The log error tolerance * @return Functor applied to arguments */ -template * = nullptr> +template * = nullptr> inline auto conditionally_grad_sw(F&& functor, T_y&& y_diff, T_a&& a, T_v&& v, T_w&& w, T_sv&& sv, T_sw&& sw, T_err&& log_error) { @@ -140,24 +140,26 @@ template ; - scalar_seq_view x_vec(x); - const auto sw_val = GradSW ? 0 : sw; - const auto new_t0 = t0 + st0 * x_vec[(sw_val != 0) ? 1 : 0]; - if (y - new_t0 <= 0) { - return ret_t(0.0); - } else { - const auto new_w = w + sw_val * (x_vec[0] - 0.5); - return ret_t(conditionally_grad_sw( - wiener7_functor, y - new_t0, a, v, new_w, sv, sw, log_error)); - } - }, integration_args...); + return hcubature( + [&wiener7_functor](auto&& x, auto&& y, auto&& a, auto&& v, auto&& w, + auto&& t0, auto&& sv, auto&& sw, auto&& st0, + auto&& log_error) { + using ret_t = return_type_t; + scalar_seq_view x_vec(x); + const auto sw_val = GradSW ? 0 : sw; + const auto new_t0 = t0 + st0 * x_vec[(sw_val != 0) ? 1 : 0]; + if (y - new_t0 <= 0) { + return ret_t(0.0); + } else { + const auto new_w = w + sw_val * (x_vec[0] - 0.5); + return ret_t(conditionally_grad_sw( + wiener7_functor, y - new_t0, a, v, new_w, sv, sw, log_error)); + } + }, + integration_args...); }; return estimate_with_err_check<0, GradW7, 8, GradientCalc::ON>( functor, hcubature_err, args...); @@ -395,13 +397,13 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, for (size_t i = 0; i < N_y_t0; ++i) { if (y_vec[i] <= t0_vec[i]) { - [&]() STAN_COLD_PATH { - std::stringstream msg; - msg << ", but must be greater than nondecision time = " << t0_vec[i]; - std::string msg_str(msg.str()); - throw_domain_error(function_name, "Random variable", y_vec[i], " = ", - msg_str.c_str()); - }(); + [&]() STAN_COLD_PATH { + std::stringstream msg; + msg << ", but must be greater than nondecision time = " << t0_vec[i]; + std::string msg_str(msg.str()); + throw_domain_error(function_name, "Random variable", y_vec[i], " = ", + msg_str.c_str()); + }(); } } size_t N_beta_sw = max_size(w, sw); @@ -475,9 +477,9 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, = log_error_absolute - log_error_density + LOG_TWO + 1; using internal::GradientCalc; auto log_err_abs = log_error_absolute - LOG_TWO; - const auto params = std::forward_as_tuple(y_value, a_value, v_value, w_value, - t0_value, sv_value, sw_value, st0_value, - log_err_abs); + const auto params + = std::forward_as_tuple(y_value, a_value, v_value, w_value, t0_value, + sv_value, sw_value, st0_value, log_err_abs); T_partials_return density = internal::wiener7_integrate( [](auto&&... args) { diff --git a/test/unit/math/mix/prob/util.hpp b/test/unit/math/mix/prob/util.hpp index 369a24d0411..5b1dea8ad59 100644 --- a/test/unit/math/mix/prob/util.hpp +++ b/test/unit/math/mix/prob/util.hpp @@ -8,20 +8,20 @@ class Wiener7MixArgs : public ::testing::Test { const char* function = "function"; void SetUp() {} - Eigen::VectorXd y{{1.0, 0.05, 3.0, 1.0, 1.0, 2.0, 1.0, 1e-14, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 100.0, 1e10}}; - Eigen::VectorXd a{{2.5, 2.5, 2.5, 0.2, 15.0, 1e-13, 2.5e10, 2.5, 2.5, 2.5, 2.5, - 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5}}; + Eigen::VectorXd y{{1.0, 0.05, 3.0, 1.0, 1.0, 2.0, 1.0, 1e-14, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 100.0, 1e10}}; + Eigen::VectorXd a{{2.5, 2.5, 2.5, 0.2, 15.0, 1e-13, 2.5e10, 2.5, 2.5, 2.5, + 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5}}; Eigen::VectorXd t0{{2.2, 0.01, 2.2, 0.2, 0.2, 1.99, 1e-13, 0.0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 1e13, 0.2, 0.2}}; - Eigen::VectorXd w{{1e-13, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1e-13, 0.999999999999, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}}; + Eigen::VectorXd w{{1e-13, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1e-13, 0.999999999999, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}}; Eigen::VectorXd v{{2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 1e-12, 0.0, 2.0, 0.0, -5.0, 8.0, 2.0, 2.0, 2.0, 2.0, 2.0, 4e10, -4e10}}; Eigen::VectorXd sv{{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 1e-14, 0.2, 0.2, 0.2, 0.02, 9.0, 0.01, 0.2, 4, 0.2, 1e14}}; - Eigen::VectorXd sw{{1, 1e-13, 0.9999999999, 0.1, 0.4, 0.1, 0.1, 0.8, 0.1, 0.1, 0.1, - 0.1, 0.1, 0.1, 0.1, 0.02, 0.4, 0.1, 0.1}}; + Eigen::VectorXd sw{{1, 1e-13, 0.9999999999, 0.1, 0.4, 0.1, 0.1, 0.8, 0.1, 0.1, + 0.1, 0.1, 0.1, 0.1, 0.1, 0.02, 0.4, 0.1, 0.1}}; Eigen::VectorXd st0{{0.0, 1e-13, 1e16, 0.3, 0.3, 0.3, 1, 10, 100, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.02, 5.0}}; }; @@ -31,14 +31,14 @@ class Wiener5MixArgs : public ::testing::Test { const char* function = "function"; void SetUp() {} - Eigen::VectorXd y{{1.0, 0.05, 3.0, 1.0, 1.0, 2.0, 1.0, 1e-14, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 100.0, 1e10}}; - Eigen::VectorXd a{{2.5, 2.5, 2.5, 0.2, 15.0, 1e-13, 2.5e10, 2.5, 2.5, 2.5, 2.5, - 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5}}; + Eigen::VectorXd y{{1.0, 0.05, 3.0, 1.0, 1.0, 2.0, 1.0, 1e-14, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 100.0, 1e10}}; + Eigen::VectorXd a{{2.5, 2.5, 2.5, 0.2, 15.0, 1e-13, 2.5e10, 2.5, 2.5, 2.5, + 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5}}; Eigen::VectorXd t0{{2.2, 0.01, 2.2, 0.2, 0.2, 1.99, 1e-13, 0.0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 1e13, 0.2, 0.2}}; - Eigen::VectorXd w{{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1e-13, 0.999999999999, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}}; + Eigen::VectorXd w{{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1e-13, 0.999999999999, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}}; Eigen::VectorXd v{{2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 1e-12, 0.0, 2.0, 0.0, -5.0, 8.0, 2.0, 2.0, 2.0, 2.0, 2.0, 4e10, -4e10}}; Eigen::VectorXd sv{{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 1e-14, 0.2, 0.2, From 8ebecc7e14fbca79dccb1d8a7e00108406e08b61 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 1 Feb 2024 12:27:23 -0500 Subject: [PATCH 157/179] change forward_as_tuple to make_tuple --- stan/math/prim/prob/wiener_full_lpdf.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 795f60e2a1b..466740d442d 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -476,10 +476,9 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, T_partials_return hcubature_err = log_error_absolute - log_error_density + LOG_TWO + 1; using internal::GradientCalc; - auto log_err_abs = log_error_absolute - LOG_TWO; const auto params - = std::forward_as_tuple(y_value, a_value, v_value, w_value, t0_value, - sv_value, sw_value, st0_value, log_err_abs); + = std::make_tuple(y_value, a_value, v_value, w_value, t0_value, + sv_value, sw_value, st0_value, log_error_absolute - LOG_TWO); T_partials_return density = internal::wiener7_integrate( [](auto&&... args) { From fa79c6aee276ffc723132a96243ea452b409ab8b Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 1 Feb 2024 12:28:35 -0500 Subject: [PATCH 158/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener_full_lpdf.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 466740d442d..c6c179dc370 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -476,9 +476,9 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, T_partials_return hcubature_err = log_error_absolute - log_error_density + LOG_TWO + 1; using internal::GradientCalc; - const auto params - = std::make_tuple(y_value, a_value, v_value, w_value, t0_value, - sv_value, sw_value, st0_value, log_error_absolute - LOG_TWO); + const auto params = std::make_tuple(y_value, a_value, v_value, w_value, + t0_value, sv_value, sw_value, st0_value, + log_error_absolute - LOG_TWO); T_partials_return density = internal::wiener7_integrate( [](auto&&... args) { From 5f25580e9a9f4a452d31024715cf51d3b8ee26d0 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 1 Feb 2024 17:34:04 -0500 Subject: [PATCH 159/179] update compute_error_term template order --- stan/math/prim/prob/wiener5_lpdf.hpp | 13 ++++++------- stan/math/prim/prob/wiener_full_lpdf.hpp | 15 ++++++--------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 8fe91c8145a..10030ab2ab3 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -637,8 +637,8 @@ inline void assign_err(std::tuple& args_tuple, Scalar err) { * @param err Error value to check against * @param args_tuple Tuple of arguments to pass to functor */ -template inline auto estimate_with_err_check(F&& functor, T_err&& err, ArgsTupleT&&... args_tuple) { @@ -777,7 +777,7 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const auto v_value = v_vec.val(i); const auto sv_value = sv_vec.val(i); using internal::GradientCalc; - auto l_density = internal::estimate_with_err_check<5, GradientCalc::OFF, 0, + auto l_density = internal::estimate_with_err_check<5, 0, GradientCalc::OFF, GradientCalc::OFF>( [](auto&&... args) { return internal::wiener5_density(args...); @@ -791,8 +791,7 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 - const auto deriv_y = internal::estimate_with_err_check<5, GradientCalc::OFF, - 0, GradientCalc::ON>( + const auto deriv_y = internal::estimate_with_err_check<5, 0, GradientCalc::OFF, GradientCalc::ON>( [](auto&&... args) { return internal::wiener5_grad_t(args...); }, @@ -805,7 +804,7 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } if (!is_constant_all::value) { partials<1>(ops_partials)[i] - = internal::estimate_with_err_check<5, GradientCalc::OFF, 0, + = internal::estimate_with_err_check<5, 0, GradientCalc::OFF, GradientCalc::ON>( [](auto&&... args) { return internal::wiener5_grad_a(args...); @@ -818,7 +817,7 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } if (!is_constant_all::value) { partials<3>(ops_partials)[i] - = internal::estimate_with_err_check<5, GradientCalc::OFF, 0, + = internal::estimate_with_err_check<5, 0, GradientCalc::OFF, GradientCalc::ON>( [](auto&&... args) { return internal::wiener5_grad_w(args...); diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index c6c179dc370..0e93944facc 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -35,11 +35,9 @@ inline auto wiener7_grad_sw(const T_y& y, const T_a& a, const T_v& v, const T_w& w, const T_sv& sv, const T_sw& sw, T_err log_error) { auto low = w - sw / 2.0; - low = (0 > low) ? 0 : low; const auto lower_value = wiener5_density(y, a, v, low, sv, log_error); auto high = w + sw / 2.0; - high = (1 < high) ? 1 : high; const auto upper_value = wiener5_density(y, a, v, high, sv, log_error); return 0.5 * (lower_value + upper_value) / sw; @@ -161,7 +159,7 @@ inline auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, }, integration_args...); }; - return estimate_with_err_check<0, GradW7, 8, GradientCalc::ON>( + return estimate_with_err_check<0, 8, GradW7, GradientCalc::ON>( functor, hcubature_err, args...); } } // namespace internal @@ -476,9 +474,9 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, T_partials_return hcubature_err = log_error_absolute - log_error_density + LOG_TWO + 1; using internal::GradientCalc; - const auto params = std::make_tuple(y_value, a_value, v_value, w_value, - t0_value, sv_value, sw_value, st0_value, - log_error_absolute - LOG_TWO); + const auto params + = std::make_tuple(y_value, a_value, v_value, w_value, t0_value, + sv_value, sw_value, st0_value, log_error_absolute - LOG_TWO); T_partials_return density = internal::wiener7_integrate( [](auto&&... args) { @@ -560,8 +558,7 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, partials<6>(ops_partials)[i] = 0; } else { if (st0_value == 0) { - derivative = internal::estimate_with_err_check<6, GradientCalc::OFF, - 0, GradientCalc::ON>( + derivative = internal::estimate_with_err_check<6, 0, GradientCalc::OFF, GradientCalc::ON>( [](auto&&... args) { return internal::wiener7_grad_sw(args...); }, hcubature_err, y_value - t0_value, a_value, v_value, w_value, sv_value, sw_value, log_error_absolute - LOG_TWO); @@ -585,7 +582,7 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } else { const T_partials_return t0_st0 = t0_value + st0_value; if (sw_value == 0) { - f = internal::estimate_with_err_check<5, GradientCalc::OFF, 0, + f = internal::estimate_with_err_check<5, 0, GradientCalc::OFF, GradientCalc::ON>( [](auto&&... args) { return internal::wiener5_density(args...); From c6724cc88bbf761d77eff35418e6b5f67fbb284c Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 1 Feb 2024 17:35:04 -0500 Subject: [PATCH 160/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 20 +++++++++++--------- stan/math/prim/prob/wiener_full_lpdf.hpp | 9 +++++---- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 10030ab2ab3..4e99d1ef315 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -637,9 +637,9 @@ inline void assign_err(std::tuple& args_tuple, Scalar err) { * @param err Error value to check against * @param args_tuple Tuple of arguments to pass to functor */ -template +template inline auto estimate_with_err_check(F&& functor, T_err&& err, ArgsTupleT&&... args_tuple) { auto result = functor(args_tuple...); @@ -791,12 +791,14 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, // computation of derivative for t and precision check in order to give // the value as deriv_y to edge1 and as -deriv_y to edge5 - const auto deriv_y = internal::estimate_with_err_check<5, 0, GradientCalc::OFF, GradientCalc::ON>( - [](auto&&... args) { - return internal::wiener5_grad_t(args...); - }, - new_est_err, y_value - t0_value, a_value, v_value, w_value, sv_value, - log_error_absolute); + const auto deriv_y + = internal::estimate_with_err_check<5, 0, GradientCalc::OFF, + GradientCalc::ON>( + [](auto&&... args) { + return internal::wiener5_grad_t(args...); + }, + new_est_err, y_value - t0_value, a_value, v_value, w_value, + sv_value, log_error_absolute); // computation of derivatives and precision checks if (!is_constant_all::value) { diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 0e93944facc..1140c40003b 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -474,9 +474,9 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, T_partials_return hcubature_err = log_error_absolute - log_error_density + LOG_TWO + 1; using internal::GradientCalc; - const auto params - = std::make_tuple(y_value, a_value, v_value, w_value, t0_value, - sv_value, sw_value, st0_value, log_error_absolute - LOG_TWO); + const auto params = std::make_tuple(y_value, a_value, v_value, w_value, + t0_value, sv_value, sw_value, st0_value, + log_error_absolute - LOG_TWO); T_partials_return density = internal::wiener7_integrate( [](auto&&... args) { @@ -558,7 +558,8 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, partials<6>(ops_partials)[i] = 0; } else { if (st0_value == 0) { - derivative = internal::estimate_with_err_check<6, 0, GradientCalc::OFF, GradientCalc::ON>( + derivative = internal::estimate_with_err_check< + 6, 0, GradientCalc::OFF, GradientCalc::ON>( [](auto&&... args) { return internal::wiener7_grad_sw(args...); }, hcubature_err, y_value - t0_value, a_value, v_value, w_value, sv_value, sw_value, log_error_absolute - LOG_TWO); From 778de8015026ad3dc9373627b0eadc879f202bd7 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 6 Feb 2024 18:00:17 +0100 Subject: [PATCH 161/179] split and rename wiener5_n_terms_large_t --- stan/math/prim/prob/wiener5_lpdf.hpp | 52 +++++++++++++++++++--------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 4e99d1ef315..5caa2a4ba26 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -121,10 +121,8 @@ inline auto wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, } /** - * Calculate the 'n_terms_small_t' term for a wiener5 density or gradient + * Calculate the 'n_terms_large_t' term for a wiener5 density * - * @tparam Density Whether the calculation is for the density - * @tparam GradW Whether the calculation is for gradient w.r.t. 't' * @tparam T_y type of scalar variable * @tparam T_a type of boundary separation * @tparam T_w_value type of relative starting point @@ -136,20 +134,41 @@ inline auto wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, * @param error The error tolerance * @return 'n_terms_large_t' term */ -template +inline auto wiener5_density_large_reaction_time_terms(T_y&& y, T_a&& a, T_w_value&& w_value, + T_err&& error) noexcept { + const auto y_asq = y / square(a); + const auto log_y_asq = log(y) - 2 * log(a); + static constexpr double PI_SQUARED = pi() * pi(); + auto n_1 = 1.0 / (pi() * sqrt(y_asq)); + const auto two_log_piy = -2.0 * (LOG_PI + log_y_asq + error); + auto n_2 + = (two_log_piy >= 0) ? sqrt(two_log_piy / (PI_SQUARED * y_asq)) : 0.0; + return ceil(fmax(n_1, n_2)); +} + +/** + * Calculate the 'n_terms_large_t' term for a wiener5 gradient + * + * @tparam GradW Whether the calculation is for gradient w.r.t. 'w' + * @tparam T_y type of scalar variable + * @tparam T_a type of boundary separation + * @tparam T_w_value type of relative starting point + * @tparam T_err type of error + * + * @param y A scalar variable; the reaction time in seconds + * @param a The boundary separation + * @param w_value The relative starting point + * @param error The error tolerance + * @return 'n_terms_large_t' term + */ +template -inline auto wiener5_n_terms_large_t(T_y&& y, T_a&& a, T_w_value&& w_value, +inline auto wiener5_gradient_large_reaction_time_terms(T_y&& y, T_a&& a, T_w_value&& w_value, T_err&& error) noexcept { const auto y_asq = y / square(a); const auto log_y_asq = log(y) - 2 * log(a); static constexpr double PI_SQUARED = pi() * pi(); - if (Density) { - auto n_1 = 1.0 / (pi() * sqrt(y_asq)); - const auto two_log_piy = -2.0 * (LOG_PI + log_y_asq + error); - auto n_2 - = (two_log_piy >= 0) ? sqrt(two_log_piy / (PI_SQUARED * y_asq)) : 0.0; - return ceil(fmax(n_1, n_2)); - } else { const auto n_1_factor = GradW ? 2 : 3; auto n_1 = sqrt(n_1_factor / y_asq) / pi(); const auto two_error = 2.0 * error; @@ -163,7 +182,6 @@ inline auto wiener5_n_terms_large_t(T_y&& y, T_a&& a, T_w_value&& w_value, auto n_2 = GradW ? ((arg > 0) ? sqrt(arg / y_asq) / pi() : n_1) : ((arg > 0) ? sqrt(arg) : n_1); return ceil(fmax(n_1, n_2)); - } } /** @@ -318,7 +336,7 @@ inline auto wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, = wiener5_n_terms_small_t( y, a, w_value, error); const auto n_terms_large_t - = wiener5_n_terms_large_t( + = wiener5_density_large_reaction_time_terms( y, a, w_value, error); auto res = wiener5_log_sum_exp( @@ -371,7 +389,7 @@ inline auto wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, = wiener5_n_terms_small_t( y, a, w_value, error); const auto n_terms_large_t - = wiener5_n_terms_large_t( + = wiener5_gradient_large_reaction_time_terms( y, a, w_value, error); auto wiener_res = wiener5_log_sum_exp( y, a, w_value, n_terms_small_t, n_terms_large_t); @@ -434,7 +452,7 @@ inline auto wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, = wiener5_n_terms_small_t( y, a, w_value, error); const auto n_terms_large_t - = wiener5_n_terms_large_t( + = wiener5_gradient_large_reaction_time_terms( y, a, w_value, error); auto wiener_res = wiener5_log_sum_exp( y, a, w_value, n_terms_small_t, n_terms_large_t); @@ -531,7 +549,7 @@ inline auto wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, = wiener5_n_terms_small_t( y, a, w_value, error); const auto n_terms_large_t - = wiener5_n_terms_large_t( + = wiener5_gradient_large_reaction_time_terms( y, a, w_value, error); auto wiener_res = wiener5_log_sum_exp( y, a, w_value, n_terms_small_t, n_terms_large_t); From e4d8cde94e5b77a0a0151c3998486487026f637f Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 6 Feb 2024 18:08:34 +0100 Subject: [PATCH 162/179] inline and delete wiener5_density_part_one --- stan/math/prim/prob/wiener5_lpdf.hpp | 70 +++++++--------------------- 1 file changed, 18 insertions(+), 52 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 5caa2a4ba26..22c86a9e361 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -39,46 +39,6 @@ inline auto wiener5_compute_error_term(T_y&& y, T_a&& a, T_v&& v_value, - two_log_a - 0.5 * log(one_plus_svsqr_y)); } -/** - * Calculate the 'density_part_one' term for a wiener5 density or gradient - * - * @tparam GradA Whether the calculation is for gradient w.r.t. 'a' - * @tparam GradT Whether the calculation is for gradient w.r.t. 't' - * @tparam T_y type of scalar variable - * @tparam T_a type of boundary separation - * @tparam T_v_value type of drift rate - * @tparam T_w_value type of relative starting point - * @tparam T_sv type of inter-trial variability in v - * - * @param y A scalar variable; the reaction time in seconds - * @param a The boundary separation - * @param v_value The drift rate - * @param w_value The relative starting point - * @param sv The inter-trial variability of the drift rate - * @return 'density_part_one' term - */ -template -inline auto wiener5_density_part_one(T_y&& y, T_a&& a, T_v_value&& v_value, - T_w_value&& w_value, T_sv&& sv) noexcept { - const auto w = 1.0 - w_value; - const auto v = -v_value; - const auto sv_sqr = square(sv); - const auto one_plus_svsqr_y = 1 + sv_sqr * y; - if (GradT) { - return -0.5 - * (square(sv_sqr) * (y + square(a * w)) - + sv_sqr * (1 - (2.0 * a * v * w)) + square(v)) - / square(one_plus_svsqr_y); - } else { - if (GradA) { - return (-v * w + sv_sqr * square(w) * a) / one_plus_svsqr_y; - } else { - return (-v * a + sv_sqr * square(a) * w) / one_plus_svsqr_y; - } - } -} - /** * Calculate the 'n_terms_small_t' term for a wiener5 density or gradient * @@ -380,10 +340,12 @@ inline auto wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, const auto two_log_a = 2 * log(a); const auto log_y_asq = log(y) - two_log_a; const auto error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); - const auto density_part_one - = wiener5_density_part_one( - y, a, v_value, w_value, sv); + = wiener5_compute_error_term(y, a, v_value, w_value, sv); + const auto w = 1.0 - w_value; + const auto v = -v_value; + const auto sv_sqr = square(sv); + const auto one_plus_svsqr_y = 1 + sv_sqr * y; + const auto density_part_one = -0.5 * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - (2.0 * a * v * w)) + square(v)) / square(one_plus_svsqr_y); const auto error = (err - error_term) + two_log_a; const auto n_terms_small_t = wiener5_n_terms_small_t( @@ -442,10 +404,12 @@ inline auto wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, const auto two_log_a = 2 * log(a); const auto log_y_asq = log(y) - two_log_a; const auto error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); - const auto density_part_one - = wiener5_density_part_one( - y, a, v_value, w_value, sv); + = wiener5_compute_error_term(y, a, v_value, w_value, sv); + const auto w = 1.0 - w_value; + const auto v = -v_value; + const auto sv_sqr = square(sv); + const auto one_plus_svsqr_y = 1 + sv_sqr * y; + const auto density_part_one = (-v * w + sv_sqr * square(w) * a) / one_plus_svsqr_y; const auto error = err - error_term + 3 * log(a) - log(y) - LOG_TWO; const auto n_terms_small_t @@ -539,10 +503,12 @@ inline auto wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, const auto two_log_a = 2 * log(a); const auto log_y_asq = log(y) - two_log_a; const auto error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); - const auto density_part_one - = wiener5_density_part_one( - y, a, v_value, w_value, sv); + = wiener5_compute_error_term(y, a, v_value, w_value, sv); + const auto w = 1.0 - w_value; + const auto v = -v_value; + const auto sv_sqr = square(sv); + const auto one_plus_svsqr_y = 1 + sv_sqr * y; + const auto density_part_one (-v * a + sv_sqr * square(a) * w) / one_plus_svsqr_y; const auto error = (err - error_term); const auto n_terms_small_t From 648d5113a3135a088031a77dc0dc14ccecf85a79 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 6 Feb 2024 18:10:37 +0100 Subject: [PATCH 163/179] delete doubled size check in wiener_full --- stan/math/prim/prob/wiener_full_lpdf.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 1140c40003b..36a6596466b 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -376,9 +376,6 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, check_finite(function_name, "Inter-trial variability in Nondecision time", st0_val); - if (size_zero(y, a, v, w, t0) || size_zero(sv, sw, st0)) { - return ret_t(0); - } const size_t N = max_size(y, a, v, w, t0, sv, sw, st0); if (!N) { return ret_t(0); From 9bb980dc938f36f2ea26c4f1274f452908d3d064 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 6 Feb 2024 22:03:00 +0100 Subject: [PATCH 164/179] possible to call wiener_lpdf(y,a,t0,w,v) and wiener_lpdf(y,a,t0,w,v,sv) --- stan/math/prim/prob.hpp | 4 +- stan/math/prim/prob/wiener5_lpdf.hpp | 18 +- stan/math/prim/prob/wiener_full_lpdf.hpp | 2 +- stan/math/prim/prob/wiener_lpdf.hpp | 218 ------------------ .../math/prim/prob/wiener_full_lpdf_test.cpp | 89 ++++++- 5 files changed, 102 insertions(+), 229 deletions(-) delete mode 100644 stan/math/prim/prob/wiener_lpdf.hpp diff --git a/stan/math/prim/prob.hpp b/stan/math/prim/prob.hpp index 598663b71e2..de2a78b46e9 100644 --- a/stan/math/prim/prob.hpp +++ b/stan/math/prim/prob.hpp @@ -370,8 +370,8 @@ #include #include #include -#include -#include +//#include +//#include #include #include #include diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 22c86a9e361..e2ea2e1ea65 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -508,7 +508,7 @@ inline auto wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, const auto v = -v_value; const auto sv_sqr = square(sv); const auto one_plus_svsqr_y = 1 + sv_sqr * y; - const auto density_part_one (-v * a + sv_sqr * square(a) * w) / one_plus_svsqr_y; + const auto density_part_one = (-v * a + sv_sqr * square(a) * w) / one_plus_svsqr_y; const auto error = (err - error_term); const auto n_terms_small_t @@ -665,10 +665,10 @@ inline auto estimate_with_err_check(F&& functor, T_err&& err, * the specified arguments for upper boundary responses */ template + typename T_w, typename T_v, typename T_sv> inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, const T_sv& sv, - const T_precision& precision_derivatives) { + const double& precision_derivatives = 1e-4) { using T_partials_return = partials_return_t; using ret_t = return_type_t; if (!include_summand::value) { @@ -825,7 +825,17 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, } } // end for loop return ops_partials.build(log_density); -} // end wiener5_lpdf +} // end wiener_lpdf + + +template +inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, + const T_w& w, const T_v& v, + const double& precision_derivatives = 1e-4) { + return wiener_lpdf(y, a, t0, w, v, 0, precision_derivatives); +} // end wiener_lpdf + } // namespace math } // namespace stan #endif diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 36a6596466b..51f37a9bcdb 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -341,7 +341,7 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, "Inter-trial variability in drift rate", sv, "Inter-trial variability in A-priori bias", sw, "Inter-trial variability in Nondecision time", st0); - + T_y_ref y_ref = y; T_a_ref a_ref = a; T_v_ref v_ref = v; diff --git a/stan/math/prim/prob/wiener_lpdf.hpp b/stan/math/prim/prob/wiener_lpdf.hpp deleted file mode 100644 index e274254637b..00000000000 --- a/stan/math/prim/prob/wiener_lpdf.hpp +++ /dev/null @@ -1,218 +0,0 @@ -// Original code from which Stan's code is derived: -// Copyright (c) 2013, Joachim Vandekerckhove. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted -// provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// * this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// * this list of conditions and the following disclaimer in the -// * documentation and/or other materials provided with the distribution. -// * Neither the name of the University of California, Irvine nor the names -// * of its contributors may be used to endorse or promote products derived -// * from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -// THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef STAN_MATH_PRIM_PROB_WIENER_LPDF_HPP -#define STAN_MATH_PRIM_PROB_WIENER_LPDF_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace stan { -namespace math { - -/** \ingroup prob_dists - * The log of the first passage time density function for a (Wiener) - * drift diffusion model for the given \f$y\f$, - * boundary separation \f$\alpha\f$, nondecision time \f$\tau\f$, - * relative bias \f$\beta\f$, and drift rate \f$\delta\f$. - * \f$\alpha\f$ and \f$\tau\f$ must be greater than 0, and - * \f$\beta\f$ must be between 0 and 1. \f$y\f$ should contain - * reaction times in seconds (strictly positive) with - * upper-boundary responses. - * - * @tparam T_y type of scalar - * @tparam T_alpha type of alpha parameter - * @tparam T_tau type of tau parameter - * @tparam T_beta type of beta parameter - * @tparam T_delta type of delta parameter - * - * @param y A scalar variate. - * @param alpha The boundary separation. - * @param tau The nondecision time. - * @param beta The relative bias. - * @param delta The drift rate. - * @return The log of the Wiener first passage time density of - * the specified arguments. - */ -template -return_type_t wiener_lpdf( - const T_y& y, const T_alpha& alpha, const T_tau& tau, const T_beta& beta, - const T_delta& delta) { - using T_return_type = return_type_t; - using T_y_ref = ref_type_t; - using T_alpha_ref = ref_type_t; - using T_tau_ref = ref_type_t; - using T_beta_ref = ref_type_t; - using T_delta_ref = ref_type_t; - using std::ceil; - using std::exp; - using std::floor; - using std::log; - using std::sin; - using std::sqrt; - static const char* function = "wiener_lpdf"; - check_consistent_sizes(function, "Random variable", y, "Boundary separation", - alpha, "A-priori bias", beta, "Nondecision time", tau, - "Drift rate", delta); - - T_y_ref y_ref = y; - T_alpha_ref alpha_ref = alpha; - T_tau_ref tau_ref = tau; - T_beta_ref beta_ref = beta; - T_delta_ref delta_ref = delta; - - check_positive(function, "Random variable", value_of(y_ref)); - check_positive_finite(function, "Boundary separation", value_of(alpha_ref)); - check_positive_finite(function, "Nondecision time", value_of(tau_ref)); - check_bounded(function, "A-priori bias", value_of(beta_ref), 0, 1); - check_finite(function, "Drift rate", value_of(delta_ref)); - - if (size_zero(y, alpha, beta, tau, delta)) { - return 0; - } - - T_return_type lp(0.0); - - size_t N = max_size(y, alpha, beta, tau, delta); - if (!N) { - return 0.0; - } - - scalar_seq_view y_vec(y_ref); - scalar_seq_view alpha_vec(alpha_ref); - scalar_seq_view beta_vec(beta_ref); - scalar_seq_view tau_vec(tau_ref); - scalar_seq_view delta_vec(delta_ref); - size_t N_y_tau = max_size(y, tau); - - for (size_t i = 0; i < N_y_tau; ++i) { - if (y_vec[i] <= tau_vec[i]) { - std::stringstream msg; - msg << ", but must be greater than nondecision time = " << tau_vec[i]; - std::string msg_str(msg.str()); - throw_domain_error(function, "Random variable", y_vec[i], " = ", - msg_str.c_str()); - } - } - - if (!include_summand::value) { - return 0; - } - - static const double WIENER_ERR = 0.000001; - static const double PI_TIMES_WIENER_ERR = pi() * WIENER_ERR; - static const double LOG_PI_LOG_WIENER_ERR = LOG_PI + log(WIENER_ERR); - static const double TWO_TIMES_SQRT_TWO_PI_TIMES_WIENER_ERR - = 2.0 * SQRT_TWO_PI * WIENER_ERR; - static const double LOG_TWO_OVER_TWO_PLUS_LOG_SQRT_PI - = LOG_TWO / 2 + LOG_SQRT_PI; - static const double SQUARE_PI_OVER_TWO = square(pi()) * 0.5; - static const double TWO_TIMES_LOG_SQRT_PI = 2.0 * LOG_SQRT_PI; - - for (size_t i = 0; i < N; i++) { - typename scalar_type::type one_minus_beta = 1.0 - beta_vec[i]; - typename scalar_type::type alpha2 = square(alpha_vec[i]); - T_return_type x = (y_vec[i] - tau_vec[i]) / alpha2; - T_return_type kl, ks, tmp = 0; - T_return_type k, K; - T_return_type sqrt_x = sqrt(x); - T_return_type log_x = log(x); - T_return_type one_over_pi_times_sqrt_x = 1.0 / pi() * sqrt_x; - - // calculate number of terms needed for large t: - // if error threshold is set low enough - if (PI_TIMES_WIENER_ERR * x < 1) { - // compute bound - kl = sqrt(-2.0 * SQRT_PI * (LOG_PI_LOG_WIENER_ERR + log_x)) / sqrt_x; - // ensure boundary conditions met - kl = (kl > one_over_pi_times_sqrt_x) ? kl : one_over_pi_times_sqrt_x; - } else { - kl = one_over_pi_times_sqrt_x; // set to boundary condition - } - // calculate number of terms needed for small t: - // if error threshold is set low enough - T_return_type tmp_expr0 = TWO_TIMES_SQRT_TWO_PI_TIMES_WIENER_ERR * sqrt_x; - if (tmp_expr0 < 1) { - // compute bound - ks = 2.0 + sqrt_x * sqrt(-2 * log(tmp_expr0)); - // ensure boundary conditions are met - T_return_type sqrt_x_plus_one = sqrt_x + 1.0; - ks = (ks > sqrt_x_plus_one) ? ks : sqrt_x_plus_one; - } else { // if error threshold was set too high - ks = 2.0; // minimal kappa for that case - } - if (ks < kl) { // small t - K = ceil(ks); // round to smallest integer meeting error - T_return_type tmp_expr1 = (K - 1.0) / 2.0; - T_return_type tmp_expr2 = ceil(tmp_expr1); - for (k = -floor(tmp_expr1); k <= tmp_expr2; k++) { - tmp += (one_minus_beta + 2.0 * k) - * exp(-(square(one_minus_beta + 2.0 * k)) * 0.5 / x); - } - tmp = log(tmp) - LOG_TWO_OVER_TWO_PLUS_LOG_SQRT_PI - 1.5 * log_x; - } else { // if large t is better... - K = ceil(kl); // round to smallest integer meeting error - for (k = 1; k <= K; ++k) { - tmp += k * exp(-(square(k)) * (SQUARE_PI_OVER_TWO * x)) - * sin(k * pi() * one_minus_beta); - } - tmp = log(tmp) + TWO_TIMES_LOG_SQRT_PI; - } - - // convert to f(t|v,a,w) and return result - lp += delta_vec[i] * alpha_vec[i] * one_minus_beta - - square(delta_vec[i]) * x * alpha2 / 2.0 - log(alpha2) + tmp; - } - return lp; -} - -template -inline return_type_t wiener_lpdf( - const T_y& y, const T_alpha& alpha, const T_tau& tau, const T_beta& beta, - const T_delta& delta) { - return wiener_lpdf(y, alpha, tau, beta, delta); -} - -} // namespace math -} // namespace stan -#endif diff --git a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp index 2773267b218..5223e0bc51b 100644 --- a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp @@ -5,7 +5,7 @@ #include #include - +/* TEST(mathPrimScalProbWienerFullScal, valid) { using stan::math::INFTY; using stan::math::wiener_lpdf; @@ -283,11 +283,11 @@ TEST(mathPrimScalProbWienerFullPrecScal, invalid_st0) { EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, NAN, 1e-4), std::domain_error); } +*/ TEST(mathPrimCorrectValues, wiener_lpdf) { - /* Test concrete values. True values are computed in R using the R-package - * WienR and the function WienerPDF. - */ + // Test concrete values. True values are computed in R using the R-package + // WienR and the function WienerPDF. std::vector y_vec = {2, 3, 4, 5, 6, 7, 8, 8.85, 8.9, 9, 1}; std::vector a_vec = {2.0, 2.0, 10.0, 4.0, 10.0, 1.0, 3.0, 1.7, 2.4, 11.0, 1.5}; @@ -387,3 +387,84 @@ TEST(mathPrimCorrectValues, wiener_lpdf) { EXPECT_NEAR(st0.adj(), true_grad_st0[i], err_tol); } } + + + +TEST(mathPrimCorrectValuesFourParamModel, wiener_lpdf) { + // Test concrete values. True values are computed in R using the R-package + // WienR and the function WienerPDF. + std::vector y_vec = {2.0}; + std::vector a_vec = {2.0}; + std::vector v_vec = {2.0}; + std::vector w_vec = {.1}; + std::vector t0_vec = {1e-9}; + + std::vector true_dens + = {-4.28564747866615}; + std::vector true_grad_y + = {-3.22509339523307}; + std::vector true_grad_a = {3.25018678924105}; + std::vector true_grad_t0 = {3.22509339523307}; + std::vector true_grad_w = {5.67120184517318}; + std::vector true_grad_v = {-2.199999998}; + + using stan::math::var; + double err_tol_dens = 1e-6; + double err_tol = 1e-4; + for (int i = 0; i < y_vec.size(); i++) { + var y = y_vec[i]; + var a = a_vec[i]; + var t0 = t0_vec[i]; + var w = w_vec[i]; + var v = v_vec[i]; + var dens = stan::math::wiener_lpdf(y, a, t0, w, v); + dens.grad(); + EXPECT_NEAR(dens.val(), true_dens[i], err_tol_dens); + EXPECT_NEAR(y.adj(), true_grad_y[i], err_tol); + EXPECT_NEAR(a.adj(), true_grad_a[i], err_tol); + EXPECT_NEAR(t0.adj(), true_grad_t0[i], err_tol); + EXPECT_NEAR(w.adj(), true_grad_w[i], err_tol); + EXPECT_NEAR(v.adj(), true_grad_v[i], err_tol); + } +} + + +TEST(mathPrimCorrectValuesFiveParameterModel, wiener_lpdf) { + // Test concrete values. True values are computed in R using the R-package + // WienR and the function WienerPDF. + std::vector y_vec = {3.0}; + std::vector a_vec = {2.0}; + std::vector v_vec = {2.0}; + std::vector w_vec = {0.5}; + std::vector t0_vec = {0.01}; + std::vector sv_vec = {0.2}; + + std::vector true_dens = {-7.52379235146909}; + std::vector true_grad_y = {-2.91155058614589}; + std::vector true_grad_a = {3.59980430191399}; + std::vector true_grad_t0 = {2.91155058614589}; + std::vector true_grad_w = {-3.64396221090076}; + std::vector true_grad_v = {-4.44801714898178}; + std::vector true_grad_sv = {3.42285198319565}; + + using stan::math::var; + double err_tol_dens = 1e-6; + double err_tol = 1e-4; + for (int i = 0; i < y_vec.size(); i++) { + var y = y_vec[i]; + var a = a_vec[i]; + var t0 = t0_vec[i]; + var w = w_vec[i]; + var v = v_vec[i]; + var sv = sv_vec[i]; + var dens = stan::math::wiener_lpdf(y, a, t0, w, v, sv); + dens.grad(); + EXPECT_NEAR(dens.val(), true_dens[i], err_tol_dens); + EXPECT_NEAR(y.adj(), true_grad_y[i], err_tol); + EXPECT_NEAR(a.adj(), true_grad_a[i], err_tol); + EXPECT_NEAR(t0.adj(), true_grad_t0[i], err_tol); + EXPECT_NEAR(w.adj(), true_grad_w[i], err_tol); + EXPECT_NEAR(v.adj(), true_grad_v[i], err_tol); + EXPECT_NEAR(sv.adj(), true_grad_sv[i], err_tol); + } +} \ No newline at end of file From 3485d1a4a99f07755d33b097406e3b60d37e81a3 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 6 Feb 2024 16:04:27 -0500 Subject: [PATCH 165/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 73 ++++++++++--------- stan/math/prim/prob/wiener_full_lpdf.hpp | 2 +- .../math/prim/prob/wiener_full_lpdf_test.cpp | 9 +-- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index e2ea2e1ea65..b04b3360d50 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -95,16 +95,17 @@ inline auto wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, * @return 'n_terms_large_t' term */ template -inline auto wiener5_density_large_reaction_time_terms(T_y&& y, T_a&& a, T_w_value&& w_value, - T_err&& error) noexcept { +inline auto wiener5_density_large_reaction_time_terms(T_y&& y, T_a&& a, + T_w_value&& w_value, + T_err&& error) noexcept { const auto y_asq = y / square(a); const auto log_y_asq = log(y) - 2 * log(a); static constexpr double PI_SQUARED = pi() * pi(); - auto n_1 = 1.0 / (pi() * sqrt(y_asq)); - const auto two_log_piy = -2.0 * (LOG_PI + log_y_asq + error); - auto n_2 - = (two_log_piy >= 0) ? sqrt(two_log_piy / (PI_SQUARED * y_asq)) : 0.0; - return ceil(fmax(n_1, n_2)); + auto n_1 = 1.0 / (pi() * sqrt(y_asq)); + const auto two_log_piy = -2.0 * (LOG_PI + log_y_asq + error); + auto n_2 + = (two_log_piy >= 0) ? sqrt(two_log_piy / (PI_SQUARED * y_asq)) : 0.0; + return ceil(fmax(n_1, n_2)); } /** @@ -122,26 +123,26 @@ inline auto wiener5_density_large_reaction_time_terms(T_y&& y, T_a&& a, T_w_valu * @param error The error tolerance * @return 'n_terms_large_t' term */ -template -inline auto wiener5_gradient_large_reaction_time_terms(T_y&& y, T_a&& a, T_w_value&& w_value, - T_err&& error) noexcept { +template +inline auto wiener5_gradient_large_reaction_time_terms(T_y&& y, T_a&& a, + T_w_value&& w_value, + T_err&& error) noexcept { const auto y_asq = y / square(a); const auto log_y_asq = log(y) - 2 * log(a); static constexpr double PI_SQUARED = pi() * pi(); - const auto n_1_factor = GradW ? 2 : 3; - auto n_1 = sqrt(n_1_factor / y_asq) / pi(); - const auto two_error = 2.0 * error; - const auto u_eps_arg - = GradW - ? log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_error + const auto n_1_factor = GradW ? 2 : 3; + auto n_1 = sqrt(n_1_factor / y_asq) / pi(); + const auto two_error = 2.0 * error; + const auto u_eps_arg + = GradW ? log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_error : log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + error; - const auto u_eps = fmin(-1, u_eps_arg); - const auto arg_mult = GradW ? 1 : (2.0 / PI_SQUARED / y_asq); - const auto arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - auto n_2 = GradW ? ((arg > 0) ? sqrt(arg / y_asq) / pi() : n_1) - : ((arg > 0) ? sqrt(arg) : n_1); - return ceil(fmax(n_1, n_2)); + const auto u_eps = fmin(-1, u_eps_arg); + const auto arg_mult = GradW ? 1 : (2.0 / PI_SQUARED / y_asq); + const auto arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + auto n_2 = GradW ? ((arg > 0) ? sqrt(arg / y_asq) / pi() : n_1) + : ((arg > 0) ? sqrt(arg) : n_1); + return ceil(fmax(n_1, n_2)); } /** @@ -296,8 +297,7 @@ inline auto wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, = wiener5_n_terms_small_t( y, a, w_value, error); const auto n_terms_large_t - = wiener5_density_large_reaction_time_terms( - y, a, w_value, error); + = wiener5_density_large_reaction_time_terms(y, a, w_value, error); auto res = wiener5_log_sum_exp( y, a, w_value, n_terms_small_t, n_terms_large_t) @@ -340,12 +340,16 @@ inline auto wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, const auto two_log_a = 2 * log(a); const auto log_y_asq = log(y) - two_log_a; const auto error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); + = wiener5_compute_error_term(y, a, v_value, w_value, sv); const auto w = 1.0 - w_value; const auto v = -v_value; const auto sv_sqr = square(sv); const auto one_plus_svsqr_y = 1 + sv_sqr * y; - const auto density_part_one = -0.5 * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - (2.0 * a * v * w)) + square(v)) / square(one_plus_svsqr_y); + const auto density_part_one + = -0.5 + * (square(sv_sqr) * (y + square(a * w)) + + sv_sqr * (1 - (2.0 * a * v * w)) + square(v)) + / square(one_plus_svsqr_y); const auto error = (err - error_term) + two_log_a; const auto n_terms_small_t = wiener5_n_terms_small_t( @@ -404,12 +408,13 @@ inline auto wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, const auto two_log_a = 2 * log(a); const auto log_y_asq = log(y) - two_log_a; const auto error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); + = wiener5_compute_error_term(y, a, v_value, w_value, sv); const auto w = 1.0 - w_value; const auto v = -v_value; const auto sv_sqr = square(sv); const auto one_plus_svsqr_y = 1 + sv_sqr * y; - const auto density_part_one = (-v * w + sv_sqr * square(w) * a) / one_plus_svsqr_y; + const auto density_part_one + = (-v * w + sv_sqr * square(w) * a) / one_plus_svsqr_y; const auto error = err - error_term + 3 * log(a) - log(y) - LOG_TWO; const auto n_terms_small_t @@ -503,12 +508,13 @@ inline auto wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, const auto two_log_a = 2 * log(a); const auto log_y_asq = log(y) - two_log_a; const auto error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); + = wiener5_compute_error_term(y, a, v_value, w_value, sv); const auto w = 1.0 - w_value; const auto v = -v_value; const auto sv_sqr = square(sv); const auto one_plus_svsqr_y = 1 + sv_sqr * y; - const auto density_part_one = (-v * a + sv_sqr * square(a) * w) / one_plus_svsqr_y; + const auto density_part_one + = (-v * a + sv_sqr * square(a) * w) / one_plus_svsqr_y; const auto error = (err - error_term); const auto n_terms_small_t @@ -827,15 +833,14 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, return ops_partials.build(log_density); } // end wiener_lpdf - template inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, const double& precision_derivatives = 1e-4) { - return wiener_lpdf(y, a, t0, w, v, 0, precision_derivatives); + return wiener_lpdf(y, a, t0, w, v, 0, precision_derivatives); } // end wiener_lpdf - + } // namespace math } // namespace stan #endif diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 51f37a9bcdb..36a6596466b 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -341,7 +341,7 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, "Inter-trial variability in drift rate", sv, "Inter-trial variability in A-priori bias", sw, "Inter-trial variability in Nondecision time", st0); - + T_y_ref y_ref = y; T_a_ref a_ref = a; T_v_ref v_ref = v; diff --git a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp index 5223e0bc51b..abea69c2fd9 100644 --- a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp @@ -388,8 +388,6 @@ TEST(mathPrimCorrectValues, wiener_lpdf) { } } - - TEST(mathPrimCorrectValuesFourParamModel, wiener_lpdf) { // Test concrete values. True values are computed in R using the R-package // WienR and the function WienerPDF. @@ -399,10 +397,8 @@ TEST(mathPrimCorrectValuesFourParamModel, wiener_lpdf) { std::vector w_vec = {.1}; std::vector t0_vec = {1e-9}; - std::vector true_dens - = {-4.28564747866615}; - std::vector true_grad_y - = {-3.22509339523307}; + std::vector true_dens = {-4.28564747866615}; + std::vector true_grad_y = {-3.22509339523307}; std::vector true_grad_a = {3.25018678924105}; std::vector true_grad_t0 = {3.22509339523307}; std::vector true_grad_w = {5.67120184517318}; @@ -428,7 +424,6 @@ TEST(mathPrimCorrectValuesFourParamModel, wiener_lpdf) { } } - TEST(mathPrimCorrectValuesFiveParameterModel, wiener_lpdf) { // Test concrete values. True values are computed in R using the R-package // WienR and the function WienerPDF. From e7b4b9f110513aaaa7d49e5c784b347926170c51 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 6 Feb 2024 22:13:50 +0100 Subject: [PATCH 166/179] whitespace --- Jenkinsfile | 5 -- stan/math/prim/prob.hpp | 4 +- stan/math/prim/prob/wiener5_lpdf.hpp | 73 +++++++++---------- stan/math/prim/prob/wiener_full_lpdf.hpp | 2 +- .../math/prim/prob/wiener_full_lpdf_test.cpp | 13 +++- 5 files changed, 46 insertions(+), 51 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index e133d0c27e7..9e7df2a5603 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -4,7 +4,6 @@ import org.stan.Utils def runTests(String testPath, boolean jumbo = false) { try { - sh "cat make/local" if (jumbo && !params.disableJumbo) { sh "python3 runTests.py -j${env.PARALLEL} ${testPath} --jumbo --debug" } else { @@ -345,7 +344,6 @@ pipeline { runTests("test/unit/multiple_translation_units_test.cpp") } } - post { always { retry(3) { deleteDir() } } } } } } @@ -395,7 +393,6 @@ pipeline { sh "python ./test/varmat_compatibility_test.py" withEnv(['PATH+TBB=./lib/tbb']) { sh "python ./test/expressions/test_expression_testing_framework.py" - sh "cat make/local" try { sh "./runTests.py -j${PARALLEL} test/expressions" } finally { junit 'test/**/*.xml' } } @@ -403,7 +400,6 @@ pipeline { sh "echo STAN_THREADS=true >> make/local" withEnv(['PATH+TBB=./lib/tbb']) { try { - sh "cat make/local" sh "./runTests.py -j${PARALLEL} test/expressions --only-functions reduce_sum map_rect" } finally { junit 'test/**/*.xml' } @@ -502,7 +498,6 @@ pipeline { sh "echo CXXFLAGS+=-DSTAN_PROB_TEST_ALL >> make/local" } } - sh "cat make/local" sh "./runTests.py -j${PARALLEL} ${names}" } deleteDir() diff --git a/stan/math/prim/prob.hpp b/stan/math/prim/prob.hpp index de2a78b46e9..b8322e7c807 100644 --- a/stan/math/prim/prob.hpp +++ b/stan/math/prim/prob.hpp @@ -370,8 +370,8 @@ #include #include #include -//#include -//#include +// #include +// #include #include #include #include diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index b04b3360d50..e2ea2e1ea65 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -95,17 +95,16 @@ inline auto wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, * @return 'n_terms_large_t' term */ template -inline auto wiener5_density_large_reaction_time_terms(T_y&& y, T_a&& a, - T_w_value&& w_value, - T_err&& error) noexcept { +inline auto wiener5_density_large_reaction_time_terms(T_y&& y, T_a&& a, T_w_value&& w_value, + T_err&& error) noexcept { const auto y_asq = y / square(a); const auto log_y_asq = log(y) - 2 * log(a); static constexpr double PI_SQUARED = pi() * pi(); - auto n_1 = 1.0 / (pi() * sqrt(y_asq)); - const auto two_log_piy = -2.0 * (LOG_PI + log_y_asq + error); - auto n_2 - = (two_log_piy >= 0) ? sqrt(two_log_piy / (PI_SQUARED * y_asq)) : 0.0; - return ceil(fmax(n_1, n_2)); + auto n_1 = 1.0 / (pi() * sqrt(y_asq)); + const auto two_log_piy = -2.0 * (LOG_PI + log_y_asq + error); + auto n_2 + = (two_log_piy >= 0) ? sqrt(two_log_piy / (PI_SQUARED * y_asq)) : 0.0; + return ceil(fmax(n_1, n_2)); } /** @@ -123,26 +122,26 @@ inline auto wiener5_density_large_reaction_time_terms(T_y&& y, T_a&& a, * @param error The error tolerance * @return 'n_terms_large_t' term */ -template -inline auto wiener5_gradient_large_reaction_time_terms(T_y&& y, T_a&& a, - T_w_value&& w_value, - T_err&& error) noexcept { +template +inline auto wiener5_gradient_large_reaction_time_terms(T_y&& y, T_a&& a, T_w_value&& w_value, + T_err&& error) noexcept { const auto y_asq = y / square(a); const auto log_y_asq = log(y) - 2 * log(a); static constexpr double PI_SQUARED = pi() * pi(); - const auto n_1_factor = GradW ? 2 : 3; - auto n_1 = sqrt(n_1_factor / y_asq) / pi(); - const auto two_error = 2.0 * error; - const auto u_eps_arg - = GradW ? log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_error + const auto n_1_factor = GradW ? 2 : 3; + auto n_1 = sqrt(n_1_factor / y_asq) / pi(); + const auto two_error = 2.0 * error; + const auto u_eps_arg + = GradW + ? log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_error : log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + error; - const auto u_eps = fmin(-1, u_eps_arg); - const auto arg_mult = GradW ? 1 : (2.0 / PI_SQUARED / y_asq); - const auto arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - auto n_2 = GradW ? ((arg > 0) ? sqrt(arg / y_asq) / pi() : n_1) - : ((arg > 0) ? sqrt(arg) : n_1); - return ceil(fmax(n_1, n_2)); + const auto u_eps = fmin(-1, u_eps_arg); + const auto arg_mult = GradW ? 1 : (2.0 / PI_SQUARED / y_asq); + const auto arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + auto n_2 = GradW ? ((arg > 0) ? sqrt(arg / y_asq) / pi() : n_1) + : ((arg > 0) ? sqrt(arg) : n_1); + return ceil(fmax(n_1, n_2)); } /** @@ -297,7 +296,8 @@ inline auto wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, = wiener5_n_terms_small_t( y, a, w_value, error); const auto n_terms_large_t - = wiener5_density_large_reaction_time_terms(y, a, w_value, error); + = wiener5_density_large_reaction_time_terms( + y, a, w_value, error); auto res = wiener5_log_sum_exp( y, a, w_value, n_terms_small_t, n_terms_large_t) @@ -340,16 +340,12 @@ inline auto wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, const auto two_log_a = 2 * log(a); const auto log_y_asq = log(y) - two_log_a; const auto error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); + = wiener5_compute_error_term(y, a, v_value, w_value, sv); const auto w = 1.0 - w_value; const auto v = -v_value; const auto sv_sqr = square(sv); const auto one_plus_svsqr_y = 1 + sv_sqr * y; - const auto density_part_one - = -0.5 - * (square(sv_sqr) * (y + square(a * w)) - + sv_sqr * (1 - (2.0 * a * v * w)) + square(v)) - / square(one_plus_svsqr_y); + const auto density_part_one = -0.5 * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - (2.0 * a * v * w)) + square(v)) / square(one_plus_svsqr_y); const auto error = (err - error_term) + two_log_a; const auto n_terms_small_t = wiener5_n_terms_small_t( @@ -408,13 +404,12 @@ inline auto wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, const auto two_log_a = 2 * log(a); const auto log_y_asq = log(y) - two_log_a; const auto error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); + = wiener5_compute_error_term(y, a, v_value, w_value, sv); const auto w = 1.0 - w_value; const auto v = -v_value; const auto sv_sqr = square(sv); const auto one_plus_svsqr_y = 1 + sv_sqr * y; - const auto density_part_one - = (-v * w + sv_sqr * square(w) * a) / one_plus_svsqr_y; + const auto density_part_one = (-v * w + sv_sqr * square(w) * a) / one_plus_svsqr_y; const auto error = err - error_term + 3 * log(a) - log(y) - LOG_TWO; const auto n_terms_small_t @@ -508,13 +503,12 @@ inline auto wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, const auto two_log_a = 2 * log(a); const auto log_y_asq = log(y) - two_log_a; const auto error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); + = wiener5_compute_error_term(y, a, v_value, w_value, sv); const auto w = 1.0 - w_value; const auto v = -v_value; const auto sv_sqr = square(sv); const auto one_plus_svsqr_y = 1 + sv_sqr * y; - const auto density_part_one - = (-v * a + sv_sqr * square(a) * w) / one_plus_svsqr_y; + const auto density_part_one = (-v * a + sv_sqr * square(a) * w) / one_plus_svsqr_y; const auto error = (err - error_term); const auto n_terms_small_t @@ -833,14 +827,15 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, return ops_partials.build(log_density); } // end wiener_lpdf + template inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, const double& precision_derivatives = 1e-4) { - return wiener_lpdf(y, a, t0, w, v, 0, precision_derivatives); + return wiener_lpdf(y, a, t0, w, v, 0, precision_derivatives); } // end wiener_lpdf - + } // namespace math } // namespace stan #endif diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 36a6596466b..51f37a9bcdb 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -341,7 +341,7 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, "Inter-trial variability in drift rate", sv, "Inter-trial variability in A-priori bias", sw, "Inter-trial variability in Nondecision time", st0); - + T_y_ref y_ref = y; T_a_ref a_ref = a; T_v_ref v_ref = v; diff --git a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp index abea69c2fd9..d0a9ceb4fd4 100644 --- a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp @@ -5,7 +5,7 @@ #include #include -/* + TEST(mathPrimScalProbWienerFullScal, valid) { using stan::math::INFTY; using stan::math::wiener_lpdf; @@ -283,7 +283,7 @@ TEST(mathPrimScalProbWienerFullPrecScal, invalid_st0) { EXPECT_THROW(wiener_lpdf(rt, a, t0, w, v, sv, sw, NAN, 1e-4), std::domain_error); } -*/ + TEST(mathPrimCorrectValues, wiener_lpdf) { // Test concrete values. True values are computed in R using the R-package @@ -388,6 +388,8 @@ TEST(mathPrimCorrectValues, wiener_lpdf) { } } + + TEST(mathPrimCorrectValuesFourParamModel, wiener_lpdf) { // Test concrete values. True values are computed in R using the R-package // WienR and the function WienerPDF. @@ -397,8 +399,10 @@ TEST(mathPrimCorrectValuesFourParamModel, wiener_lpdf) { std::vector w_vec = {.1}; std::vector t0_vec = {1e-9}; - std::vector true_dens = {-4.28564747866615}; - std::vector true_grad_y = {-3.22509339523307}; + std::vector true_dens + = {-4.28564747866615}; + std::vector true_grad_y + = {-3.22509339523307}; std::vector true_grad_a = {3.25018678924105}; std::vector true_grad_t0 = {3.22509339523307}; std::vector true_grad_w = {5.67120184517318}; @@ -424,6 +428,7 @@ TEST(mathPrimCorrectValuesFourParamModel, wiener_lpdf) { } } + TEST(mathPrimCorrectValuesFiveParameterModel, wiener_lpdf) { // Test concrete values. True values are computed in R using the R-package // WienR and the function WienerPDF. From 025cab3c541a56fbad4edded46647bef67f21a14 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 6 Feb 2024 16:15:04 -0500 Subject: [PATCH 167/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 73 ++++++++++--------- stan/math/prim/prob/wiener_full_lpdf.hpp | 2 +- .../math/prim/prob/wiener_full_lpdf_test.cpp | 10 +-- 3 files changed, 42 insertions(+), 43 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index e2ea2e1ea65..b04b3360d50 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -95,16 +95,17 @@ inline auto wiener5_n_terms_small_t(T_y&& y, T_a&& a, T_w_value&& w_value, * @return 'n_terms_large_t' term */ template -inline auto wiener5_density_large_reaction_time_terms(T_y&& y, T_a&& a, T_w_value&& w_value, - T_err&& error) noexcept { +inline auto wiener5_density_large_reaction_time_terms(T_y&& y, T_a&& a, + T_w_value&& w_value, + T_err&& error) noexcept { const auto y_asq = y / square(a); const auto log_y_asq = log(y) - 2 * log(a); static constexpr double PI_SQUARED = pi() * pi(); - auto n_1 = 1.0 / (pi() * sqrt(y_asq)); - const auto two_log_piy = -2.0 * (LOG_PI + log_y_asq + error); - auto n_2 - = (two_log_piy >= 0) ? sqrt(two_log_piy / (PI_SQUARED * y_asq)) : 0.0; - return ceil(fmax(n_1, n_2)); + auto n_1 = 1.0 / (pi() * sqrt(y_asq)); + const auto two_log_piy = -2.0 * (LOG_PI + log_y_asq + error); + auto n_2 + = (two_log_piy >= 0) ? sqrt(two_log_piy / (PI_SQUARED * y_asq)) : 0.0; + return ceil(fmax(n_1, n_2)); } /** @@ -122,26 +123,26 @@ inline auto wiener5_density_large_reaction_time_terms(T_y&& y, T_a&& a, T_w_valu * @param error The error tolerance * @return 'n_terms_large_t' term */ -template -inline auto wiener5_gradient_large_reaction_time_terms(T_y&& y, T_a&& a, T_w_value&& w_value, - T_err&& error) noexcept { +template +inline auto wiener5_gradient_large_reaction_time_terms(T_y&& y, T_a&& a, + T_w_value&& w_value, + T_err&& error) noexcept { const auto y_asq = y / square(a); const auto log_y_asq = log(y) - 2 * log(a); static constexpr double PI_SQUARED = pi() * pi(); - const auto n_1_factor = GradW ? 2 : 3; - auto n_1 = sqrt(n_1_factor / y_asq) / pi(); - const auto two_error = 2.0 * error; - const auto u_eps_arg - = GradW - ? log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_error + const auto n_1_factor = GradW ? 2 : 3; + auto n_1 = sqrt(n_1_factor / y_asq) / pi(); + const auto two_error = 2.0 * error; + const auto u_eps_arg + = GradW ? log(4.0) - log(9.0) + 2.0 * LOG_PI + 3.0 * log_y_asq + two_error : log(3.0) - log(5.0) + LOG_PI + 2.0 * log_y_asq + error; - const auto u_eps = fmin(-1, u_eps_arg); - const auto arg_mult = GradW ? 1 : (2.0 / PI_SQUARED / y_asq); - const auto arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); - auto n_2 = GradW ? ((arg > 0) ? sqrt(arg / y_asq) / pi() : n_1) - : ((arg > 0) ? sqrt(arg) : n_1); - return ceil(fmax(n_1, n_2)); + const auto u_eps = fmin(-1, u_eps_arg); + const auto arg_mult = GradW ? 1 : (2.0 / PI_SQUARED / y_asq); + const auto arg = -arg_mult * (u_eps - sqrt(-2.0 * u_eps - 2.0)); + auto n_2 = GradW ? ((arg > 0) ? sqrt(arg / y_asq) / pi() : n_1) + : ((arg > 0) ? sqrt(arg) : n_1); + return ceil(fmax(n_1, n_2)); } /** @@ -296,8 +297,7 @@ inline auto wiener5_density(const T_y& y, const T_a& a, const T_v& v_value, = wiener5_n_terms_small_t( y, a, w_value, error); const auto n_terms_large_t - = wiener5_density_large_reaction_time_terms( - y, a, w_value, error); + = wiener5_density_large_reaction_time_terms(y, a, w_value, error); auto res = wiener5_log_sum_exp( y, a, w_value, n_terms_small_t, n_terms_large_t) @@ -340,12 +340,16 @@ inline auto wiener5_grad_t(const T_y& y, const T_a& a, const T_v& v_value, const auto two_log_a = 2 * log(a); const auto log_y_asq = log(y) - two_log_a; const auto error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); + = wiener5_compute_error_term(y, a, v_value, w_value, sv); const auto w = 1.0 - w_value; const auto v = -v_value; const auto sv_sqr = square(sv); const auto one_plus_svsqr_y = 1 + sv_sqr * y; - const auto density_part_one = -0.5 * (square(sv_sqr) * (y + square(a * w)) + sv_sqr * (1 - (2.0 * a * v * w)) + square(v)) / square(one_plus_svsqr_y); + const auto density_part_one + = -0.5 + * (square(sv_sqr) * (y + square(a * w)) + + sv_sqr * (1 - (2.0 * a * v * w)) + square(v)) + / square(one_plus_svsqr_y); const auto error = (err - error_term) + two_log_a; const auto n_terms_small_t = wiener5_n_terms_small_t( @@ -404,12 +408,13 @@ inline auto wiener5_grad_a(const T_y& y, const T_a& a, const T_v& v_value, const auto two_log_a = 2 * log(a); const auto log_y_asq = log(y) - two_log_a; const auto error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); + = wiener5_compute_error_term(y, a, v_value, w_value, sv); const auto w = 1.0 - w_value; const auto v = -v_value; const auto sv_sqr = square(sv); const auto one_plus_svsqr_y = 1 + sv_sqr * y; - const auto density_part_one = (-v * w + sv_sqr * square(w) * a) / one_plus_svsqr_y; + const auto density_part_one + = (-v * w + sv_sqr * square(w) * a) / one_plus_svsqr_y; const auto error = err - error_term + 3 * log(a) - log(y) - LOG_TWO; const auto n_terms_small_t @@ -503,12 +508,13 @@ inline auto wiener5_grad_w(const T_y& y, const T_a& a, const T_v& v_value, const auto two_log_a = 2 * log(a); const auto log_y_asq = log(y) - two_log_a; const auto error_term - = wiener5_compute_error_term(y, a, v_value, w_value, sv); + = wiener5_compute_error_term(y, a, v_value, w_value, sv); const auto w = 1.0 - w_value; const auto v = -v_value; const auto sv_sqr = square(sv); const auto one_plus_svsqr_y = 1 + sv_sqr * y; - const auto density_part_one = (-v * a + sv_sqr * square(a) * w) / one_plus_svsqr_y; + const auto density_part_one + = (-v * a + sv_sqr * square(a) * w) / one_plus_svsqr_y; const auto error = (err - error_term); const auto n_terms_small_t @@ -827,15 +833,14 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, return ops_partials.build(log_density); } // end wiener_lpdf - template inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, const T_w& w, const T_v& v, const double& precision_derivatives = 1e-4) { - return wiener_lpdf(y, a, t0, w, v, 0, precision_derivatives); + return wiener_lpdf(y, a, t0, w, v, 0, precision_derivatives); } // end wiener_lpdf - + } // namespace math } // namespace stan #endif diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 51f37a9bcdb..36a6596466b 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -341,7 +341,7 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, "Inter-trial variability in drift rate", sv, "Inter-trial variability in A-priori bias", sw, "Inter-trial variability in Nondecision time", st0); - + T_y_ref y_ref = y; T_a_ref a_ref = a; T_v_ref v_ref = v; diff --git a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp index d0a9ceb4fd4..a68094da6d7 100644 --- a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp @@ -284,7 +284,6 @@ TEST(mathPrimScalProbWienerFullPrecScal, invalid_st0) { std::domain_error); } - TEST(mathPrimCorrectValues, wiener_lpdf) { // Test concrete values. True values are computed in R using the R-package // WienR and the function WienerPDF. @@ -388,8 +387,6 @@ TEST(mathPrimCorrectValues, wiener_lpdf) { } } - - TEST(mathPrimCorrectValuesFourParamModel, wiener_lpdf) { // Test concrete values. True values are computed in R using the R-package // WienR and the function WienerPDF. @@ -399,10 +396,8 @@ TEST(mathPrimCorrectValuesFourParamModel, wiener_lpdf) { std::vector w_vec = {.1}; std::vector t0_vec = {1e-9}; - std::vector true_dens - = {-4.28564747866615}; - std::vector true_grad_y - = {-3.22509339523307}; + std::vector true_dens = {-4.28564747866615}; + std::vector true_grad_y = {-3.22509339523307}; std::vector true_grad_a = {3.25018678924105}; std::vector true_grad_t0 = {3.22509339523307}; std::vector true_grad_w = {5.67120184517318}; @@ -428,7 +423,6 @@ TEST(mathPrimCorrectValuesFourParamModel, wiener_lpdf) { } } - TEST(mathPrimCorrectValuesFiveParameterModel, wiener_lpdf) { // Test concrete values. True values are computed in R using the R-package // WienR and the function WienerPDF. From 33793f06656f4c3930ad3ffae4c4f8f0ace0a109 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Tue, 6 Feb 2024 22:19:48 +0100 Subject: [PATCH 168/179] newline --- test/unit/math/prim/prob/wiener_full_lpdf_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp index a68094da6d7..8dedb448428 100644 --- a/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp +++ b/test/unit/math/prim/prob/wiener_full_lpdf_test.cpp @@ -461,4 +461,4 @@ TEST(mathPrimCorrectValuesFiveParameterModel, wiener_lpdf) { EXPECT_NEAR(v.adj(), true_grad_v[i], err_tol); EXPECT_NEAR(sv.adj(), true_grad_sv[i], err_tol); } -} \ No newline at end of file +} From cea2d39eb7f0e745c1073cca0014121692c2d5b5 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 15 Feb 2024 16:26:45 +0200 Subject: [PATCH 169/179] Minor tidying for log_sum_exp helper function --- stan/math/prim/prob/wiener5_lpdf.hpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index b04b3360d50..c205114ac0d 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -181,11 +181,10 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, if (small_n_terms_small_t) { constexpr double mult = Density ? 1.0 : 3.0; if (GradW) { - const auto offset = y_asq; for (auto k = n_terms_small_t; k >= 1; k--) { const auto w_plus_2_k = w + 2.0 * k; const auto w_minus_2_k = w - 2.0 * k; - const auto square_w_plus_2_k_minus_offset = square(w_plus_2_k) - offset; + const auto square_w_plus_2_k_minus_offset = square(w_plus_2_k) - y_asq; if (square_w_plus_2_k_minus_offset > 0) { const auto summand_plus = log(square_w_plus_2_k_minus_offset) - square(w_plus_2_k) * scaling; @@ -196,7 +195,7 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, fminus = log_sum_exp(fminus, summand_plus); } const auto square_w_minus_2_k_minus_offset - = square(w_minus_2_k) - offset; + = square(w_minus_2_k) - y_asq; if (square_w_minus_2_k_minus_offset > 0) { const auto summand_minus = log(square_w_minus_2_k_minus_offset) - square(w_minus_2_k) * scaling; @@ -207,7 +206,7 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, fminus = log_sum_exp(fminus, summand_minus); } } - const auto square_w_minus_offset = square(w) - offset; + const auto square_w_minus_offset = square(w) - y_asq; if (square_w_minus_offset > 0) { const auto new_val = log(square_w_minus_offset) - square(w) * scaling; fplus = log_sum_exp(fplus, new_val); @@ -229,9 +228,9 @@ inline auto wiener5_log_sum_exp(T_y&& y, T_a&& a, T_w&& w_value, } else if (summand_minus <= NEGATIVE_INFTY) { continue; } else if (fminus > summand_minus) { - fminus = fminus + log1p(exp(summand_minus - fminus)); + fminus = fminus + log1p_exp(summand_minus - fminus); } else { - fminus = summand_minus + log1p(exp(fminus - summand_minus)); + fminus = summand_minus + log1p_exp(fminus - summand_minus); } } const auto new_val = mult * log(w) - square(w) * scaling; From 4cc95d4ce9545404c0c1d0e543ea3dff94084df8 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Thu, 15 Feb 2024 17:54:17 +0100 Subject: [PATCH 170/179] uncomment include --- stan/math/prim/prob.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stan/math/prim/prob.hpp b/stan/math/prim/prob.hpp index b8322e7c807..598663b71e2 100644 --- a/stan/math/prim/prob.hpp +++ b/stan/math/prim/prob.hpp @@ -370,8 +370,8 @@ #include #include #include -// #include -// #include +#include +#include #include #include #include From 9d7f821e766bfd96289067d6c1df3ee55447e9f0 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Thu, 15 Feb 2024 18:37:33 +0100 Subject: [PATCH 171/179] header tests --- stan/math/prim/prob/wiener5_lpdf.hpp | 16 +- stan/math/prim/prob/wiener_lpdf.hpp | 218 +++++++++++++++++++++++++++ 2 files changed, 227 insertions(+), 7 deletions(-) create mode 100644 stan/math/prim/prob/wiener_lpdf.hpp diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index c205114ac0d..4bba9d4b113 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -832,13 +832,15 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, return ops_partials.build(log_density); } // end wiener_lpdf -template -inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, - const T_w& w, const T_v& v, - const double& precision_derivatives = 1e-4) { - return wiener_lpdf(y, a, t0, w, v, 0, precision_derivatives); -} // end wiener_lpdf + +// ToDo: delete old wiener_lpdf implementation to use this one +//template +//inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, +// const T_w& w, const T_v& v, +// const double& precision_derivatives = 1e-4) { +// return wiener_lpdf(y, a, t0, w, v, 0, precision_derivatives); +//} // end wiener_lpdf } // namespace math } // namespace stan diff --git a/stan/math/prim/prob/wiener_lpdf.hpp b/stan/math/prim/prob/wiener_lpdf.hpp new file mode 100644 index 00000000000..e274254637b --- /dev/null +++ b/stan/math/prim/prob/wiener_lpdf.hpp @@ -0,0 +1,218 @@ +// Original code from which Stan's code is derived: +// Copyright (c) 2013, Joachim Vandekerckhove. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted +// provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// * this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// * this list of conditions and the following disclaimer in the +// * documentation and/or other materials provided with the distribution. +// * Neither the name of the University of California, Irvine nor the names +// * of its contributors may be used to endorse or promote products derived +// * from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef STAN_MATH_PRIM_PROB_WIENER_LPDF_HPP +#define STAN_MATH_PRIM_PROB_WIENER_LPDF_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace stan { +namespace math { + +/** \ingroup prob_dists + * The log of the first passage time density function for a (Wiener) + * drift diffusion model for the given \f$y\f$, + * boundary separation \f$\alpha\f$, nondecision time \f$\tau\f$, + * relative bias \f$\beta\f$, and drift rate \f$\delta\f$. + * \f$\alpha\f$ and \f$\tau\f$ must be greater than 0, and + * \f$\beta\f$ must be between 0 and 1. \f$y\f$ should contain + * reaction times in seconds (strictly positive) with + * upper-boundary responses. + * + * @tparam T_y type of scalar + * @tparam T_alpha type of alpha parameter + * @tparam T_tau type of tau parameter + * @tparam T_beta type of beta parameter + * @tparam T_delta type of delta parameter + * + * @param y A scalar variate. + * @param alpha The boundary separation. + * @param tau The nondecision time. + * @param beta The relative bias. + * @param delta The drift rate. + * @return The log of the Wiener first passage time density of + * the specified arguments. + */ +template +return_type_t wiener_lpdf( + const T_y& y, const T_alpha& alpha, const T_tau& tau, const T_beta& beta, + const T_delta& delta) { + using T_return_type = return_type_t; + using T_y_ref = ref_type_t; + using T_alpha_ref = ref_type_t; + using T_tau_ref = ref_type_t; + using T_beta_ref = ref_type_t; + using T_delta_ref = ref_type_t; + using std::ceil; + using std::exp; + using std::floor; + using std::log; + using std::sin; + using std::sqrt; + static const char* function = "wiener_lpdf"; + check_consistent_sizes(function, "Random variable", y, "Boundary separation", + alpha, "A-priori bias", beta, "Nondecision time", tau, + "Drift rate", delta); + + T_y_ref y_ref = y; + T_alpha_ref alpha_ref = alpha; + T_tau_ref tau_ref = tau; + T_beta_ref beta_ref = beta; + T_delta_ref delta_ref = delta; + + check_positive(function, "Random variable", value_of(y_ref)); + check_positive_finite(function, "Boundary separation", value_of(alpha_ref)); + check_positive_finite(function, "Nondecision time", value_of(tau_ref)); + check_bounded(function, "A-priori bias", value_of(beta_ref), 0, 1); + check_finite(function, "Drift rate", value_of(delta_ref)); + + if (size_zero(y, alpha, beta, tau, delta)) { + return 0; + } + + T_return_type lp(0.0); + + size_t N = max_size(y, alpha, beta, tau, delta); + if (!N) { + return 0.0; + } + + scalar_seq_view y_vec(y_ref); + scalar_seq_view alpha_vec(alpha_ref); + scalar_seq_view beta_vec(beta_ref); + scalar_seq_view tau_vec(tau_ref); + scalar_seq_view delta_vec(delta_ref); + size_t N_y_tau = max_size(y, tau); + + for (size_t i = 0; i < N_y_tau; ++i) { + if (y_vec[i] <= tau_vec[i]) { + std::stringstream msg; + msg << ", but must be greater than nondecision time = " << tau_vec[i]; + std::string msg_str(msg.str()); + throw_domain_error(function, "Random variable", y_vec[i], " = ", + msg_str.c_str()); + } + } + + if (!include_summand::value) { + return 0; + } + + static const double WIENER_ERR = 0.000001; + static const double PI_TIMES_WIENER_ERR = pi() * WIENER_ERR; + static const double LOG_PI_LOG_WIENER_ERR = LOG_PI + log(WIENER_ERR); + static const double TWO_TIMES_SQRT_TWO_PI_TIMES_WIENER_ERR + = 2.0 * SQRT_TWO_PI * WIENER_ERR; + static const double LOG_TWO_OVER_TWO_PLUS_LOG_SQRT_PI + = LOG_TWO / 2 + LOG_SQRT_PI; + static const double SQUARE_PI_OVER_TWO = square(pi()) * 0.5; + static const double TWO_TIMES_LOG_SQRT_PI = 2.0 * LOG_SQRT_PI; + + for (size_t i = 0; i < N; i++) { + typename scalar_type::type one_minus_beta = 1.0 - beta_vec[i]; + typename scalar_type::type alpha2 = square(alpha_vec[i]); + T_return_type x = (y_vec[i] - tau_vec[i]) / alpha2; + T_return_type kl, ks, tmp = 0; + T_return_type k, K; + T_return_type sqrt_x = sqrt(x); + T_return_type log_x = log(x); + T_return_type one_over_pi_times_sqrt_x = 1.0 / pi() * sqrt_x; + + // calculate number of terms needed for large t: + // if error threshold is set low enough + if (PI_TIMES_WIENER_ERR * x < 1) { + // compute bound + kl = sqrt(-2.0 * SQRT_PI * (LOG_PI_LOG_WIENER_ERR + log_x)) / sqrt_x; + // ensure boundary conditions met + kl = (kl > one_over_pi_times_sqrt_x) ? kl : one_over_pi_times_sqrt_x; + } else { + kl = one_over_pi_times_sqrt_x; // set to boundary condition + } + // calculate number of terms needed for small t: + // if error threshold is set low enough + T_return_type tmp_expr0 = TWO_TIMES_SQRT_TWO_PI_TIMES_WIENER_ERR * sqrt_x; + if (tmp_expr0 < 1) { + // compute bound + ks = 2.0 + sqrt_x * sqrt(-2 * log(tmp_expr0)); + // ensure boundary conditions are met + T_return_type sqrt_x_plus_one = sqrt_x + 1.0; + ks = (ks > sqrt_x_plus_one) ? ks : sqrt_x_plus_one; + } else { // if error threshold was set too high + ks = 2.0; // minimal kappa for that case + } + if (ks < kl) { // small t + K = ceil(ks); // round to smallest integer meeting error + T_return_type tmp_expr1 = (K - 1.0) / 2.0; + T_return_type tmp_expr2 = ceil(tmp_expr1); + for (k = -floor(tmp_expr1); k <= tmp_expr2; k++) { + tmp += (one_minus_beta + 2.0 * k) + * exp(-(square(one_minus_beta + 2.0 * k)) * 0.5 / x); + } + tmp = log(tmp) - LOG_TWO_OVER_TWO_PLUS_LOG_SQRT_PI - 1.5 * log_x; + } else { // if large t is better... + K = ceil(kl); // round to smallest integer meeting error + for (k = 1; k <= K; ++k) { + tmp += k * exp(-(square(k)) * (SQUARE_PI_OVER_TWO * x)) + * sin(k * pi() * one_minus_beta); + } + tmp = log(tmp) + TWO_TIMES_LOG_SQRT_PI; + } + + // convert to f(t|v,a,w) and return result + lp += delta_vec[i] * alpha_vec[i] * one_minus_beta + - square(delta_vec[i]) * x * alpha2 / 2.0 - log(alpha2) + tmp; + } + return lp; +} + +template +inline return_type_t wiener_lpdf( + const T_y& y, const T_alpha& alpha, const T_tau& tau, const T_beta& beta, + const T_delta& delta) { + return wiener_lpdf(y, alpha, tau, beta, delta); +} + +} // namespace math +} // namespace stan +#endif From 57e272b5dd3e853d7a7b142cad44561926cff2c8 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 15 Feb 2024 12:38:37 -0500 Subject: [PATCH 172/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener5_lpdf.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/stan/math/prim/prob/wiener5_lpdf.hpp b/stan/math/prim/prob/wiener5_lpdf.hpp index 4bba9d4b113..075b54906b6 100644 --- a/stan/math/prim/prob/wiener5_lpdf.hpp +++ b/stan/math/prim/prob/wiener5_lpdf.hpp @@ -832,11 +832,10 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, return ops_partials.build(log_density); } // end wiener_lpdf - // ToDo: delete old wiener_lpdf implementation to use this one -//template -//inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, +// inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, // const T_w& w, const T_v& v, // const double& precision_derivatives = 1e-4) { // return wiener_lpdf(y, a, t0, w, v, 0, precision_derivatives); From 679445446803d7f7957ea7608038d11ed1d112cd Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 16 Feb 2024 09:47:28 +0100 Subject: [PATCH 173/179] !N to N==0 --- stan/math/prim/prob/wiener_full_lpdf.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 36a6596466b..1a6a79aa551 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -377,7 +377,7 @@ inline auto wiener_lpdf(const T_y& y, const T_a& a, const T_t0& t0, st0_val); const size_t N = max_size(y, a, v, w, t0, sv, sw, st0); - if (!N) { + if (N == 0) { return ret_t(0); } scalar_seq_view y_vec(y_ref); From 899652e997c2c087f2567e70629c42a055b4056a Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 16 Feb 2024 11:00:00 +0100 Subject: [PATCH 174/179] docu --- stan/math/prim/prob/wiener_full_lpdf.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index 1a6a79aa551..c0ddbbb3cd5 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -277,6 +277,11 @@ inline auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, @code target += wiener_lpdf(y, a, 0, w, v, sv, sw, 0) @endcode + * If only inter-trial variability for the drift rate is needed can write + something like: + @code + target += wiener_lpdf(y, a, t0, w, v, sv) + @endcode * * To also control the precision in the estimation of the partial derivatives: @code From 5904b52e17d40ae43529406f732996720fb28a09 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Fri, 16 Feb 2024 05:01:04 -0500 Subject: [PATCH 175/179] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/prim/prob/wiener_full_lpdf.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/prim/prob/wiener_full_lpdf.hpp b/stan/math/prim/prob/wiener_full_lpdf.hpp index c0ddbbb3cd5..be4496c7484 100644 --- a/stan/math/prim/prob/wiener_full_lpdf.hpp +++ b/stan/math/prim/prob/wiener_full_lpdf.hpp @@ -277,7 +277,7 @@ inline auto wiener7_integrate(const Wiener7FunctorT& wiener7_functor, @code target += wiener_lpdf(y, a, 0, w, v, sv, sw, 0) @endcode - * If only inter-trial variability for the drift rate is needed can write + * If only inter-trial variability for the drift rate is needed can write something like: @code target += wiener_lpdf(y, a, t0, w, v, sv) From 3979ff50139a5fd369363d4e4a2f69106a6d9dc7 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Wed, 28 Feb 2024 16:58:00 +0100 Subject: [PATCH 176/179] remove obsolete includes --- stan/math/prim/functor/hcubature.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index da5acfd73ff..c4a41a24cf3 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -27,8 +27,6 @@ #include #include #include -#include -#include namespace stan { namespace math { From b4353c4454e59de90ea3d38502494751c3103438 Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Wed, 28 Feb 2024 17:01:22 +0100 Subject: [PATCH 177/179] update docs --- stan/math/prim/functor/hcubature.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stan/math/prim/functor/hcubature.hpp b/stan/math/prim/functor/hcubature.hpp index c4a41a24cf3..48b77c2a0fb 100644 --- a/stan/math/prim/functor/hcubature.hpp +++ b/stan/math/prim/functor/hcubature.hpp @@ -90,10 +90,10 @@ inline void combination(Eigen::Matrix& c, const int dim, } /** - * Compute a vector [p] of all [dim]-component vectors + * Compute a matrix [p] of all [dim]-component vectors * with [k] components equal to [lambda] and other components equal to zero. * - * @param[in,out] p vector of vectors + * @param[in,out] p matrix * @param k number of components equal to lambda * @param lambda scalar * @param dim dimension @@ -115,11 +115,11 @@ inline Eigen::Matrix combos( } /** - * Compute a vector [p] of all [dim]-component vectors + * Compute a matrix [p] of all [dim]-component vectors * with [k] components equal to [±lambda] and other components equal to zero * (with all possible signs). * - * @param[in,out] p vector of vectors + * @param[in,out] p matrix * @param k number of components equal to lambda * @param lambda scalar * @param dim dimension From bb12079fa6b0ed2662fb48edcf8357e164a054ba Mon Sep 17 00:00:00 2001 From: Franzi2114 Date: Fri, 1 Mar 2024 16:58:04 +0100 Subject: [PATCH 178/179] Jenkinsfile from develop branch --- Jenkinsfile | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 9e7df2a5603..47fb513d2c6 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -4,6 +4,7 @@ import org.stan.Utils def runTests(String testPath, boolean jumbo = false) { try { + sh "cat make/local" if (jumbo && !params.disableJumbo) { sh "python3 runTests.py -j${env.PARALLEL} ${testPath} --jumbo --debug" } else { @@ -141,11 +142,11 @@ pipeline { } post { always { - recordIssues enabledForFailure: true, tools: - [cppLint(), - groovyScript(parserId: 'mathDependencies', pattern: '**/dependencies.log')] + recordIssues( + enabledForFailure: true, + tools: [cppLint(),groovyScript(parserId: 'mathDependencies', pattern: '**/dependencies.log')] + ) deleteDir() - } } } @@ -344,6 +345,7 @@ pipeline { runTests("test/unit/multiple_translation_units_test.cpp") } } + post { always { retry(3) { deleteDir() } } } } } } @@ -393,6 +395,7 @@ pipeline { sh "python ./test/varmat_compatibility_test.py" withEnv(['PATH+TBB=./lib/tbb']) { sh "python ./test/expressions/test_expression_testing_framework.py" + sh "cat make/local" try { sh "./runTests.py -j${PARALLEL} test/expressions" } finally { junit 'test/**/*.xml' } } @@ -400,6 +403,7 @@ pipeline { sh "echo STAN_THREADS=true >> make/local" withEnv(['PATH+TBB=./lib/tbb']) { try { + sh "cat make/local" sh "./runTests.py -j${PARALLEL} test/expressions --only-functions reduce_sum map_rect" } finally { junit 'test/**/*.xml' } @@ -498,6 +502,7 @@ pipeline { sh "echo CXXFLAGS+=-DSTAN_PROB_TEST_ALL >> make/local" } } + sh "cat make/local" sh "./runTests.py -j${PARALLEL} ${names}" } deleteDir() @@ -569,7 +574,10 @@ pipeline { post { always { node("linux") { - recordIssues enabledForFailure: false, tool: clang() + recordIssues( + enabledForFailure: false, + tool: clang() + ) } } success { @@ -581,4 +589,4 @@ pipeline { unstable { script { utils.mailBuildResults("UNSTABLE", alsoNotify()) } } failure { script { utils.mailBuildResults("FAILURE", alsoNotify()) } } } -} +} \ No newline at end of file From 2d5d4f734524f002cdb4f5a9e5a1dcb4c01e49d2 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 7 Mar 2024 09:47:09 +0200 Subject: [PATCH 179/179] Revert stray Jenkinsfile changes --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 47fb513d2c6..9a7c06fef06 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -589,4 +589,4 @@ pipeline { unstable { script { utils.mailBuildResults("UNSTABLE", alsoNotify()) } } failure { script { utils.mailBuildResults("FAILURE", alsoNotify()) } } } -} \ No newline at end of file +}