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