error_handling.hpp 32 KB

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