From f1c5e6c7d852dd295527bd5d34879ce8da328123 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 16 Jun 2025 15:35:42 +0800 Subject: [PATCH 1/2] Improve numerical stability of fwd gradients for std_normal_log_qf --- stan/math/fwd/prob/std_normal_log_qf.hpp | 8 +------- test/unit/math/mix/prob/std_normal_log_qf_test.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/stan/math/fwd/prob/std_normal_log_qf.hpp b/stan/math/fwd/prob/std_normal_log_qf.hpp index 2dc0a855cf7..18ffd5ce74a 100644 --- a/stan/math/fwd/prob/std_normal_log_qf.hpp +++ b/stan/math/fwd/prob/std_normal_log_qf.hpp @@ -16,15 +16,9 @@ namespace math { template inline fvar std_normal_log_qf(const fvar& p) { const T xv = std_normal_log_qf(p.val_); - int p_sign = 1; - auto p_d = p.d_; - if (p.d_ < 0) { - p_sign = -1; - p_d *= -1; - } return fvar( xv, - p_sign * exp(p.val_ + log(p_d) - NEG_LOG_SQRT_TWO_PI + 0.5 * square(xv))); + p.d_ * exp(p.val_ - std_normal_lpdf(xv))); } } // namespace math } // namespace stan diff --git a/test/unit/math/mix/prob/std_normal_log_qf_test.cpp b/test/unit/math/mix/prob/std_normal_log_qf_test.cpp index 1ae44dd9c27..f26d386ee66 100644 --- a/test/unit/math/mix/prob/std_normal_log_qf_test.cpp +++ b/test/unit/math/mix/prob/std_normal_log_qf_test.cpp @@ -4,6 +4,7 @@ #include #include + TEST_F(AgradRev, mathMixLogFun_stdNormalLogQf) { auto f = [](const auto& x1) { return stan::math::std_normal_log_qf(x1); }; stan::test::expect_ad(f, -100.25); @@ -46,3 +47,14 @@ TEST_F(AgradRev, mathMixMatFunLog_stdNormalLogQfVarmat) { } expect_ad_vector_matvar(f, A); } + +TEST_F(AgradRev, GradientStabilityStdNormalLogQf) { + auto f = [](const auto& y) { + return stan::math::sum(stan::math::std_normal_log_qf(y)); + }; + + Eigen::VectorXd y1(2); + y1 << -10, -2; + + stan::test::expect_ad(f, y1); +} From 597fd7e41b8a2c532c0eb640b513d2fbe0ba9993 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 16 Jun 2025 03:40:26 -0400 Subject: [PATCH 2/2] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- stan/math/fwd/prob/std_normal_log_qf.hpp | 4 +--- test/unit/math/mix/prob/std_normal_log_qf_test.cpp | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/stan/math/fwd/prob/std_normal_log_qf.hpp b/stan/math/fwd/prob/std_normal_log_qf.hpp index 18ffd5ce74a..52f53dc107f 100644 --- a/stan/math/fwd/prob/std_normal_log_qf.hpp +++ b/stan/math/fwd/prob/std_normal_log_qf.hpp @@ -16,9 +16,7 @@ namespace math { template inline fvar std_normal_log_qf(const fvar& p) { const T xv = std_normal_log_qf(p.val_); - return fvar( - xv, - p.d_ * exp(p.val_ - std_normal_lpdf(xv))); + return fvar(xv, p.d_ * exp(p.val_ - std_normal_lpdf(xv))); } } // namespace math } // namespace stan diff --git a/test/unit/math/mix/prob/std_normal_log_qf_test.cpp b/test/unit/math/mix/prob/std_normal_log_qf_test.cpp index f26d386ee66..8a2908da869 100644 --- a/test/unit/math/mix/prob/std_normal_log_qf_test.cpp +++ b/test/unit/math/mix/prob/std_normal_log_qf_test.cpp @@ -4,7 +4,6 @@ #include #include - TEST_F(AgradRev, mathMixLogFun_stdNormalLogQf) { auto f = [](const auto& x1) { return stan::math::std_normal_log_qf(x1); }; stan::test::expect_ad(f, -100.25);