xref: /aosp_15_r20/external/deqp/framework/common/tcuFloat.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker #ifndef _TCUFLOAT_HPP
2*35238bceSAndroid Build Coastguard Worker #define _TCUFLOAT_HPP
3*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program Tester Core
5*35238bceSAndroid Build Coastguard Worker  * ----------------------------------------
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
8*35238bceSAndroid Build Coastguard Worker  *
9*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
10*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
11*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
14*35238bceSAndroid Build Coastguard Worker  *
15*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
16*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
17*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
19*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
20*35238bceSAndroid Build Coastguard Worker  *
21*35238bceSAndroid Build Coastguard Worker  *//*!
22*35238bceSAndroid Build Coastguard Worker  * \file
23*35238bceSAndroid Build Coastguard Worker  * \brief Reconfigurable floating-point value template.
24*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
25*35238bceSAndroid Build Coastguard Worker 
26*35238bceSAndroid Build Coastguard Worker #include "tcuDefs.hpp"
27*35238bceSAndroid Build Coastguard Worker 
28*35238bceSAndroid Build Coastguard Worker // For memcpy().
29*35238bceSAndroid Build Coastguard Worker #include <limits>
30*35238bceSAndroid Build Coastguard Worker #include <string.h>
31*35238bceSAndroid Build Coastguard Worker 
32*35238bceSAndroid Build Coastguard Worker namespace tcu
33*35238bceSAndroid Build Coastguard Worker {
34*35238bceSAndroid Build Coastguard Worker 
35*35238bceSAndroid Build Coastguard Worker enum FloatFlags
36*35238bceSAndroid Build Coastguard Worker {
37*35238bceSAndroid Build Coastguard Worker     FLOAT_HAS_SIGN       = (1 << 0),
38*35238bceSAndroid Build Coastguard Worker     FLOAT_SUPPORT_DENORM = (1 << 1)
39*35238bceSAndroid Build Coastguard Worker };
40*35238bceSAndroid Build Coastguard Worker 
41*35238bceSAndroid Build Coastguard Worker enum RoundingDirection
42*35238bceSAndroid Build Coastguard Worker {
43*35238bceSAndroid Build Coastguard Worker     ROUND_TO_EVEN = 0,
44*35238bceSAndroid Build Coastguard Worker     ROUND_DOWNWARD, // Towards -Inf.
45*35238bceSAndroid Build Coastguard Worker     ROUND_UPWARD,   // Towards +Inf.
46*35238bceSAndroid Build Coastguard Worker     ROUND_TO_ZERO
47*35238bceSAndroid Build Coastguard Worker };
48*35238bceSAndroid Build Coastguard Worker 
49*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
50*35238bceSAndroid Build Coastguard Worker  * \brief Floating-point format template
51*35238bceSAndroid Build Coastguard Worker  *
52*35238bceSAndroid Build Coastguard Worker  * This template implements arbitrary floating-point handling. Template
53*35238bceSAndroid Build Coastguard Worker  * can be used for conversion between different formats and checking
54*35238bceSAndroid Build Coastguard Worker  * various properties of floating-point values.
55*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
56*35238bceSAndroid Build Coastguard Worker template <typename StorageType_, int ExponentBits, int MantissaBits, int ExponentBias, uint32_t Flags>
57*35238bceSAndroid Build Coastguard Worker class Float
58*35238bceSAndroid Build Coastguard Worker {
59*35238bceSAndroid Build Coastguard Worker public:
60*35238bceSAndroid Build Coastguard Worker     typedef StorageType_ StorageType;
61*35238bceSAndroid Build Coastguard Worker 
62*35238bceSAndroid Build Coastguard Worker     enum
63*35238bceSAndroid Build Coastguard Worker     {
64*35238bceSAndroid Build Coastguard Worker         EXPONENT_BITS = ExponentBits,
65*35238bceSAndroid Build Coastguard Worker         MANTISSA_BITS = MantissaBits,
66*35238bceSAndroid Build Coastguard Worker         EXPONENT_BIAS = ExponentBias,
67*35238bceSAndroid Build Coastguard Worker         FLAGS         = Flags,
68*35238bceSAndroid Build Coastguard Worker     };
69*35238bceSAndroid Build Coastguard Worker 
70*35238bceSAndroid Build Coastguard Worker     Float(void);
71*35238bceSAndroid Build Coastguard Worker     explicit Float(StorageType value);
72*35238bceSAndroid Build Coastguard Worker     explicit Float(float v, RoundingDirection rd = ROUND_TO_EVEN);
73*35238bceSAndroid Build Coastguard Worker     explicit Float(double v, RoundingDirection rd = ROUND_TO_EVEN);
74*35238bceSAndroid Build Coastguard Worker 
75*35238bceSAndroid Build Coastguard Worker     template <typename OtherStorageType, int OtherExponentBits, int OtherMantissaBits, int OtherExponentBias,
76*35238bceSAndroid Build Coastguard Worker               uint32_t OtherFlags>
77*35238bceSAndroid Build Coastguard Worker     static Float convert(
78*35238bceSAndroid Build Coastguard Worker         const Float<OtherStorageType, OtherExponentBits, OtherMantissaBits, OtherExponentBias, OtherFlags> &src,
79*35238bceSAndroid Build Coastguard Worker         RoundingDirection rd = ROUND_TO_EVEN);
80*35238bceSAndroid Build Coastguard Worker 
convert(const Float<StorageType,ExponentBits,MantissaBits,ExponentBias,Flags> & src,RoundingDirection=ROUND_TO_EVEN)81*35238bceSAndroid Build Coastguard Worker     static inline Float convert(const Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags> &src,
82*35238bceSAndroid Build Coastguard Worker                                 RoundingDirection = ROUND_TO_EVEN)
83*35238bceSAndroid Build Coastguard Worker     {
84*35238bceSAndroid Build Coastguard Worker         return src;
85*35238bceSAndroid Build Coastguard Worker     }
86*35238bceSAndroid Build Coastguard Worker 
87*35238bceSAndroid Build Coastguard Worker     /*--------------------------------------------------------------------*//*!
88*35238bceSAndroid Build Coastguard Worker      * \brief Construct floating point value
89*35238bceSAndroid Build Coastguard Worker      * \param sign        Sign. Must be +1/-1
90*35238bceSAndroid Build Coastguard Worker      * \param exponent    Exponent in range [1-ExponentBias, ExponentBias+1]
91*35238bceSAndroid Build Coastguard Worker      * \param mantissa    Mantissa bits with implicit leading bit explicitly set
92*35238bceSAndroid Build Coastguard Worker      * \return The specified float
93*35238bceSAndroid Build Coastguard Worker      *
94*35238bceSAndroid Build Coastguard Worker      * This function constructs a floating point value from its inputs.
95*35238bceSAndroid Build Coastguard Worker      * The normally implicit leading bit of the mantissa must be explicitly set.
96*35238bceSAndroid Build Coastguard Worker      * The exponent normally used for zero/subnormals is an invalid input. Such
97*35238bceSAndroid Build Coastguard Worker      * values are specified with the leading mantissa bit of zero and the lowest
98*35238bceSAndroid Build Coastguard Worker      * normal exponent (1-ExponentBias). Additionally having both exponent and
99*35238bceSAndroid Build Coastguard Worker      * mantissa set to zero is a shorthand notation for the correctly signed
100*35238bceSAndroid Build Coastguard Worker      * floating point zero. Inf and NaN must be specified directly with an
101*35238bceSAndroid Build Coastguard Worker      * exponent of ExponentBias+1 and the appropriate mantissa (with leading
102*35238bceSAndroid Build Coastguard Worker      * bit set)
103*35238bceSAndroid Build Coastguard Worker      *//*--------------------------------------------------------------------*/
104*35238bceSAndroid Build Coastguard Worker     static inline Float construct(int sign, int exponent, StorageType mantissa);
105*35238bceSAndroid Build Coastguard Worker 
106*35238bceSAndroid Build Coastguard Worker     /*--------------------------------------------------------------------*//*!
107*35238bceSAndroid Build Coastguard Worker      * \brief Construct floating point value. Explicit version
108*35238bceSAndroid Build Coastguard Worker      * \param sign        Sign. Must be +1/-1
109*35238bceSAndroid Build Coastguard Worker      * \param exponent    Exponent in range [-ExponentBias, ExponentBias+1]
110*35238bceSAndroid Build Coastguard Worker      * \param mantissa    Mantissa bits
111*35238bceSAndroid Build Coastguard Worker      * \return The specified float
112*35238bceSAndroid Build Coastguard Worker      *
113*35238bceSAndroid Build Coastguard Worker      * This function constructs a floating point value from its inputs with
114*35238bceSAndroid Build Coastguard Worker      * minimal intervention.
115*35238bceSAndroid Build Coastguard Worker      * The sign is turned into a sign bit and the exponent bias is added.
116*35238bceSAndroid Build Coastguard Worker      * See IEEE-754 for additional information on the inputs and
117*35238bceSAndroid Build Coastguard Worker      * the encoding of special values.
118*35238bceSAndroid Build Coastguard Worker      *//*--------------------------------------------------------------------*/
119*35238bceSAndroid Build Coastguard Worker     static Float constructBits(int sign, int exponent, StorageType mantissaBits);
120*35238bceSAndroid Build Coastguard Worker 
bits(void) const121*35238bceSAndroid Build Coastguard Worker     StorageType bits(void) const
122*35238bceSAndroid Build Coastguard Worker     {
123*35238bceSAndroid Build Coastguard Worker         return m_value;
124*35238bceSAndroid Build Coastguard Worker     }
125*35238bceSAndroid Build Coastguard Worker     float asFloat(void) const;
126*35238bceSAndroid Build Coastguard Worker     double asDouble(void) const;
127*35238bceSAndroid Build Coastguard Worker 
signBit(void) const128*35238bceSAndroid Build Coastguard Worker     inline int signBit(void) const
129*35238bceSAndroid Build Coastguard Worker     {
130*35238bceSAndroid Build Coastguard Worker         return (int)(m_value >> (ExponentBits + MantissaBits)) & 1;
131*35238bceSAndroid Build Coastguard Worker     }
exponentBits(void) const132*35238bceSAndroid Build Coastguard Worker     inline StorageType exponentBits(void) const
133*35238bceSAndroid Build Coastguard Worker     {
134*35238bceSAndroid Build Coastguard Worker         return (m_value >> MantissaBits) & ((StorageType(1) << ExponentBits) - 1);
135*35238bceSAndroid Build Coastguard Worker     }
mantissaBits(void) const136*35238bceSAndroid Build Coastguard Worker     inline StorageType mantissaBits(void) const
137*35238bceSAndroid Build Coastguard Worker     {
138*35238bceSAndroid Build Coastguard Worker         return m_value & ((StorageType(1) << MantissaBits) - 1);
139*35238bceSAndroid Build Coastguard Worker     }
140*35238bceSAndroid Build Coastguard Worker 
sign(void) const141*35238bceSAndroid Build Coastguard Worker     inline int sign(void) const
142*35238bceSAndroid Build Coastguard Worker     {
143*35238bceSAndroid Build Coastguard Worker         return signBit() ? -1 : 1;
144*35238bceSAndroid Build Coastguard Worker     }
exponent(void) const145*35238bceSAndroid Build Coastguard Worker     inline int exponent(void) const
146*35238bceSAndroid Build Coastguard Worker     {
147*35238bceSAndroid Build Coastguard Worker         return isDenorm() ? 1 - ExponentBias : (int)exponentBits() - ExponentBias;
148*35238bceSAndroid Build Coastguard Worker     }
mantissa(void) const149*35238bceSAndroid Build Coastguard Worker     inline StorageType mantissa(void) const
150*35238bceSAndroid Build Coastguard Worker     {
151*35238bceSAndroid Build Coastguard Worker         return isZero() || isDenorm() ? mantissaBits() : (mantissaBits() | (StorageType(1) << MantissaBits));
152*35238bceSAndroid Build Coastguard Worker     }
153*35238bceSAndroid Build Coastguard Worker 
isInf(void) const154*35238bceSAndroid Build Coastguard Worker     inline bool isInf(void) const
155*35238bceSAndroid Build Coastguard Worker     {
156*35238bceSAndroid Build Coastguard Worker         return exponentBits() == ((1 << ExponentBits) - 1) && mantissaBits() == 0;
157*35238bceSAndroid Build Coastguard Worker     }
isNaN(void) const158*35238bceSAndroid Build Coastguard Worker     inline bool isNaN(void) const
159*35238bceSAndroid Build Coastguard Worker     {
160*35238bceSAndroid Build Coastguard Worker         return exponentBits() == ((1 << ExponentBits) - 1) && mantissaBits() != 0;
161*35238bceSAndroid Build Coastguard Worker     }
isZero(void) const162*35238bceSAndroid Build Coastguard Worker     inline bool isZero(void) const
163*35238bceSAndroid Build Coastguard Worker     {
164*35238bceSAndroid Build Coastguard Worker         return exponentBits() == 0 && mantissaBits() == 0;
165*35238bceSAndroid Build Coastguard Worker     }
isDenorm(void) const166*35238bceSAndroid Build Coastguard Worker     inline bool isDenorm(void) const
167*35238bceSAndroid Build Coastguard Worker     {
168*35238bceSAndroid Build Coastguard Worker         return exponentBits() == 0 && mantissaBits() != 0;
169*35238bceSAndroid Build Coastguard Worker     }
170*35238bceSAndroid Build Coastguard Worker 
operator <(const Float<StorageType,ExponentBits,MantissaBits,ExponentBias,Flags> & other) const171*35238bceSAndroid Build Coastguard Worker     inline bool operator<(const Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags> &other) const
172*35238bceSAndroid Build Coastguard Worker     {
173*35238bceSAndroid Build Coastguard Worker         return this->asDouble() < other.asDouble();
174*35238bceSAndroid Build Coastguard Worker     }
175*35238bceSAndroid Build Coastguard Worker 
176*35238bceSAndroid Build Coastguard Worker     static Float zero(int sign);
177*35238bceSAndroid Build Coastguard Worker     static Float inf(int sign);
178*35238bceSAndroid Build Coastguard Worker     static Float nan(void);
179*35238bceSAndroid Build Coastguard Worker 
180*35238bceSAndroid Build Coastguard Worker     static Float largestNormal(int sign);
181*35238bceSAndroid Build Coastguard Worker     static Float smallestNormal(int sign);
182*35238bceSAndroid Build Coastguard Worker 
183*35238bceSAndroid Build Coastguard Worker private:
184*35238bceSAndroid Build Coastguard Worker     StorageType m_value;
185*35238bceSAndroid Build Coastguard Worker } DE_WARN_UNUSED_TYPE;
186*35238bceSAndroid Build Coastguard Worker 
187*35238bceSAndroid Build Coastguard Worker // Common floating-point types.
188*35238bceSAndroid Build Coastguard Worker typedef Float<uint16_t, 5, 10, 15, FLOAT_HAS_SIGN | FLOAT_SUPPORT_DENORM>
189*35238bceSAndroid Build Coastguard Worker     Float16; //!< IEEE 754-2008 16-bit floating-point value
190*35238bceSAndroid Build Coastguard Worker typedef Float<uint32_t, 8, 23, 127, FLOAT_HAS_SIGN | FLOAT_SUPPORT_DENORM>
191*35238bceSAndroid Build Coastguard Worker     Float32; //!< IEEE 754 32-bit floating-point value
192*35238bceSAndroid Build Coastguard Worker typedef Float<uint64_t, 11, 52, 1023, FLOAT_HAS_SIGN | FLOAT_SUPPORT_DENORM>
193*35238bceSAndroid Build Coastguard Worker     Float64; //!< IEEE 754 64-bit floating-point value
194*35238bceSAndroid Build Coastguard Worker 
195*35238bceSAndroid Build Coastguard Worker typedef Float<uint16_t, 5, 10, 15, FLOAT_HAS_SIGN>
196*35238bceSAndroid Build Coastguard Worker     Float16Denormless; //!< IEEE 754-2008 16-bit floating-point value without denormalized support
197*35238bceSAndroid Build Coastguard Worker 
198*35238bceSAndroid Build Coastguard Worker template <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, uint32_t Flags>
Float(void)199*35238bceSAndroid Build Coastguard Worker inline Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::Float(void) : m_value(0)
200*35238bceSAndroid Build Coastguard Worker {
201*35238bceSAndroid Build Coastguard Worker }
202*35238bceSAndroid Build Coastguard Worker 
203*35238bceSAndroid Build Coastguard Worker template <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, uint32_t Flags>
Float(StorageType value)204*35238bceSAndroid Build Coastguard Worker inline Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::Float(StorageType value) : m_value(value)
205*35238bceSAndroid Build Coastguard Worker {
206*35238bceSAndroid Build Coastguard Worker }
207*35238bceSAndroid Build Coastguard Worker 
208*35238bceSAndroid Build Coastguard Worker template <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, uint32_t Flags>
Float(float value,RoundingDirection rd)209*35238bceSAndroid Build Coastguard Worker inline Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::Float(float value, RoundingDirection rd)
210*35238bceSAndroid Build Coastguard Worker     : m_value(0)
211*35238bceSAndroid Build Coastguard Worker {
212*35238bceSAndroid Build Coastguard Worker     uint32_t u32;
213*35238bceSAndroid Build Coastguard Worker     memcpy(&u32, &value, sizeof(uint32_t));
214*35238bceSAndroid Build Coastguard Worker     *this = convert(Float32(u32), rd);
215*35238bceSAndroid Build Coastguard Worker }
216*35238bceSAndroid Build Coastguard Worker 
217*35238bceSAndroid Build Coastguard Worker template <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, uint32_t Flags>
Float(double value,RoundingDirection rd)218*35238bceSAndroid Build Coastguard Worker inline Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::Float(double value, RoundingDirection rd)
219*35238bceSAndroid Build Coastguard Worker     : m_value(0)
220*35238bceSAndroid Build Coastguard Worker {
221*35238bceSAndroid Build Coastguard Worker     uint64_t u64;
222*35238bceSAndroid Build Coastguard Worker     memcpy(&u64, &value, sizeof(uint64_t));
223*35238bceSAndroid Build Coastguard Worker     *this = convert(Float64(u64), rd);
224*35238bceSAndroid Build Coastguard Worker }
225*35238bceSAndroid Build Coastguard Worker 
226*35238bceSAndroid Build Coastguard Worker template <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, uint32_t Flags>
asFloat(void) const227*35238bceSAndroid Build Coastguard Worker inline float Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::asFloat(void) const
228*35238bceSAndroid Build Coastguard Worker {
229*35238bceSAndroid Build Coastguard Worker     float v;
230*35238bceSAndroid Build Coastguard Worker     uint32_t u32 = Float32::convert(*this).bits();
231*35238bceSAndroid Build Coastguard Worker     memcpy(&v, &u32, sizeof(uint32_t));
232*35238bceSAndroid Build Coastguard Worker     return v;
233*35238bceSAndroid Build Coastguard Worker }
234*35238bceSAndroid Build Coastguard Worker 
235*35238bceSAndroid Build Coastguard Worker template <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, uint32_t Flags>
asDouble(void) const236*35238bceSAndroid Build Coastguard Worker inline double Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::asDouble(void) const
237*35238bceSAndroid Build Coastguard Worker {
238*35238bceSAndroid Build Coastguard Worker     double v;
239*35238bceSAndroid Build Coastguard Worker     uint64_t u64 = Float64::convert(*this).bits();
240*35238bceSAndroid Build Coastguard Worker     memcpy(&v, &u64, sizeof(uint64_t));
241*35238bceSAndroid Build Coastguard Worker     return v;
242*35238bceSAndroid Build Coastguard Worker }
243*35238bceSAndroid Build Coastguard Worker 
244*35238bceSAndroid Build Coastguard Worker template <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, uint32_t Flags>
245*35238bceSAndroid Build Coastguard Worker inline Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags> Float<
zero(int sign)246*35238bceSAndroid Build Coastguard Worker     StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::zero(int sign)
247*35238bceSAndroid Build Coastguard Worker {
248*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(sign == 1 || ((Flags & FLOAT_HAS_SIGN) && sign == -1));
249*35238bceSAndroid Build Coastguard Worker     return Float(StorageType((sign > 0 ? 0ull : 1ull) << (ExponentBits + MantissaBits)));
250*35238bceSAndroid Build Coastguard Worker }
251*35238bceSAndroid Build Coastguard Worker 
252*35238bceSAndroid Build Coastguard Worker template <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, uint32_t Flags>
253*35238bceSAndroid Build Coastguard Worker inline Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags> Float<
inf(int sign)254*35238bceSAndroid Build Coastguard Worker     StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::inf(int sign)
255*35238bceSAndroid Build Coastguard Worker {
256*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(sign == 1 || ((Flags & FLOAT_HAS_SIGN) && sign == -1));
257*35238bceSAndroid Build Coastguard Worker     return Float(StorageType(((sign > 0 ? 0ull : 1ull) << (ExponentBits + MantissaBits)) |
258*35238bceSAndroid Build Coastguard Worker                              (((1ull << ExponentBits) - 1) << MantissaBits)));
259*35238bceSAndroid Build Coastguard Worker }
260*35238bceSAndroid Build Coastguard Worker 
261*35238bceSAndroid Build Coastguard Worker template <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, uint32_t Flags>
262*35238bceSAndroid Build Coastguard Worker inline Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags> Float<
nan(void)263*35238bceSAndroid Build Coastguard Worker     StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::nan(void)
264*35238bceSAndroid Build Coastguard Worker {
265*35238bceSAndroid Build Coastguard Worker     return Float(StorageType((1ull << (ExponentBits + MantissaBits)) - 1));
266*35238bceSAndroid Build Coastguard Worker }
267*35238bceSAndroid Build Coastguard Worker 
268*35238bceSAndroid Build Coastguard Worker template <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, uint32_t Flags>
269*35238bceSAndroid Build Coastguard Worker inline Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags> Float<
largestNormal(int sign)270*35238bceSAndroid Build Coastguard Worker     StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::largestNormal(int sign)
271*35238bceSAndroid Build Coastguard Worker {
272*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(sign == 1 || ((Flags & FLOAT_HAS_SIGN) && sign == -1));
273*35238bceSAndroid Build Coastguard Worker     return Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::construct(
274*35238bceSAndroid Build Coastguard Worker         sign, ExponentBias, (static_cast<StorageType>(1) << (MantissaBits + 1)) - 1);
275*35238bceSAndroid Build Coastguard Worker }
276*35238bceSAndroid Build Coastguard Worker 
277*35238bceSAndroid Build Coastguard Worker template <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, uint32_t Flags>
278*35238bceSAndroid Build Coastguard Worker inline Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags> Float<
smallestNormal(int sign)279*35238bceSAndroid Build Coastguard Worker     StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::smallestNormal(int sign)
280*35238bceSAndroid Build Coastguard Worker {
281*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(sign == 1 || ((Flags & FLOAT_HAS_SIGN) && sign == -1));
282*35238bceSAndroid Build Coastguard Worker     return Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::construct(
283*35238bceSAndroid Build Coastguard Worker         sign, 1 - ExponentBias, (static_cast<StorageType>(1) << MantissaBits));
284*35238bceSAndroid Build Coastguard Worker }
285*35238bceSAndroid Build Coastguard Worker 
286*35238bceSAndroid Build Coastguard Worker template <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, uint32_t Flags>
287*35238bceSAndroid Build Coastguard Worker Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags> Float<
construct(int sign,int exponent,StorageType mantissa)288*35238bceSAndroid Build Coastguard Worker     StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::construct(int sign, int exponent,
289*35238bceSAndroid Build Coastguard Worker                                                                              StorageType mantissa)
290*35238bceSAndroid Build Coastguard Worker {
291*35238bceSAndroid Build Coastguard Worker     // Repurpose this otherwise invalid input as a shorthand notation for zero (no need for caller to care about internal representation)
292*35238bceSAndroid Build Coastguard Worker     const bool isShorthandZero = exponent == 0 && mantissa == 0;
293*35238bceSAndroid Build Coastguard Worker 
294*35238bceSAndroid Build Coastguard Worker     // Handles the typical notation for zero (min exponent, mantissa 0). Note that the exponent usually used exponent (-ExponentBias) for zero/subnormals is not used.
295*35238bceSAndroid Build Coastguard Worker     // Instead zero/subnormals have the (normally implicit) leading mantissa bit set to zero.
296*35238bceSAndroid Build Coastguard Worker     const bool isDenormOrZero = (exponent == 1 - ExponentBias) && (mantissa >> MantissaBits == 0);
297*35238bceSAndroid Build Coastguard Worker     const StorageType s   = StorageType((StorageType(sign < 0 ? 1 : 0)) << (StorageType(ExponentBits + MantissaBits)));
298*35238bceSAndroid Build Coastguard Worker     const StorageType exp = (isShorthandZero || isDenormOrZero) ? StorageType(0) : StorageType(exponent + ExponentBias);
299*35238bceSAndroid Build Coastguard Worker 
300*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(sign == +1 || sign == -1);
301*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isShorthandZero || isDenormOrZero || mantissa >> MantissaBits == 1);
302*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(exp >> ExponentBits == 0);
303*35238bceSAndroid Build Coastguard Worker 
304*35238bceSAndroid Build Coastguard Worker     return Float(StorageType(s | (exp << MantissaBits) | (mantissa & ((StorageType(1) << MantissaBits) - 1))));
305*35238bceSAndroid Build Coastguard Worker }
306*35238bceSAndroid Build Coastguard Worker 
307*35238bceSAndroid Build Coastguard Worker template <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, uint32_t Flags>
308*35238bceSAndroid Build Coastguard Worker Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags> Float<
constructBits(int sign,int exponent,StorageType mantissaBits)309*35238bceSAndroid Build Coastguard Worker     StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::constructBits(int sign, int exponent,
310*35238bceSAndroid Build Coastguard Worker                                                                                  StorageType mantissaBits)
311*35238bceSAndroid Build Coastguard Worker {
312*35238bceSAndroid Build Coastguard Worker     const StorageType signBit      = static_cast<StorageType>(sign < 0 ? 1 : 0);
313*35238bceSAndroid Build Coastguard Worker     const StorageType exponentBits = static_cast<StorageType>(exponent + ExponentBias);
314*35238bceSAndroid Build Coastguard Worker 
315*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(sign == +1 || sign == -1);
316*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(exponentBits >> ExponentBits == 0);
317*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(mantissaBits >> MantissaBits == 0);
318*35238bceSAndroid Build Coastguard Worker 
319*35238bceSAndroid Build Coastguard Worker     return Float(
320*35238bceSAndroid Build Coastguard Worker         StorageType((signBit << (ExponentBits + MantissaBits)) | (exponentBits << MantissaBits) | (mantissaBits)));
321*35238bceSAndroid Build Coastguard Worker }
322*35238bceSAndroid Build Coastguard Worker 
323*35238bceSAndroid Build Coastguard Worker template <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, uint32_t Flags>
324*35238bceSAndroid Build Coastguard Worker template <typename OtherStorageType, int OtherExponentBits, int OtherMantissaBits, int OtherExponentBias,
325*35238bceSAndroid Build Coastguard Worker           uint32_t OtherFlags>
326*35238bceSAndroid Build Coastguard Worker Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags> Float<StorageType, ExponentBits, MantissaBits,
327*35238bceSAndroid Build Coastguard Worker                                                                           ExponentBias, Flags>::
convert(const Float<OtherStorageType,OtherExponentBits,OtherMantissaBits,OtherExponentBias,OtherFlags> & other,RoundingDirection rd)328*35238bceSAndroid Build Coastguard Worker     convert(const Float<OtherStorageType, OtherExponentBits, OtherMantissaBits, OtherExponentBias, OtherFlags> &other,
329*35238bceSAndroid Build Coastguard Worker             RoundingDirection rd)
330*35238bceSAndroid Build Coastguard Worker {
331*35238bceSAndroid Build Coastguard Worker     int sign = other.sign();
332*35238bceSAndroid Build Coastguard Worker 
333*35238bceSAndroid Build Coastguard Worker     if (!(Flags & FLOAT_HAS_SIGN) && sign < 0)
334*35238bceSAndroid Build Coastguard Worker     {
335*35238bceSAndroid Build Coastguard Worker         // Negative number, truncate to zero.
336*35238bceSAndroid Build Coastguard Worker         return zero(+1);
337*35238bceSAndroid Build Coastguard Worker     }
338*35238bceSAndroid Build Coastguard Worker 
339*35238bceSAndroid Build Coastguard Worker     if (other.isInf())
340*35238bceSAndroid Build Coastguard Worker     {
341*35238bceSAndroid Build Coastguard Worker         return inf(sign);
342*35238bceSAndroid Build Coastguard Worker     }
343*35238bceSAndroid Build Coastguard Worker 
344*35238bceSAndroid Build Coastguard Worker     if (other.isNaN())
345*35238bceSAndroid Build Coastguard Worker     {
346*35238bceSAndroid Build Coastguard Worker         return nan();
347*35238bceSAndroid Build Coastguard Worker     }
348*35238bceSAndroid Build Coastguard Worker 
349*35238bceSAndroid Build Coastguard Worker     if (other.isZero())
350*35238bceSAndroid Build Coastguard Worker     {
351*35238bceSAndroid Build Coastguard Worker         return zero(sign);
352*35238bceSAndroid Build Coastguard Worker     }
353*35238bceSAndroid Build Coastguard Worker 
354*35238bceSAndroid Build Coastguard Worker     const int eMin = 1 - ExponentBias;
355*35238bceSAndroid Build Coastguard Worker     const int eMax = ((1 << ExponentBits) - 2) - ExponentBias;
356*35238bceSAndroid Build Coastguard Worker 
357*35238bceSAndroid Build Coastguard Worker     const StorageType s = StorageType((StorageType(other.signBit()))
358*35238bceSAndroid Build Coastguard Worker                                       << (StorageType(ExponentBits + MantissaBits))); // \note Not sign, but sign bit.
359*35238bceSAndroid Build Coastguard Worker     int e               = other.exponent();
360*35238bceSAndroid Build Coastguard Worker     uint64_t m          = other.mantissa();
361*35238bceSAndroid Build Coastguard Worker 
362*35238bceSAndroid Build Coastguard Worker     // Normalize denormalized values prior to conversion.
363*35238bceSAndroid Build Coastguard Worker     while (!(m & (1ull << OtherMantissaBits)))
364*35238bceSAndroid Build Coastguard Worker     {
365*35238bceSAndroid Build Coastguard Worker         m <<= 1;
366*35238bceSAndroid Build Coastguard Worker         e -= 1;
367*35238bceSAndroid Build Coastguard Worker     }
368*35238bceSAndroid Build Coastguard Worker 
369*35238bceSAndroid Build Coastguard Worker     if (e < eMin)
370*35238bceSAndroid Build Coastguard Worker     {
371*35238bceSAndroid Build Coastguard Worker         // Underflow.
372*35238bceSAndroid Build Coastguard Worker         if ((Flags & FLOAT_SUPPORT_DENORM) && (eMin - e - 1 <= MantissaBits))
373*35238bceSAndroid Build Coastguard Worker         {
374*35238bceSAndroid Build Coastguard Worker             // Shift and round.
375*35238bceSAndroid Build Coastguard Worker             int bitDiff           = (OtherMantissaBits - MantissaBits) + (eMin - e);
376*35238bceSAndroid Build Coastguard Worker             uint64_t lastBitsMask = (1ull << bitDiff) - 1ull;
377*35238bceSAndroid Build Coastguard Worker             uint64_t lastBits     = (static_cast<uint64_t>(m) & lastBitsMask);
378*35238bceSAndroid Build Coastguard Worker             uint64_t half         = (1ull << (bitDiff - 1)) - 1;
379*35238bceSAndroid Build Coastguard Worker             uint64_t bias         = (m >> bitDiff) & 1;
380*35238bceSAndroid Build Coastguard Worker 
381*35238bceSAndroid Build Coastguard Worker             switch (rd)
382*35238bceSAndroid Build Coastguard Worker             {
383*35238bceSAndroid Build Coastguard Worker             case ROUND_TO_EVEN:
384*35238bceSAndroid Build Coastguard Worker                 return Float(StorageType(s | (m + half + bias) >> bitDiff));
385*35238bceSAndroid Build Coastguard Worker 
386*35238bceSAndroid Build Coastguard Worker             case ROUND_DOWNWARD:
387*35238bceSAndroid Build Coastguard Worker                 m = (m >> bitDiff);
388*35238bceSAndroid Build Coastguard Worker                 if (lastBits != 0ull && sign < 0)
389*35238bceSAndroid Build Coastguard Worker                 {
390*35238bceSAndroid Build Coastguard Worker                     m += 1;
391*35238bceSAndroid Build Coastguard Worker                 }
392*35238bceSAndroid Build Coastguard Worker                 return Float(StorageType(s | m));
393*35238bceSAndroid Build Coastguard Worker 
394*35238bceSAndroid Build Coastguard Worker             case ROUND_UPWARD:
395*35238bceSAndroid Build Coastguard Worker                 m = (m >> bitDiff);
396*35238bceSAndroid Build Coastguard Worker                 if (lastBits != 0ull && sign > 0)
397*35238bceSAndroid Build Coastguard Worker                 {
398*35238bceSAndroid Build Coastguard Worker                     m += 1;
399*35238bceSAndroid Build Coastguard Worker                 }
400*35238bceSAndroid Build Coastguard Worker                 return Float(StorageType(s | m));
401*35238bceSAndroid Build Coastguard Worker 
402*35238bceSAndroid Build Coastguard Worker             case ROUND_TO_ZERO:
403*35238bceSAndroid Build Coastguard Worker                 return Float(StorageType(s | (m >> bitDiff)));
404*35238bceSAndroid Build Coastguard Worker 
405*35238bceSAndroid Build Coastguard Worker             default:
406*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(false);
407*35238bceSAndroid Build Coastguard Worker                 break;
408*35238bceSAndroid Build Coastguard Worker             }
409*35238bceSAndroid Build Coastguard Worker         }
410*35238bceSAndroid Build Coastguard Worker 
411*35238bceSAndroid Build Coastguard Worker         return zero(sign);
412*35238bceSAndroid Build Coastguard Worker     }
413*35238bceSAndroid Build Coastguard Worker 
414*35238bceSAndroid Build Coastguard Worker     // Remove leading 1.
415*35238bceSAndroid Build Coastguard Worker     m = m & ~(1ull << OtherMantissaBits);
416*35238bceSAndroid Build Coastguard Worker 
417*35238bceSAndroid Build Coastguard Worker     if (MantissaBits < OtherMantissaBits)
418*35238bceSAndroid Build Coastguard Worker     {
419*35238bceSAndroid Build Coastguard Worker         // Round mantissa.
420*35238bceSAndroid Build Coastguard Worker         int bitDiff           = OtherMantissaBits - MantissaBits;
421*35238bceSAndroid Build Coastguard Worker         uint64_t lastBitsMask = (1ull << bitDiff) - 1ull;
422*35238bceSAndroid Build Coastguard Worker         uint64_t lastBits     = (static_cast<uint64_t>(m) & lastBitsMask);
423*35238bceSAndroid Build Coastguard Worker         uint64_t half         = (1ull << (bitDiff - 1)) - 1;
424*35238bceSAndroid Build Coastguard Worker         uint64_t bias         = (m >> bitDiff) & 1;
425*35238bceSAndroid Build Coastguard Worker 
426*35238bceSAndroid Build Coastguard Worker         switch (rd)
427*35238bceSAndroid Build Coastguard Worker         {
428*35238bceSAndroid Build Coastguard Worker         case ROUND_TO_EVEN:
429*35238bceSAndroid Build Coastguard Worker             m = (m + half + bias) >> bitDiff;
430*35238bceSAndroid Build Coastguard Worker             break;
431*35238bceSAndroid Build Coastguard Worker 
432*35238bceSAndroid Build Coastguard Worker         case ROUND_DOWNWARD:
433*35238bceSAndroid Build Coastguard Worker             m = (m >> bitDiff);
434*35238bceSAndroid Build Coastguard Worker             if (lastBits != 0ull && sign < 0)
435*35238bceSAndroid Build Coastguard Worker             {
436*35238bceSAndroid Build Coastguard Worker                 m += 1;
437*35238bceSAndroid Build Coastguard Worker             }
438*35238bceSAndroid Build Coastguard Worker             break;
439*35238bceSAndroid Build Coastguard Worker 
440*35238bceSAndroid Build Coastguard Worker         case ROUND_UPWARD:
441*35238bceSAndroid Build Coastguard Worker             m = (m >> bitDiff);
442*35238bceSAndroid Build Coastguard Worker             if (lastBits != 0ull && sign > 0)
443*35238bceSAndroid Build Coastguard Worker             {
444*35238bceSAndroid Build Coastguard Worker                 m += 1;
445*35238bceSAndroid Build Coastguard Worker             }
446*35238bceSAndroid Build Coastguard Worker             break;
447*35238bceSAndroid Build Coastguard Worker 
448*35238bceSAndroid Build Coastguard Worker         case ROUND_TO_ZERO:
449*35238bceSAndroid Build Coastguard Worker             m = (m >> bitDiff);
450*35238bceSAndroid Build Coastguard Worker             break;
451*35238bceSAndroid Build Coastguard Worker 
452*35238bceSAndroid Build Coastguard Worker         default:
453*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
454*35238bceSAndroid Build Coastguard Worker             break;
455*35238bceSAndroid Build Coastguard Worker         }
456*35238bceSAndroid Build Coastguard Worker 
457*35238bceSAndroid Build Coastguard Worker         if (m & (1ull << MantissaBits))
458*35238bceSAndroid Build Coastguard Worker         {
459*35238bceSAndroid Build Coastguard Worker             // Overflow in mantissa.
460*35238bceSAndroid Build Coastguard Worker             m = 0;
461*35238bceSAndroid Build Coastguard Worker             e += 1;
462*35238bceSAndroid Build Coastguard Worker         }
463*35238bceSAndroid Build Coastguard Worker     }
464*35238bceSAndroid Build Coastguard Worker     else
465*35238bceSAndroid Build Coastguard Worker     {
466*35238bceSAndroid Build Coastguard Worker         int bitDiff = MantissaBits - OtherMantissaBits;
467*35238bceSAndroid Build Coastguard Worker         m           = m << bitDiff;
468*35238bceSAndroid Build Coastguard Worker     }
469*35238bceSAndroid Build Coastguard Worker 
470*35238bceSAndroid Build Coastguard Worker     if (e > eMax)
471*35238bceSAndroid Build Coastguard Worker     {
472*35238bceSAndroid Build Coastguard Worker         // Overflow.
473*35238bceSAndroid Build Coastguard Worker         return (((sign < 0 && rd == ROUND_UPWARD) || (sign > 0 && rd == ROUND_DOWNWARD)) ? largestNormal(sign) :
474*35238bceSAndroid Build Coastguard Worker                                                                                            inf(sign));
475*35238bceSAndroid Build Coastguard Worker     }
476*35238bceSAndroid Build Coastguard Worker 
477*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::inRange(e, eMin, eMax));
478*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(((e + ExponentBias) & ~((1ull << ExponentBits) - 1)) == 0);
479*35238bceSAndroid Build Coastguard Worker     DE_ASSERT((m & ~((1ull << MantissaBits) - 1)) == 0);
480*35238bceSAndroid Build Coastguard Worker 
481*35238bceSAndroid Build Coastguard Worker     return Float(StorageType(s | (StorageType(e + ExponentBias) << MantissaBits) | m));
482*35238bceSAndroid Build Coastguard Worker }
483*35238bceSAndroid Build Coastguard Worker 
484*35238bceSAndroid Build Coastguard Worker typedef typename Float16::StorageType float16_t;
485*35238bceSAndroid Build Coastguard Worker template <class F>
486*35238bceSAndroid Build Coastguard Worker inline constexpr F floatQuietNaN = std::numeric_limits<F>::quiet_NaN();
487*35238bceSAndroid Build Coastguard Worker template <>
488*35238bceSAndroid Build Coastguard Worker inline constexpr float16_t floatQuietNaN<float16_t> = 0x7e01;
489*35238bceSAndroid Build Coastguard Worker template <class F>
490*35238bceSAndroid Build Coastguard Worker inline constexpr F floatSignalingNaN = std::numeric_limits<F>::signaling_NaN();
491*35238bceSAndroid Build Coastguard Worker template <>
492*35238bceSAndroid Build Coastguard Worker inline constexpr float16_t floatSignalingNaN<float16_t> = 0x7c01;
493*35238bceSAndroid Build Coastguard Worker 
494*35238bceSAndroid Build Coastguard Worker } // namespace tcu
495*35238bceSAndroid Build Coastguard Worker 
496*35238bceSAndroid Build Coastguard Worker #endif // _TCUFLOAT_HPP
497