From 4052f7cbb8fd2a7f1332d46de035257cfc486a17 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sun, 30 Aug 2026 20:12:17 +0800 Subject: [PATCH 1/3] Replace lexical_cast with from_chars --- stan/math/prim/core/init_threadpool_tbb.hpp | 44 +++++++++---------- .../math/prim/core/get_num_threads_test.cpp | 4 +- 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/stan/math/prim/core/init_threadpool_tbb.hpp b/stan/math/prim/core/init_threadpool_tbb.hpp index 26c8915f387..4601f3a3218 100644 --- a/stan/math/prim/core/init_threadpool_tbb.hpp +++ b/stan/math/prim/core/init_threadpool_tbb.hpp @@ -3,8 +3,6 @@ #include -#include - #ifndef TBB_INTERFACE_NEW #include @@ -20,7 +18,9 @@ #include #endif +#include #include +#include #include namespace stan { @@ -44,32 +44,28 @@ namespace internal { * is invalid */ inline int get_num_threads() { - int num_threads = 1; #ifdef STAN_THREADS const char* env_stan_num_threads = std::getenv("STAN_NUM_THREADS"); - if (env_stan_num_threads != nullptr) { - try { - const int env_num_threads - = boost::lexical_cast(env_stan_num_threads); - if (env_num_threads > 0) { - num_threads = env_num_threads; - } else if (env_num_threads == -1) { - num_threads = std::thread::hardware_concurrency(); - } else { - invalid_argument("get_num_threads(int)", "STAN_NUM_THREADS", - env_stan_num_threads, - "The STAN_NUM_THREADS environment variable is '", - "' but it must be positive or -1"); - } - } catch (const boost::bad_lexical_cast&) { - invalid_argument("get_num_threads(int)", "STAN_NUM_THREADS", - env_stan_num_threads, - "The STAN_NUM_THREADS environment variable is '", - "' but it must be a positive number or -1"); - } + if (env_stan_num_threads == nullptr) { + return 1; + } + + const std::string_view value(env_stan_num_threads); + int num_threads{}; + const auto [end, error] + = std::from_chars(value.begin(), value.end(), num_threads); + if (error != std::errc{} || end != value.end() + || (num_threads < 1 && num_threads != -1)) { + invalid_argument("get_num_threads(int)", "STAN_NUM_THREADS", + env_stan_num_threads, + "The STAN_NUM_THREADS environment variable is '", + "' but it must be a positive number or -1"); } + + return num_threads == -1 ? std::thread::hardware_concurrency() : num_threads; +#else + return 1; #endif - return num_threads; } } // namespace internal diff --git a/test/unit/math/prim/core/get_num_threads_test.cpp b/test/unit/math/prim/core/get_num_threads_test.cpp index 3a91eba9f67..5b86e308c89 100644 --- a/test/unit/math/prim/core/get_num_threads_test.cpp +++ b/test/unit/math/prim/core/get_num_threads_test.cpp @@ -27,11 +27,11 @@ TEST(get_num_threads, incorrect_values) { set_n_threads("-2"); EXPECT_THROW_MSG(stan::math::internal::get_num_threads(), - std::invalid_argument, "must be positive or -1"); + std::invalid_argument, "positive number or -1"); set_n_threads("0"); EXPECT_THROW_MSG(stan::math::internal::get_num_threads(), - std::invalid_argument, "must be positive or -1"); + std::invalid_argument, "positive number or -1"); } #else TEST(get_num_threads, correct_values_no_stan_threads) { From b5736bb5849a501719dac267a1c96a4877050a15 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sun, 30 Aug 2026 20:17:11 +0800 Subject: [PATCH 2/3] Replace boost optional with std --- stan/math/prim/fun/grad_2F1.hpp | 1 - stan/math/prim/fun/hypergeometric_2F1.hpp | 16 ++++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/stan/math/prim/fun/grad_2F1.hpp b/stan/math/prim/fun/grad_2F1.hpp index 42d5d2a50dd..8731c6d30b7 100644 --- a/stan/math/prim/fun/grad_2F1.hpp +++ b/stan/math/prim/fun/grad_2F1.hpp @@ -13,7 +13,6 @@ #include #include #include -#include namespace stan { namespace math { diff --git a/stan/math/prim/fun/hypergeometric_2F1.hpp b/stan/math/prim/fun/hypergeometric_2F1.hpp index ae327e033f1..fc33f7062d0 100644 --- a/stan/math/prim/fun/hypergeometric_2F1.hpp +++ b/stan/math/prim/fun/hypergeometric_2F1.hpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include namespace stan { namespace math { @@ -29,7 +29,7 @@ namespace internal { * more background (and other possible special-cases), see: * https://functions.wolfram.com/HypergeometricFunctions/Hypergeometric2F1/03/ * - * The return value is wrapped in a boost::optional<> type so that a void + * The return value is wrapped in a std::optional<> type so that a void * return is possible if no special-case rules are applicable * * @tparam Ta1 Type of scalar first 'a' argument @@ -43,7 +43,7 @@ namespace internal { * @return Gauss hypergeometric function */ template >, + typename RtnT = std::optional>, require_all_arithmetic_t* = nullptr> inline RtnT hyper_2F1_special_cases(const Ta1& a1, const Ta2& a2, const Tb& b, const Tz& z) { @@ -149,7 +149,7 @@ inline RtnT hyper_2F1_special_cases(const Ta1& a1, const Ta2& a2, const Tb& b, */ template , - typename OptT = boost::optional, + typename OptT = std::optional, require_all_arithmetic_t* = nullptr> inline return_type_t hypergeometric_2F1(const Ta1& a1, const Ta2& a2, @@ -168,15 +168,15 @@ inline return_type_t hypergeometric_2F1(const Ta1& a1, // Check whether value can be calculated by any special-case rules // before estimating infinite sum OptT special_case_a1a2 = internal::hyper_2F1_special_cases(a1, a2, b, z); - if (special_case_a1a2.is_initialized()) { - return special_case_a1a2.get(); + if (special_case_a1a2.has_value()) { + return special_case_a1a2.value(); } // Check whether any special case rules apply with 'a' arguments reversed // as 2F1(a1, a2, b, z) = 2F1(a2, a1, b, z) OptT special_case_a2a1 = internal::hyper_2F1_special_cases(a2, a1, b, z); - if (special_case_a2a1.is_initialized()) { - return special_case_a2a1.get(); + if (special_case_a2a1.has_value()) { + return special_case_a2a1.value(); } Eigen::Matrix a_args(2); From bc3e31c55eaade38a1d3c89e2a4d7b294ad331e1 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sun, 30 Aug 2026 20:40:49 +0800 Subject: [PATCH 3/3] cpplint --- stan/math/prim/core/init_threadpool_tbb.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stan/math/prim/core/init_threadpool_tbb.hpp b/stan/math/prim/core/init_threadpool_tbb.hpp index 4601f3a3218..ca96dc3a8b2 100644 --- a/stan/math/prim/core/init_threadpool_tbb.hpp +++ b/stan/math/prim/core/init_threadpool_tbb.hpp @@ -51,10 +51,10 @@ inline int get_num_threads() { } const std::string_view value(env_stan_num_threads); - int num_threads{}; + int num_threads; const auto [end, error] = std::from_chars(value.begin(), value.end(), num_threads); - if (error != std::errc{} || end != value.end() + if (error != std::errc() || end != value.end() || (num_threads < 1 && num_threads != -1)) { invalid_argument("get_num_threads(int)", "STAN_NUM_THREADS", env_stan_num_threads,