| /*------------------------------------------------------------------------- |
| * 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) |
| { |
| deUint32 sign; |
| int expotent; |
| deUint32 mantissa; |
| union |
| { |
| float f; |
| deUint32 u; |
| } x; |
| |
| x.f = val32; |
| sign = (x.u >> 16u) & 0x00008000u; |
| expotent = (int)((x.u >> 23u) & 0x000000ffu) - (127 - 15); |
| mantissa = x.u & 0x007fffffu; |
| |
| if (expotent <= 0) |
| { |
| if (expotent < -10) |
| { |
| /* Rounds to zero. */ |
| return (deFloat16) sign; |
| } |
| |
| /* Converted to denormalized half, add leading 1 to significand. */ |
| mantissa = mantissa | 0x00800000u; |
| |
| /* Round mantissa to nearest (10+e) */ |
| { |
| deUint32 t = 14u - expotent; |
| deUint32 a = (1u << (t - 1u)) - 1u; |
| deUint32 b = (mantissa >> t) & 1u; |
| |
| mantissa = (mantissa + a + b) >> t; |
| } |
| |
| return (deFloat16) (sign | mantissa); |
| } |
| else if (expotent == 0xff - (127 - 15)) |
| { |
| if (mantissa == 0u) |
| { |
| /* InF */ |
| return (deFloat16) (sign | 0x7c00u); |
| } |
| else |
| { |
| /* NaN */ |
| mantissa >>= 13u; |
| return (deFloat16) (sign | 0x7c00u | mantissa | (mantissa == 0u)); |
| } |
| } |
| else |
| { |
| /* Normalized float. */ |
| mantissa = mantissa + 0x00000fffu + ((mantissa >> 13u) & 1u); |
| |
| if (mantissa & 0x00800000u) |
| { |
| /* Overflow in mantissa. */ |
| mantissa = 0u; |
| expotent += 1; |
| } |
| |
| if (expotent > 30) |
| { |
| /* \todo [pyry] Cause hw fp overflow */ |
| return (deFloat16) (sign | 0x7c00u); |
| } |
| |
| return (deFloat16) (sign | ((deUint32)expotent << 10u) | (mantissa >> 13u)); |
| } |
| } |
| |
| float deFloat16To32 (deFloat16 val16) |
| { |
| deUint32 sign; |
| deUint32 expotent; |
| deUint32 mantissa; |
| union |
| { |
| float f; |
| deUint32 u; |
| } x; |
| |
| x.u = 0u; |
| |
| sign = ((deUint32)val16 >> 15u) & 0x00000001u; |
| expotent = ((deUint32)val16 >> 10u) & 0x0000001fu; |
| mantissa = (deUint32)val16 & 0x000003ffu; |
| |
| if (expotent == 0u) |
| { |
| if (mantissa == 0u) |
| { |
| /* +/- 0 */ |
| x.u = sign << 31u; |
| return x.f; |
| } |
| else |
| { |
| /* Denormalized, normalize it. */ |
| |
| while (!(mantissa & 0x00000400u)) |
| { |
| mantissa <<= 1u; |
| expotent -= 1u; |
| } |
| |
| expotent += 1u; |
| mantissa &= ~0x00000400u; |
| } |
| } |
| else if (expotent == 31u) |
| { |
| if (mantissa == 0u) |
| { |
| /* +/- InF */ |
| x.u = (sign << 31u) | 0x7f800000u; |
| return x.f; |
| } |
| else |
| { |
| /* +/- NaN */ |
| x.u = (sign << 31u) | 0x7f800000u | (mantissa << 13u); |
| return x.f; |
| } |
| } |
| |
| expotent = expotent + (127u - 15u); |
| mantissa = mantissa << 13u; |
| |
| x.u = (sign << 31u) | (expotent << 23u) | mantissa; |
| return x.f; |
| } |
| |
| DE_END_EXTERN_C |