checking.htm 12 KB

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