unsigned short hs_floatToHalf (float f) {
union { float d; unsigned int i; } u = { f };
int s = (u.i >> 16) & 0x8000;
int e = ((u.i >> 23) & 0xff) - 112;
int m = u.i & 0x7fffff;
if (e <= 0) {
if (e < -10) return s;
m |= 0x800000;
int t = 14 - e;
int a = (1 << (t - 1)) - 1;
int b = (m >> t) & 1;
return s | ((m + a + b) >> t);
}
if (e == 143) {
if (m == 0) return s | 0x7c00;
m >>= 13;
return s | 0x7c00 | m | (m == 0);
}
m = m + 0xfff + ((m >> 13) & 1);
if (m & 0x800000) {
m = 0;
e += 1;
}
if (e > 30) return s | 0x7c00;
return s | (e << 10) | (m >> 13);
}
int hs_halfToFloatRep (unsigned short c) {
int s = (c >> 15) & 0x001;
int e = (c >> 10) & 0x01f;
int m = c & 0x3ff;
if (e == 0) {
if (m == 0) return s << 31;
while (!(m & 0x400)) {
m <<= 1;
e -= 1;
}
e += 1;
m &= ~0x400;
} else if (e == 31) return (s << 31) | 0x7f800000 | (m << 13);
e += 112;
m <<= 13;
return (s << 31) | (e << 23) | m;
}
float hs_halfToFloat (unsigned short c) {
union { float d; unsigned int i; } u;
u.i = hs_halfToFloatRep(c);
return u.d;
}