1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkFloat.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,387 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2008 The Android Open Source Project 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#include "SkFloat.h" 1.14 +#include "SkMathPriv.h" 1.15 + 1.16 +#define EXP_BIAS (127+23) 1.17 + 1.18 +static int get_unsigned_exp(uint32_t packed) 1.19 +{ 1.20 + return (packed << 1 >> 24); 1.21 +} 1.22 + 1.23 +static unsigned get_unsigned_value(uint32_t packed) 1.24 +{ 1.25 + return (packed << 9 >> 9) | (1 << 23); 1.26 +} 1.27 + 1.28 +static int get_signed_value(int32_t packed) 1.29 +{ 1.30 + return SkApplySign(get_unsigned_value(packed), SkExtractSign(packed)); 1.31 +} 1.32 + 1.33 +///////////////////////////////////////////////////////////////////////// 1.34 + 1.35 +int SkFloat::GetShift(int32_t packed, int shift) 1.36 +{ 1.37 + if (packed == 0) 1.38 + return 0; 1.39 + 1.40 + int exp = get_unsigned_exp(packed) - EXP_BIAS - shift; 1.41 + int value = get_unsigned_value(packed); 1.42 + 1.43 + if (exp >= 0) 1.44 + { 1.45 + if (exp > 8) // overflow 1.46 + value = SK_MaxS32; 1.47 + else 1.48 + value <<= exp; 1.49 + } 1.50 + else 1.51 + { 1.52 + exp = -exp; 1.53 + if (exp > 23) // underflow 1.54 + value = 0; 1.55 + else 1.56 + value >>= exp; 1.57 + } 1.58 + return SkApplySign(value, SkExtractSign(packed)); 1.59 +} 1.60 + 1.61 +///////////////////////////////////////////////////////////////////////////////////// 1.62 + 1.63 +int32_t SkFloat::SetShift(int value, int shift) 1.64 +{ 1.65 + if (value == 0) 1.66 + return 0; 1.67 + 1.68 + // record the sign and make value positive 1.69 + int sign = SkExtractSign(value); 1.70 + value = SkApplySign(value, sign); 1.71 + 1.72 + if (value >> 24) // value is too big (has more than 24 bits set) 1.73 + { 1.74 + int bias = 8 - SkCLZ(value); 1.75 + SkASSERT(bias > 0 && bias < 8); 1.76 + value >>= bias; 1.77 + shift += bias; 1.78 + } 1.79 + else 1.80 + { 1.81 + int zeros = SkCLZ(value << 8); 1.82 + SkASSERT(zeros >= 0 && zeros <= 23); 1.83 + value <<= zeros; 1.84 + shift -= zeros; 1.85 + } 1.86 + // now value is left-aligned to 24 bits 1.87 + SkASSERT((value >> 23) == 1); 1.88 + 1.89 + shift += EXP_BIAS; 1.90 + if (shift < 0) // underflow 1.91 + return 0; 1.92 + else 1.93 + { 1.94 + if (shift > 255) // overflow 1.95 + { 1.96 + shift = 255; 1.97 + value = 0x00FFFFFF; 1.98 + } 1.99 + int32_t packed = sign << 31; // set the sign-bit 1.100 + packed |= shift << 23; // store the packed exponent 1.101 + packed |= ((unsigned)(value << 9) >> 9); // clear 24th bit of value (its implied) 1.102 + 1.103 +#ifdef SK_DEBUG 1.104 + { 1.105 + int n; 1.106 + 1.107 + n = SkExtractSign(packed); 1.108 + SkASSERT(n == sign); 1.109 + n = get_unsigned_exp(packed); 1.110 + SkASSERT(n == shift); 1.111 + n = get_unsigned_value(packed); 1.112 + SkASSERT(n == value); 1.113 + } 1.114 +#endif 1.115 + return packed; 1.116 + } 1.117 +} 1.118 + 1.119 +int32_t SkFloat::Neg(int32_t packed) 1.120 +{ 1.121 + if (packed) 1.122 + packed = packed ^ (1 << 31); 1.123 + return packed; 1.124 +} 1.125 + 1.126 +int32_t SkFloat::Add(int32_t packed_a, int32_t packed_b) 1.127 +{ 1.128 + if (packed_a == 0) 1.129 + return packed_b; 1.130 + if (packed_b == 0) 1.131 + return packed_a; 1.132 + 1.133 + int exp_a = get_unsigned_exp(packed_a); 1.134 + int exp_b = get_unsigned_exp(packed_b); 1.135 + int exp_diff = exp_a - exp_b; 1.136 + 1.137 + int shift_a = 0, shift_b = 0; 1.138 + int exp; 1.139 + 1.140 + if (exp_diff >= 0) 1.141 + { 1.142 + if (exp_diff > 24) // B is too small to contribute 1.143 + return packed_a; 1.144 + shift_b = exp_diff; 1.145 + exp = exp_a; 1.146 + } 1.147 + else 1.148 + { 1.149 + exp_diff = -exp_diff; 1.150 + if (exp_diff > 24) // A is too small to contribute 1.151 + return packed_b; 1.152 + shift_a = exp_diff; 1.153 + exp = exp_b; 1.154 + } 1.155 + 1.156 + int value_a = get_signed_value(packed_a) >> shift_a; 1.157 + int value_b = get_signed_value(packed_b) >> shift_b; 1.158 + 1.159 + return SkFloat::SetShift(value_a + value_b, exp - EXP_BIAS); 1.160 +} 1.161 + 1.162 +static inline int32_t mul24(int32_t a, int32_t b) { 1.163 + int64_t tmp = (sk_64_mul(a, b) + (1 << 23)) >> 24; 1.164 + return sk_64_asS32(tmp); 1.165 +} 1.166 + 1.167 +int32_t SkFloat::Mul(int32_t packed_a, int32_t packed_b) 1.168 +{ 1.169 + if (packed_a == 0 || packed_b == 0) 1.170 + return 0; 1.171 + 1.172 + int exp_a = get_unsigned_exp(packed_a); 1.173 + int exp_b = get_unsigned_exp(packed_b); 1.174 + 1.175 + int value_a = get_signed_value(packed_a); 1.176 + int value_b = get_signed_value(packed_b); 1.177 + 1.178 + return SkFloat::SetShift(mul24(value_a, value_b), exp_a + exp_b - 2*EXP_BIAS + 24); 1.179 +} 1.180 + 1.181 +int32_t SkFloat::MulInt(int32_t packed, int n) 1.182 +{ 1.183 + return Mul(packed, SetShift(n, 0)); 1.184 +} 1.185 + 1.186 +int32_t SkFloat::Div(int32_t packed_n, int32_t packed_d) 1.187 +{ 1.188 + SkASSERT(packed_d != 0); 1.189 + 1.190 + if (packed_n == 0) 1.191 + return 0; 1.192 + 1.193 + int exp_n = get_unsigned_exp(packed_n); 1.194 + int exp_d = get_unsigned_exp(packed_d); 1.195 + 1.196 + int value_n = get_signed_value(packed_n); 1.197 + int value_d = get_signed_value(packed_d); 1.198 + 1.199 + return SkFloat::SetShift(SkDivBits(value_n, value_d, 24), exp_n - exp_d - 24); 1.200 +} 1.201 + 1.202 +int32_t SkFloat::DivInt(int32_t packed, int n) 1.203 +{ 1.204 + return Div(packed, SetShift(n, 0)); 1.205 +} 1.206 + 1.207 +int32_t SkFloat::Invert(int32_t packed) 1.208 +{ 1.209 + return Div(packed, SetShift(1, 0)); 1.210 +} 1.211 + 1.212 +int32_t SkFloat::Sqrt(int32_t packed) 1.213 +{ 1.214 + if (packed < 0) 1.215 + { 1.216 + SkDEBUGFAIL("can't sqrt a negative number"); 1.217 + return 0; 1.218 + } 1.219 + 1.220 + int exp = get_unsigned_exp(packed); 1.221 + int value = get_unsigned_value(packed); 1.222 + 1.223 + int nexp = exp - EXP_BIAS; 1.224 + int root = SkSqrtBits(value << (nexp & 1), 26); 1.225 + nexp >>= 1; 1.226 + return SkFloat::SetShift(root, nexp - 11); 1.227 +} 1.228 + 1.229 +#if defined _WIN32 && _MSC_VER >= 1300 // disable warning : unreachable code 1.230 +#pragma warning ( push ) 1.231 +#pragma warning ( disable : 4702 ) 1.232 +#endif 1.233 + 1.234 +int32_t SkFloat::CubeRoot(int32_t packed) 1.235 +{ 1.236 + sk_throw(); 1.237 + return 0; 1.238 +} 1.239 + 1.240 +#if defined _WIN32 && _MSC_VER >= 1300 1.241 +#pragma warning ( pop ) 1.242 +#endif 1.243 + 1.244 +static inline int32_t clear_high_bit(int32_t n) 1.245 +{ 1.246 + return ((uint32_t)(n << 1)) >> 1; 1.247 +} 1.248 + 1.249 +static inline int int_sign(int32_t a, int32_t b) 1.250 +{ 1.251 + return a > b ? 1 : (a < b ? -1 : 0); 1.252 +} 1.253 + 1.254 +int SkFloat::Cmp(int32_t packed_a, int32_t packed_b) 1.255 +{ 1.256 + packed_a = SkApplySign(clear_high_bit(packed_a), SkExtractSign(packed_a)); 1.257 + packed_b = SkApplySign(clear_high_bit(packed_b), SkExtractSign(packed_b)); 1.258 + 1.259 + return int_sign(packed_a, packed_b); 1.260 +} 1.261 + 1.262 +///////////////////////////////////////////////////////////////////////////////////// 1.263 +///////////////////////////////////////////////////////////////////////////////////// 1.264 + 1.265 +#ifdef SK_DEBUG 1.266 + 1.267 +#include "SkRandom.h" 1.268 +#include "SkFloatingPoint.h" 1.269 + 1.270 +void SkFloat::UnitTest() 1.271 +{ 1.272 +#if 0 // def SK_SUPPORT_UNITTEST 1.273 + SkFloat a, b, c, d; 1.274 + int n; 1.275 + 1.276 + a.setZero(); 1.277 + n = a.getInt(); 1.278 + SkASSERT(n == 0); 1.279 + 1.280 + b.setInt(5); 1.281 + n = b.getInt(); 1.282 + SkASSERT(n == 5); 1.283 + 1.284 + c.setInt(-3); 1.285 + n = c.getInt(); 1.286 + SkASSERT(n == -3); 1.287 + 1.288 + d.setAdd(c, b); 1.289 + SkDebugf("SkFloat: %d + %d = %d\n", c.getInt(), b.getInt(), d.getInt()); 1.290 + 1.291 + SkRandom rand; 1.292 + 1.293 + int i; 1.294 + for (i = 0; i < 1000; i++) 1.295 + { 1.296 + float fa, fb; 1.297 + int aa = rand.nextS() >> 14; 1.298 + int bb = rand.nextS() >> 14; 1.299 + a.setInt(aa); 1.300 + b.setInt(bb); 1.301 + SkASSERT(a.getInt() == aa); 1.302 + SkASSERT(b.getInt() == bb); 1.303 + 1.304 + c.setAdd(a, b); 1.305 + int cc = c.getInt(); 1.306 + SkASSERT(cc == aa + bb); 1.307 + 1.308 + c.setSub(a, b); 1.309 + cc = c.getInt(); 1.310 + SkASSERT(cc == aa - bb); 1.311 + 1.312 + aa >>= 5; 1.313 + bb >>= 5; 1.314 + a.setInt(aa); 1.315 + b.setInt(bb); 1.316 + c.setMul(a, b); 1.317 + cc = c.getInt(); 1.318 + SkASSERT(cc == aa * bb); 1.319 + ///////////////////////////////////// 1.320 + 1.321 + aa = rand.nextS() >> 11; 1.322 + a.setFixed(aa); 1.323 + cc = a.getFixed(); 1.324 + SkASSERT(aa == cc); 1.325 + 1.326 + bb = rand.nextS() >> 11; 1.327 + b.setFixed(bb); 1.328 + cc = b.getFixed(); 1.329 + SkASSERT(bb == cc); 1.330 + 1.331 + cc = SkFixedMul(aa, bb); 1.332 + c.setMul(a, b); 1.333 + SkFixed dd = c.getFixed(); 1.334 + int diff = cc - dd; 1.335 + SkASSERT(SkAbs32(diff) <= 1); 1.336 + 1.337 + fa = (float)aa / 65536.0f; 1.338 + fb = (float)bb / 65536.0f; 1.339 + a.assertEquals(fa); 1.340 + b.assertEquals(fb); 1.341 + fa = a.getFloat(); 1.342 + fb = b.getFloat(); 1.343 + 1.344 + c.assertEquals(fa * fb, 1); 1.345 + 1.346 + c.setDiv(a, b); 1.347 + cc = SkFixedDiv(aa, bb); 1.348 + dd = c.getFixed(); 1.349 + diff = cc - dd; 1.350 + SkASSERT(SkAbs32(diff) <= 3); 1.351 + 1.352 + c.assertEquals(fa / fb, 1); 1.353 + 1.354 + SkASSERT((aa == bb) == (a == b)); 1.355 + SkASSERT((aa != bb) == (a != b)); 1.356 + SkASSERT((aa < bb) == (a < b)); 1.357 + SkASSERT((aa <= bb) == (a <= b)); 1.358 + SkASSERT((aa > bb) == (a > b)); 1.359 + SkASSERT((aa >= bb) == (a >= b)); 1.360 + 1.361 + if (aa < 0) 1.362 + { 1.363 + aa = -aa; 1.364 + fa = -fa; 1.365 + } 1.366 + a.setFixed(aa); 1.367 + c.setSqrt(a); 1.368 + cc = SkFixedSqrt(aa); 1.369 + dd = c.getFixed(); 1.370 + SkASSERT(dd == cc); 1.371 + 1.372 + c.assertEquals(sk_float_sqrt(fa), 2); 1.373 + 1.374 + // cuberoot 1.375 +#if 0 1.376 + a.setInt(1); 1.377 + a.cubeRoot(); 1.378 + a.assertEquals(1.0f, 0); 1.379 + a.setInt(8); 1.380 + a.cubeRoot(); 1.381 + a.assertEquals(2.0f, 0); 1.382 + a.setInt(27); 1.383 + a.cubeRoot(); 1.384 + a.assertEquals(3.0f, 0); 1.385 +#endif 1.386 + } 1.387 +#endif 1.388 +} 1.389 + 1.390 +#endif