Home | History | Annotate | Download | only in debase
      1 /*-------------------------------------------------------------------------
      2  * drawElements Base Portability Library
      3  * -------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief 16-bit floating-point math.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "deFloat16.h"
     25 
     26 DE_BEGIN_EXTERN_C
     27 
     28 deFloat16 deFloat32To16 (float val32)
     29 {
     30 	deUint32	sign;
     31 	int			expotent;
     32 	deUint32	mantissa;
     33 	union
     34 	{
     35 		float		f;
     36 		deUint32	u;
     37 	} x;
     38 
     39 	x.f 		= val32;
     40 	sign		= (x.u >> 16u) & 0x00008000u;
     41 	expotent	= (int)((x.u >> 23u) & 0x000000ffu) - (127 - 15);
     42 	mantissa	= x.u & 0x007fffffu;
     43 
     44 	if (expotent <= 0)
     45 	{
     46 		if (expotent < -10)
     47 		{
     48 			/* Rounds to zero. */
     49 			return (deFloat16) sign;
     50 		}
     51 
     52 		/* Converted to denormalized half, add leading 1 to significand. */
     53 		mantissa = mantissa | 0x00800000u;
     54 
     55 		/* Round mantissa to nearest (10+e) */
     56 		{
     57 			deUint32 t = 14u - expotent;
     58 			deUint32 a = (1u << (t - 1u)) - 1u;
     59 			deUint32 b = (mantissa >> t) & 1u;
     60 
     61 			mantissa = (mantissa + a + b) >> t;
     62 		}
     63 
     64 		return (deFloat16) (sign | mantissa);
     65 	}
     66 	else if (expotent == 0xff - (127 - 15))
     67 	{
     68 		if (mantissa == 0u)
     69 		{
     70 			/* InF */
     71 			return (deFloat16) (sign | 0x7c00u);
     72 		}
     73 		else
     74 		{
     75 			/* NaN */
     76 			mantissa >>= 13u;
     77 			return (deFloat16) (sign | 0x7c00u | mantissa | (mantissa == 0u));
     78 		}
     79 	}
     80 	else
     81 	{
     82 		/* Normalized float. */
     83 		mantissa = mantissa + 0x00000fffu + ((mantissa >> 13u) & 1u);
     84 
     85 		if (mantissa & 0x00800000u)
     86 		{
     87 			/* Overflow in mantissa. */
     88 			mantissa  = 0u;
     89 			expotent += 1;
     90 		}
     91 
     92 		if (expotent > 30)
     93 		{
     94 			/* \todo [pyry] Cause hw fp overflow */
     95 			return (deFloat16) (sign | 0x7c00u);
     96 		}
     97 
     98 		return (deFloat16) (sign | ((deUint32)expotent << 10u) | (mantissa >> 13u));
     99 	}
    100 }
    101 
    102 float deFloat16To32 (deFloat16 val16)
    103 {
    104 	deUint32 sign;
    105 	deUint32 expotent;
    106 	deUint32 mantissa;
    107 	union
    108 	{
    109 		float		f;
    110 		deUint32	u;
    111 	} x;
    112 
    113 	x.u			= 0u;
    114 
    115 	sign		= ((deUint32)val16 >> 15u) & 0x00000001u;
    116 	expotent	= ((deUint32)val16 >> 10u) & 0x0000001fu;
    117 	mantissa	= (deUint32)val16 & 0x000003ffu;
    118 
    119 	if (expotent == 0u)
    120 	{
    121 		if (mantissa == 0u)
    122 		{
    123 			/* +/- 0 */
    124 			x.u = sign << 31u;
    125 			return x.f;
    126 		}
    127 		else
    128 		{
    129 			/* Denormalized, normalize it. */
    130 
    131 			while (!(mantissa & 0x00000400u))
    132 			{
    133 				mantissa <<= 1u;
    134 				expotent -=  1u;
    135 			}
    136 
    137 			expotent += 1u;
    138 			mantissa &= ~0x00000400u;
    139 		}
    140 	}
    141 	else if (expotent == 31u)
    142 	{
    143 		if (mantissa == 0u)
    144 		{
    145 			/* +/- InF */
    146 			x.u = (sign << 31u) | 0x7f800000u;
    147 			return x.f;
    148 		}
    149 		else
    150 		{
    151 			/* +/- NaN */
    152 			x.u = (sign << 31u) | 0x7f800000u | (mantissa << 13u);
    153 			return x.f;
    154 		}
    155 	}
    156 
    157 	expotent = expotent + (127u - 15u);
    158 	mantissa = mantissa << 13u;
    159 
    160 	x.u = (sign << 31u) | (expotent << 23u) | mantissa;
    161 	return x.f;
    162 }
    163 
    164 DE_END_EXTERN_C
    165