/src/gdal/port/cpl_float.h
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /******************************************************************************  | 
2  |  |  *  | 
3  |  |  * Project:  CPL  | 
4  |  |  * Purpose:  Floating point conversion functions. Convert 16- and 24-bit  | 
5  |  |  *           floating point numbers into the 32-bit IEEE 754 compliant ones.  | 
6  |  |  * Author:   Andrey Kiselev, dron@remotesensing.org  | 
7  |  |  *  | 
8  |  |  ******************************************************************************  | 
9  |  |  * Copyright (c) 2005, Andrey Kiselev <dron@remotesensing.org>  | 
10  |  |  * Copyright (c) 2010, Even Rouault <even dot rouault at spatialys.com>  | 
11  |  |  *  | 
12  |  |  * This code is based on the code from OpenEXR project with the following  | 
13  |  |  * copyright:  | 
14  |  |  *  | 
15  |  |  * Copyright (c) 2002, Industrial Light & Magic, a division of Lucas  | 
16  |  |  * Digital Ltd. LLC  | 
17  |  |  *  | 
18  |  |  * All rights reserved.  | 
19  |  |  *  | 
20  |  |  * Redistribution and use in source and binary forms, with or without  | 
21  |  |  * modification, are permitted provided that the following conditions are  | 
22  |  |  * met:  | 
23  |  |  * *       Redistributions of source code must retain the above copyright  | 
24  |  |  * notice, this list of conditions and the following disclaimer.  | 
25  |  |  * *       Redistributions in binary form must reproduce the above  | 
26  |  |  * copyright notice, this list of conditions and the following disclaimer  | 
27  |  |  * in the documentation and/or other materials provided with the  | 
28  |  |  * distribution.  | 
29  |  |  * *       Neither the name of Industrial Light & Magic nor the names of  | 
30  |  |  * its contributors may be used to endorse or promote products derived  | 
31  |  |  * from this software without specific prior written permission.  | 
32  |  |  *  | 
33  |  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  | 
34  |  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT  | 
35  |  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  | 
36  |  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  | 
37  |  |  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  | 
38  |  |  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT  | 
39  |  |  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  | 
40  |  |  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  | 
41  |  |  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  | 
42  |  |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  | 
43  |  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  | 
44  |  |  *  | 
45  |  |  ****************************************************************************/  | 
46  |  |  | 
47  |  | #ifndef CPL_FLOAT_H_INCLUDED  | 
48  |  | #define CPL_FLOAT_H_INCLUDED  | 
49  |  |  | 
50  |  | #include "cpl_port.h"  | 
51  |  |  | 
52  |  | #ifdef __cplusplus  | 
53  |  | #include <algorithm>  | 
54  |  | #include <cmath>  | 
55  |  | #include <cstdint>  | 
56  |  | #include <cstring>  | 
57  |  | #include <limits>  | 
58  |  | #ifdef HAVE_STD_FLOAT16_T  | 
59  |  | #include <stdfloat>  | 
60  |  | #endif  | 
61  |  | #endif  | 
62  |  |  | 
63  |  | CPL_C_START  | 
64  |  | GUInt32 CPL_DLL CPLHalfToFloat(GUInt16 iHalf);  | 
65  |  | GUInt32 CPL_DLL CPLTripleToFloat(GUInt32 iTriple);  | 
66  |  | CPL_C_END  | 
67  |  |  | 
68  |  | #ifdef __cplusplus  | 
69  |  |  | 
70  |  | GUInt16 CPL_DLL CPLFloatToHalf(GUInt32 iFloat32, bool &bHasWarned);  | 
71  |  |  | 
72  |  | GUInt16 CPL_DLL CPLConvertFloatToHalf(float fFloat32);  | 
73  |  | float CPL_DLL CPLConvertHalfToFloat(GUInt16 nHalf);  | 
74  |  |  | 
75  |  | namespace cpl  | 
76  |  | { | 
77  |  |  | 
78  |  | // We define our own version of `std::numeric_limits` so that we can  | 
79  |  | // specialize it for `cpl::Float16` if necessary. Specializing  | 
80  |  | // `std::numeric_limits` doesn't always work because some libraries  | 
81  |  | // use `std::numeric_limits`, and one cannot specialize a type  | 
82  |  | // template after it has been used.  | 
83  |  | template <typename T> struct NumericLimits : std::numeric_limits<T>  | 
84  |  | { | 
85  |  | };  | 
86  |  |  | 
87  |  | #ifndef HAVE_STD_FLOAT16_T  | 
88  |  |  | 
89  |  | // Define a type `cpl::Float16`. If the compiler supports it natively  | 
90  |  | // (as `_Float16`), then this class is a simple wrapper. Otherwise we  | 
91  |  | // store the values in a `GUInt16` as bit pattern.  | 
92  |  |  | 
93  |  | //! @cond Doxygen_Suppress  | 
94  |  | struct Float16  | 
95  |  | { | 
96  |  |     struct make_from_bits_and_value  | 
97  |  |     { | 
98  |  |     };  | 
99  |  |  | 
100  |  | #ifdef HAVE__FLOAT16  | 
101  |  |  | 
102  |  |     // How we represent a `Float16` internally  | 
103  |  |     using repr = _Float16;  | 
104  |  |  | 
105  |  |     // How we compute on `Float16` values  | 
106  |  |     using compute = _Float16;  | 
107  |  |  | 
108  |  |     // Create a Float16 in a constexpr manner. Since we can't convert  | 
109  |  |     // bits in a constexpr function, we need to take both the bit  | 
110  |  |     // pattern and a float value as input, and can then choose which  | 
111  |  |     // of the two to use.  | 
112  |  |     constexpr Float16(make_from_bits_and_value, CPL_UNUSED std::uint16_t bits,  | 
113  |  |                       float fValue)  | 
114  | 0  |         : rValue(repr(fValue))  | 
115  | 0  |     { | 
116  | 0  |     }  | 
117  |  |  | 
118  |  |     static constexpr repr computeToRepr(compute fValue)  | 
119  | 0  |     { | 
120  | 0  |         return fValue;  | 
121  | 0  |     }  | 
122  |  |  | 
123  |  |     static constexpr compute reprToCompute(repr rValue)  | 
124  | 0  |     { | 
125  | 0  |         return rValue;  | 
126  | 0  |     }  | 
127  |  |  | 
128  |  |     template <typename T> static constexpr repr toRepr(T fValue)  | 
129  | 0  |     { | 
130  | 0  |         return static_cast<repr>(fValue);  | 
131  | 0  |     } Unexecuted instantiation: _ZN3cpl7Float166toReprIfEEDF16_T_ Unexecuted instantiation: _ZN3cpl7Float166toReprIdEEDF16_T_ Unexecuted instantiation: _ZN3cpl7Float166toReprIcEEDF16_T_ Unexecuted instantiation: _ZN3cpl7Float166toReprIaEEDF16_T_ Unexecuted instantiation: _ZN3cpl7Float166toReprIsEEDF16_T_ Unexecuted instantiation: _ZN3cpl7Float166toReprIiEEDF16_T_ Unexecuted instantiation: _ZN3cpl7Float166toReprIlEEDF16_T_ Unexecuted instantiation: _ZN3cpl7Float166toReprIxEEDF16_T_ Unexecuted instantiation: _ZN3cpl7Float166toReprIhEEDF16_T_ Unexecuted instantiation: _ZN3cpl7Float166toReprItEEDF16_T_ Unexecuted instantiation: _ZN3cpl7Float166toReprIjEEDF16_T_ Unexecuted instantiation: _ZN3cpl7Float166toReprImEEDF16_T_ Unexecuted instantiation: _ZN3cpl7Float166toReprIyEEDF16_T_  | 
132  |  |  | 
133  |  |     template <typename T> static constexpr T fromRepr(repr rValue)  | 
134  | 0  |     { | 
135  | 0  |         return static_cast<T>(rValue);  | 
136  | 0  |     } Unexecuted instantiation: _ZN3cpl7Float168fromReprIfEET_DF16_ Unexecuted instantiation: _ZN3cpl7Float168fromReprIdEET_DF16_ Unexecuted instantiation: _ZN3cpl7Float168fromReprIcEET_DF16_ Unexecuted instantiation: _ZN3cpl7Float168fromReprIaEET_DF16_ Unexecuted instantiation: _ZN3cpl7Float168fromReprIsEET_DF16_ Unexecuted instantiation: _ZN3cpl7Float168fromReprIiEET_DF16_ Unexecuted instantiation: _ZN3cpl7Float168fromReprIlEET_DF16_ Unexecuted instantiation: _ZN3cpl7Float168fromReprIxEET_DF16_ Unexecuted instantiation: _ZN3cpl7Float168fromReprIhEET_DF16_ Unexecuted instantiation: _ZN3cpl7Float168fromReprItEET_DF16_ Unexecuted instantiation: _ZN3cpl7Float168fromReprIjEET_DF16_ Unexecuted instantiation: _ZN3cpl7Float168fromReprImEET_DF16_ Unexecuted instantiation: _ZN3cpl7Float168fromReprIyEET_DF16_  | 
137  |  |  | 
138  |  | #else  // #ifndef HAVE__FLOAT16  | 
139  |  |  | 
140  |  |     // How we represent a `Float16` internally  | 
141  |  |     using repr = std::uint16_t;  | 
142  |  |  | 
143  |  |     // How we compute on `Float16` values  | 
144  |  |     using compute = float;  | 
145  |  |  | 
146  |  |     // Create a Float16 in a constexpr manner. Since we can't convert  | 
147  |  |     // bits in a constexpr function, we need to take both the bit  | 
148  |  |     // pattern and a float value as input, and can then choose which  | 
149  |  |     // of the two to use.  | 
150  |  |     constexpr Float16(make_from_bits_and_value, std::uint16_t bits,  | 
151  |  |                       CPL_UNUSED float fValue)  | 
152  |  |         : rValue(bits)  | 
153  |  |     { | 
154  |  |     }  | 
155  |  |  | 
156  |  |     static unsigned float2unsigned(float f)  | 
157  |  |     { | 
158  |  |         unsigned u;  | 
159  |  |         std::memcpy(&u, &f, 4);  | 
160  |  |         return u;  | 
161  |  |     }  | 
162  |  |  | 
163  |  |     static float unsigned2float(unsigned u)  | 
164  |  |     { | 
165  |  |         float f;  | 
166  |  |         std::memcpy(&f, &u, 4);  | 
167  |  |         return f;  | 
168  |  |     }  | 
169  |  |  | 
170  |  |     // Copied from cpl_float.cpp so that we can inline for performance  | 
171  |  |     static std::uint16_t computeToRepr(float fFloat32)  | 
172  |  |     { | 
173  |  |         std::uint32_t iFloat32 = float2unsigned(fFloat32);  | 
174  |  |  | 
175  |  |         std::uint32_t iSign = (iFloat32 >> 31) & 0x00000001;  | 
176  |  |         std::uint32_t iExponent = (iFloat32 >> 23) & 0x000000ff;  | 
177  |  |         std::uint32_t iMantissa = iFloat32 & 0x007fffff;  | 
178  |  |  | 
179  |  |         if (iExponent == 255)  | 
180  |  |         { | 
181  |  |             if (iMantissa == 0)  | 
182  |  |             { | 
183  |  |                 // Positive or negative infinity.  | 
184  |  |                 return static_cast<std::int16_t>((iSign << 15) | 0x7C00);  | 
185  |  |             }  | 
186  |  |  | 
187  |  |             // NaN -- preserve sign and significand bits.  | 
188  |  |             if (iMantissa >> 13)  | 
189  |  |                 return static_cast<std::int16_t>((iSign << 15) | 0x7C00 |  | 
190  |  |                                                  (iMantissa >> 13));  | 
191  |  |             return static_cast<std::int16_t>((iSign << 15) | 0x7E00);  | 
192  |  |         }  | 
193  |  |  | 
194  |  |         if (iExponent <= 127 - 15)  | 
195  |  |         { | 
196  |  |             // Zero, float32 denormalized number or float32 too small normalized  | 
197  |  |             // number  | 
198  |  |             if (13 + 1 + 127 - 15 - iExponent >= 32)  | 
199  |  |                 return static_cast<std::int16_t>(iSign << 15);  | 
200  |  |  | 
201  |  |             // Return a denormalized number  | 
202  |  |             return static_cast<std::int16_t>(  | 
203  |  |                 (iSign << 15) |  | 
204  |  |                 ((iMantissa | 0x00800000) >> (13 + 1 + 127 - 15 - iExponent)));  | 
205  |  |         }  | 
206  |  |  | 
207  |  |         if (iExponent - (127 - 15) >= 31)  | 
208  |  |         { | 
209  |  |             return static_cast<std::int16_t>((iSign << 15) |  | 
210  |  |                                              0x7C00);  // Infinity  | 
211  |  |         }  | 
212  |  |  | 
213  |  |         // Normalized number.  | 
214  |  |         iExponent = iExponent - (127 - 15);  | 
215  |  |         iMantissa = iMantissa >> 13;  | 
216  |  |  | 
217  |  |         // Assemble sign, exponent and mantissa.  | 
218  |  |         // coverity[overflow_sink]  | 
219  |  |         return static_cast<std::int16_t>((iSign << 15) | (iExponent << 10) |  | 
220  |  |                                          iMantissa);  | 
221  |  |     }  | 
222  |  |  | 
223  |  |     // Copied from cpl_float.cpp so that we can inline for performance  | 
224  |  |     static float reprToCompute(std::uint16_t iHalf)  | 
225  |  |     { | 
226  |  |         std::uint32_t iSign = (iHalf >> 15) & 0x00000001;  | 
227  |  |         int iExponent = (iHalf >> 10) & 0x0000001f;  | 
228  |  |         std::uint32_t iMantissa = iHalf & 0x000003ff;  | 
229  |  |  | 
230  |  |         if (iExponent == 31)  | 
231  |  |         { | 
232  |  |             if (iMantissa == 0)  | 
233  |  |             { | 
234  |  |                 // Positive or negative infinity.  | 
235  |  |                 return unsigned2float((iSign << 31) | 0x7f800000);  | 
236  |  |             }  | 
237  |  |  | 
238  |  |             // NaN -- preserve sign and significand bits.  | 
239  |  |             return unsigned2float((iSign << 31) | 0x7f800000 |  | 
240  |  |                                   (iMantissa << 13));  | 
241  |  |         }  | 
242  |  |  | 
243  |  |         if (iExponent == 0)  | 
244  |  |         { | 
245  |  |             if (iMantissa == 0)  | 
246  |  |             { | 
247  |  |                 // Plus or minus zero.  | 
248  |  |                 return unsigned2float(iSign << 31);  | 
249  |  |             }  | 
250  |  |  | 
251  |  |             // Denormalized number -- renormalize it.  | 
252  |  |             while (!(iMantissa & 0x00000400))  | 
253  |  |             { | 
254  |  |                 iMantissa <<= 1;  | 
255  |  |                 iExponent -= 1;  | 
256  |  |             }  | 
257  |  |  | 
258  |  |             iExponent += 1;  | 
259  |  |             iMantissa &= ~0x00000400U;  | 
260  |  |         }  | 
261  |  |  | 
262  |  |         // Normalized number.  | 
263  |  |         iExponent = iExponent + (127 - 15);  | 
264  |  |         iMantissa = iMantissa << 13;  | 
265  |  |  | 
266  |  |         // Assemble sign, exponent and mantissa.  | 
267  |  |         /* coverity[overflow_sink] */  | 
268  |  |         return unsigned2float((iSign << 31) |  | 
269  |  |                               (static_cast<std::uint32_t>(iExponent) << 23) |  | 
270  |  |                               iMantissa);  | 
271  |  |     }  | 
272  |  |  | 
273  |  |     template <typename T> static repr toRepr(T fValue)  | 
274  |  |     { | 
275  |  |         return computeToRepr(static_cast<compute>(fValue));  | 
276  |  |     }  | 
277  |  |  | 
278  |  |     template <typename T> static T fromRepr(repr rValue)  | 
279  |  |     { | 
280  |  |         return static_cast<T>(reprToCompute(rValue));  | 
281  |  |     }  | 
282  |  |  | 
283  |  | #endif  // #ifndef HAVE__FLOAT16  | 
284  |  |  | 
285  |  |   private:  | 
286  |  |     repr rValue;  | 
287  |  |  | 
288  |  |   public:  | 
289  |  |     compute get() const  | 
290  | 0  |     { | 
291  | 0  |         return reprToCompute(rValue);  | 
292  | 0  |     }  | 
293  |  |  | 
294  |  |     // cppcheck-suppress uninitMemberVar  | 
295  |  |     Float16() = default;  | 
296  |  |     Float16(const Float16 &) = default;  | 
297  |  |     Float16(Float16 &&) = default;  | 
298  |  |     Float16 &operator=(const Float16 &) = default;  | 
299  |  |     Float16 &operator=(Float16 &&) = default;  | 
300  |  |  | 
301  |  |     // Constructors and conversion operators  | 
302  |  |  | 
303  |  | #ifdef HAVE__FLOAT16  | 
304  |  |     // cppcheck-suppress noExplicitConstructor  | 
305  | 0  |     constexpr Float16(_Float16 hfValue) : rValue(hfValue)  | 
306  | 0  |     { | 
307  | 0  |     }  | 
308  |  |  | 
309  |  |     constexpr operator _Float16() const  | 
310  | 0  |     { | 
311  | 0  |         return rValue;  | 
312  | 0  |     }  | 
313  |  | #endif  | 
314  |  |  | 
315  |  |     // cppcheck-suppress-macro noExplicitConstructor  | 
316  |  | #define GDAL_DEFINE_CONVERSION(TYPE)                                           \  | 
317  |  |                                                                                \  | 
318  | 0  |     Float16(TYPE fValue) : rValue(toRepr(fValue))                              \  | 
319  | 0  |     {                                                                          \ | 
320  | 0  |     }                                                                          \ Unexecuted instantiation: cpl::Float16::Float16(float) Unexecuted instantiation: cpl::Float16::Float16(double) Unexecuted instantiation: cpl::Float16::Float16(signed char) Unexecuted instantiation: cpl::Float16::Float16(short) Unexecuted instantiation: cpl::Float16::Float16(int) Unexecuted instantiation: cpl::Float16::Float16(long) Unexecuted instantiation: cpl::Float16::Float16(unsigned char) Unexecuted instantiation: cpl::Float16::Float16(unsigned short) Unexecuted instantiation: cpl::Float16::Float16(unsigned int) Unexecuted instantiation: cpl::Float16::Float16(unsigned long) Unexecuted instantiation: cpl::Float16::Float16(char) Unexecuted instantiation: cpl::Float16::Float16(long long) Unexecuted instantiation: cpl::Float16::Float16(unsigned long long)  | 
321  |  |                                                                                \  | 
322  |  |     operator TYPE() const                                                      \  | 
323  | 0  |     {                                                                          \ | 
324  | 0  |         return fromRepr<TYPE>(rValue);                                         \  | 
325  | 0  |     } Unexecuted instantiation: cpl::Float16::operator float() const Unexecuted instantiation: cpl::Float16::operator double() const Unexecuted instantiation: cpl::Float16::operator char() const Unexecuted instantiation: cpl::Float16::operator signed char() const Unexecuted instantiation: cpl::Float16::operator short() const Unexecuted instantiation: cpl::Float16::operator int() const Unexecuted instantiation: cpl::Float16::operator long() const Unexecuted instantiation: cpl::Float16::operator long long() const Unexecuted instantiation: cpl::Float16::operator unsigned char() const Unexecuted instantiation: cpl::Float16::operator unsigned short() const Unexecuted instantiation: cpl::Float16::operator unsigned int() const Unexecuted instantiation: cpl::Float16::operator unsigned long() const Unexecuted instantiation: cpl::Float16::operator unsigned long long() const  | 
326  |  |  | 
327  |  |     GDAL_DEFINE_CONVERSION(float)  | 
328  |  |     GDAL_DEFINE_CONVERSION(double)  | 
329  |  |     GDAL_DEFINE_CONVERSION(char)  | 
330  |  |     GDAL_DEFINE_CONVERSION(signed char)  | 
331  |  |     GDAL_DEFINE_CONVERSION(short)  | 
332  |  |     GDAL_DEFINE_CONVERSION(int)  | 
333  |  |     GDAL_DEFINE_CONVERSION(long)  | 
334  |  |     GDAL_DEFINE_CONVERSION(long long)  | 
335  |  |     GDAL_DEFINE_CONVERSION(unsigned char)  | 
336  |  |     GDAL_DEFINE_CONVERSION(unsigned short)  | 
337  |  |     GDAL_DEFINE_CONVERSION(unsigned int)  | 
338  |  |     GDAL_DEFINE_CONVERSION(unsigned long)  | 
339  |  |     GDAL_DEFINE_CONVERSION(unsigned long long)  | 
340  |  |  | 
341  |  | #undef GDAL_DEFINE_CONVERSION  | 
342  |  |  | 
343  |  |     // Arithmetic operators  | 
344  |  |  | 
345  |  |     friend Float16 operator+(Float16 x)  | 
346  | 0  |     { | 
347  | 0  |         return +x.get();  | 
348  | 0  |     }  | 
349  |  |  | 
350  |  |     friend Float16 operator-(Float16 x)  | 
351  | 0  |     { | 
352  | 0  |         return -x.get();  | 
353  | 0  |     }  | 
354  |  |  | 
355  |  | #define GDAL_DEFINE_ARITHOP(OP)                                                \  | 
356  |  |                                                                                \  | 
357  |  |     friend Float16 operator OP(Float16 x, Float16 y)                           \  | 
358  | 0  |     {                                                                          \ | 
359  | 0  |         return x.get() OP y.get();                                             \  | 
360  | 0  |     }                                                                          \ Unexecuted instantiation: cpl::operator+(cpl::Float16, cpl::Float16) Unexecuted instantiation: cpl::operator-(cpl::Float16, cpl::Float16) Unexecuted instantiation: cpl::operator*(cpl::Float16, cpl::Float16) Unexecuted instantiation: cpl::operator/(cpl::Float16, cpl::Float16)  | 
361  |  |                                                                                \  | 
362  |  |     friend double operator OP(double x, Float16 y)                             \  | 
363  | 0  |     {                                                                          \ | 
364  | 0  |         return x OP y.get();                                                   \  | 
365  | 0  |     }                                                                          \ Unexecuted instantiation: cpl::operator+(double, cpl::Float16) Unexecuted instantiation: cpl::operator-(double, cpl::Float16) Unexecuted instantiation: cpl::operator*(double, cpl::Float16) Unexecuted instantiation: cpl::operator/(double, cpl::Float16)  | 
366  |  |                                                                                \  | 
367  |  |     friend float operator OP(float x, Float16 y)                               \  | 
368  | 0  |     {                                                                          \ | 
369  | 0  |         return x OP y.get();                                                   \  | 
370  | 0  |     }                                                                          \ Unexecuted instantiation: cpl::operator+(float, cpl::Float16) Unexecuted instantiation: cpl::operator-(float, cpl::Float16) Unexecuted instantiation: cpl::operator*(float, cpl::Float16) Unexecuted instantiation: cpl::operator/(float, cpl::Float16)  | 
371  |  |                                                                                \  | 
372  |  |     friend Float16 operator OP(int x, Float16 y)                               \  | 
373  | 0  |     {                                                                          \ | 
374  | 0  |         return x OP y.get();                                                   \  | 
375  | 0  |     }                                                                          \ Unexecuted instantiation: cpl::operator+(int, cpl::Float16) Unexecuted instantiation: cpl::operator-(int, cpl::Float16) Unexecuted instantiation: cpl::operator*(int, cpl::Float16) Unexecuted instantiation: cpl::operator/(int, cpl::Float16)  | 
376  |  |                                                                                \  | 
377  |  |     friend double operator OP(Float16 x, double y)                             \  | 
378  | 0  |     {                                                                          \ | 
379  | 0  |         return x.get() OP y;                                                   \  | 
380  | 0  |     }                                                                          \ Unexecuted instantiation: cpl::operator+(cpl::Float16, double) Unexecuted instantiation: cpl::operator-(cpl::Float16, double) Unexecuted instantiation: cpl::operator*(cpl::Float16, double) Unexecuted instantiation: cpl::operator/(cpl::Float16, double)  | 
381  |  |                                                                                \  | 
382  |  |     friend float operator OP(Float16 x, float y)                               \  | 
383  | 0  |     {                                                                          \ | 
384  | 0  |         return x.get() OP y;                                                   \  | 
385  | 0  |     }                                                                          \ Unexecuted instantiation: cpl::operator+(cpl::Float16, float) Unexecuted instantiation: cpl::operator-(cpl::Float16, float) Unexecuted instantiation: cpl::operator*(cpl::Float16, float) Unexecuted instantiation: cpl::operator/(cpl::Float16, float)  | 
386  |  |                                                                                \  | 
387  |  |     friend Float16 operator OP(Float16 x, int y)                               \  | 
388  | 0  |     {                                                                          \ | 
389  | 0  |         return x.get() OP y;                                                   \  | 
390  | 0  |     } Unexecuted instantiation: cpl::operator+(cpl::Float16, int) Unexecuted instantiation: cpl::operator-(cpl::Float16, int) Unexecuted instantiation: cpl::operator*(cpl::Float16, int) Unexecuted instantiation: cpl::operator/(cpl::Float16, int)  | 
391  |  |  | 
392  |  |     GDAL_DEFINE_ARITHOP(+)  | 
393  |  |     GDAL_DEFINE_ARITHOP(-)  | 
394  |  |     GDAL_DEFINE_ARITHOP(*)  | 
395  |  |     GDAL_DEFINE_ARITHOP(/)  | 
396  |  |  | 
397  |  | #undef GDAL_DEFINE_ARITHOP  | 
398  |  |  | 
399  |  |     // Comparison operators  | 
400  |  |  | 
401  |  | #define GDAL_DEFINE_COMPARISON(OP)                                             \  | 
402  |  |                                                                                \  | 
403  |  |     friend bool operator OP(Float16 x, Float16 y)                              \  | 
404  | 0  |     {                                                                          \ | 
405  | 0  |         return x.get() OP y.get();                                             \  | 
406  | 0  |     }                                                                          \ Unexecuted instantiation: cpl::operator==(cpl::Float16, cpl::Float16) Unexecuted instantiation: cpl::operator!=(cpl::Float16, cpl::Float16) Unexecuted instantiation: cpl::operator<(cpl::Float16, cpl::Float16) Unexecuted instantiation: cpl::operator>(cpl::Float16, cpl::Float16) Unexecuted instantiation: cpl::operator<=(cpl::Float16, cpl::Float16) Unexecuted instantiation: cpl::operator>=(cpl::Float16, cpl::Float16)  | 
407  |  |                                                                                \  | 
408  |  |     friend bool operator OP(float x, Float16 y)                                \  | 
409  | 0  |     {                                                                          \ | 
410  | 0  |         return x OP y.get();                                                   \  | 
411  | 0  |     }                                                                          \ Unexecuted instantiation: cpl::operator==(float, cpl::Float16) Unexecuted instantiation: cpl::operator!=(float, cpl::Float16) Unexecuted instantiation: cpl::operator<(float, cpl::Float16) Unexecuted instantiation: cpl::operator>(float, cpl::Float16) Unexecuted instantiation: cpl::operator<=(float, cpl::Float16) Unexecuted instantiation: cpl::operator>=(float, cpl::Float16)  | 
412  |  |                                                                                \  | 
413  |  |     friend bool operator OP(double x, Float16 y)                               \  | 
414  | 0  |     {                                                                          \ | 
415  | 0  |         return x OP y.get();                                                   \  | 
416  | 0  |     }                                                                          \ Unexecuted instantiation: cpl::operator==(double, cpl::Float16) Unexecuted instantiation: cpl::operator!=(double, cpl::Float16) Unexecuted instantiation: cpl::operator<(double, cpl::Float16) Unexecuted instantiation: cpl::operator>(double, cpl::Float16) Unexecuted instantiation: cpl::operator<=(double, cpl::Float16) Unexecuted instantiation: cpl::operator>=(double, cpl::Float16)  | 
417  |  |                                                                                \  | 
418  |  |     friend bool operator OP(int x, Float16 y)                                  \  | 
419  | 0  |     {                                                                          \ | 
420  | 0  |         return x OP y.get();                                                   \  | 
421  | 0  |     }                                                                          \ Unexecuted instantiation: cpl::operator==(int, cpl::Float16) Unexecuted instantiation: cpl::operator!=(int, cpl::Float16) Unexecuted instantiation: cpl::operator<(int, cpl::Float16) Unexecuted instantiation: cpl::operator>(int, cpl::Float16) Unexecuted instantiation: cpl::operator<=(int, cpl::Float16) Unexecuted instantiation: cpl::operator>=(int, cpl::Float16)  | 
422  |  |                                                                                \  | 
423  |  |     friend bool operator OP(Float16 x, float y)                                \  | 
424  | 0  |     {                                                                          \ | 
425  | 0  |         return x.get() OP y;                                                   \  | 
426  | 0  |     }                                                                          \ Unexecuted instantiation: cpl::operator==(cpl::Float16, float) Unexecuted instantiation: cpl::operator!=(cpl::Float16, float) Unexecuted instantiation: cpl::operator<(cpl::Float16, float) Unexecuted instantiation: cpl::operator>(cpl::Float16, float) Unexecuted instantiation: cpl::operator<=(cpl::Float16, float) Unexecuted instantiation: cpl::operator>=(cpl::Float16, float)  | 
427  |  |                                                                                \  | 
428  |  |     friend bool operator OP(Float16 x, double y)                               \  | 
429  | 0  |     {                                                                          \ | 
430  | 0  |         return x.get() OP y;                                                   \  | 
431  | 0  |     }                                                                          \ Unexecuted instantiation: cpl::operator==(cpl::Float16, double) Unexecuted instantiation: cpl::operator!=(cpl::Float16, double) Unexecuted instantiation: cpl::operator<(cpl::Float16, double) Unexecuted instantiation: cpl::operator>(cpl::Float16, double) Unexecuted instantiation: cpl::operator<=(cpl::Float16, double) Unexecuted instantiation: cpl::operator>=(cpl::Float16, double)  | 
432  |  |                                                                                \  | 
433  |  |     friend bool operator OP(Float16 x, int y)                                  \  | 
434  | 0  |     {                                                                          \ | 
435  | 0  |         return x.get() OP y;                                                   \  | 
436  | 0  |     } Unexecuted instantiation: cpl::operator==(cpl::Float16, int) Unexecuted instantiation: cpl::operator!=(cpl::Float16, int) Unexecuted instantiation: cpl::operator<(cpl::Float16, int) Unexecuted instantiation: cpl::operator>(cpl::Float16, int) Unexecuted instantiation: cpl::operator<=(cpl::Float16, int) Unexecuted instantiation: cpl::operator>=(cpl::Float16, int)  | 
437  |  |  | 
438  |  |     GDAL_DEFINE_COMPARISON(==)  | 
439  |  |     GDAL_DEFINE_COMPARISON(!=)  | 
440  |  |     GDAL_DEFINE_COMPARISON(<)  | 
441  |  |     GDAL_DEFINE_COMPARISON(>)  | 
442  |  |     GDAL_DEFINE_COMPARISON(<=)  | 
443  |  |     GDAL_DEFINE_COMPARISON(>=)  | 
444  |  |  | 
445  |  | #undef GDAL_DEFINE_COMPARISON  | 
446  |  |  | 
447  |  |     // Standard math functions  | 
448  |  |  | 
449  |  |     friend bool isfinite(Float16 x)  | 
450  | 0  |     { | 
451  | 0  |         using std::isfinite;  | 
452  | 0  |         return isfinite(float(x));  | 
453  | 0  |     }  | 
454  |  |  | 
455  |  |     friend bool isinf(Float16 x)  | 
456  | 0  |     { | 
457  | 0  |         using std::isinf;  | 
458  | 0  |         return isinf(float(x));  | 
459  | 0  |     }  | 
460  |  |  | 
461  |  |     friend bool isnan(Float16 x)  | 
462  | 0  |     { | 
463  | 0  |         using std::isnan;  | 
464  | 0  |         return isnan(float(x));  | 
465  | 0  |     }  | 
466  |  |  | 
467  |  |     friend bool isnormal(Float16 x)  | 
468  | 0  |     { | 
469  | 0  |         using std::isnormal;  | 
470  | 0  |         return isnormal(float(x));  | 
471  | 0  |     }  | 
472  |  |  | 
473  |  |     friend bool signbit(Float16 x)  | 
474  | 0  |     { | 
475  | 0  |         using std::signbit;  | 
476  | 0  |         return signbit(float(x));  | 
477  | 0  |     }  | 
478  |  |  | 
479  |  |     friend Float16 abs(Float16 x)  | 
480  | 0  |     { | 
481  | 0  |         using std::abs;  | 
482  | 0  |         return Float16(abs(float(x)));  | 
483  | 0  |     }  | 
484  |  |  | 
485  |  |     friend Float16 cbrt(Float16 x)  | 
486  | 0  |     { | 
487  | 0  |         using std::cbrt;  | 
488  | 0  |         return Float16(cbrt(float(x)));  | 
489  | 0  |     }  | 
490  |  |  | 
491  |  |     friend Float16 ceil(Float16 x)  | 
492  | 0  |     { | 
493  | 0  |         using std::ceil;  | 
494  | 0  |         return Float16(ceil(float(x)));  | 
495  | 0  |     }  | 
496  |  |  | 
497  |  |     friend Float16 copysign(Float16 x, Float16 y)  | 
498  | 0  |     { | 
499  | 0  |         using std::copysign;  | 
500  | 0  |         return Float16(copysign(float(x), float(y)));  | 
501  | 0  |     }  | 
502  |  |  | 
503  |  |     friend Float16 fabs(Float16 x)  | 
504  | 0  |     { | 
505  | 0  |         using std::fabs;  | 
506  | 0  |         return Float16(fabs(float(x)));  | 
507  | 0  |     }  | 
508  |  |  | 
509  |  |     friend Float16 floor(Float16 x)  | 
510  | 0  |     { | 
511  | 0  |         using std::floor;  | 
512  | 0  |         return Float16(floor(float(x)));  | 
513  | 0  |     }  | 
514  |  |  | 
515  |  |     friend Float16 fmax(Float16 x, Float16 y)  | 
516  | 0  |     { | 
517  | 0  |         using std::fmax;  | 
518  | 0  |         return Float16(fmax(float(x), float(y)));  | 
519  | 0  |     }  | 
520  |  |  | 
521  |  |     friend Float16 fmin(Float16 x, Float16 y)  | 
522  | 0  |     { | 
523  | 0  |         using std::fmin;  | 
524  | 0  |         return Float16(fmin(float(x), float(y)));  | 
525  | 0  |     }  | 
526  |  |  | 
527  |  |     friend Float16 hypot(Float16 x, Float16 y)  | 
528  | 0  |     { | 
529  | 0  |         using std::hypot;  | 
530  | 0  |         return Float16(hypot(float(x), float(y)));  | 
531  | 0  |     }  | 
532  |  |  | 
533  |  |     friend Float16 max(Float16 x, Float16 y)  | 
534  | 0  |     { | 
535  | 0  |         using std::max;  | 
536  | 0  |         return Float16(max(float(x), float(y)));  | 
537  | 0  |     }  | 
538  |  |  | 
539  |  |     friend Float16 min(Float16 x, Float16 y)  | 
540  | 0  |     { | 
541  | 0  |         using std::min;  | 
542  | 0  |         return Float16(min(float(x), float(y)));  | 
543  | 0  |     }  | 
544  |  |  | 
545  |  |     // Adapted from the LLVM Project, under the Apache License v2.0  | 
546  |  |     friend Float16 nextafter(Float16 x, Float16 y)  | 
547  | 0  |     { | 
548  | 0  |         if (isnan(x))  | 
549  | 0  |             return x;  | 
550  | 0  |         if (isnan(y))  | 
551  | 0  |             return y;  | 
552  | 0  |         if (x == y)  | 
553  | 0  |             return y;  | 
554  |  |  | 
555  | 0  |         std::uint16_t bits;  | 
556  | 0  |         if (x != Float16(0))  | 
557  | 0  |         { | 
558  | 0  |             std::memcpy(&bits, &x.rValue, 2);  | 
559  | 0  |             if ((x < y) == (x > Float16(0)))  | 
560  | 0  |                 ++bits;  | 
561  | 0  |             else  | 
562  | 0  |                 --bits;  | 
563  | 0  |         }  | 
564  | 0  |         else  | 
565  | 0  |         { | 
566  | 0  |             bits = (signbit(y) << 15) | 0x0001;  | 
567  | 0  |         }  | 
568  |  | 
  | 
569  | 0  |         Float16 r;  | 
570  | 0  |         std::memcpy(&r.rValue, &bits, 2);  | 
571  |  | 
  | 
572  | 0  |         return r;  | 
573  | 0  |     }  | 
574  |  |  | 
575  |  |     friend Float16 pow(Float16 x, Float16 y)  | 
576  | 0  |     { | 
577  | 0  |         using std::pow;  | 
578  | 0  |         return Float16(pow(float(x), float(y)));  | 
579  | 0  |     }  | 
580  |  |  | 
581  |  |     friend Float16 pow(Float16 x, int n)  | 
582  | 0  |     { | 
583  | 0  |         using std::pow;  | 
584  | 0  |         return Float16(pow(float(x), n));  | 
585  | 0  |     }  | 
586  |  |  | 
587  |  |     friend Float16 round(Float16 x)  | 
588  | 0  |     { | 
589  | 0  |         using std::round;  | 
590  | 0  |         return Float16(round(float(x)));  | 
591  | 0  |     }  | 
592  |  |  | 
593  |  |     friend Float16 sqrt(Float16 x)  | 
594  | 0  |     { | 
595  | 0  |         using std::sqrt;  | 
596  | 0  |         return Float16(sqrt(float(x)));  | 
597  | 0  |     }  | 
598  |  | };  | 
599  |  |  | 
600  |  | template <> struct NumericLimits<Float16>  | 
601  |  | { | 
602  |  |     static constexpr bool is_specialized = true;  | 
603  |  |     static constexpr bool is_signed = true;  | 
604  |  |     static constexpr bool is_integer = false;  | 
605  |  |     static constexpr bool is_exact = false;  | 
606  |  |     static constexpr bool has_infinity = true;  | 
607  |  |     static constexpr bool has_quiet_NaN = true;  | 
608  |  |     static constexpr bool has_signaling_NaN = true;  | 
609  |  |     static constexpr bool has_denorm = true;  | 
610  |  |     static constexpr bool is_iec559 = true;  | 
611  |  |  | 
612  |  |     static constexpr int digits = 11;  | 
613  |  |     static constexpr int digits10 = 3;  | 
614  |  |     static constexpr int max_digits10 = 5;  | 
615  |  |     static constexpr int radix = 2;  | 
616  |  |  | 
617  |  |     static constexpr Float16 epsilon()  | 
618  | 0  |     { | 
619  | 0  |         return Float16(Float16::make_from_bits_and_value{}, 0x1400, 0.000977f); | 
620  | 0  |     }  | 
621  |  |  | 
622  |  |     static constexpr Float16 min()  | 
623  | 0  |     { | 
624  | 0  |         return Float16(Float16::make_from_bits_and_value{}, 0x0001, 6.0e-8f); | 
625  | 0  |     }  | 
626  |  |  | 
627  |  |     static constexpr Float16 lowest()  | 
628  | 0  |     { | 
629  | 0  |         return Float16(Float16::make_from_bits_and_value{}, 0xfbff, -65504.0f); | 
630  | 0  |     }  | 
631  |  |  | 
632  |  |     static constexpr Float16 max()  | 
633  | 0  |     { | 
634  | 0  |         return Float16(Float16::make_from_bits_and_value{}, 0x7bff, +65504.0f); | 
635  | 0  |     }  | 
636  |  |  | 
637  |  |     static constexpr Float16 infinity()  | 
638  | 0  |     { | 
639  | 0  |         return Float16(Float16::make_from_bits_and_value{}, 0x7c00, | 
640  | 0  |                        std::numeric_limits<float>::infinity());  | 
641  | 0  |     }  | 
642  |  |  | 
643  |  |     static constexpr Float16 quiet_NaN()  | 
644  | 0  |     { | 
645  | 0  |         return Float16(Float16::make_from_bits_and_value{}, 0x7e00, | 
646  | 0  |                        std::numeric_limits<float>::quiet_NaN());  | 
647  | 0  |     }  | 
648  |  |  | 
649  |  |     static constexpr Float16 signaling_NaN()  | 
650  | 0  |     { | 
651  | 0  |         return Float16(Float16::make_from_bits_and_value{}, 0xfe00, | 
652  | 0  |                        std::numeric_limits<float>::signaling_NaN());  | 
653  | 0  |     }  | 
654  |  | };  | 
655  |  |  | 
656  |  | //! @endcond  | 
657  |  |  | 
658  |  | #endif  // #ifndef HAVE_STD_FLOAT16_T  | 
659  |  |  | 
660  |  | }  // namespace cpl  | 
661  |  |  | 
662  |  | #ifdef HAVE_STD_FLOAT16_T  | 
663  |  | using GFloat16 = std::float16_t;  | 
664  |  | #else  | 
665  |  | using GFloat16 = cpl::Float16;  | 
666  |  | #endif  | 
667  |  |  | 
668  |  | // Define some GDAL wrappers. Their C equivalents are defined in `cpl_port.h`.  | 
669  |  | // (These wrappers are not necessary any more in C++, one can always  | 
670  |  | // call `isnan` etc directly.)  | 
671  |  |  | 
672  |  | template <typename T> constexpr int CPLIsNan(T x)  | 
673  | 0  | { | 
674  |  |     // We need to write `using std::isnan` instead of directly using  | 
675  |  |     // `std::isnan` because `std::isnan` only supports the types  | 
676  |  |     // `float` and `double`. The `isnan` for `cpl::Float16` is found in the  | 
677  |  |     // `cpl` namespace via argument-dependent lookup  | 
678  |  |     // <https://en.cppreference.com/w/cpp/language/adl>.  | 
679  | 0  |     using std::isnan;  | 
680  | 0  |     return isnan(x);  | 
681  | 0  | } Unexecuted instantiation: int CPLIsNan<double>(double) Unexecuted instantiation: int CPLIsNan<cpl::Float16>(cpl::Float16) Unexecuted instantiation: int CPLIsNan<float>(float)  | 
682  |  |  | 
683  |  | template <typename T> constexpr int CPLIsInf(T x)  | 
684  | 0  | { | 
685  | 0  |     using std::isinf;  | 
686  | 0  |     return isinf(x);  | 
687  | 0  | } Unexecuted instantiation: int CPLIsInf<double>(double) Unexecuted instantiation: int CPLIsInf<cpl::Float16>(cpl::Float16)  | 
688  |  |  | 
689  |  | template <typename T> constexpr int CPLIsFinite(T x)  | 
690  |  | { | 
691  |  |     using std::isfinite;  | 
692  |  |     return isfinite(x);  | 
693  |  | }  | 
694  |  |  | 
695  |  | #endif  // #ifdef __cplusplus  | 
696  |  |  | 
697  |  | double CPL_DLL CPLGreatestCommonDivisor(double x, double y);  | 
698  |  |  | 
699  |  | #endif  // CPL_FLOAT_H_INCLUDED  |