BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlb_float.h
Go to the documentation of this file.
1/// @file bdlb_float.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlb_float.h -*-C++-*-
8#ifndef INCLUDED_BDLB_FLOAT
9#define INCLUDED_BDLB_FLOAT
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlb_float bdlb_float
15/// @brief Provide floating-point classification types and functions.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlb
19/// @{
20/// @addtogroup bdlb_float
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlb_float-purpose"> Purpose</a>
25/// * <a href="#bdlb_float-classes"> Classes </a>
26/// * <a href="#bdlb_float-description"> Description </a>
27/// * <a href="#bdlb_float-classification-of-floating-point-numbers"> Classification of Floating-Point Numbers </a>
28/// * <a href="#bdlb_float-future-enhancements"> Future Enhancements </a>
29/// * <a href="#bdlb_float-thread-safety"> Thread Safety </a>
30/// * <a href="#bdlb_float-usage"> Usage </a>
31/// * <a href="#bdlb_float-example-1-basic-syntax"> Example 1: Basic Syntax </a>
32///
33/// # Purpose {#bdlb_float-purpose}
34/// Provide floating-point classification types and functions.
35///
36/// # Classes {#bdlb_float-classes}
37///
38/// - bdlb::Float: namespace for floating-point classification types and functions
39///
40/// # Description {#bdlb_float-description}
41/// This component defines a utility `struct`, `bdlb::Float`, that
42/// provides functions analogous to C99 `<math.h>` library macros such as
43/// `isinf` and `isnan` that return whether a `float` or `double` value is
44/// infinite or not-a-number, respectively. These macros are not available in
45/// C++98 and so are provided as functions in this component.
46///
47/// ## Classification of Floating-Point Numbers {#bdlb_float-classification-of-floating-point-numbers}
48///
49///
50/// Floating-point numbers are used to represent a subset of the set of real
51/// numbers. The C++ `float` and `double` types are used to hold floating-point
52/// numbers, with `float` having (much) less precision than `double`. Floating
53/// point numbers can be classified into the following disjoint sets:
54/// @code
55/// Zero positive and negative zero
56/// Normal full-precision, non-zero, normal numbers
57/// Subnormal reduced-precision numbers with small absolute values
58/// Infinity positive and negative infinities
59/// NaN not a number
60/// @endcode
61/// A NaN value can be further classified into two disjoint subsets:
62/// @code
63/// Signaling NaN invalid values that raises a signal in computations
64/// Quiet NaN indeterminate values that propagate through computations
65/// @endcode
66/// Note that not all platforms support signaling NaNs and that even those that
67/// do often require a specific action to enable signals on floating-point
68/// traps. Signaling NaNs are never the result of a normal floating-point
69/// operation. They are most often used as sentinels to detect the use of a
70/// value that has not yet been computed.
71///
72/// Quiet NaNs are the result of certain operations where the result is not
73/// defined mathematically. If an expression that results in a (quiet) NaN is
74/// used in a subsequent computation, the result is usually also a (quiet) NaN.
75///
76/// On platforms that implement the IEEE 754 standard for floating-point
77/// arithmetic, the following conditions result in non-normal floating-point
78/// values. In the following table, "NaN" always refers to a quiet NaN:
79/// @code
80/// Condition Result
81/// ------------------- -----------------
82/// Overflow Infinity
83/// Underflow Subnormal or Zero
84/// Normal / Infinity Zero
85/// Infinity * Infinity Infinity
86/// nonzero / Zero Infinity
87/// Infinity + Infinity Infinity
88/// Zero / Zero NaN
89/// Infinity - Infinity NaN
90/// Infinity / Infinity NaN
91/// Infinity * Zero NaN
92/// @endcode
93/// Note that the operations that result in Infinity follow the normal rules for
94/// sign propagation, e.g., -5.0 / 0.0 results in negative Infinity.
95///
96/// ## Future Enhancements {#bdlb_float-future-enhancements}
97///
98///
99/// At present, this component works with `float` and `double` numbers. In the
100/// future, it will also work with `long double`. Note that casting a
101/// `long double` to `double` before applying these classification functions
102/// will not always yield correct results. For example, a large `long double`
103/// may get demoted to an infinite `double`. Similarly, a small `long double`
104/// may get demoted to a subnormal or zero `double`.
105///
106/// ## Thread Safety {#bdlb_float-thread-safety}
107///
108///
109/// Any of the functions in this component may safely be called simultaneously
110/// from multiple threads, even with the same arguments.
111///
112/// ## Usage {#bdlb_float-usage}
113///
114///
115/// This section illustrates intended use of this component.
116///
117/// ### Example 1: Basic Syntax {#bdlb_float-example-1-basic-syntax}
118///
119///
120/// On platforms that implement the IEEE 754 standard for floating-point
121/// arithmetic, dividing a positive number by zero yields positive infinity and
122/// dividing a negative number by zero yields negative infinity. The result of
123/// division by zero will therefore be detected as infinite by the `isInfinite`
124/// method and classified as infinity by the `classify` and `classifyFine`
125/// methods in this component:
126/// @code
127/// double zero = 0.0;
128/// double a = 2.3 / zero;
129/// double b = -0.55 / zero;
130/// assert(true == bdlb::Float::isZero(zero));
131/// assert(true == bdlb::Float::isInfinite(a));
132/// assert(true == bdlb::Float::isInfinite(b));
133/// assert(bdlb::Float::k_ZERO == bdlb::Float::classify(zero));
134/// assert(bdlb::Float::k_INFINITE == bdlb::Float::classify(a));
135/// assert(bdlb::Float::k_INFINITE == bdlb::Float::classify(b));
136/// assert(bdlb::Float::k_POSITIVE_INFINITY == bdlb::Float::classifyFine(a));
137/// assert(bdlb::Float::k_NEGATIVE_INFINITY == bdlb::Float::classifyFine(b));
138/// @endcode
139/// Note that the sign rules apply as usual:
140/// @code
141/// double nzero = -0.0;
142/// double bn = -0.55 / nzero;
143/// assert(bdlb::Float::k_POSITIVE_INFINITY == bdlb::Float::classifyFine(bn));
144/// @endcode
145/// The result of multiplying infinity by infinity is also infinity, but the
146/// result of multiplying infinity by zero is an indeterminate value (quiet
147/// NaN):
148/// @code
149/// double c = a * b;
150/// double d = a * zero;
151/// assert(true == bdlb::Float::isInfinite(c));
152/// assert(false == bdlb::Float::isInfinite(d));
153/// assert(true == bdlb::Float::isNan(d));
154/// assert(true == bdlb::Float::isQuietNan(d));
155/// assert(false == bdlb::Float::isSignalingNan(d));
156/// @endcode
157/// Quiet NaNs propagate such that further calculations also yield quiet NaNs:
158/// @code
159/// double g = d - 3.4e12;
160/// assert(false == bdlb::Float::isInfinite(g));
161/// assert(true == bdlb::Float::isNan(g));
162/// assert(true == bdlb::Float::isQuietNan(g));
163/// @endcode
164/// We can also detect whether a value has full precision (normal) or is so
165/// small (close to zero) that precision has been lost (subnormal):
166/// @code
167/// double e = -10.0 / 11.0; // Full precision
168/// double f = e / DBL_MAX; // Lost precision
169/// assert(true == bdlb::Float::isNormal(e));
170/// assert(false == bdlb::Float::isSubnormal(e));
171/// assert(false == bdlb::Float::isNormal(f));
172/// assert(true == bdlb::Float::isSubnormal(f));
173/// assert(bdlb::Float::k_NORMAL == bdlb::Float::classify(e));
174/// assert(bdlb::Float::k_SUBNORMAL == bdlb::Float::classify(f));
175/// @endcode
176/// The `Classification` enumeration type is designed so that each
177/// classification occupies a separate bit. This makes it easy to test for
178/// multiple classifications in one test. For example, if we are interested in
179/// very that zero or denormalized (i.e., very small), we can detect both
180/// conditions with a single mask:
181/// @code
182/// const int SMALL_MASK = bdlb::Float::k_ZERO | bdlb::Float::k_SUBNORMAL;
183/// assert(0 != (SMALL_MASK & bdlb::Float::classify(0.0)));
184/// assert(0 != (SMALL_MASK & bdlb::Float::classify(f)));
185/// assert(0 == (SMALL_MASK & bdlb::Float::classify(e)));
186/// @endcode
187/// Note, however, that although we can create a mask with several
188/// classification bits, a single number belongs to only one classification and
189/// the return value of `classify` will have only one bit set at a time.
190/// @}
191/** @} */
192/** @} */
193
194/** @addtogroup bdl
195 * @{
196 */
197/** @addtogroup bdlb
198 * @{
199 */
200/** @addtogroup bdlb_float
201 * @{
202 */
203
204#include <bdlscm_version.h>
205
206
207namespace bdlb {
208
209 // ============
210 // struct Float
211 // ============
212
213/// Namespace for floating-point classification types and functions.
214struct Float {
215
216 // TYPES
217
218 /// Basic classifications for floating-point numbers. Every
219 /// floating-point number belongs to exactly one of these
220 /// classifications. However, the enumerated values have disjoint
221 /// bit-patterns to make it easy to create a "set" of classifications
222 /// using bit-wise OR.
224 k_ZERO = 0x01, // positive or negative zero
225 k_NORMAL = 0x02, // full-precision, non-zero, normal number
226 k_SUBNORMAL = 0x04, // reduced-precision numb with a small abs value
227 k_INFINITE = 0x08, // positive or negative infinity
228 k_NAN = 0x10 // not a number
229#ifndef BDE_OMIT_INTERNAL_DEPRECATED
235#endif // BDE_OMIT_INTERNAL_DEPRECATED
236 };
237
238 /// Fine-grained classifications for floating-point numbers that
239 /// distinguish positive numbers from negative numbers and quiet NaNs
240 /// from signaling NaNs. Every floating-point number belongs to exactly
241 /// one of these classifications.
271
272 // CLASS METHODS
273
274 static Classification classify(float number);
275 /// Return the coarse classification (`k_ZERO`, `k_NORMAL`,
276 /// `k_SUBNORMAL`, `k_INFINITE`, or 'k_NAN) for the specified floating
277 /// point `number`. This function has the same functionality as the
278 /// `fpclassify` macro in C99.
279 static Classification classify(double number);
280
281 static FineClassification classifyFine(float number);
282 /// Return the fine-grained classification for the specified floating
283 /// point `number`. For positive numbers and quiet NaNs, the
284 /// `classifyFine` function returns the same integer value as
285 /// `classify`. For negative numbers, `classifyFine` returns an integer
286 /// value equal to value returned by `classify` bit-wise OR'ed with
287 /// `k_NEGATIVE`. For signaling NaNs, `classifyFine` returns `k_SNAN`,
288 /// which has the integer value of `k_NAN | k_SIGNALING`.
289 static FineClassification classifyFine(double number);
290
291 static bool isZero(float number);
292 /// Return `true` if the specified floating point `number` has a value
293 /// of positive or negative zero, and `false` otherwise.
294 static bool isZero(double number);
295
296 static bool isNormal(float number);
297 /// Return `true` if the specified floating point `number` holds a
298 /// normal value (neither zero, subnormal, infinite, nor NaN). This
299 /// function is equivalent to the `isnormal` macro in C99.
300 static bool isNormal(double number);
301
302 static bool isSubnormal(float number);
303 /// Return `true` if the specified floating point `number` holds a
304 /// subnormal value, and `false` otherwise.
305 static bool isSubnormal(double number);
306
307 static bool isInfinite(float number);
308 /// Return `true` if the specified floating point `number` has a value
309 /// of positive or negative infinity, and `false` otherwise. This
310 /// function is equivalent to the `isinf` macro in C99. Note that
311 /// infinity is a valid floating-point value and is not a "NaN".
312 static bool isInfinite(double number);
313
314 static bool isNan(float number);
315 /// Return `true` if the specified floating point `number` has a value
316 /// that does not represent a real number ("not-a-number" or "NaN"), and
317 /// `false` otherwise. This function is equivalent to the `isnan` macro
318 /// in C99. Note that if this method returns `true`, then either
319 /// `isQuietNan` or `isSignalingNan` will also return `true`.
320 static bool isNan(double number);
321
322 static bool signBit(float number);
323 /// Return `true` if the specified floating point `number` has its sign
324 /// bit set (i.e., it is negative), and `false` otherwise. This
325 /// function is equivalent to the `signbit` macro in C99. Note that
326 /// this function will return `true` for some NaNs, even though the
327 /// concepts of negative and positive do not apply to NaNs.
328 static bool signBit(double number);
329
330 static bool isFinite(float number);
331 /// Return `true` if the specified floating point `number` is normal,
332 /// subnormal or zero, and `false` if `number` is infinite or NaN. This
333 /// function is equivalent to the `isfinite` macro in C99.
334 static bool isFinite(double number);
335
336 static bool isQuietNan(float number);
337 /// Return `true` if the specified floating point `number` has an
338 /// indeterminate value, and `false` otherwise. An indeterminate
339 /// floating-point value ("quiet NaN" or "QNaN") results from an
340 /// operation for which the result is not mathematically defined, such
341 /// as multiplying infinity by zero. If a QNaN is used in a subsequent
342 /// operations the result will also be a QNaN. Note that, because a
343 /// QNaN is a NaN, if this method returns `true`, then `isNan(x)` will
344 /// also return `true`.
345 static bool isQuietNan(double number);
346
347 static bool isSignalingNan(float number);
348 /// Return `true` if the specified floating point `number` has an
349 /// invalid value, and `false` otherwise. An invalid floating-point
350 /// value ("signaling NaN" or "SNaN")is never the result of a valid
351 /// operation -- it must be produced deliberately (i.e., by calling
352 /// `bsl::numeric_limits<float>::signaling_NaN()`). If an SNaN is used
353 /// in a subsequent operation, the result is undefined and may result in
354 /// a hardware trap leading to a signal. Some platforms do not support
355 /// signaling NaNs, especially for single-precision floats, and will
356 /// convert an SNaN to a QNaN on assignment or copy-initialization
357 /// (including argument passing). `isSignalingNan` will always return
358 /// `false` on such platforms. Note that, because an SNaN is a NaN, if
359 /// this method returns `true`, then `isNan(x)` will also return `true`.
360 static bool isSignalingNan(double number);
361};
362} // close package namespace
363
364
365// ============================================================================
366// INLINE FUNCTION DEFINITIONS
367// ============================================================================
368
369
370#endif
371
372// ----------------------------------------------------------------------------
373// Copyright 2015 Bloomberg Finance L.P.
374//
375// Licensed under the Apache License, Version 2.0 (the "License");
376// you may not use this file except in compliance with the License.
377// You may obtain a copy of the License at
378//
379// http://www.apache.org/licenses/LICENSE-2.0
380//
381// Unless required by applicable law or agreed to in writing, software
382// distributed under the License is distributed on an "AS IS" BASIS,
383// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
384// See the License for the specific language governing permissions and
385// limitations under the License.
386// ----------------------------- END-OF-FILE ----------------------------------
387
388/** @} */
389/** @} */
390/** @} */
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlb_algorithmworkaroundutil.h:74
Namespace for floating-point classification types and functions.
Definition bdlb_float.h:214
static bool isFinite(float number)
static bool isNan(float number)
static bool isNormal(double number)
Classification
Definition bdlb_float.h:223
@ k_NORMAL
Definition bdlb_float.h:225
@ BDES_SUBNORMAL
Definition bdlb_float.h:232
@ k_NAN
Definition bdlb_float.h:228
@ k_SUBNORMAL
Definition bdlb_float.h:226
@ k_INFINITE
Definition bdlb_float.h:227
@ k_ZERO
Definition bdlb_float.h:224
@ BDES_NAN
Definition bdlb_float.h:234
@ BDES_INFINITE
Definition bdlb_float.h:233
@ BDES_ZERO
Definition bdlb_float.h:230
@ BDES_NORMAL
Definition bdlb_float.h:231
static bool isQuietNan(float number)
static Classification classify(double number)
static bool isZero(float number)
static bool isZero(double number)
static bool isInfinite(double number)
static FineClassification classifyFine(float number)
static bool isNormal(float number)
static bool signBit(float number)
static FineClassification classifyFine(double number)
static bool isInfinite(float number)
static bool isQuietNan(double number)
static bool signBit(double number)
static bool isFinite(double number)
static bool isSubnormal(float number)
static bool isSignalingNan(float number)
FineClassification
Definition bdlb_float.h:242
@ k_NEGATIVE_NORMAL
Definition bdlb_float.h:251
@ k_POSITIVE_NORMAL
Definition bdlb_float.h:250
@ BDES_NEGATIVE_ZERO
Definition bdlb_float.h:268
@ k_NEGATIVE
Definition bdlb_float.h:243
@ BDES_NEGATIVE_INFINITY
Definition bdlb_float.h:260
@ k_SNAN
Definition bdlb_float.h:249
@ BDES_POSITIVE_SUBNORMAL
Definition bdlb_float.h:265
@ BDES_NEGATIVE_SUBNORMAL
Definition bdlb_float.h:266
@ k_POSITIVE_SUBNORMAL
Definition bdlb_float.h:252
@ BDES_POSITIVE_NORMAL
Definition bdlb_float.h:263
@ k_NEGATIVE_ZERO
Definition bdlb_float.h:255
@ k_NEGATIVE_SUBNORMAL
Definition bdlb_float.h:253
@ BDES_SIGNALING
Definition bdlb_float.h:258
@ BDES_NEGATIVE_NORMAL
Definition bdlb_float.h:264
@ k_POSITIVE_ZERO
Definition bdlb_float.h:254
@ BDES_NEGATIVE
Definition bdlb_float.h:257
@ BDES_POSITIVE_ZERO
Definition bdlb_float.h:267
@ k_NEGATIVE_INFINITY
Definition bdlb_float.h:247
@ k_SIGNALING
Definition bdlb_float.h:244
@ BDES_POSITIVE_INFINITY
Definition bdlb_float.h:259
@ BDES_SNAN
Definition bdlb_float.h:262
@ k_QNAN
Definition bdlb_float.h:248
@ k_POSITIVE_INFINITY
Definition bdlb_float.h:246
@ BDES_QNAN
Definition bdlb_float.h:261
static bool isNan(double number)
static bool isSignalingNan(double number)
static Classification classify(float number)
static bool isSubnormal(double number)