u_half.h revision c476305cdeb1ca9d755983e2058cb44f5b9109f0
17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert#ifndef U_HALF_H
27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert#define U_HALF_H
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert#include "pipe/p_compiler.h"
57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert#include "util/u_math.h"
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert#ifdef __cplusplus
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertextern "C" {
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert#endif
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertextern uint32_t util_half_to_float_mantissa_table[2048];
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertextern uint32_t util_half_to_float_exponent_table[64];
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertextern uint32_t util_half_to_float_offset_table[64];
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertextern uint16_t util_float_to_half_base_table[512];
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertextern uint8_t util_float_to_half_shift_table[512];
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Note that if the half float is a signaling NaN, the x87 FPU will turn
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * it into a quiet NaN immediately upon loading into a float.
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Additionally, denormals may be flushed to zero.
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * To avoid this, use the floatui functions instead of the float ones
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * when just doing conversion rather than computation on the resulting
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * floats.
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertstatic INLINE uint32_t
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertutil_half_to_floatui(half h)
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert{
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert   unsigned exp = h >> 10;
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert   return util_half_to_float_mantissa_table[util_half_to_float_offset_table[exp] + (h & 0x3ff)] + util_half_to_float_exponent_table[exp];
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertstatic INLINE float
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertutil_half_to_float(half h)
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert{
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert   union fi r;
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert   r.ui = util_half_to_floatui(h);
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert   return r.f;
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertstatic INLINE half
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertutil_floatui_to_half(uint32_t v)
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert{
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert   unsigned signexp = v >> 23;
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert   return util_float_to_half_base_table[signexp] + ((v & 0x007fffff) >> util_float_to_half_shift_table[signexp]);
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertstatic INLINE half
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertutil_float_to_half(float f)
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert{
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert   union fi i;
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert   i.f = f;
557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert   return util_floatui_to_half(i.ui);
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert#ifdef __cplusplus
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert#endif
617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert#endif /* U_HALF_H */
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert