/*------------------------------------------------------------------------- * drawElements Base Portability Library * ------------------------------------- * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief 16-bit floating-point math. *//*--------------------------------------------------------------------*/ #include "deFloat16.h" DE_BEGIN_EXTERN_C deFloat16 deFloat32To16 (float val32) { int sign; int expotent; int mantissa; union { float f; int i; } x; x.f = val32; sign = (x.i >> 16) & 0x00008000; expotent = ((x.i >> 23) & 0x000000ff) - (127 - 15); mantissa = x.i & 0x007fffff; if (expotent <= 0) { if (expotent < -10) { /* Rounds to zero. */ return (deFloat16) sign; } /* Converted to denormalized half, add leading 1 to significand. */ mantissa = mantissa | 0x00800000; /* Round mantissa to nearest (10+e) */ { int t = 14 - expotent; int a = (1 << (t - 1)) - 1; int b = (mantissa >> t) & 1; mantissa = (mantissa + a + b) >> t; } return (deFloat16) (sign | mantissa); } else if (expotent == 0xff - (127 - 15)) { if (mantissa == 0) { /* InF */ return (deFloat16) (sign | 0x7c00); } else { /* NaN */ mantissa >>= 13; return (deFloat16) (sign | 0x7c00 | mantissa | (mantissa == 0)); } } else { /* Normalized float. */ mantissa = mantissa + 0x00000fff + ((mantissa >> 13) & 1); if (mantissa & 0x00800000) { /* Overflow in mantissa. */ mantissa = 0; expotent += 1; } if (expotent > 30) { /* \todo [pyry] Cause hw fp overflow */ return (deFloat16) (sign | 0x7c00); } return (deFloat16) (sign | (expotent << 10) | (mantissa >> 13)); } } float deFloat16To32 (deFloat16 val16) { int sign; int expotent; int mantissa; union { float f; int i; } x; x.i = 0; sign = ((int) val16 >> 15) & 0x00000001; expotent = ((int) val16 >> 10) & 0x0000001f; mantissa = (int) val16 & 0x000003ff; if (expotent == 0) { if (mantissa == 0) { /* +/- 0 */ x.i = sign << 31; return x.f; } else { /* Denormalized, normalize it. */ while (!(mantissa & 0x00000400)) { mantissa <<= 1; expotent -= 1; } expotent += 1; mantissa &= ~0x00000400; } } else if (expotent == 31) { if (mantissa == 0) { /* +/- InF */ x.i = (sign << 31) | 0x7f800000; return x.f; } else { /* +/- NaN */ x.i = (sign << 31) | 0x7f800000 | (mantissa << 13); return x.f; } } expotent = expotent + (127 - 15); mantissa = mantissa << 13; x.i = (sign << 31) | (expotent << 23) | mantissa; return x.f; } DE_END_EXTERN_C