xref: /aosp_15_r20/external/swiftshader/src/System/Half.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "Half.hpp"
16 
17 namespace sw {
18 
half(float fp32)19 half::half(float fp32)
20 {
21 	unsigned int fp32i = bit_cast<unsigned int>(fp32);
22 	unsigned int sign = (fp32i & 0x80000000) >> 16;
23 	unsigned int abs = fp32i & 0x7FFFFFFF;
24 
25 	if(abs > 0x47FFEFFF)  // Infinity
26 	{
27 		fp16i = sign | 0x7FFF;
28 	}
29 	else if(abs < 0x38800000)  // Denormal
30 	{
31 		unsigned int mantissa = (abs & 0x007FFFFF) | 0x00800000;
32 		unsigned int e = 113 - (abs >> 23);
33 
34 		if(e < 24)
35 		{
36 			abs = mantissa >> e;
37 		}
38 		else
39 		{
40 			abs = 0;
41 		}
42 
43 		fp16i = sign | (abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13;
44 	}
45 	else
46 	{
47 		fp16i = sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13;
48 	}
49 }
50 
operator float() const51 half::operator float() const
52 {
53 	unsigned int fp32i;
54 
55 	int s = (fp16i >> 15) & 0x00000001;
56 	int e = (fp16i >> 10) & 0x0000001F;
57 	int m = fp16i & 0x000003FF;
58 
59 	if(e == 0)
60 	{
61 		if(m == 0)
62 		{
63 			fp32i = s << 31;
64 
65 			return bit_cast<float>(fp32i);
66 		}
67 		else
68 		{
69 			while(!(m & 0x00000400))
70 			{
71 				m <<= 1;
72 				e -= 1;
73 			}
74 
75 			e += 1;
76 			m &= ~0x00000400;
77 		}
78 	}
79 
80 	e = e + (127 - 15);
81 	m = m << 13;
82 
83 	fp32i = (s << 31) | (e << 23) | m;
84 
85 	return bit_cast<float>(fp32i);
86 }
87 
operator =(float f)88 half &half::operator=(float f)
89 {
90 	*this = half(f);
91 
92 	return *this;
93 }
94 
95 }  // namespace sw
96