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 | { |
19 | half::half(float fp32) |
20 | { |
21 | unsigned int fp32i = *(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 | 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 | |
51 | 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 (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 (float&)fp32i; |
86 | } |
87 | |
88 | half &half::operator=(half h) |
89 | { |
90 | fp16i = h.fp16i; |
91 | |
92 | return *this; |
93 | } |
94 | |
95 | |
96 | half &half::operator=(float f) |
97 | { |
98 | *this = half(f); |
99 | |
100 | return *this; |
101 | } |
102 | } |
103 | |