]>
Commit | Line | Data |
---|---|---|
1 | [section:next_float Floating-Point Representation Distance (ULP), | |
2 | and Finding Adjacent Floating-Point Values] | |
3 | ||
4 | [@http://en.wikipedia.org/wiki/Unit_in_the_last_place Unit of Least Precision or Unit in the Last Place] | |
5 | is the gap between two different, but as close as possible, floating-point numbers. | |
6 | ||
7 | Most decimal values, for example 0.1, cannot be exactly represented as floating-point values, | |
8 | but will be stored as the | |
9 | [@http://en.wikipedia.org/wiki/Floating_point#Representable_numbers.2C_conversion_and_rounding | |
10 | closest representable floating-point]. | |
11 | ||
12 | Functions are provided for finding adjacent greater and lesser floating-point values, | |
13 | and estimating the number of gaps between any two floating-point values. | |
14 | ||
15 | The floating-point type (FPT) must have has a fixed number of bits in the representation. | |
16 | The number of bits may set at runtime, but must be the same for all numbers. | |
17 | For example, __NTL_quad_float type (fixed 128-bit representation), | |
18 | __NTL_RR type (arbitrary but fixed decimal digits, default 150) or | |
19 | __multiprecision __cpp_dec_float and__cpp_bin_float are fixed at runtime, | |
20 | but [*not] a type that extends the representation to provide an exact representation | |
21 | for any number, for example [@http://keithbriggs.info/xrc.html XRC eXact Real in C]. | |
22 | ||
23 | [section:nextafter Finding the Next Representable Value in a Specific Direction (nextafter)] | |
24 | ||
25 | [h4 Synopsis] | |
26 | ||
27 | `` | |
28 | #include <boost/math/special_functions/next.hpp> | |
29 | `` | |
30 | ||
31 | namespace boost{ namespace math{ | |
32 | ||
33 | template <class FPT> | |
34 | FPT nextafter(FPT val, FPT direction); | |
35 | ||
36 | }} // namespaces | |
37 | ||
38 | [h4 Description - nextafter] | |
39 | ||
40 | This is an implementation of the `nextafter` function included in the C99 standard. | |
41 | (It is also effectively an implementation of the C99 `nexttoward` legacy function | |
42 | which differs only having a `long double` direction, | |
43 | and can generally serve in its place if required). | |
44 | ||
45 | [note The C99 functions must use suffixes f and l to distinguish `float` and `long double` versions. | |
46 | C++ uses the template mechanism instead.] | |
47 | ||
48 | Returns the next representable value after /x/ in the direction of /y/. If | |
49 | `x == y` then returns /x/. If /x/ is non-finite then returns the result of | |
50 | a __domain_error. If there is no such value in the direction of /y/ then | |
51 | returns an __overflow_error. | |
52 | ||
53 | [warning The template parameter FTP must be a floating-point type. | |
54 | An integer type, for example, will produce an unhelpful error message.] | |
55 | ||
56 | [tip Nearly always, you just want the next or prior representable value, | |
57 | so instead use `float_next` or `float_prior` below.] | |
58 | ||
59 | [h4 Examples - nextafter] | |
60 | ||
61 | The two representations using a 32-bit float either side of unity are: | |
62 | `` | |
63 | The nearest (exact) representation of 1.F is 1.00000000 | |
64 | nextafter(1.F, 999) is 1.00000012 | |
65 | nextafter(1/f, -999) is 0.99999994 | |
66 | ||
67 | The nearest (not exact) representation of 0.1F is 0.100000001 | |
68 | nextafter(0.1F, 10) is 0.100000009 | |
69 | nextafter(0.1F, 10) is 0.099999994 | |
70 | `` | |
71 | ||
72 | [endsect] [/section:nextafter Finding the Next Representable Value in a Specific Direction (nextafter)] | |
73 | ||
74 | [section:float_next Finding the Next Greater Representable Value (float_next)] | |
75 | ||
76 | [h4 Synopsis] | |
77 | ||
78 | `` | |
79 | #include <boost/math/special_functions/next.hpp> | |
80 | `` | |
81 | ||
82 | namespace boost{ namespace math{ | |
83 | ||
84 | template <class FPT> | |
85 | FPT float_next(FPT val); | |
86 | ||
87 | }} // namespaces | |
88 | ||
89 | [h4 Description - float_next] | |
90 | ||
91 | Returns the next representable value which is greater than /x/. | |
92 | If /x/ is non-finite then returns the result of | |
93 | a __domain_error. If there is no such value greater than /x/ then | |
94 | returns an __overflow_error. | |
95 | ||
96 | Has the same effect as | |
97 | ||
98 | nextafter(val, (std::numeric_limits<FPT>::max)()); | |
99 | ||
100 | [endsect] [/section:float_next Finding the Next Greater Representable Value (float_prior)] | |
101 | ||
102 | [section:float_prior Finding the Next Smaller Representable Value (float_prior)] | |
103 | ||
104 | [h4 Synopsis] | |
105 | ||
106 | `` | |
107 | #include <boost/math/special_functions/next.hpp> | |
108 | `` | |
109 | ||
110 | namespace boost{ namespace math{ | |
111 | ||
112 | template <class FPT> | |
113 | FPT float_prior(FPT val); | |
114 | ||
115 | }} // namespaces | |
116 | ||
117 | ||
118 | [h4 Description - float_prior] | |
119 | ||
120 | Returns the next representable value which is less than /x/. | |
121 | If /x/ is non-finite then returns the result of | |
122 | a __domain_error. If there is no such value less than /x/ then | |
123 | returns an __overflow_error. | |
124 | ||
125 | Has the same effect as | |
126 | ||
127 | nextafter(val, -(std::numeric_limits<FPT>::max)()); // Note most negative value -max. | |
128 | ||
129 | [endsect] [/section:float_prior Finding the Next Smaller Representable Value (float_prior)] | |
130 | ||
131 | [section:float_distance Calculating the Representation Distance | |
132 | Between Two floating-point Values (ULP) float_distance] | |
133 | ||
134 | Function float_distance finds the number of gaps/bits/ULP between any two floating-point values. | |
135 | If the significands of floating-point numbers are viewed as integers, | |
136 | then their difference is the number of ULP/gaps/bits different. | |
137 | ||
138 | [h4 Synopsis] | |
139 | ||
140 | `` | |
141 | #include <boost/math/special_functions/next.hpp> | |
142 | `` | |
143 | ||
144 | namespace boost{ namespace math{ | |
145 | ||
146 | template <class FPT> | |
147 | FPT float_distance(FPT a, FPT b); | |
148 | ||
149 | }} // namespaces | |
150 | ||
151 | [h4 Description - float_distance] | |
152 | ||
153 | Returns the distance between /a/ and /b/: the result is always | |
154 | a signed integer value (stored in floating-point type FPT) | |
155 | representing the number of distinct representations between /a/ and /b/. | |
156 | ||
157 | Note that | |
158 | ||
159 | * `float_distance(a, a)` always returns 0. | |
160 | * `float_distance(float_next(a), a)` always returns -1. | |
161 | * `float_distance(float_prior(a), a)` always returns 1. | |
162 | ||
163 | The function `float_distance` is equivalent to calculating the number | |
164 | of ULP (Units in the Last Place) between /a/ and /b/ except that it | |
165 | returns a signed value indicating whether `a > b` or not. | |
166 | ||
167 | If the distance is too great then it may not be able | |
168 | to be represented as an exact integer by type FPT, | |
169 | but in practice this is unlikely to be a issue. | |
170 | ||
171 | [endsect] [/section:float_distance Calculating the Representation Distance | |
172 | Between Two floating-point Values (ULP) float_distance] | |
173 | ||
174 | [section:float_advance Advancing a floating-point Value by a Specific | |
175 | Representation Distance (ULP) float_advance] | |
176 | ||
177 | Function `float_advance` advances a floating-point number by a specified number | |
178 | of ULP. | |
179 | ||
180 | [h4 Synopsis] | |
181 | ||
182 | `` | |
183 | #include <boost/math/special_functions/next.hpp> | |
184 | `` | |
185 | ||
186 | namespace boost{ namespace math{ | |
187 | ||
188 | template <class FPT> | |
189 | FPT float_advance(FPT val, int distance); | |
190 | ||
191 | }} // namespaces | |
192 | ||
193 | [h4 Description - float_advance] | |
194 | ||
195 | Returns a floating-point number /r/ such that `float_distance(val, r) == distance`. | |
196 | ||
197 | [endsect] [/section:float_advance] | |
198 | ||
199 | [section:ulp Obtaining the Size of a Unit In the Last Place - ULP] | |
200 | ||
201 | Function `ulp` gives the size of a unit-in-the-last-place for a specified floating-point value. | |
202 | ||
203 | [h4 Synopsis] | |
204 | ||
205 | `` | |
206 | #include <boost/math/special_functions/ulp.hpp> | |
207 | `` | |
208 | ||
209 | namespace boost{ namespace math{ | |
210 | ||
211 | template <class FPT> | |
212 | FPT ulp(const FPT& x); | |
213 | ||
214 | template <class FPT, class Policy> | |
215 | FPT ulp(const FPT& x, const Policy&); | |
216 | ||
217 | }} // namespaces | |
218 | ||
219 | [h4 Description - ulp] | |
220 | ||
221 | Returns one [@http://en.wikipedia.org/wiki/Unit_in_the_last_place unit in the last place] of ['x]. | |
222 | ||
223 | Corner cases are handled as followes: | |
224 | ||
225 | * If the argument is a NaN, then raises a __domain_error. | |
226 | * If the argument is an infinity, then raises an __overflow_error. | |
227 | * If the argument is zero then returns the smallest representable value: for example for type | |
228 | `double` this would be either `std::numeric_limits<double>::min()` or `std::numeric_limits<double>::denorm_min()` | |
229 | depending whether denormals are supported (which have the values 2.`2250738585072014e-308` and `4.9406564584124654e-324` respectively). | |
230 | * If the result is too small to represent, then returns the smallest representable value. | |
231 | * Always returns a positive value such that `ulp(x) == ulp(-x)`. | |
232 | ||
233 | [*Important:] The behavior of this function is aligned to that of [@http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html#ulp%28double%29 | |
234 | Java's ulp function], please note | |
235 | however that this function should only ever be used for rough and ready calculations as there are enough | |
236 | corner cases to trap even careful programmers. In particular: | |
237 | ||
238 | * The function is asymetrical, which is to say, given `u = ulp(x)` if `x > 0` then `x + u` is the | |
239 | next floating-point value, but `x - u` is not necessarily the previous value. Similarly, if | |
240 | `x < 0` then `x - u` is the previous floating-point value, but `x + u` is not necessarily the next | |
241 | value. The corner cases occur at power of 2 boundaries. | |
242 | * When the argument becomes very small, it may be that there is no floating-point value that | |
243 | represents one ULP. Whether this is the case or not depends not only on whether the hardware | |
244 | may ['sometimes] support denormals (as signalled by `std::numeric_limits<FPT>::has_denorm`), but also whether these are | |
245 | currently enabled at runtime (for example on SSE hardware, the DAZ or FTZ flags will disable denormal support). | |
246 | In this situation, the `ulp` function may return a value that is many orders of magnitude too large. | |
247 | ||
248 | In light of the issues above, we recomend that: | |
249 | ||
250 | * To move between adjacent floating-point values always use __float_next, __float_prior or __nextafter (`std::nextafter` | |
251 | is another candidate, but our experience is that this also often breaks depending which optimizations and | |
252 | hardware flags are in effect). | |
253 | * To move several floating-point values away use __float_advance. | |
254 | * To calculate the edit distance between two floats use __float_distance. | |
255 | ||
256 | There is none the less, one important use case for this function: | |
257 | ||
258 | If it is known that the true result of some function is x[sub t] and the calculated result | |
259 | is x[sub c], then the error measured in ulp is simply [^fabs(x[sub t] - x[sub c]) / ulp(x[sub t])]. | |
260 | ||
261 | [endsect] [/section ulp] | |
262 | ||
263 | [endsect] [/ section:next_float Floating-Point Representation Distance (ULP), | |
264 | and Finding Adjacent Floating-Point Values] | |
265 | ||
266 | [/ | |
267 | Copyright 2008 John Maddock and Paul A. Bristow. | |
268 | Distributed under the Boost Software License, Version 1.0. | |
269 | (See accompanying file LICENSE_1_0.txt or copy at | |
270 | http://www.boost.org/LICENSE_1_0.txt). | |
271 | ] | |
272 |