1/****************************************************************************
2**
3** Copyright (C) 2019 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qnumeric.h"
41#include "qnumeric_p.h"
42#include <string.h>
43
44QT_BEGIN_NAMESPACE
45
46/*!
47 Returns \c true if the double \a {d} is equivalent to infinity.
48 \relates <QtGlobal>
49 \sa qInf()
50*/
51Q_CORE_EXPORT bool qIsInf(double d) { return qt_is_inf(d); }
52
53/*!
54 Returns \c true if the double \a {d} is not a number (NaN).
55 \relates <QtGlobal>
56*/
57Q_CORE_EXPORT bool qIsNaN(double d) { return qt_is_nan(d); }
58
59/*!
60 Returns \c true if the double \a {d} is a finite number.
61 \relates <QtGlobal>
62*/
63Q_CORE_EXPORT bool qIsFinite(double d) { return qt_is_finite(d); }
64
65/*!
66 Returns \c true if the float \a {f} is equivalent to infinity.
67 \relates <QtGlobal>
68 \sa qInf()
69*/
70Q_CORE_EXPORT bool qIsInf(float f) { return qt_is_inf(f); }
71
72/*!
73 Returns \c true if the float \a {f} is not a number (NaN).
74 \relates <QtGlobal>
75*/
76Q_CORE_EXPORT bool qIsNaN(float f) { return qt_is_nan(f); }
77
78/*!
79 Returns \c true if the float \a {f} is a finite number.
80 \relates <QtGlobal>
81*/
82Q_CORE_EXPORT bool qIsFinite(float f) { return qt_is_finite(f); }
83
84#if QT_CONFIG(signaling_nan)
85/*!
86 Returns the bit pattern of a signalling NaN as a double.
87 \relates <QtGlobal>
88*/
89Q_CORE_EXPORT double qSNaN() { return qt_snan(); }
90#endif
91
92/*!
93 Returns the bit pattern of a quiet NaN as a double.
94 \relates <QtGlobal>
95 \sa qIsNaN()
96*/
97Q_CORE_EXPORT double qQNaN() { return qt_qnan(); }
98
99/*!
100 Returns the bit pattern for an infinite number as a double.
101 \relates <QtGlobal>
102 \sa qIsInf()
103*/
104Q_CORE_EXPORT double qInf() { return qt_inf(); }
105
106/*!
107 \relates <QtGlobal>
108 Classifies a floating-point value.
109
110 The return values are defined in \c{<cmath>}: returns one of the following,
111 determined by the floating-point class of \a val:
112 \list
113 \li FP_NAN not a number
114 \li FP_INFINITE infinities (positive or negative)
115 \li FP_ZERO zero (positive or negative)
116 \li FP_NORMAL finite with a full mantissa
117 \li FP_SUBNORMAL finite with a reduced mantissa
118 \endlist
119*/
120Q_CORE_EXPORT int qFpClassify(double val) { return qt_fpclassify(val); }
121
122/*!
123 \overload
124*/
125Q_CORE_EXPORT int qFpClassify(float val) { return qt_fpclassify(val); }
126
127
128/*!
129 \internal
130 */
131static inline quint32 f2i(float f)
132{
133 quint32 i;
134 memcpy(&i, &f, sizeof(f));
135 return i;
136}
137
138/*!
139 Returns the number of representable floating-point numbers between \a a and \a b.
140
141 This function provides an alternative way of doing approximated comparisons of floating-point
142 numbers similar to qFuzzyCompare(). However, it returns the distance between two numbers, which
143 gives the caller a possibility to choose the accepted error. Errors are relative, so for
144 instance the distance between 1.0E-5 and 1.00001E-5 will give 110, while the distance between
145 1.0E36 and 1.00001E36 will give 127.
146
147 This function is useful if a floating point comparison requires a certain precision.
148 Therefore, if \a a and \a b are equal it will return 0. The maximum value it will return for 32-bit
149 floating point numbers is 4,278,190,078. This is the distance between \c{-FLT_MAX} and
150 \c{+FLT_MAX}.
151
152 The function does not give meaningful results if any of the arguments are \c Infinite or \c NaN.
153 You can check for this by calling qIsFinite().
154
155 The return value can be considered as the "error", so if you for instance want to compare
156 two 32-bit floating point numbers and all you need is an approximated 24-bit precision, you can
157 use this function like this:
158
159 \snippet code/src_corelib_global_qnumeric.cpp 0
160
161 \sa qFuzzyCompare()
162 \since 5.2
163 \relates <QtGlobal>
164*/
165Q_CORE_EXPORT quint32 qFloatDistance(float a, float b)
166{
167 static const quint32 smallestPositiveFloatAsBits = 0x00000001; // denormalized, (SMALLEST), (1.4E-45)
168 /* Assumes:
169 * IEE754 format.
170 * Integers and floats have the same endian
171 */
172 static_assert(sizeof(quint32) == sizeof(float));
173 Q_ASSERT(qIsFinite(a) && qIsFinite(b));
174 if (a == b)
175 return 0;
176 if ((a < 0) != (b < 0)) {
177 // if they have different signs
178 if (a < 0)
179 a = -a;
180 else /*if (b < 0)*/
181 b = -b;
182 return qFloatDistance(0.0F, a) + qFloatDistance(0.0F, b);
183 }
184 if (a < 0) {
185 a = -a;
186 b = -b;
187 }
188 // at this point a and b should not be negative
189
190 // 0 is special
191 if (!a)
192 return f2i(b) - smallestPositiveFloatAsBits + 1;
193 if (!b)
194 return f2i(a) - smallestPositiveFloatAsBits + 1;
195
196 // finally do the common integer subtraction
197 return a > b ? f2i(a) - f2i(b) : f2i(b) - f2i(a);
198}
199
200
201/*!
202 \internal
203 */
204static inline quint64 d2i(double d)
205{
206 quint64 i;
207 memcpy(&i, &d, sizeof(d));
208 return i;
209}
210
211/*!
212 Returns the number of representable floating-point numbers between \a a and \a b.
213
214 This function serves the same purpose as \c{qFloatDistance(float, float)}, but
215 returns the distance between two \c double numbers. Since the range is larger
216 than for two \c float numbers (\c{[-DBL_MAX,DBL_MAX]}), the return type is quint64.
217
218
219 \sa qFuzzyCompare()
220 \since 5.2
221 \relates <QtGlobal>
222*/
223Q_CORE_EXPORT quint64 qFloatDistance(double a, double b)
224{
225 static const quint64 smallestPositiveFloatAsBits = 0x1; // denormalized, (SMALLEST)
226 /* Assumes:
227 * IEE754 format double precision
228 * Integers and floats have the same endian
229 */
230 static_assert(sizeof(quint64) == sizeof(double));
231 Q_ASSERT(qIsFinite(a) && qIsFinite(b));
232 if (a == b)
233 return 0;
234 if ((a < 0) != (b < 0)) {
235 // if they have different signs
236 if (a < 0)
237 a = -a;
238 else /*if (b < 0)*/
239 b = -b;
240 return qFloatDistance(0.0, a) + qFloatDistance(0.0, b);
241 }
242 if (a < 0) {
243 a = -a;
244 b = -b;
245 }
246 // at this point a and b should not be negative
247
248 // 0 is special
249 if (!a)
250 return d2i(b) - smallestPositiveFloatAsBits + 1;
251 if (!b)
252 return d2i(a) - smallestPositiveFloatAsBits + 1;
253
254 // finally do the common integer subtraction
255 return a > b ? d2i(a) - d2i(b) : d2i(b) - d2i(a);
256}
257
258
259QT_END_NAMESPACE
260