1 /*-------------------------------------------------------------------------
2  * drawElements Base Portability Library
3  * -------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
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
21  * \brief 16-bit floating-point math.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "deFloat16.h"
25 
26 DE_BEGIN_EXTERN_C
27 
deFloat32To16(float val32)28 deFloat16 deFloat32To16 (float val32)
29 {
30 	deUint32	sign;
31 	int			expotent;
32 	deUint32	mantissa;
33 	union
34 	{
35 		float		f;
36 		deUint32	u;
37 	} x;
38 
39 	x.f 		= val32;
40 	sign		= (x.u >> 16u) & 0x00008000u;
41 	expotent	= (int)((x.u >> 23u) & 0x000000ffu) - (127 - 15);
42 	mantissa	= x.u & 0x007fffffu;
43 
44 	if (expotent <= 0)
45 	{
46 		if (expotent < -10)
47 		{
48 			/* Rounds to zero. */
49 			return (deFloat16) sign;
50 		}
51 
52 		/* Converted to denormalized half, add leading 1 to significand. */
53 		mantissa = mantissa | 0x00800000u;
54 
55 		/* Round mantissa to nearest (10+e) */
56 		{
57 			deUint32 t = 14u - expotent;
58 			deUint32 a = (1u << (t - 1u)) - 1u;
59 			deUint32 b = (mantissa >> t) & 1u;
60 
61 			mantissa = (mantissa + a + b) >> t;
62 		}
63 
64 		return (deFloat16) (sign | mantissa);
65 	}
66 	else if (expotent == 0xff - (127 - 15))
67 	{
68 		if (mantissa == 0u)
69 		{
70 			/* InF */
71 			return (deFloat16) (sign | 0x7c00u);
72 		}
73 		else
74 		{
75 			/* NaN */
76 			mantissa >>= 13u;
77 			return (deFloat16) (sign | 0x7c00u | mantissa | (mantissa == 0u));
78 		}
79 	}
80 	else
81 	{
82 		/* Normalized float. */
83 		mantissa = mantissa + 0x00000fffu + ((mantissa >> 13u) & 1u);
84 
85 		if (mantissa & 0x00800000u)
86 		{
87 			/* Overflow in mantissa. */
88 			mantissa  = 0u;
89 			expotent += 1;
90 		}
91 
92 		if (expotent > 30)
93 		{
94 			/* \todo [pyry] Cause hw fp overflow */
95 			return (deFloat16) (sign | 0x7c00u);
96 		}
97 
98 		return (deFloat16) (sign | ((deUint32)expotent << 10u) | (mantissa >> 13u));
99 	}
100 }
101 
deFloat16To32(deFloat16 val16)102 float deFloat16To32 (deFloat16 val16)
103 {
104 	deUint32 sign;
105 	deUint32 expotent;
106 	deUint32 mantissa;
107 	union
108 	{
109 		float		f;
110 		deUint32	u;
111 	} x;
112 
113 	x.u			= 0u;
114 
115 	sign		= ((deUint32)val16 >> 15u) & 0x00000001u;
116 	expotent	= ((deUint32)val16 >> 10u) & 0x0000001fu;
117 	mantissa	= (deUint32)val16 & 0x000003ffu;
118 
119 	if (expotent == 0u)
120 	{
121 		if (mantissa == 0u)
122 		{
123 			/* +/- 0 */
124 			x.u = sign << 31u;
125 			return x.f;
126 		}
127 		else
128 		{
129 			/* Denormalized, normalize it. */
130 
131 			while (!(mantissa & 0x00000400u))
132 			{
133 				mantissa <<= 1u;
134 				expotent -=  1u;
135 			}
136 
137 			expotent += 1u;
138 			mantissa &= ~0x00000400u;
139 		}
140 	}
141 	else if (expotent == 31u)
142 	{
143 		if (mantissa == 0u)
144 		{
145 			/* +/- InF */
146 			x.u = (sign << 31u) | 0x7f800000u;
147 			return x.f;
148 		}
149 		else
150 		{
151 			/* +/- NaN */
152 			x.u = (sign << 31u) | 0x7f800000u | (mantissa << 13u);
153 			return x.f;
154 		}
155 	}
156 
157 	expotent = expotent + (127u - 15u);
158 	mantissa = mantissa << 13u;
159 
160 	x.u = (sign << 31u) | (expotent << 23u) | mantissa;
161 	return x.f;
162 }
163 
164 DE_END_EXTERN_C
165