1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkFloatBits.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,206 @@ 1.4 +/* 1.5 + * Copyright 2011 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "SkFloatBits.h" 1.12 +#include "SkMathPriv.h" 1.13 + 1.14 +/****************************************************************************** 1.15 + SkFloatBits_toInt[Floor, Round, Ceil] are identical except for what they 1.16 + do right before they return ... >> exp; 1.17 + Floor - adds nothing 1.18 + Round - adds 1 << (exp - 1) 1.19 + Ceil - adds (1 << exp) - 1 1.20 + 1.21 + Floor and Cast are very similar, but Cast applies its sign after all other 1.22 + computations on value. Also, Cast does not need to check for negative zero, 1.23 + as that value (0x80000000) "does the right thing" for Ceil. Note that it 1.24 + doesn't for Floor/Round/Ceil, hence the explicit check. 1.25 +******************************************************************************/ 1.26 + 1.27 +#define EXP_BIAS (127+23) 1.28 +#define MATISSA_MAGIC_BIG (1 << 23) 1.29 + 1.30 +static inline int unpack_exp(uint32_t packed) { 1.31 + return (packed << 1 >> 24); 1.32 +} 1.33 + 1.34 +#if 0 1.35 +// the ARM compiler generates an extra BIC, so I use the dirty version instead 1.36 +static inline int unpack_matissa(uint32_t packed) { 1.37 + // we could mask with 0x7FFFFF, but that is harder for ARM to encode 1.38 + return (packed & ~0xFF000000) | MATISSA_MAGIC_BIG; 1.39 +} 1.40 +#endif 1.41 + 1.42 +// returns the low 24-bits, so we need to OR in the magic_bit afterwards 1.43 +static inline int unpack_matissa_dirty(uint32_t packed) { 1.44 + return packed & ~0xFF000000; 1.45 +} 1.46 + 1.47 +// same as (int)float 1.48 +int32_t SkFloatBits_toIntCast(int32_t packed) { 1.49 + int exp = unpack_exp(packed) - EXP_BIAS; 1.50 + int value = unpack_matissa_dirty(packed) | MATISSA_MAGIC_BIG; 1.51 + 1.52 + if (exp >= 0) { 1.53 + if (exp > 7) { // overflow 1.54 + value = SK_MaxS32; 1.55 + } else { 1.56 + value <<= exp; 1.57 + } 1.58 + } else { 1.59 + exp = -exp; 1.60 + if (exp > 25) { // underflow 1.61 + exp = 25; 1.62 + } 1.63 + value >>= exp; 1.64 + } 1.65 + return SkApplySign(value, SkExtractSign(packed)); 1.66 +} 1.67 + 1.68 +// same as (int)floor(float) 1.69 +int32_t SkFloatBits_toIntFloor(int32_t packed) { 1.70 + // curse you negative 0 1.71 + if ((packed << 1) == 0) { 1.72 + return 0; 1.73 + } 1.74 + 1.75 + int exp = unpack_exp(packed) - EXP_BIAS; 1.76 + int value = unpack_matissa_dirty(packed) | MATISSA_MAGIC_BIG; 1.77 + 1.78 + if (exp >= 0) { 1.79 + if (exp > 7) { // overflow 1.80 + value = SK_MaxS32; 1.81 + } else { 1.82 + value <<= exp; 1.83 + } 1.84 + // apply the sign after we check for overflow 1.85 + return SkApplySign(value, SkExtractSign(packed)); 1.86 + } else { 1.87 + // apply the sign before we right-shift 1.88 + value = SkApplySign(value, SkExtractSign(packed)); 1.89 + exp = -exp; 1.90 + if (exp > 25) { // underflow 1.91 + exp = 25; 1.92 + } 1.93 + // int add = 0; 1.94 + return value >> exp; 1.95 + } 1.96 +} 1.97 + 1.98 +// same as (int)floor(float + 0.5) 1.99 +int32_t SkFloatBits_toIntRound(int32_t packed) { 1.100 + // curse you negative 0 1.101 + if ((packed << 1) == 0) { 1.102 + return 0; 1.103 + } 1.104 + 1.105 + int exp = unpack_exp(packed) - EXP_BIAS; 1.106 + int value = unpack_matissa_dirty(packed) | MATISSA_MAGIC_BIG; 1.107 + 1.108 + if (exp >= 0) { 1.109 + if (exp > 7) { // overflow 1.110 + value = SK_MaxS32; 1.111 + } else { 1.112 + value <<= exp; 1.113 + } 1.114 + // apply the sign after we check for overflow 1.115 + return SkApplySign(value, SkExtractSign(packed)); 1.116 + } else { 1.117 + // apply the sign before we right-shift 1.118 + value = SkApplySign(value, SkExtractSign(packed)); 1.119 + exp = -exp; 1.120 + if (exp > 25) { // underflow 1.121 + exp = 25; 1.122 + } 1.123 + int add = 1 << (exp - 1); 1.124 + return (value + add) >> exp; 1.125 + } 1.126 +} 1.127 + 1.128 +// same as (int)ceil(float) 1.129 +int32_t SkFloatBits_toIntCeil(int32_t packed) { 1.130 + // curse you negative 0 1.131 + if ((packed << 1) == 0) { 1.132 + return 0; 1.133 + } 1.134 + 1.135 + int exp = unpack_exp(packed) - EXP_BIAS; 1.136 + int value = unpack_matissa_dirty(packed) | MATISSA_MAGIC_BIG; 1.137 + 1.138 + if (exp >= 0) { 1.139 + if (exp > 7) { // overflow 1.140 + value = SK_MaxS32; 1.141 + } else { 1.142 + value <<= exp; 1.143 + } 1.144 + // apply the sign after we check for overflow 1.145 + return SkApplySign(value, SkExtractSign(packed)); 1.146 + } else { 1.147 + // apply the sign before we right-shift 1.148 + value = SkApplySign(value, SkExtractSign(packed)); 1.149 + exp = -exp; 1.150 + if (exp > 25) { // underflow 1.151 + exp = 25; 1.152 + } 1.153 + int add = (1 << exp) - 1; 1.154 + return (value + add) >> exp; 1.155 + } 1.156 +} 1.157 + 1.158 +float SkIntToFloatCast(int32_t value) { 1.159 + if (0 == value) { 1.160 + return 0; 1.161 + } 1.162 + 1.163 + int shift = EXP_BIAS; 1.164 + 1.165 + // record the sign and make value positive 1.166 + int sign = SkExtractSign(value); 1.167 + value = SkApplySign(value, sign); 1.168 + 1.169 + if (value >> 24) { // value is too big (has more than 24 bits set) 1.170 + int bias = 8 - SkCLZ(value); 1.171 + SkDebugf("value = %d, bias = %d\n", value, bias); 1.172 + SkASSERT(bias > 0 && bias < 8); 1.173 + value >>= bias; // need to round? 1.174 + shift += bias; 1.175 + } else { 1.176 + int zeros = SkCLZ(value << 8); 1.177 + SkASSERT(zeros >= 0 && zeros <= 23); 1.178 + value <<= zeros; 1.179 + shift -= zeros; 1.180 + } 1.181 + 1.182 + // now value is left-aligned to 24 bits 1.183 + SkASSERT((value >> 23) == 1); 1.184 + SkASSERT(shift >= 0 && shift <= 255); 1.185 + 1.186 + SkFloatIntUnion data; 1.187 + data.fSignBitInt = (sign << 31) | (shift << 23) | (value & ~MATISSA_MAGIC_BIG); 1.188 + return data.fFloat; 1.189 +} 1.190 + 1.191 +float SkIntToFloatCast_NoOverflowCheck(int32_t value) { 1.192 + if (0 == value) { 1.193 + return 0; 1.194 + } 1.195 + 1.196 + int shift = EXP_BIAS; 1.197 + 1.198 + // record the sign and make value positive 1.199 + int sign = SkExtractSign(value); 1.200 + value = SkApplySign(value, sign); 1.201 + 1.202 + int zeros = SkCLZ(value << 8); 1.203 + value <<= zeros; 1.204 + shift -= zeros; 1.205 + 1.206 + SkFloatIntUnion data; 1.207 + data.fSignBitInt = (sign << 31) | (shift << 23) | (value & ~MATISSA_MAGIC_BIG); 1.208 + return data.fFloat; 1.209 +}