error_handling.hpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  1. // Copyright John Maddock 2007.
  2. // Copyright Paul A. Bristow 2007.
  3. // Copyright Matt Borland 2024.
  4. // Use, modification and distribution are subject to the
  5. // Boost Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_MATH_POLICY_ERROR_HANDLING_HPP
  8. #define BOOST_MATH_POLICY_ERROR_HANDLING_HPP
  9. #include <boost/math/policies/policy.hpp>
  10. #include <boost/math/tools/config.hpp>
  11. #include <boost/math/tools/numeric_limits.hpp>
  12. #include <boost/math/tools/precision.hpp>
  13. #include <boost/math/tools/tuple.hpp>
  14. #include <boost/math/tools/type_traits.hpp>
  15. #ifndef BOOST_MATH_HAS_NVRTC
  16. #ifndef BOOST_MATH_NO_EXCEPTIONS
  17. #include <boost/math/tools/throw_exception.hpp>
  18. #endif
  19. #include <cerrno>
  20. #include <cmath>
  21. #include <complex>
  22. #include <cstdint>
  23. #include <cstring>
  24. #include <iomanip>
  25. #include <sstream>
  26. #ifndef BOOST_MATH_NO_EXCEPTIONS
  27. #include <stdexcept>
  28. #endif
  29. #include <string>
  30. #ifndef BOOST_MATH_NO_RTTI
  31. #include <typeinfo>
  32. #endif
  33. #ifdef _MSC_VER
  34. # pragma warning(push) // Quiet warnings in boost/format.hpp
  35. # pragma warning(disable: 4996) // _SCL_SECURE_NO_DEPRECATE
  36. # pragma warning(disable: 4512) // assignment operator could not be generated.
  37. # pragma warning(disable: 4127) // conditional expression is constant
  38. // And warnings in error handling:
  39. # pragma warning(disable: 4702) // unreachable code.
  40. // Note that this only occurs when the compiler can deduce code is unreachable,
  41. // for example when policy macros are used to ignore errors rather than throw.
  42. #endif
  43. namespace boost{ namespace math{
  44. #ifndef BOOST_MATH_NO_EXCEPTIONS
  45. class evaluation_error : public std::runtime_error
  46. {
  47. public:
  48. explicit evaluation_error(const std::string& s) : std::runtime_error(s){}
  49. };
  50. class rounding_error : public std::runtime_error
  51. {
  52. public:
  53. explicit rounding_error(const std::string& s) : std::runtime_error(s){}
  54. };
  55. #else
  56. class evaluation_error {};
  57. class rounding_error {};
  58. #endif
  59. namespace policies{
  60. //
  61. // Forward declarations of user error handlers,
  62. // it's up to the user to provide the definition of these:
  63. //
  64. template <class T>
  65. T user_domain_error(const char* function, const char* message, const T& val);
  66. template <class T>
  67. T user_pole_error(const char* function, const char* message, const T& val);
  68. template <class T>
  69. T user_overflow_error(const char* function, const char* message, const T& val);
  70. template <class T>
  71. T user_underflow_error(const char* function, const char* message, const T& val);
  72. template <class T>
  73. T user_denorm_error(const char* function, const char* message, const T& val);
  74. template <class T>
  75. T user_evaluation_error(const char* function, const char* message, const T& val);
  76. template <class T, class TargetType>
  77. TargetType user_rounding_error(const char* function, const char* message, const T& val, const TargetType& t);
  78. template <class T>
  79. T user_indeterminate_result_error(const char* function, const char* message, const T& val);
  80. namespace detail
  81. {
  82. template <class T>
  83. inline std::string prec_format(const T& val)
  84. {
  85. using prec_type = typename boost::math::policies::precision<T, boost::math::policies::policy<> >::type;
  86. std::stringstream strm { };
  87. if(prec_type::value)
  88. {
  89. const std::streamsize prec { static_cast<std::streamsize>(2UL + (prec_type::value * 30103UL) / 100000UL) };
  90. strm << std::setprecision(prec);
  91. }
  92. strm << val;
  93. return strm.str();
  94. }
  95. #ifdef BOOST_MATH_USE_CHARCONV_FOR_CONVERSION
  96. template <>
  97. inline std::string prec_format<std::float128_t>(const std::float128_t& val)
  98. {
  99. char buffer[128] {};
  100. const auto r = std::to_chars(buffer, buffer + sizeof(buffer), val);
  101. return std::string(buffer, r.ptr);
  102. }
  103. #endif
  104. inline void replace_all_in_string(std::string& result, const char* what, const char* with)
  105. {
  106. std::string::size_type pos = 0;
  107. std::string::size_type slen = std::strlen(what);
  108. std::string::size_type rlen = std::strlen(with);
  109. while((pos = result.find(what, pos)) != std::string::npos)
  110. {
  111. result.replace(pos, slen, with);
  112. pos += rlen;
  113. }
  114. }
  115. template <class T>
  116. inline const char* name_of()
  117. {
  118. #ifndef BOOST_MATH_NO_RTTI
  119. return typeid(T).name();
  120. #else
  121. return "unknown";
  122. #endif
  123. }
  124. template <> inline const char* name_of<float>(){ return "float"; }
  125. template <> inline const char* name_of<double>(){ return "double"; }
  126. template <> inline const char* name_of<long double>(){ return "long double"; }
  127. #ifdef BOOST_MATH_USE_FLOAT128
  128. template <>
  129. inline const char* name_of<BOOST_MATH_FLOAT128_TYPE>()
  130. {
  131. return "__float128";
  132. }
  133. #endif
  134. #ifndef BOOST_MATH_NO_EXCEPTIONS
  135. template <class E, class T>
  136. void raise_error(const char* pfunction, const char* message)
  137. {
  138. if(pfunction == nullptr)
  139. {
  140. pfunction = "Unknown function operating on type %1%";
  141. }
  142. if(message == nullptr)
  143. {
  144. message = "Cause unknown";
  145. }
  146. std::string function(pfunction);
  147. std::string msg("Error in function ");
  148. #ifndef BOOST_MATH_NO_RTTI
  149. replace_all_in_string(function, "%1%", boost::math::policies::detail::name_of<T>());
  150. #else
  151. replace_all_in_string(function, "%1%", "Unknown");
  152. #endif
  153. msg += function;
  154. msg += ": ";
  155. msg += message;
  156. BOOST_MATH_THROW_EXCEPTION(E(msg))
  157. }
  158. template <class E, class T>
  159. void raise_error(const char* pfunction, const char* pmessage, const T& val)
  160. {
  161. if(pfunction == nullptr)
  162. {
  163. pfunction = "Unknown function operating on type %1%";
  164. }
  165. if(pmessage == nullptr)
  166. {
  167. pmessage = "Cause unknown: error caused by bad argument with value %1%";
  168. }
  169. std::string function(pfunction);
  170. std::string message(pmessage);
  171. std::string msg("Error in function ");
  172. #ifndef BOOST_MATH_NO_RTTI
  173. replace_all_in_string(function, "%1%", boost::math::policies::detail::name_of<T>());
  174. #else
  175. replace_all_in_string(function, "%1%", "Unknown");
  176. #endif
  177. msg += function;
  178. msg += ": ";
  179. std::string sval = prec_format(val);
  180. replace_all_in_string(message, "%1%", sval.c_str());
  181. msg += message;
  182. BOOST_MATH_THROW_EXCEPTION(E(msg))
  183. }
  184. #endif
  185. template <class T>
  186. BOOST_MATH_GPU_ENABLED inline T raise_domain_error(
  187. const char* function,
  188. const char* message,
  189. const T& val,
  190. const ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>&)
  191. {
  192. #ifdef BOOST_MATH_NO_EXCEPTIONS
  193. static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");
  194. #else
  195. raise_error<std::domain_error, T>(function, message, val);
  196. // we never get here:
  197. return boost::math::numeric_limits<T>::quiet_NaN();
  198. #endif
  199. }
  200. template <class T>
  201. BOOST_MATH_GPU_ENABLED constexpr T raise_domain_error(
  202. const char* ,
  203. const char* ,
  204. const T& ,
  205. const ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
  206. {
  207. // This may or may not do the right thing, but the user asked for the error
  208. // to be ignored so here we go anyway:
  209. return boost::math::numeric_limits<T>::quiet_NaN();
  210. }
  211. template <class T>
  212. BOOST_MATH_GPU_ENABLED inline T raise_domain_error(
  213. const char* ,
  214. const char* ,
  215. const T& ,
  216. const ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
  217. {
  218. errno = EDOM;
  219. // This may or may not do the right thing, but the user asked for the error
  220. // to be silent so here we go anyway:
  221. return boost::math::numeric_limits<T>::quiet_NaN();
  222. }
  223. template <class T>
  224. BOOST_MATH_GPU_ENABLED inline T raise_domain_error(
  225. const char* function,
  226. const char* message,
  227. const T& val,
  228. const ::boost::math::policies::domain_error< ::boost::math::policies::user_error>&)
  229. {
  230. return user_domain_error(function, message, val);
  231. }
  232. template <class T>
  233. BOOST_MATH_GPU_ENABLED inline T raise_pole_error(
  234. const char* function,
  235. const char* message,
  236. const T& val,
  237. const ::boost::math::policies::pole_error< ::boost::math::policies::throw_on_error>&)
  238. {
  239. #ifdef BOOST_MATH_NO_EXCEPTIONS
  240. static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");
  241. #else
  242. return boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>());
  243. #endif
  244. }
  245. template <class T>
  246. BOOST_MATH_GPU_ENABLED constexpr T raise_pole_error(
  247. const char* function,
  248. const char* message,
  249. const T& val,
  250. const ::boost::math::policies::pole_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
  251. {
  252. return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>());
  253. }
  254. template <class T>
  255. BOOST_MATH_GPU_ENABLED constexpr T raise_pole_error(
  256. const char* function,
  257. const char* message,
  258. const T& val,
  259. const ::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
  260. {
  261. return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>());
  262. }
  263. template <class T>
  264. BOOST_MATH_GPU_ENABLED inline T raise_pole_error(
  265. const char* function,
  266. const char* message,
  267. const T& val,
  268. const ::boost::math::policies::pole_error< ::boost::math::policies::user_error>&)
  269. {
  270. return user_pole_error(function, message, val);
  271. }
  272. template <class T>
  273. BOOST_MATH_GPU_ENABLED inline T raise_overflow_error(
  274. const char* function,
  275. const char* message,
  276. const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)
  277. {
  278. #ifdef BOOST_MATH_NO_EXCEPTIONS
  279. static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");
  280. #else
  281. raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow");
  282. // We should never get here:
  283. return boost::math::numeric_limits<T>::has_infinity ? boost::math::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
  284. #endif
  285. }
  286. template <class T>
  287. BOOST_MATH_GPU_ENABLED inline T raise_overflow_error(
  288. const char* function,
  289. const char* message,
  290. const T& val,
  291. const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)
  292. {
  293. #ifdef BOOST_MATH_NO_EXCEPTIONS
  294. static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");
  295. #else
  296. raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow", val);
  297. // We should never get here:
  298. return boost::math::numeric_limits<T>::has_infinity ? boost::math::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
  299. #endif
  300. }
  301. template <class T>
  302. BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error(
  303. const char* ,
  304. const char* ,
  305. const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
  306. {
  307. // This may or may not do the right thing, but the user asked for the error
  308. // to be ignored so here we go anyway:
  309. return boost::math::numeric_limits<T>::has_infinity ? boost::math::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
  310. }
  311. template <class T>
  312. BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error(
  313. const char* ,
  314. const char* ,
  315. const T&,
  316. const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
  317. {
  318. // This may or may not do the right thing, but the user asked for the error
  319. // to be ignored so here we go anyway:
  320. return boost::math::numeric_limits<T>::has_infinity ? boost::math::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
  321. }
  322. template <class T>
  323. BOOST_MATH_GPU_ENABLED inline T raise_overflow_error(
  324. const char* ,
  325. const char* ,
  326. const ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
  327. {
  328. errno = ERANGE;
  329. // This may or may not do the right thing, but the user asked for the error
  330. // to be silent so here we go anyway:
  331. return boost::math::numeric_limits<T>::has_infinity ? boost::math::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
  332. }
  333. template <class T>
  334. BOOST_MATH_GPU_ENABLED inline T raise_overflow_error(
  335. const char* ,
  336. const char* ,
  337. const T&,
  338. const ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
  339. {
  340. errno = ERANGE;
  341. // This may or may not do the right thing, but the user asked for the error
  342. // to be silent so here we go anyway:
  343. return boost::math::numeric_limits<T>::has_infinity ? boost::math::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
  344. }
  345. template <class T>
  346. BOOST_MATH_GPU_ENABLED inline T raise_overflow_error(
  347. const char* function,
  348. const char* message,
  349. const ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&)
  350. {
  351. return user_overflow_error(function, message, boost::math::numeric_limits<T>::infinity());
  352. }
  353. template <class T>
  354. BOOST_MATH_GPU_ENABLED inline T raise_overflow_error(
  355. const char* function,
  356. const char* message,
  357. const T& val,
  358. const ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&)
  359. {
  360. std::string m(message ? message : "");
  361. std::string sval = prec_format(val);
  362. replace_all_in_string(m, "%1%", sval.c_str());
  363. return user_overflow_error(function, m.c_str(), boost::math::numeric_limits<T>::infinity());
  364. }
  365. template <class T>
  366. BOOST_MATH_GPU_ENABLED inline T raise_underflow_error(
  367. const char* function,
  368. const char* message,
  369. const ::boost::math::policies::underflow_error< ::boost::math::policies::throw_on_error>&)
  370. {
  371. #ifdef BOOST_MATH_NO_EXCEPTIONS
  372. static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");
  373. #else
  374. raise_error<std::underflow_error, T>(function, message ? message : "numeric underflow");
  375. // We should never get here:
  376. return 0;
  377. #endif
  378. }
  379. template <class T>
  380. BOOST_MATH_GPU_ENABLED constexpr T raise_underflow_error(
  381. const char* ,
  382. const char* ,
  383. const ::boost::math::policies::underflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
  384. {
  385. // This may or may not do the right thing, but the user asked for the error
  386. // to be ignored so here we go anyway:
  387. return T(0);
  388. }
  389. template <class T>
  390. BOOST_MATH_GPU_ENABLED inline T raise_underflow_error(
  391. const char* /* function */,
  392. const char* /* message */,
  393. const ::boost::math::policies::underflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
  394. {
  395. errno = ERANGE;
  396. // This may or may not do the right thing, but the user asked for the error
  397. // to be silent so here we go anyway:
  398. return T(0);
  399. }
  400. template <class T>
  401. BOOST_MATH_GPU_ENABLED inline T raise_underflow_error(
  402. const char* function,
  403. const char* message,
  404. const ::boost::math::policies::underflow_error< ::boost::math::policies::user_error>&)
  405. {
  406. return user_underflow_error(function, message, T(0));
  407. }
  408. template <class T>
  409. BOOST_MATH_GPU_ENABLED inline T raise_denorm_error(
  410. const char* function,
  411. const char* message,
  412. const T& /* val */,
  413. const ::boost::math::policies::denorm_error< ::boost::math::policies::throw_on_error>&)
  414. {
  415. #ifdef BOOST_MATH_NO_EXCEPTIONS
  416. static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");
  417. #else
  418. raise_error<std::underflow_error, T>(function, message ? message : "denormalised result");
  419. // we never get here:
  420. return T(0);
  421. #endif
  422. }
  423. template <class T>
  424. BOOST_MATH_GPU_ENABLED inline constexpr T raise_denorm_error(
  425. const char* ,
  426. const char* ,
  427. const T& val,
  428. const ::boost::math::policies::denorm_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
  429. {
  430. // This may or may not do the right thing, but the user asked for the error
  431. // to be ignored so here we go anyway:
  432. return val;
  433. }
  434. template <class T>
  435. BOOST_MATH_GPU_ENABLED inline T raise_denorm_error(
  436. const char* ,
  437. const char* ,
  438. const T& val,
  439. const ::boost::math::policies::denorm_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
  440. {
  441. errno = ERANGE;
  442. // This may or may not do the right thing, but the user asked for the error
  443. // to be silent so here we go anyway:
  444. return val;
  445. }
  446. template <class T>
  447. BOOST_MATH_GPU_ENABLED inline T raise_denorm_error(
  448. const char* function,
  449. const char* message,
  450. const T& val,
  451. const ::boost::math::policies::denorm_error< ::boost::math::policies::user_error>&)
  452. {
  453. return user_denorm_error(function, message, val);
  454. }
  455. template <class T>
  456. BOOST_MATH_GPU_ENABLED inline T raise_evaluation_error(
  457. const char* function,
  458. const char* message,
  459. const T& val,
  460. const ::boost::math::policies::evaluation_error< ::boost::math::policies::throw_on_error>&)
  461. {
  462. #ifdef BOOST_MATH_NO_EXCEPTIONS
  463. static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");
  464. #else
  465. raise_error<boost::math::evaluation_error, T>(function, message, val);
  466. // we never get here:
  467. return T(0);
  468. #endif
  469. }
  470. template <class T>
  471. BOOST_MATH_GPU_ENABLED constexpr T raise_evaluation_error(
  472. const char* ,
  473. const char* ,
  474. const T& val,
  475. const ::boost::math::policies::evaluation_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
  476. {
  477. // This may or may not do the right thing, but the user asked for the error
  478. // to be ignored so here we go anyway:
  479. return val;
  480. }
  481. template <class T>
  482. BOOST_MATH_GPU_ENABLED inline T raise_evaluation_error(
  483. const char* ,
  484. const char* ,
  485. const T& val,
  486. const ::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
  487. {
  488. errno = EDOM;
  489. // This may or may not do the right thing, but the user asked for the error
  490. // to be silent so here we go anyway:
  491. return val;
  492. }
  493. template <class T>
  494. BOOST_MATH_GPU_ENABLED inline T raise_evaluation_error(
  495. const char* function,
  496. const char* message,
  497. const T& val,
  498. const ::boost::math::policies::evaluation_error< ::boost::math::policies::user_error>&)
  499. {
  500. return user_evaluation_error(function, message, val);
  501. }
  502. template <class T, class TargetType>
  503. BOOST_MATH_GPU_ENABLED inline TargetType raise_rounding_error(
  504. const char* function,
  505. const char* message,
  506. const T& val,
  507. const TargetType&,
  508. const ::boost::math::policies::rounding_error< ::boost::math::policies::throw_on_error>&)
  509. {
  510. #ifdef BOOST_MATH_NO_EXCEPTIONS
  511. static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");
  512. #else
  513. raise_error<boost::math::rounding_error, T>(function, message, val);
  514. // we never get here:
  515. return TargetType(0);
  516. #endif
  517. }
  518. template <class T, class TargetType>
  519. BOOST_MATH_GPU_ENABLED constexpr TargetType raise_rounding_error(
  520. const char* ,
  521. const char* ,
  522. const T& val,
  523. const TargetType&,
  524. const ::boost::math::policies::rounding_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
  525. {
  526. // This may or may not do the right thing, but the user asked for the error
  527. // to be ignored so here we go anyway:
  528. static_assert(boost::math::numeric_limits<TargetType>::is_specialized, "The target type must have std::numeric_limits specialized.");
  529. return val > 0 ? (boost::math::numeric_limits<TargetType>::max)() : (boost::math::numeric_limits<TargetType>::is_integer ? (boost::math::numeric_limits<TargetType>::min)() : -(boost::math::numeric_limits<TargetType>::max)());
  530. }
  531. template <class T, class TargetType>
  532. BOOST_MATH_GPU_ENABLED inline TargetType raise_rounding_error(
  533. const char* ,
  534. const char* ,
  535. const T& val,
  536. const TargetType&,
  537. const ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
  538. {
  539. errno = ERANGE;
  540. // This may or may not do the right thing, but the user asked for the error
  541. // to be silent so here we go anyway:
  542. static_assert(boost::math::numeric_limits<TargetType>::is_specialized, "The target type must have std::numeric_limits specialized.");
  543. return val > 0 ? (boost::math::numeric_limits<TargetType>::max)() : (boost::math::numeric_limits<TargetType>::is_integer ? (boost::math::numeric_limits<TargetType>::min)() : -(boost::math::numeric_limits<TargetType>::max)());
  544. }
  545. template <class T, class TargetType>
  546. BOOST_MATH_GPU_ENABLED inline TargetType raise_rounding_error(
  547. const char* function,
  548. const char* message,
  549. const T& val,
  550. const TargetType& t,
  551. const ::boost::math::policies::rounding_error< ::boost::math::policies::user_error>&)
  552. {
  553. return user_rounding_error(function, message, val, t);
  554. }
  555. template <class T, class R>
  556. BOOST_MATH_GPU_ENABLED inline T raise_indeterminate_result_error(
  557. const char* function,
  558. const char* message,
  559. const T& val,
  560. const R& ,
  561. const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::throw_on_error>&)
  562. {
  563. #ifdef BOOST_MATH_NO_EXCEPTIONS
  564. static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set.");
  565. #else
  566. raise_error<std::domain_error, T>(function, message, val);
  567. // we never get here:
  568. return boost::math::numeric_limits<T>::quiet_NaN();
  569. #endif
  570. }
  571. template <class T, class R>
  572. BOOST_MATH_GPU_ENABLED inline constexpr T raise_indeterminate_result_error(
  573. const char* ,
  574. const char* ,
  575. const T& ,
  576. const R& result,
  577. const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
  578. {
  579. // This may or may not do the right thing, but the user asked for the error
  580. // to be ignored so here we go anyway:
  581. return result;
  582. }
  583. template <class T, class R>
  584. BOOST_MATH_GPU_ENABLED inline T raise_indeterminate_result_error(
  585. const char* ,
  586. const char* ,
  587. const T& ,
  588. const R& result,
  589. const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::errno_on_error>&)
  590. {
  591. errno = EDOM;
  592. // This may or may not do the right thing, but the user asked for the error
  593. // to be silent so here we go anyway:
  594. return result;
  595. }
  596. template <class T, class R>
  597. BOOST_MATH_GPU_ENABLED inline T raise_indeterminate_result_error(
  598. const char* function,
  599. const char* message,
  600. const T& val,
  601. const R& ,
  602. const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::user_error>&)
  603. {
  604. return user_indeterminate_result_error(function, message, val);
  605. }
  606. } // namespace detail
  607. template <class T, class Policy>
  608. BOOST_MATH_GPU_ENABLED constexpr T raise_domain_error(const char* function, const char* message, const T& val, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
  609. {
  610. typedef typename Policy::domain_error_type policy_type;
  611. return detail::raise_domain_error(
  612. function, message ? message : "Domain Error evaluating function at %1%",
  613. val, policy_type());
  614. }
  615. template <class T, class Policy>
  616. BOOST_MATH_GPU_ENABLED constexpr T raise_pole_error(const char* function, const char* message, const T& val, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
  617. {
  618. typedef typename Policy::pole_error_type policy_type;
  619. return detail::raise_pole_error(
  620. function, message ? message : "Evaluation of function at pole %1%",
  621. val, policy_type());
  622. }
  623. template <class T, class Policy>
  624. BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error(const char* function, const char* message, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
  625. {
  626. typedef typename Policy::overflow_error_type policy_type;
  627. return detail::raise_overflow_error<T>(
  628. function, message ? message : "Overflow Error",
  629. policy_type());
  630. }
  631. template <class T, class Policy>
  632. BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error(const char* function, const char* message, const T& val, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
  633. {
  634. typedef typename Policy::overflow_error_type policy_type;
  635. return detail::raise_overflow_error(
  636. function, message ? message : "Overflow evaluating function at %1%",
  637. val, policy_type());
  638. }
  639. template <class T, class Policy>
  640. BOOST_MATH_GPU_ENABLED constexpr T raise_underflow_error(const char* function, const char* message, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
  641. {
  642. typedef typename Policy::underflow_error_type policy_type;
  643. return detail::raise_underflow_error<T>(
  644. function, message ? message : "Underflow Error",
  645. policy_type());
  646. }
  647. template <class T, class Policy>
  648. BOOST_MATH_GPU_ENABLED constexpr T raise_denorm_error(const char* function, const char* message, const T& val, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
  649. {
  650. typedef typename Policy::denorm_error_type policy_type;
  651. return detail::raise_denorm_error<T>(
  652. function, message ? message : "Denorm Error",
  653. val,
  654. policy_type());
  655. }
  656. template <class T, class Policy>
  657. BOOST_MATH_GPU_ENABLED constexpr T raise_evaluation_error(const char* function, const char* message, const T& val, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
  658. {
  659. typedef typename Policy::evaluation_error_type policy_type;
  660. return detail::raise_evaluation_error(
  661. function, message ? message : "Internal Evaluation Error, best value so far was %1%",
  662. val, policy_type());
  663. }
  664. template <class T, class TargetType, class Policy>
  665. BOOST_MATH_GPU_ENABLED constexpr TargetType raise_rounding_error(const char* function, const char* message, const T& val, const TargetType& t, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
  666. {
  667. typedef typename Policy::rounding_error_type policy_type;
  668. return detail::raise_rounding_error(
  669. function, message ? message : "Value %1% can not be represented in the target integer type.",
  670. val, t, policy_type());
  671. }
  672. template <class T, class R, class Policy>
  673. BOOST_MATH_GPU_ENABLED constexpr T raise_indeterminate_result_error(const char* function, const char* message, const T& val, const R& result, const Policy&) noexcept(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
  674. {
  675. typedef typename Policy::indeterminate_result_error_type policy_type;
  676. return detail::raise_indeterminate_result_error(
  677. function, message ? message : "Indeterminate result with value %1%",
  678. val, result, policy_type());
  679. }
  680. //
  681. // checked_narrowing_cast:
  682. //
  683. namespace detail
  684. {
  685. template <class R, class T, class Policy>
  686. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE bool check_overflow(T val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
  687. {
  688. BOOST_MATH_STD_USING
  689. if(fabs(val) > tools::max_value<R>())
  690. {
  691. boost::math::policies::detail::raise_overflow_error<R>(function, nullptr, pol);
  692. *result = static_cast<R>(val);
  693. return true;
  694. }
  695. return false;
  696. }
  697. template <class R, class T, class Policy>
  698. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE bool check_overflow(std::complex<T> val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
  699. {
  700. typedef typename R::value_type r_type;
  701. r_type re, im;
  702. bool r = check_overflow<r_type>(val.real(), &re, function, pol);
  703. r = check_overflow<r_type>(val.imag(), &im, function, pol) || r;
  704. *result = R(re, im);
  705. return r;
  706. }
  707. template <class R, class T, class Policy>
  708. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE bool check_underflow(T val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
  709. {
  710. if((val != 0) && (static_cast<R>(val) == 0))
  711. {
  712. *result = static_cast<R>(boost::math::policies::detail::raise_underflow_error<R>(function, nullptr, pol));
  713. return true;
  714. }
  715. return false;
  716. }
  717. template <class R, class T, class Policy>
  718. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE bool check_underflow(std::complex<T> val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
  719. {
  720. typedef typename R::value_type r_type;
  721. r_type re, im;
  722. bool r = check_underflow<r_type>(val.real(), &re, function, pol);
  723. r = check_underflow<r_type>(val.imag(), &im, function, pol) || r;
  724. *result = R(re, im);
  725. return r;
  726. }
  727. template <class R, class T, class Policy>
  728. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE bool check_denorm(T val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
  729. {
  730. BOOST_MATH_STD_USING
  731. if((fabs(val) < static_cast<T>(tools::min_value<R>())) && (static_cast<R>(val) != 0))
  732. {
  733. *result = static_cast<R>(boost::math::policies::detail::raise_denorm_error<R>(function, 0, static_cast<R>(val), pol));
  734. return true;
  735. }
  736. return false;
  737. }
  738. template <class R, class T, class Policy>
  739. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE bool check_denorm(std::complex<T> val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
  740. {
  741. typedef typename R::value_type r_type;
  742. r_type re, im;
  743. bool r = check_denorm<r_type>(val.real(), &re, function, pol);
  744. r = check_denorm<r_type>(val.imag(), &im, function, pol) || r;
  745. *result = R(re, im);
  746. return r;
  747. }
  748. // Default instantiations with ignore_error policy.
  749. template <class R, class T>
  750. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE constexpr bool check_overflow(T /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
  751. { return false; }
  752. template <class R, class T>
  753. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE constexpr bool check_overflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
  754. { return false; }
  755. template <class R, class T>
  756. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE constexpr bool check_underflow(T /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
  757. { return false; }
  758. template <class R, class T>
  759. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE constexpr bool check_underflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
  760. { return false; }
  761. template <class R, class T>
  762. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE constexpr bool check_denorm(T /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
  763. { return false; }
  764. template <class R, class T>
  765. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE constexpr bool check_denorm(std::complex<T> /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
  766. { return false; }
  767. } // namespace detail
  768. template <class R, class Policy, class T>
  769. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE R checked_narrowing_cast(T val, const char* function) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
  770. {
  771. typedef typename Policy::overflow_error_type overflow_type;
  772. typedef typename Policy::underflow_error_type underflow_type;
  773. typedef typename Policy::denorm_error_type denorm_type;
  774. //
  775. // Most of what follows will evaluate to a no-op:
  776. //
  777. R result = 0;
  778. if(detail::check_overflow<R>(val, &result, function, overflow_type()))
  779. return result;
  780. if(detail::check_underflow<R>(val, &result, function, underflow_type()))
  781. return result;
  782. if(detail::check_denorm<R>(val, &result, function, denorm_type()))
  783. return result;
  784. return static_cast<R>(val);
  785. }
  786. template <class T, class Policy>
  787. BOOST_MATH_GPU_ENABLED inline void check_series_iterations(const char* function, std::uintmax_t max_iter, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
  788. {
  789. if(max_iter >= policies::get_max_series_iterations<Policy>())
  790. raise_evaluation_error<T>(
  791. function,
  792. "Series evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
  793. }
  794. template <class T, class Policy>
  795. BOOST_MATH_GPU_ENABLED inline void check_root_iterations(const char* function, std::uintmax_t max_iter, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
  796. {
  797. if(max_iter >= policies::get_max_root_iterations<Policy>())
  798. raise_evaluation_error<T>(
  799. function,
  800. "Root finding evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
  801. }
  802. } //namespace policies
  803. #ifdef _MSC_VER
  804. # pragma warning(pop)
  805. #endif
  806. }} // namespaces boost/math
  807. #else // Special values for NVRTC
  808. namespace boost {
  809. namespace math {
  810. namespace policies {
  811. template <class T, class Policy>
  812. BOOST_MATH_GPU_ENABLED constexpr T raise_domain_error(
  813. const char* ,
  814. const char* ,
  815. const T& ,
  816. const Policy&) BOOST_MATH_NOEXCEPT(T)
  817. {
  818. // This may or may not do the right thing, but the user asked for the error
  819. // to be ignored so here we go anyway:
  820. return boost::math::numeric_limits<T>::quiet_NaN();
  821. }
  822. template <class T, class Policy>
  823. BOOST_MATH_GPU_ENABLED constexpr T raise_pole_error(
  824. const char* function,
  825. const char* message,
  826. const T& val,
  827. const Policy&) BOOST_MATH_NOEXCEPT(T)
  828. {
  829. return boost::math::numeric_limits<T>::quiet_NaN();
  830. }
  831. template <class T, class Policy>
  832. BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error(
  833. const char* ,
  834. const char* ,
  835. const Policy&) BOOST_MATH_NOEXCEPT(T)
  836. {
  837. // This may or may not do the right thing, but the user asked for the error
  838. // to be ignored so here we go anyway:
  839. return boost::math::numeric_limits<T>::has_infinity ? boost::math::numeric_limits<T>::infinity() : (boost::math::numeric_limits<T>::max)();
  840. }
  841. template <class T, class Policy>
  842. BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error(
  843. const char* ,
  844. const char* ,
  845. const T&,
  846. const Policy&) BOOST_MATH_NOEXCEPT(T)
  847. {
  848. // This may or may not do the right thing, but the user asked for the error
  849. // to be ignored so here we go anyway:
  850. return boost::math::numeric_limits<T>::has_infinity ? boost::math::numeric_limits<T>::infinity() : (boost::math::numeric_limits<T>::max)();
  851. }
  852. template <class T, class Policy>
  853. BOOST_MATH_GPU_ENABLED constexpr T raise_underflow_error(
  854. const char* ,
  855. const char* ,
  856. const Policy&) BOOST_MATH_NOEXCEPT(T)
  857. {
  858. // This may or may not do the right thing, but the user asked for the error
  859. // to be ignored so here we go anyway:
  860. return static_cast<T>(0);
  861. }
  862. template <class T, class Policy>
  863. BOOST_MATH_GPU_ENABLED inline constexpr T raise_denorm_error(
  864. const char* ,
  865. const char* ,
  866. const T& val,
  867. const Policy&) BOOST_MATH_NOEXCEPT(T)
  868. {
  869. // This may or may not do the right thing, but the user asked for the error
  870. // to be ignored so here we go anyway:
  871. return val;
  872. }
  873. template <class T, class Policy>
  874. BOOST_MATH_GPU_ENABLED constexpr T raise_evaluation_error(
  875. const char* ,
  876. const char* ,
  877. const T& val,
  878. const Policy&) BOOST_MATH_NOEXCEPT(T)
  879. {
  880. // This may or may not do the right thing, but the user asked for the error
  881. // to be ignored so here we go anyway:
  882. return val;
  883. }
  884. template <class T, class TargetType, class Policy>
  885. BOOST_MATH_GPU_ENABLED constexpr TargetType raise_rounding_error(
  886. const char* ,
  887. const char* ,
  888. const T& val,
  889. const TargetType&,
  890. const Policy&) BOOST_MATH_NOEXCEPT(T)
  891. {
  892. // This may or may not do the right thing, but the user asked for the error
  893. // to be ignored so here we go anyway:
  894. static_assert(boost::math::numeric_limits<TargetType>::is_specialized, "The target type must have std::numeric_limits specialized.");
  895. return val > 0 ? (boost::math::numeric_limits<TargetType>::max)() : (boost::math::numeric_limits<TargetType>::is_integer ? (boost::math::numeric_limits<TargetType>::min)() : -(boost::math::numeric_limits<TargetType>::max)());
  896. }
  897. template <class T, class R, class Policy>
  898. BOOST_MATH_GPU_ENABLED inline constexpr T raise_indeterminate_result_error(
  899. const char* ,
  900. const char* ,
  901. const T& ,
  902. const R& result,
  903. const Policy&) BOOST_MATH_NOEXCEPT(T)
  904. {
  905. // This may or may not do the right thing, but the user asked for the error
  906. // to be ignored so here we go anyway:
  907. return result;
  908. }
  909. template <class R, class Policy, class T>
  910. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE R checked_narrowing_cast(T val, const char* function) noexcept(boost::math::is_floating_point_v<R> && boost::math::is_floating_point_v<T>)
  911. {
  912. // We only have ignore error policy so no reason to check
  913. return static_cast<R>(val);
  914. }
  915. template <class T, class Policy>
  916. BOOST_MATH_GPU_ENABLED inline void check_series_iterations(const char* function, boost::math::uintmax_t max_iter, const Policy& pol) noexcept(boost::math::is_floating_point_v<T>)
  917. {
  918. if(max_iter >= policies::get_max_series_iterations<Policy>())
  919. raise_evaluation_error<T>(
  920. function,
  921. "Series evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
  922. }
  923. template <class T, class Policy>
  924. BOOST_MATH_GPU_ENABLED inline void check_root_iterations(const char* function, boost::math::uintmax_t max_iter, const Policy& pol) noexcept(boost::math::is_floating_point_v<T>)
  925. {
  926. if(max_iter >= policies::get_max_root_iterations<Policy>())
  927. raise_evaluation_error<T>(
  928. function,
  929. "Root finding evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
  930. }
  931. } // namespace policies
  932. } // namespace math
  933. } // namespace boost
  934. #endif // BOOST_MATH_HAS_NVRTC
  935. namespace boost { namespace math { namespace detail {
  936. //
  937. // Simple helper function to assist in returning a pair from a single value,
  938. // that value usually comes from one of the error handlers above:
  939. //
  940. template <class T>
  941. BOOST_MATH_GPU_ENABLED boost::math::pair<T, T> pair_from_single(const T& val) BOOST_MATH_NOEXCEPT(T)
  942. {
  943. return boost::math::make_pair(val, val);
  944. }
  945. }}} // boost::math::detail
  946. #endif // BOOST_MATH_POLICY_ERROR_HANDLING_HPP