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