/*-------------------------------------------------------------------------
* 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