error_handling.hpp 25 KB

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