error_handling.hpp 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058
  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