1783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca/**************************************************************************
2783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca *
3783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * Copyright 2010 Luca Barbieri
4783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca *
5783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * Permission is hereby granted, free of charge, to any person obtaining
6783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * a copy of this software and associated documentation files (the
7783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * "Software"), to deal in the Software without restriction, including
8783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * without limitation the rights to use, copy, modify, merge, publish,
9783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * distribute, sublicense, and/or sell copies of the Software, and to
10783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * permit persons to whom the Software is furnished to do so, subject to
11783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * the following conditions:
12783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca *
13783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * The above copyright notice and this permission notice (including the
14783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * next paragraph) shall be included in all copies or substantial
15783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * portions of the Software.
16783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca *
17783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca *
25783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca **************************************************************************/
26783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca
27783e94243a46e5d11d9db51924839a1c64a281bcJosé Fonseca
283ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri#ifndef U_HALF_H
293ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri#define U_HALF_H
303ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri
313ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri#include "pipe/p_compiler.h"
32aee5bb5b8ad80d4aed849519a80b1d696991e866Luca Barbieri#include "util/u_math.h"
333ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri
3489034b8ae71ca12f9a12935807a33caa686ede00José Fonseca#ifdef __cplusplus
3589034b8ae71ca12f9a12935807a33caa686ede00José Fonsecaextern "C" {
3689034b8ae71ca12f9a12935807a33caa686ede00José Fonseca#endif
3789034b8ae71ca12f9a12935807a33caa686ede00José Fonseca
383ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri/*
396dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton * References for float <-> half conversions
403ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri *
416dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton *  http://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/
426dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton *  https://gist.github.com/2156668
436dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton *  https://gist.github.com/2144712
443ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri */
453ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri
466dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Bentonstatic INLINE uint16_t
476dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Bentonutil_float_to_half(float f)
483ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri{
496dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   uint32_t sign_mask  = 0x80000000;
506dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   uint32_t round_mask = ~0xfff;
516dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   uint32_t f32inf = 0xff << 23;
526dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   uint32_t f16inf = 0x1f << 23;
536dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   uint32_t sign;
546dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   union fi magic;
556dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   union fi f32;
566dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   uint16_t f16;
576dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton
586dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   magic.ui = 0xf << 23;
596dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton
606dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   f32.f = f;
616dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton
626dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   /* Sign */
636dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   sign = f32.ui & sign_mask;
646dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   f32.ui ^= sign;
656dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton
666dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   if (f32.ui == f32inf) {
676dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton      /* Inf */
686dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton      f16 = 0x7c00;
696dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   } else if (f32.ui > f32inf) {
706dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton      /* NaN */
716dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton      f16 = 0x7e00;
726dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   } else {
736dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton      /* Number */
746dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton      f32.ui &= round_mask;
756dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton      f32.f  *= magic.f;
766dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton      f32.ui -= round_mask;
776dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton
786dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton      /* Clamp to infinity if overflowed */
796dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton      if (f32.ui > f16inf)
806dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton         f32.ui = f16inf;
816dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton
826dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton      f16 = f32.ui >> 13;
836dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   }
846dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton
856dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   /* Sign */
866dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   f16 |= sign >> 16;
876dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton
886dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   return f16;
893ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri}
903ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri
913ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieristatic INLINE float
926dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Bentonutil_half_to_float(uint16_t f16)
933ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri{
946dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   union fi infnan;
956dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   union fi magic;
966dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   union fi f32;
973ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri
986dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   infnan.ui = 0x8f << 23;
996dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   infnan.f = 65536.0f;
1006dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   magic.ui  = 0xef << 23;
1013ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri
1026dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   /* Exponent / Mantissa */
1036dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   f32.ui = (f16 & 0x7fff) << 13;
1046dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton
1056dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   /* Adjust */
1066dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   f32.f *= magic.f;
1076dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton
1086dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   /* Inf / NaN */
1096dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   if (f32.f >= infnan.f)
1106dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton      f32.ui |= 0xff << 23;
1116dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton
1126dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   /* Sign */
1136dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   f32.ui |= (f16 & 0x8000) << 16;
1146dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton
1156dd8e6f9cbca63b222fe4a1c2c49ddb53e75999eJames Benton   return f32.f;
1163ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri}
1173ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri
11889034b8ae71ca12f9a12935807a33caa686ede00José Fonseca#ifdef __cplusplus
11989034b8ae71ca12f9a12935807a33caa686ede00José Fonseca}
12089034b8ae71ca12f9a12935807a33caa686ede00José Fonseca#endif
12189034b8ae71ca12f9a12935807a33caa686ede00José Fonseca
1223ff175d6de89ad92d167362355501f99d06f0f97Luca Barbieri#endif /* U_HALF_H */
1236c5f444f596984778a786b49058d3cf2a4fd2c2cLuca Barbieri
124