summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/math/example/policy_eg_8.cpp
blob: 775f042e250d1f609e9e93a924d19c3b71e8e8e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//  Copyright John Maddock 2007.
//  Copyright Paul a. Bristow 2010
//  Use, modification and distribution are subject to the
//  Boost Software License, Version 1.0. (See accompanying file
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!

#ifdef _MSC_VER
# pragma warning (disable : 4100) // unreferenced formal parameters
#endif

#include <iostream>
using std::cout;  using std::endl; using std::cerr;

//[policy_eg_8

/*`
Suppose we want our own user-defined error handlers rather than the
any of the default ones supplied by the library to be used.
If we set the policy for a specific type of error to `user_error`
then the library will call a user-supplied error handler.
These are forward declared, but not defined in
boost/math/policies/error_handling.hpp like this:

   namespace boost{ namespace math{ namespace policies{

   template <class T>
   T user_domain_error(const char* function, const char* message, const T& val);
   template <class T>
   T user_pole_error(const char* function, const char* message, const T& val);
   template <class T>
   T user_overflow_error(const char* function, const char* message, const T& val);
   template <class T>
   T user_underflow_error(const char* function, const char* message, const T& val);
   template <class T>
   T user_denorm_error(const char* function, const char* message, const T& val);
   template <class T>
   T user_evaluation_error(const char* function, const char* message, const T& val);
   template <class T, class TargetType>
   T user_rounding_error(const char* function, const char* message, const T& val, const TargetType& t);
   template <class T>
   T user_indeterminate_result_error(const char* function, const char* message, const T& val);

   }}} // namespaces

So out first job is to include the header we want to use, and then
provide definitions for our user-defined error handlers that we want to use.
We only provide our special domain and pole error handlers;
other errors like overflow and underflow use the default.
*/

#include <boost/math/special_functions.hpp>

namespace boost{ namespace math
{
  namespace policies
  {
    template <class T>
    T user_domain_error(const char* function, const char* message, const T& val)
    { // Ignoring function, message and val for this example, perhaps unhelpfully.
       cerr << "Domain Error!" << endl;
       return std::numeric_limits<T>::quiet_NaN();
    }

    template <class T>
    T user_pole_error(const char* function, const char* message, const T& val)
    { // Ignoring function, message and val for this example, perhaps unhelpfully.
       cerr << "Pole Error!" << endl;
       return std::numeric_limits<T>::quiet_NaN();
    }
  } // namespace policies
}} // namespace boost{ namespace math


/*`
Now we'll need to define a suitable policy that will call these handlers,
and define some forwarding functions that make use of the policy:
*/

namespace mymath{

using namespace boost::math::policies;

typedef policy<
   domain_error<user_error>,
   pole_error<user_error>
> user_error_policy;

BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(user_error_policy)

} // close unnamed namespace

/*`
We now have a set of forwarding functions defined in namespace mymath
that all look something like this:

``
template <class RealType>
inline typename boost::math::tools::promote_args<RT>::type
   tgamma(RT z)
{
   return boost::math::tgamma(z, user_error_policy());
}
``

So that when we call `mymath::tgamma(z)` we really end up calling
`boost::math::tgamma(z, user_error_policy())`, and any
errors will get directed to our own error handlers.
*/

int main()
{
   cout << "Result of erf_inv(-10) is: "
      << mymath::erf_inv(-10) << endl;
   cout << "Result of tgamma(-10) is: "
      << mymath::tgamma(-10) << endl;
}

/*`

Which outputs:

[pre
  Domain Error!
  Pole Error!
  Result of erf_inv(-10) is: 1.#QNAN
  Result of tgamma(-10) is: 1.#QNAN
]
*/

//] // //[/policy_eg_8]