error_handling.hpp 31 KB

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