1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2014 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/private/SkFloatBits.h" 9cb93a386Sopenharmony_ci#include "include/private/SkHalf.h" 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ciuint16_t halfMantissa(SkHalf h) { 12cb93a386Sopenharmony_ci return h & 0x03ff; 13cb93a386Sopenharmony_ci} 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ciuint16_t halfExponent(SkHalf h) { 16cb93a386Sopenharmony_ci return (h >> 10) & 0x001f; 17cb93a386Sopenharmony_ci} 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ciuint16_t halfSign(SkHalf h) { 20cb93a386Sopenharmony_ci return h >> 15; 21cb93a386Sopenharmony_ci} 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_ciunion FloatUIntUnion { 24cb93a386Sopenharmony_ci uint32_t fUInt; // this must come first for the initializations below to work 25cb93a386Sopenharmony_ci float fFloat; 26cb93a386Sopenharmony_ci}; 27cb93a386Sopenharmony_ci 28cb93a386Sopenharmony_ci// based on Fabien Giesen's float_to_half_fast3() 29cb93a386Sopenharmony_ci// see https://gist.github.com/rygorous/2156668 30cb93a386Sopenharmony_ciSkHalf SkFloatToHalf(float f) { 31cb93a386Sopenharmony_ci static const uint32_t f32infty = { 255 << 23 }; 32cb93a386Sopenharmony_ci static const uint32_t f16infty = { 31 << 23 }; 33cb93a386Sopenharmony_ci static const FloatUIntUnion magic = { 15 << 23 }; 34cb93a386Sopenharmony_ci static const uint32_t sign_mask = 0x80000000u; 35cb93a386Sopenharmony_ci static const uint32_t round_mask = ~0xfffu; 36cb93a386Sopenharmony_ci SkHalf o = 0; 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ci FloatUIntUnion floatUnion; 39cb93a386Sopenharmony_ci floatUnion.fFloat = f; 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ci uint32_t sign = floatUnion.fUInt & sign_mask; 42cb93a386Sopenharmony_ci floatUnion.fUInt ^= sign; 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ci // NOTE all the integer compares in this function can be safely 45cb93a386Sopenharmony_ci // compiled into signed compares since all operands are below 46cb93a386Sopenharmony_ci // 0x80000000. Important if you want fast straight SSE2 code 47cb93a386Sopenharmony_ci // (since there's no unsigned PCMPGTD). 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ci // Inf or NaN (all exponent bits set) 50cb93a386Sopenharmony_ci if (floatUnion.fUInt >= f32infty) 51cb93a386Sopenharmony_ci // NaN->qNaN and Inf->Inf 52cb93a386Sopenharmony_ci o = (floatUnion.fUInt > f32infty) ? 0x7e00 : 0x7c00; 53cb93a386Sopenharmony_ci // (De)normalized number or zero 54cb93a386Sopenharmony_ci else { 55cb93a386Sopenharmony_ci floatUnion.fUInt &= round_mask; 56cb93a386Sopenharmony_ci floatUnion.fFloat *= magic.fFloat; 57cb93a386Sopenharmony_ci floatUnion.fUInt -= round_mask; 58cb93a386Sopenharmony_ci // Clamp to signed infinity if overflowed 59cb93a386Sopenharmony_ci if (floatUnion.fUInt > f16infty) { 60cb93a386Sopenharmony_ci floatUnion.fUInt = f16infty; 61cb93a386Sopenharmony_ci } 62cb93a386Sopenharmony_ci 63cb93a386Sopenharmony_ci o = floatUnion.fUInt >> 13; // Take the bits! 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_ci o |= sign >> 16; 67cb93a386Sopenharmony_ci return o; 68cb93a386Sopenharmony_ci} 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_ci// based on Fabien Giesen's half_to_float_fast2() 71cb93a386Sopenharmony_ci// see https://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/ 72cb93a386Sopenharmony_cifloat SkHalfToFloat(SkHalf h) { 73cb93a386Sopenharmony_ci static const FloatUIntUnion magic = { 126 << 23 }; 74cb93a386Sopenharmony_ci FloatUIntUnion o; 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci if (halfExponent(h) == 0) 77cb93a386Sopenharmony_ci { 78cb93a386Sopenharmony_ci // Zero / Denormal 79cb93a386Sopenharmony_ci o.fUInt = magic.fUInt + halfMantissa(h); 80cb93a386Sopenharmony_ci o.fFloat -= magic.fFloat; 81cb93a386Sopenharmony_ci } 82cb93a386Sopenharmony_ci else 83cb93a386Sopenharmony_ci { 84cb93a386Sopenharmony_ci // Set mantissa 85cb93a386Sopenharmony_ci o.fUInt = halfMantissa(h) << 13; 86cb93a386Sopenharmony_ci // Set exponent 87cb93a386Sopenharmony_ci if (halfExponent(h) == 0x1f) 88cb93a386Sopenharmony_ci // Inf/NaN 89cb93a386Sopenharmony_ci o.fUInt |= (255 << 23); 90cb93a386Sopenharmony_ci else 91cb93a386Sopenharmony_ci o.fUInt |= ((127 - 15 + halfExponent(h)) << 23); 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_ci // Set sign 95cb93a386Sopenharmony_ci o.fUInt |= (halfSign(h) << 31); 96cb93a386Sopenharmony_ci return o.fFloat; 97cb93a386Sopenharmony_ci} 98