1 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
---|
2 | "http://www.w3.org/TR/html4/loose.dtd"> |
---|
3 | <html> |
---|
4 | <head> |
---|
5 | <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
---|
6 | <link rel="stylesheet" type="text/css" href="../../../../boost.css"> |
---|
7 | <title>Checking policies</title> |
---|
8 | </head> |
---|
9 | |
---|
10 | <body> |
---|
11 | <h1>Checking policies</h1> |
---|
12 | |
---|
13 | <p>A checking policy controls how the <code>interval</code> class will deal |
---|
14 | with special cases like: empty intervals, infinite numbers, invalid |
---|
15 | values.</p> |
---|
16 | |
---|
17 | <p>For example, let's consider <code>operator+(interval, T)</code>. The |
---|
18 | second argument could be an invalid value (for a floating-point number, it is |
---|
19 | a NaN). What to do in such a case? First, we could say that the second |
---|
20 | argument can never be an invalid number. Second, we could also say such a |
---|
21 | situation can arise but is forbidden. Third, we could allow such values and |
---|
22 | generate an empty interval when encountered. And there is many other |
---|
23 | possibilities.</p> |
---|
24 | |
---|
25 | <p>It is the reason why such a policy is used: there is a lot of interesting |
---|
26 | behaviors and it would be sad to arbitrarily select one of these.</p> |
---|
27 | |
---|
28 | <h2>Requirements</h2> |
---|
29 | |
---|
30 | <p>The checking class should satisfy the following requirement (in the form |
---|
31 | of an interface):</p> |
---|
32 | <pre>/* requirements for checking policy */ |
---|
33 | struct checking |
---|
34 | { |
---|
35 | static T pos_inf(); |
---|
36 | static T neg_inf(); |
---|
37 | static T nan(); |
---|
38 | static bool is_nan(const T&); |
---|
39 | static T empty_lower(); |
---|
40 | static T empty_upper(); |
---|
41 | static bool is_empty(const T&, const T&); |
---|
42 | };</pre> |
---|
43 | |
---|
44 | <p>The first two functions, <code>pos_inf</code> and <code>neg_inf</code>, |
---|
45 | are invoked each time the library has to create the infinite bound of an |
---|
46 | interval. For example, <code>interval::whole</code> computes |
---|
47 | <code>interval(checking::neg_inf(), checking::pos_inf())</code>. If infinite |
---|
48 | values are allowed and <code>std::numeric_limits<T>::infinity()</code> |
---|
49 | returns a correct value, such a value can be used.</p> |
---|
50 | |
---|
51 | <p>Next comes <code>nan</code>. This function is used each time a function |
---|
52 | need to return a value of type <code>T</code> but is unable to compute it. It |
---|
53 | only happens when one of the arguments of the function is invalid. For |
---|
54 | example, if you ask what the median value of an empty interval is, |
---|
55 | <code>nan</code> will be used. But please remember: <code>lower</code> and |
---|
56 | <code>upper</code> directly return the value stocked in the interval; so, if |
---|
57 | the interval is empty, <code>lower</code> will not answer <code>by</code> a |
---|
58 | call to <code>checking::nan</code> (but will return the same value than |
---|
59 | <code>checking::empty_lower</code> could return).</p> |
---|
60 | |
---|
61 | <p><code>empty_lower</code> and <code>empty_upper</code> respectively return |
---|
62 | the lower and upper bound of the empty interval. There is no requirements for |
---|
63 | <code>empty_lower</code> and <code>empty_upper</code> to return the same |
---|
64 | value than <code>checking::nan</code>. For example, if the type |
---|
65 | <code>T</code> does not have any invalid value, the <code>empty_</code> |
---|
66 | functions can return the [1;0] interval.</p> |
---|
67 | |
---|
68 | <p><code>is_nan</code> is used to test if a value of type <code>T</code> is |
---|
69 | invalid or not. <code>is_empty</code> tests if the interval formed by the two |
---|
70 | arguments is empty or not. Such tests will generally be at the beginning of |
---|
71 | each function which involves an argument of type <code>T</code>. If one of |
---|
72 | the inputs is declared invalid, the the function will try to produce an |
---|
73 | invalid value or an input interval.</p> |
---|
74 | |
---|
75 | <h2>Synopsis</h2> |
---|
76 | <pre>namespace boost { |
---|
77 | namespace numeric { |
---|
78 | namespace interval_lib { |
---|
79 | |
---|
80 | template<class T> |
---|
81 | struct checking_base; |
---|
82 | template<class T, class Checking = checking_base<T>, class Exception = exception_create_empty<T> > |
---|
83 | struct checking_no_empty; |
---|
84 | template<class T, class Checking = checking_base<T> > |
---|
85 | struct checking_no_nan; |
---|
86 | template<class T, class Checking = checking_base<T>, class Exception = exception_invalid_number<T> > |
---|
87 | struct checking_catch_nan; |
---|
88 | |
---|
89 | template<class T> struct exception_create_empty { T operator()(); }; |
---|
90 | template<class T> struct exception_invalid_number { void operator()(); }; |
---|
91 | |
---|
92 | } // namespace numeric |
---|
93 | } // namespace interval_lib |
---|
94 | } // namespace boost</pre> |
---|
95 | |
---|
96 | <h2>Predefined classes</h2> |
---|
97 | |
---|
98 | <p>In order to simplify the customization of the policy, some templates are |
---|
99 | already defined in the library.</p> |
---|
100 | |
---|
101 | <p>First of all, there is <code>checking_base</code>. Thanks to the |
---|
102 | information provided by <code>std::numeric_limits<T></code>, this class |
---|
103 | is able to generate a base for the policy. If <code>T</code> has quiet NaNs |
---|
104 | (as said by <code>numeric_limits::has_quiet_NaN</code>), then the value is |
---|
105 | used for <code>nan</code>, <code>empty_lower</code>, |
---|
106 | <code>empty_upper</code>; and a basic test is used for <code>is_nan</code> |
---|
107 | (it is <code>x!=x</code>). If <code>T</code> does not have quiet NaNs, then |
---|
108 | <code>nan</code> is an <code>assert(false)</code>, the empty interval is |
---|
109 | [1,0], and <code>is_nan</code> always return <code>false</code>. As for |
---|
110 | <code>nan</code>, <code>pos_inf</code> returns |
---|
111 | <code>numeric_limits::infinity()</code> if possible, or is an |
---|
112 | <code>assert(false</code>) otherwise. <code>neg_inf</code> returns the |
---|
113 | opposite. Finally, <code>is_empty(T l,T u)</code> is always defined by |
---|
114 | <code>!(l<=u)</code>.</p> |
---|
115 | |
---|
116 | <p>Next comes <code>checking_no_empty</code>. Using it means that each time |
---|
117 | an empty interval should be produced (by <code>empty_lower</code> and |
---|
118 | <code>empty_upper</code>), the function object given by the |
---|
119 | <code>Exception</code> argument of the template is invoked and the value it |
---|
120 | returns is propagated. So, if <code>Exception</code> is appropriately defined |
---|
121 | (for example it could throw an exception, hence the name of the argument), |
---|
122 | you can be sure no empty interval will ever be created. So |
---|
123 | <code>is_empty</code> will always return <code>false</code> (since there is |
---|
124 | no need to test for an empty interval). And as explained before, in that case |
---|
125 | we can also replace <code>nan</code> by an <code>assert(false)</code>; you |
---|
126 | will be sure no invalid number will ever be produced. If this template is not |
---|
127 | used, it implicitly means that all the functions can produce empty intervals |
---|
128 | and they correctly deal with empty interval arguments.</p> |
---|
129 | |
---|
130 | <p>Finally there are <code>checking_no_nan</code> and |
---|
131 | <code>checking_catch_nan</code>. The first one expresses the functions of the |
---|
132 | library will never get an invalid number as argument. So <code>is_nan</code> |
---|
133 | will only return <code>false</code>. The other one means the arguments can be |
---|
134 | an invalid number but in that case, <code>is_nan</code> will call the |
---|
135 | function object <code>Exception</code> and return <code>false</code>. Indeed, |
---|
136 | this template means invalid numbers should never make their way through to |
---|
137 | the body of the function. If none of this two templates is used, it |
---|
138 | implicitly means that all the functions can get invalid number arguments and |
---|
139 | they will correctly deal with them.</p> |
---|
140 | |
---|
141 | <p><code>exception_create_empty</code> throws <code>std::runtime_error</code> |
---|
142 | with the message <code>"boost::interval: empty interval created"</code> and |
---|
143 | <code>exception_invalid_number</code> throws |
---|
144 | <code>std::invalid_argument</code> with the message <code>"boost::interval: |
---|
145 | invalid number"</code>.</p> |
---|
146 | |
---|
147 | <h2>Customizing your own checking policy</h2> |
---|
148 | |
---|
149 | <p>In order to define a suitable policy, you need to correctly say what you |
---|
150 | expect from your interval class. First of all, are you interested in getting |
---|
151 | empty intervals at the end of a calculus? If you do not want to obtain empty |
---|
152 | intervals, <code>empty_lower</code> and <code>empty_upper</code> have to fail |
---|
153 | when invoked (they can throw an exception, set a flag, etc). However, if no |
---|
154 | function is able to produce an empty interval, it is no more necessary to do |
---|
155 | the test, so <code>is_empty</code> may always return <code>false</code>. In |
---|
156 | this case, a good compiler will do a lot of optimizations.</p> |
---|
157 | |
---|
158 | <p>You could also be interested in getting empty intervals at the end of the |
---|
159 | calculus. For example, if you need to transform an array of unsure values (or |
---|
160 | intervals) in a new array of intervals, you may not want to stop the |
---|
161 | conversion at the first encountered problem. So <code>empty_lower</code> and |
---|
162 | <code>empty_upper</code> need to return suitable values in order to define an |
---|
163 | empty interval (you can use an upper bound which is not greater or equal than |
---|
164 | the lower bound for example); and <code>is_empty</code> must be able to |
---|
165 | distinguish empty intervals from the valid intervals.</p> |
---|
166 | |
---|
167 | <p>Another important question is: is it possible that some base numbers |
---|
168 | (objects of type <code>T</code>) are invalid? And if it is possible, are they |
---|
169 | allowed or not ? If it is not possible, no test is necessary; |
---|
170 | <code>is_nan</code> may always return <code>false</code>. In this case too, a |
---|
171 | good compiler will do a lot of optimizations. If function arguments can hold |
---|
172 | invalid numbers, two cases must be considered according to whether they are |
---|
173 | allowed or not. If they are allowed, <code>is_nan</code> just has to test if |
---|
174 | they are invalid or not. If they are forbidden, <code>is_nan</code> should |
---|
175 | fail (exception, assert, etc.) when invoked on an invalid argument and return |
---|
176 | <code>false</code> otherwise. The value returned by <code>nan</code> does not |
---|
177 | have any interest since the interval functions are guaranteed not to produce |
---|
178 | invalid interval bounds unless the user passes invalid numbers to the |
---|
179 | constructors. So you can put an assert inside if you do not trust the |
---|
180 | library. :-)</p> |
---|
181 | |
---|
182 | <p>And finally, you need to decide what to do with <code>nan</code> if it has |
---|
183 | not already been decided at the beginning, and with <code>pos_inf</code> and |
---|
184 | <code>neg_inf</code>. These functions should return a value or start an |
---|
185 | exceptional behavior (especially if the base type does not have corresponding |
---|
186 | values).</p> |
---|
187 | |
---|
188 | <h2>Some examples</h2> |
---|
189 | <ul> |
---|
190 | <li>If you need a checking policy that allows the library to correctly |
---|
191 | manipulate data, even if they contain invalid numbers and empty |
---|
192 | intervals, then <code>checking_base<T></code> is a possibility.</li> |
---|
193 | <li>If you do not want empty intervals to be created and are not sure all |
---|
194 | the numbers are valid, then <code>checking_catch_nan<T, |
---|
195 | checking_no_empty<T> ></code> can help you.</li> |
---|
196 | <li>If all the numbers will be valid and if no empty interval is supposed |
---|
197 | to be created (or if you do not want them to be created), then you can |
---|
198 | use <code>checking_no_nan<T, checking_no_empty<T> ></code>. |
---|
199 | Please note that if <code>T</code> does not have a way to represent |
---|
200 | invalid numbers, then this policy will behave the same way as |
---|
201 | <code>checking_no_empty<T></code>. This is the default policy and |
---|
202 | it is also called <code>interval_lib::checking_strict</code>.</li> |
---|
203 | <li>If all numerical data are valid but the algorithm can produce and |
---|
204 | manipulate empty intervals, then <code>checking_no_nan<T></code> |
---|
205 | should be used.</li> |
---|
206 | <li>Similarly, if invalid data have to be signaled and the algorithm can |
---|
207 | manipulate empty intervals, the <code>checking_catch_nan<T></code> |
---|
208 | is a solution.</li> |
---|
209 | <li>If you do not mind having undefined results when an empty interval or |
---|
210 | an interval number is produced, your best bet is to create your own |
---|
211 | policy by overloading <code>checking_base</code> and modifying |
---|
212 | <code>is_nan</code> et <code>is_empty</code> in order for them to always |
---|
213 | return <code>false</code>. It is probably the fastest checking policy |
---|
214 | available; however, it suffers from its deficient security.</li> |
---|
215 | </ul> |
---|
216 | <hr> |
---|
217 | |
---|
218 | <p>Revised: 2004-02-16<br> |
---|
219 | Copyright (c) Guillaume Melquiond, Sylvain Pion, Hervé Brönnimann, 2002. |
---|
220 | Polytechnic University.<br> |
---|
221 | Copyright (c) Guillaume Melquiond, 2003-2004.</p> |
---|
222 | </body> |
---|
223 | </html> |
---|