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