• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 		float		 v;
45 		unsigned int x;
46 	};
47 	v				  = f;
48 	unsigned int sign = (GLhalf)(x >> 31);
49 	unsigned int mantissa;
50 	unsigned int exp;
51 	GLhalf		 hf;
52 
53 	/* get mantissa */
54 	mantissa = x & ((1 << 23) - 1);
55 	/* get exponent bits */
56 	exp = x & FLOAT_MAX_BIASED_EXP;
57 	if (exp >= HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP)
58 	{
59 		/* check if the original single precision float number is a NaN */
60 		if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
61 		{
62 			/* we have a single precision NaN */
63 			mantissa = (1 << 23) - 1;
64 		}
65 		else
66 		{
67 			/* 16-bit half-float representation stores number as Inf */
68 			mantissa = 0;
69 		}
70 		hf = (((GLhalf)sign) << 15) | (GLhalf)(HALF_FLOAT_MAX_BIASED_EXP) | (GLhalf)(mantissa >> 13);
71 	}
72 	/* check if exponent is <= -15 */
73 	else if (exp <= HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP)
74 	{
75 		/* store a denorm half-float value or zero */
76 		exp = (HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23;
77 		mantissa |= (1 << 23);
78 
79 		if (exp < 18)
80 			mantissa >>= (14 + exp);
81 		else
82 			mantissa = 0;
83 
84 		hf = (((GLhalf)sign) << 15) | (GLhalf)(mantissa);
85 	}
86 	else
87 	{
88 		hf = (((GLhalf)sign) << 15) | (GLhalf)((exp - HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 13) |
89 			 (GLhalf)(mantissa >> 13);
90 	}
91 
92 	return hf;
93 }
94 
95 /* -15 stored using a single precision bias of 127 */
96 const unsigned int FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP = 0x38000000;
97 /* max exponent value in single precision that will be converted */
98 /* to Inf or Nan when stored as a half-float */
99 const unsigned int FLOAT11_MAX_BIASED_EXP_AS_SINGLE_FP_EXP = 0x47800000;
100 const unsigned int FLOAT11_MAX_BIASED_EXP				   = (0x1F << 6);
101 
floatToUnisgnedF11(float f)102 GLuint floatToUnisgnedF11(float f)
103 {
104 	union {
105 		float		 v;
106 		unsigned int x;
107 	};
108 	v				  = f;
109 	unsigned int sign = (GLhalf)(x >> 31);
110 	unsigned int mantissa;
111 	unsigned int exp;
112 	GLuint		 f11;
113 
114 	/* get mantissa */
115 	mantissa = x & ((1 << 23) - 1);
116 	/* get exponent bits */
117 	exp = x & FLOAT_MAX_BIASED_EXP;
118 
119 	/* minus f32 value */
120 	if (sign > 0)
121 	{
122 		/* f32 NaN -> f11 NaN */
123 		if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
124 		{
125 			f11 = (GLuint)(FLOAT11_MAX_BIASED_EXP) | (GLuint)(0x0000003F);
126 		}
127 		/* Others round to 0.0 */
128 		else
129 		{
130 			f11 = 0x00000000;
131 		}
132 
133 		return f11;
134 	}
135 
136 	/* only check positive value below */
137 	if (exp >= FLOAT11_MAX_BIASED_EXP_AS_SINGLE_FP_EXP)
138 	{
139 		/* check if the original single precision float number is a NaN */
140 		if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
141 		{
142 			/* we have a single precision NaN */
143 			mantissa = (1 << 23) - 1;
144 		}
145 		else
146 		{
147 			/* 11-bit float representation stores number as Inf */
148 			mantissa = 0;
149 		}
150 		f11 = (GLuint)(FLOAT11_MAX_BIASED_EXP) | (GLuint)(mantissa >> 17);
151 	}
152 	/* check if exponent is <= -15 */
153 	else if (exp <= FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP)
154 	{
155 		/* store a denorm 11-bit float value or zero */
156 		exp = (FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23;
157 		mantissa |= (1 << 23);
158 		if (18 + exp >= sizeof(mantissa) * 8)
159 		{
160 			mantissa = 0;
161 		}
162 		else
163 		{
164 			mantissa >>= (18 + exp);
165 		}
166 		f11 = mantissa;
167 	}
168 	else
169 	{
170 		f11 = ((exp - FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 17) | (mantissa >> 17);
171 	}
172 
173 	return f11;
174 }
175 
176 /* -15 stored using a single precision bias of 127 */
177 const unsigned int FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP = 0x38000000;
178 /* max exponent value in single precision that will be converted */
179 /* to Inf or Nan when stored as a half-float */
180 const unsigned int FLOAT10_MAX_BIASED_EXP_AS_SINGLE_FP_EXP = 0x47800000;
181 const unsigned int FLOAT10_MAX_BIASED_EXP				   = (0x1F << 5);
182 
floatToUnisgnedF10(float f)183 GLuint floatToUnisgnedF10(float f)
184 {
185 	union {
186 		float		 v;
187 		unsigned int x;
188 	};
189 	v				  = f;
190 	unsigned int sign = (GLhalf)(x >> 31);
191 	unsigned int mantissa;
192 	unsigned int exp;
193 	GLuint		 f10;
194 
195 	/* get mantissa */
196 	mantissa = x & ((1 << 23) - 1);
197 	/* get exponent bits */
198 	exp = x & FLOAT_MAX_BIASED_EXP;
199 
200 	/* minus f32 value */
201 	if (sign > 0)
202 	{
203 		/* f32 NaN -> f10 NaN */
204 		if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
205 		{
206 			f10 = (GLuint)(FLOAT10_MAX_BIASED_EXP) | (GLuint)(0x0000001F);
207 		}
208 		/* Others round to 0.0 */
209 		else
210 		{
211 			f10 = 0x00000000;
212 		}
213 
214 		return f10;
215 	}
216 
217 	/* only check positive value below */
218 	if (exp >= FLOAT10_MAX_BIASED_EXP_AS_SINGLE_FP_EXP)
219 	{
220 		/* check if the original single precision float number is a NaN */
221 		if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
222 		{
223 			/* we have a single precision NaN */
224 			mantissa = (1 << 23) - 1;
225 		}
226 		else
227 		{
228 			/* 10-bit float representation stores number as Inf */
229 			mantissa = 0;
230 		}
231 		f10 = (GLuint)(FLOAT10_MAX_BIASED_EXP) | (GLuint)(mantissa >> 18);
232 	}
233 	/* check if exponent is <= -15 */
234 	else if (exp <= FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP)
235 	{
236 		/* store a denorm 11-bit float value or zero */
237 		exp = (FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23;
238 		mantissa |= (1 << 23);
239 		if (19 + exp >= sizeof(mantissa) * 8)
240 		{
241 			mantissa = 0;
242 		}
243 		else
244 		{
245 			mantissa >>= (19 + exp);
246 		}
247 		f10 = mantissa;
248 	}
249 	else
250 	{
251 		f10 = ((exp - FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 18) | (mantissa >> 18);
252 	}
253 
254 	return f10;
255 }
256 
halfFloatToFloat(GLhalf hf)257 float halfFloatToFloat(GLhalf hf)
258 {
259 	unsigned int sign	 = (unsigned int)(hf >> 15);
260 	unsigned int mantissa = (unsigned int)(hf & ((1 << 10) - 1));
261 	unsigned int exp	  = (unsigned int)(hf & HALF_FLOAT_MAX_BIASED_EXP);
262 	union {
263 		float		 f;
264 		unsigned int ui;
265 	};
266 
267 	if (exp == HALF_FLOAT_MAX_BIASED_EXP)
268 	{
269 		/* we have a half-float NaN or Inf */
270 		/* half-float NaNs will be converted to a single precision NaN */
271 		/* half-float Infs will be converted to a single precision Inf */
272 		exp = FLOAT_MAX_BIASED_EXP;
273 		if (mantissa)
274 			mantissa = (1 << 23) - 1; /* set all bits to indicate a NaN */
275 	}
276 	else if (exp == 0x0)
277 	{
278 		/* convert half-float zero/denorm to single precision value */
279 		if (mantissa)
280 		{
281 			mantissa <<= 1;
282 			exp = HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
283 			/* check for leading 1 in denorm mantissa */
284 			while ((mantissa & (1 << 10)) == 0)
285 			{
286 				/* for every leading 0, decrement single precision exponent by 1 */
287 				/* and shift half-float mantissa value to the left */
288 				mantissa <<= 1;
289 				exp -= (1 << 23);
290 			}
291 			/* clamp the mantissa to 10-bits */
292 			mantissa &= ((1 << 10) - 1);
293 			/* shift left to generate single-precision mantissa of 23-bits */
294 			mantissa <<= 13;
295 		}
296 	}
297 	else
298 	{
299 		/* shift left to generate single-precision mantissa of 23-bits */
300 		mantissa <<= 13;
301 		/* generate single precision biased exponent value */
302 		exp = (exp << 13) + HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
303 	}
304 	ui = (sign << 31) | exp | mantissa;
305 	return f;
306 }
307 
unsignedF11ToFloat(GLuint f11)308 float unsignedF11ToFloat(GLuint f11)
309 {
310 	unsigned int mantissa = (unsigned int)(f11 & ((1 << 6) - 1));
311 	unsigned int exp	  = (unsigned int)(f11 & FLOAT11_MAX_BIASED_EXP);
312 	union {
313 		float		 f;
314 		unsigned int ui;
315 	};
316 
317 	if (exp == FLOAT11_MAX_BIASED_EXP)
318 	{
319 		/* we have a f11 NaN or Inf */
320 		/* f11 NaNs will be converted to a single precision NaN */
321 		/* f11 Infs will be converted to a single precision Inf */
322 		exp = FLOAT_MAX_BIASED_EXP;
323 		if (mantissa)
324 			mantissa = (1 << 23) - 1; /* set all bits to indicate a NaN */
325 	}
326 	else if (exp == 0x0)
327 	{
328 		/* convert f11 zero/denorm to single precision value */
329 		if (mantissa)
330 		{
331 			mantissa <<= 1;
332 			exp = FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
333 			/* check for leading 1 in denorm mantissa */
334 			while ((mantissa & (1 << 10)) == 0)
335 			{
336 				/* for every leading 0, decrement single precision exponent by 1 */
337 				/* and shift half-float mantissa value to the left */
338 				mantissa <<= 1;
339 				exp -= (1 << 23);
340 			}
341 			/* clamp the mantissa to 6-bits */
342 			mantissa &= ((1 << 6) - 1);
343 			/* shift left to generate single-precision mantissa of 23-bits */
344 			mantissa <<= 17;
345 		}
346 	}
347 	else
348 	{
349 		/* shift left to generate single-precision mantissa of 23-bits */
350 		mantissa <<= 17;
351 		/* generate single precision biased exponent value */
352 		exp = (exp << 17) + FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
353 	}
354 	ui = exp | mantissa;
355 	return f;
356 }
357 
unsignedF10ToFloat(GLuint f10)358 float unsignedF10ToFloat(GLuint f10)
359 {
360 	unsigned int mantissa = (unsigned int)(f10 & ((1 << 5) - 1));
361 	unsigned int exp	  = (unsigned int)(f10 & FLOAT10_MAX_BIASED_EXP);
362 	union {
363 		float		 f;
364 		unsigned int ui;
365 	};
366 
367 	if (exp == FLOAT10_MAX_BIASED_EXP)
368 	{
369 		/* we have a f11 NaN or Inf */
370 		/* f11 NaNs will be converted to a single precision NaN */
371 		/* f11 Infs will be converted to a single precision Inf */
372 		exp = FLOAT_MAX_BIASED_EXP;
373 		if (mantissa)
374 			mantissa = (1 << 23) - 1; /* set all bits to indicate a NaN */
375 	}
376 	else if (exp == 0x0)
377 	{
378 		/* convert f11 zero/denorm to single precision value */
379 		if (mantissa)
380 		{
381 			mantissa <<= 1;
382 			exp = FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
383 			/* check for leading 1 in denorm mantissa */
384 			while ((mantissa & (1 << 10)) == 0)
385 			{
386 				/* for every leading 0, decrement single precision exponent by 1 */
387 				/* and shift half-float mantissa value to the left */
388 				mantissa <<= 1;
389 				exp -= (1 << 23);
390 			}
391 			/* clamp the mantissa to 5-bits */
392 			mantissa &= ((1 << 5) - 1);
393 			/* shift left to generate single-precision mantissa of 23-bits */
394 			mantissa <<= 18;
395 		}
396 	}
397 	else
398 	{
399 		/* shift left to generate single-precision mantissa of 23-bits */
400 		mantissa <<= 18;
401 		/* generate single precision biased exponent value */
402 		exp = (exp << 18) + FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
403 	}
404 	ui = exp | mantissa;
405 	return f;
406 }
407 
408 } // glcts
409