policy_eg_8.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // Copyright John Maddock 2007.
  2. // Copyright Paul a. Bristow 2010
  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. // Note that this file contains quickbook mark-up as well as code
  7. // and comments, don't change any of the special comment mark-ups!
  8. #ifdef _MSC_VER
  9. # pragma warning (disable : 4100) // unreferenced formal parameters
  10. #endif
  11. #include <iostream>
  12. using std::cout; using std::endl; using std::cerr;
  13. //[policy_eg_8
  14. /*`
  15. Suppose we want our own user-defined error handlers rather than the
  16. any of the default ones supplied by the library to be used.
  17. If we set the policy for a specific type of error to `user_error`
  18. then the library will call a user-supplied error handler.
  19. These are forward declared, but not defined in
  20. boost/math/policies/error_handling.hpp like this:
  21. namespace boost{ namespace math{ namespace policies{
  22. template <class T>
  23. T user_domain_error(const char* function, const char* message, const T& val);
  24. template <class T>
  25. T user_pole_error(const char* function, const char* message, const T& val);
  26. template <class T>
  27. T user_overflow_error(const char* function, const char* message, const T& val);
  28. template <class T>
  29. T user_underflow_error(const char* function, const char* message, const T& val);
  30. template <class T>
  31. T user_denorm_error(const char* function, const char* message, const T& val);
  32. template <class T>
  33. T user_evaluation_error(const char* function, const char* message, const T& val);
  34. template <class T, class TargetType>
  35. T user_rounding_error(const char* function, const char* message, const T& val, const TargetType& t);
  36. template <class T>
  37. T user_indeterminate_result_error(const char* function, const char* message, const T& val);
  38. }}} // namespaces
  39. So out first job is to include the header we want to use, and then
  40. provide definitions for our user-defined error handlers that we want to use.
  41. We only provide our special domain and pole error handlers;
  42. other errors like overflow and underflow use the default.
  43. */
  44. #include <boost/math/special_functions.hpp>
  45. namespace boost{ namespace math
  46. {
  47. namespace policies
  48. {
  49. template <class T>
  50. T user_domain_error(const char* function, const char* message, const T& val)
  51. { // Ignoring function, message and val for this example, perhaps unhelpfully.
  52. cerr << "Domain Error!" << endl;
  53. return std::numeric_limits<T>::quiet_NaN();
  54. }
  55. template <class T>
  56. T user_pole_error(const char* function, const char* message, const T& val)
  57. { // Ignoring function, message and val for this example, perhaps unhelpfully.
  58. cerr << "Pole Error!" << endl;
  59. return std::numeric_limits<T>::quiet_NaN();
  60. }
  61. } // namespace policies
  62. }} // namespace boost{ namespace math
  63. /*`
  64. Now we'll need to define a suitable policy that will call these handlers,
  65. and define some forwarding functions that make use of the policy:
  66. */
  67. namespace mymath{
  68. using namespace boost::math::policies;
  69. typedef policy<
  70. domain_error<user_error>,
  71. pole_error<user_error>
  72. > user_error_policy;
  73. BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(user_error_policy)
  74. } // close unnamed namespace
  75. /*`
  76. We now have a set of forwarding functions defined in namespace mymath
  77. that all look something like this:
  78. ``
  79. template <class RealType>
  80. inline typename boost::math::tools::promote_args<RT>::type
  81. tgamma(RT z)
  82. {
  83. return boost::math::tgamma(z, user_error_policy());
  84. }
  85. ``
  86. So that when we call `mymath::tgamma(z)` we really end up calling
  87. `boost::math::tgamma(z, user_error_policy())`, and any
  88. errors will get directed to our own error handlers.
  89. */
  90. int main()
  91. {
  92. cout << "Result of erf_inv(-10) is: "
  93. << mymath::erf_inv(-10) << endl;
  94. cout << "Result of tgamma(-10) is: "
  95. << mymath::tgamma(-10) << endl;
  96. }
  97. /*`
  98. Which outputs:
  99. [pre
  100. Domain Error!
  101. Pole Error!
  102. Result of erf_inv(-10) is: 1.#QNAN
  103. Result of tgamma(-10) is: 1.#QNAN
  104. ]
  105. */
  106. //] // //[/policy_eg_8]