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