xref: /aosp_15_r20/external/deqp/external/openglcts/modules/common/glcMisc.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file glcMisc.cpp
21  * \brief Miscellaneous helper functions.
22  */ /*-------------------------------------------------------------------*/
23 
24 #include "glcMisc.hpp"
25 
26 using namespace glw;
27 
28 namespace glcts
29 {
30 
31 /* utility functions from the book OpenGL ES 2.0 Programming Guide */
32 /* -15 stored using a single precision bias of 127 */
33 const unsigned int HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP = 0x38000000;
34 /* max exponent value in single precision that will be converted */
35 /* to Inf or Nan when stored as a half-float */
36 const unsigned int HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP = 0x47800000;
37 /* 255 is the max exponent biased value */
38 const unsigned int FLOAT_MAX_BIASED_EXP      = (0xFF << 23);
39 const unsigned int HALF_FLOAT_MAX_BIASED_EXP = (0x1F << 10);
40 
floatToHalfFloat(float f)41 GLhalf floatToHalfFloat(float f)
42 {
43     union
44     {
45         float v;
46         unsigned int x;
47     };
48     v                 = f;
49     unsigned int sign = (GLhalf)(x >> 31);
50     unsigned int mantissa;
51     unsigned int exp;
52     GLhalf hf;
53 
54     /* get mantissa */
55     mantissa = x & ((1 << 23) - 1);
56     /* get exponent bits */
57     exp = x & FLOAT_MAX_BIASED_EXP;
58     if (exp >= HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP)
59     {
60         /* check if the original single precision float number is a NaN */
61         if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
62         {
63             /* we have a single precision NaN */
64             mantissa = (1 << 23) - 1;
65         }
66         else
67         {
68             /* 16-bit half-float representation stores number as Inf */
69             mantissa = 0;
70         }
71         hf = (((GLhalf)sign) << 15) | (GLhalf)(HALF_FLOAT_MAX_BIASED_EXP) | (GLhalf)(mantissa >> 13);
72     }
73     /* check if exponent is <= -15 */
74     else if (exp <= HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP)
75     {
76         /* store a denorm half-float value or zero */
77         exp = (HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23;
78         mantissa |= (1 << 23);
79 
80         if (exp < 18)
81             mantissa >>= (14 + exp);
82         else
83             mantissa = 0;
84 
85         hf = (((GLhalf)sign) << 15) | (GLhalf)(mantissa);
86     }
87     else
88     {
89         hf = (((GLhalf)sign) << 15) | (GLhalf)((exp - HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 13) |
90              (GLhalf)(mantissa >> 13);
91     }
92 
93     return hf;
94 }
95 
96 /* -15 stored using a single precision bias of 127 */
97 const unsigned int FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP = 0x38000000;
98 /* max exponent value in single precision that will be converted */
99 /* to Inf or Nan when stored as a half-float */
100 const unsigned int FLOAT11_MAX_BIASED_EXP_AS_SINGLE_FP_EXP = 0x47800000;
101 const unsigned int FLOAT11_MAX_BIASED_EXP                  = (0x1F << 6);
102 
floatToUnisgnedF11(float f)103 GLuint floatToUnisgnedF11(float f)
104 {
105     union
106     {
107         float v;
108         unsigned int x;
109     };
110     v                 = f;
111     unsigned int sign = (GLhalf)(x >> 31);
112     unsigned int mantissa;
113     unsigned int exp;
114     GLuint f11;
115 
116     /* get mantissa */
117     mantissa = x & ((1 << 23) - 1);
118     /* get exponent bits */
119     exp = x & FLOAT_MAX_BIASED_EXP;
120 
121     /* minus f32 value */
122     if (sign > 0)
123     {
124         /* f32 NaN -> f11 NaN */
125         if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
126         {
127             f11 = (GLuint)(FLOAT11_MAX_BIASED_EXP) | (GLuint)(0x0000003F);
128         }
129         /* Others round to 0.0 */
130         else
131         {
132             f11 = 0x00000000;
133         }
134 
135         return f11;
136     }
137 
138     /* only check positive value below */
139     if (exp >= FLOAT11_MAX_BIASED_EXP_AS_SINGLE_FP_EXP)
140     {
141         /* check if the original single precision float number is a NaN */
142         if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
143         {
144             /* we have a single precision NaN */
145             mantissa = (1 << 23) - 1;
146         }
147         else
148         {
149             /* 11-bit float representation stores number as Inf */
150             mantissa = 0;
151         }
152         f11 = (GLuint)(FLOAT11_MAX_BIASED_EXP) | (GLuint)(mantissa >> 17);
153     }
154     /* check if exponent is <= -15 */
155     else if (exp <= FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP)
156     {
157         /* store a denorm 11-bit float value or zero */
158         exp = (FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23;
159         mantissa |= (1 << 23);
160         if (18 + exp >= sizeof(mantissa) * 8)
161         {
162             mantissa = 0;
163         }
164         else
165         {
166             mantissa >>= (18 + exp);
167         }
168         f11 = mantissa;
169     }
170     else
171     {
172         f11 = ((exp - FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 17) | (mantissa >> 17);
173     }
174 
175     return f11;
176 }
177 
178 /* -15 stored using a single precision bias of 127 */
179 const unsigned int FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP = 0x38000000;
180 /* max exponent value in single precision that will be converted */
181 /* to Inf or Nan when stored as a half-float */
182 const unsigned int FLOAT10_MAX_BIASED_EXP_AS_SINGLE_FP_EXP = 0x47800000;
183 const unsigned int FLOAT10_MAX_BIASED_EXP                  = (0x1F << 5);
184 
floatToUnisgnedF10(float f)185 GLuint floatToUnisgnedF10(float f)
186 {
187     union
188     {
189         float v;
190         unsigned int x;
191     };
192     v                 = f;
193     unsigned int sign = (GLhalf)(x >> 31);
194     unsigned int mantissa;
195     unsigned int exp;
196     GLuint f10;
197 
198     /* get mantissa */
199     mantissa = x & ((1 << 23) - 1);
200     /* get exponent bits */
201     exp = x & FLOAT_MAX_BIASED_EXP;
202 
203     /* minus f32 value */
204     if (sign > 0)
205     {
206         /* f32 NaN -> f10 NaN */
207         if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
208         {
209             f10 = (GLuint)(FLOAT10_MAX_BIASED_EXP) | (GLuint)(0x0000001F);
210         }
211         /* Others round to 0.0 */
212         else
213         {
214             f10 = 0x00000000;
215         }
216 
217         return f10;
218     }
219 
220     /* only check positive value below */
221     if (exp >= FLOAT10_MAX_BIASED_EXP_AS_SINGLE_FP_EXP)
222     {
223         /* check if the original single precision float number is a NaN */
224         if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
225         {
226             /* we have a single precision NaN */
227             mantissa = (1 << 23) - 1;
228         }
229         else
230         {
231             /* 10-bit float representation stores number as Inf */
232             mantissa = 0;
233         }
234         f10 = (GLuint)(FLOAT10_MAX_BIASED_EXP) | (GLuint)(mantissa >> 18);
235     }
236     /* check if exponent is <= -15 */
237     else if (exp <= FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP)
238     {
239         /* store a denorm 11-bit float value or zero */
240         exp = (FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23;
241         mantissa |= (1 << 23);
242         if (19 + exp >= sizeof(mantissa) * 8)
243         {
244             mantissa = 0;
245         }
246         else
247         {
248             mantissa >>= (19 + exp);
249         }
250         f10 = mantissa;
251     }
252     else
253     {
254         f10 = ((exp - FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 18) | (mantissa >> 18);
255     }
256 
257     return f10;
258 }
259 
halfFloatToFloat(GLhalf hf)260 float halfFloatToFloat(GLhalf hf)
261 {
262     unsigned int sign     = (unsigned int)(hf >> 15);
263     unsigned int mantissa = (unsigned int)(hf & ((1 << 10) - 1));
264     unsigned int exp      = (unsigned int)(hf & HALF_FLOAT_MAX_BIASED_EXP);
265     union
266     {
267         float f;
268         unsigned int ui;
269     };
270 
271     if (exp == HALF_FLOAT_MAX_BIASED_EXP)
272     {
273         /* we have a half-float NaN or Inf */
274         /* half-float NaNs will be converted to a single precision NaN */
275         /* half-float Infs will be converted to a single precision Inf */
276         exp = FLOAT_MAX_BIASED_EXP;
277         if (mantissa)
278             mantissa = (1 << 23) - 1; /* set all bits to indicate a NaN */
279     }
280     else if (exp == 0x0)
281     {
282         /* convert half-float zero/denorm to single precision value */
283         if (mantissa)
284         {
285             mantissa <<= 1;
286             exp = HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
287             /* check for leading 1 in denorm mantissa */
288             while ((mantissa & (1 << 10)) == 0)
289             {
290                 /* for every leading 0, decrement single precision exponent by 1 */
291                 /* and shift half-float mantissa value to the left */
292                 mantissa <<= 1;
293                 exp -= (1 << 23);
294             }
295             /* clamp the mantissa to 10-bits */
296             mantissa &= ((1 << 10) - 1);
297             /* shift left to generate single-precision mantissa of 23-bits */
298             mantissa <<= 13;
299         }
300     }
301     else
302     {
303         /* shift left to generate single-precision mantissa of 23-bits */
304         mantissa <<= 13;
305         /* generate single precision biased exponent value */
306         exp = (exp << 13) + HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
307     }
308     ui = (sign << 31) | exp | mantissa;
309     return f;
310 }
311 
unsignedF11ToFloat(GLuint f11)312 float unsignedF11ToFloat(GLuint f11)
313 {
314     unsigned int mantissa = (unsigned int)(f11 & ((1 << 6) - 1));
315     unsigned int exp      = (unsigned int)(f11 & FLOAT11_MAX_BIASED_EXP);
316     union
317     {
318         float f;
319         unsigned int ui;
320     };
321 
322     if (exp == FLOAT11_MAX_BIASED_EXP)
323     {
324         /* we have a f11 NaN or Inf */
325         /* f11 NaNs will be converted to a single precision NaN */
326         /* f11 Infs will be converted to a single precision Inf */
327         exp = FLOAT_MAX_BIASED_EXP;
328         if (mantissa)
329             mantissa = (1 << 23) - 1; /* set all bits to indicate a NaN */
330     }
331     else if (exp == 0x0)
332     {
333         /* convert f11 zero/denorm to single precision value */
334         if (mantissa)
335         {
336             mantissa <<= 1;
337             exp = FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
338             /* check for leading 1 in denorm mantissa */
339             while ((mantissa & (1 << 10)) == 0)
340             {
341                 /* for every leading 0, decrement single precision exponent by 1 */
342                 /* and shift half-float mantissa value to the left */
343                 mantissa <<= 1;
344                 exp -= (1 << 23);
345             }
346             /* clamp the mantissa to 6-bits */
347             mantissa &= ((1 << 6) - 1);
348             /* shift left to generate single-precision mantissa of 23-bits */
349             mantissa <<= 17;
350         }
351     }
352     else
353     {
354         /* shift left to generate single-precision mantissa of 23-bits */
355         mantissa <<= 17;
356         /* generate single precision biased exponent value */
357         exp = (exp << 17) + FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
358     }
359     ui = exp | mantissa;
360     return f;
361 }
362 
unsignedF10ToFloat(GLuint f10)363 float unsignedF10ToFloat(GLuint f10)
364 {
365     unsigned int mantissa = (unsigned int)(f10 & ((1 << 5) - 1));
366     unsigned int exp      = (unsigned int)(f10 & FLOAT10_MAX_BIASED_EXP);
367     union
368     {
369         float f;
370         unsigned int ui;
371     };
372 
373     if (exp == FLOAT10_MAX_BIASED_EXP)
374     {
375         /* we have a f11 NaN or Inf */
376         /* f11 NaNs will be converted to a single precision NaN */
377         /* f11 Infs will be converted to a single precision Inf */
378         exp = FLOAT_MAX_BIASED_EXP;
379         if (mantissa)
380             mantissa = (1 << 23) - 1; /* set all bits to indicate a NaN */
381     }
382     else if (exp == 0x0)
383     {
384         /* convert f11 zero/denorm to single precision value */
385         if (mantissa)
386         {
387             mantissa <<= 1;
388             exp = FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
389             /* check for leading 1 in denorm mantissa */
390             while ((mantissa & (1 << 10)) == 0)
391             {
392                 /* for every leading 0, decrement single precision exponent by 1 */
393                 /* and shift half-float mantissa value to the left */
394                 mantissa <<= 1;
395                 exp -= (1 << 23);
396             }
397             /* clamp the mantissa to 5-bits */
398             mantissa &= ((1 << 5) - 1);
399             /* shift left to generate single-precision mantissa of 23-bits */
400             mantissa <<= 18;
401         }
402     }
403     else
404     {
405         /* shift left to generate single-precision mantissa of 23-bits */
406         mantissa <<= 18;
407         /* generate single precision biased exponent value */
408         exp = (exp << 18) + FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
409     }
410     ui = exp | mantissa;
411     return f;
412 }
413 
414 } // namespace glcts
415