1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 The Android Open Source Project 48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFloat.h" 114b163ed2c22facbe8891616874ae07ba7827d9c9reed@google.com#include "SkMathPriv.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define EXP_BIAS (127+23) 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int get_unsigned_exp(uint32_t packed) 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (packed << 1 >> 24); 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic unsigned get_unsigned_value(uint32_t packed) 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (packed << 9 >> 9) | (1 << 23); 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int get_signed_value(int32_t packed) 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkApplySign(get_unsigned_value(packed), SkExtractSign(packed)); 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////// 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkFloat::GetShift(int32_t packed, int shift) 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (packed == 0) 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int exp = get_unsigned_exp(packed) - EXP_BIAS - shift; 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int value = get_unsigned_value(packed); 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (exp >= 0) 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (exp > 8) // overflow 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value = SK_MaxS32; 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value <<= exp; 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com exp = -exp; 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (exp > 23) // underflow 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value = 0; 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value >>= exp; 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkApplySign(value, SkExtractSign(packed)); 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////////// 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::SetShift(int value, int shift) 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value == 0) 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // record the sign and make value positive 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int sign = SkExtractSign(value); 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value = SkApplySign(value, sign); 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value >> 24) // value is too big (has more than 24 bits set) 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int bias = 8 - SkCLZ(value); 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(bias > 0 && bias < 8); 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value >>= bias; 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shift += bias; 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int zeros = SkCLZ(value << 8); 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(zeros >= 0 && zeros <= 23); 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value <<= zeros; 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shift -= zeros; 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now value is left-aligned to 24 bits 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((value >> 23) == 1); 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shift += EXP_BIAS; 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (shift < 0) // underflow 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (shift > 255) // overflow 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shift = 255; 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value = 0x00FFFFFF; 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int32_t packed = sign << 31; // set the sign-bit 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com packed |= shift << 23; // store the packed exponent 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com packed |= ((unsigned)(value << 9) >> 9); // clear 24th bit of value (its implied) 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int n; 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n = SkExtractSign(packed); 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(n == sign); 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n = get_unsigned_exp(packed); 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(n == shift); 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n = get_unsigned_value(packed); 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(n == value); 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return packed; 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::Neg(int32_t packed) 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (packed) 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com packed = packed ^ (1 << 31); 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return packed; 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::Add(int32_t packed_a, int32_t packed_b) 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (packed_a == 0) 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return packed_b; 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (packed_b == 0) 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return packed_a; 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int exp_a = get_unsigned_exp(packed_a); 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int exp_b = get_unsigned_exp(packed_b); 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int exp_diff = exp_a - exp_b; 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int shift_a = 0, shift_b = 0; 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int exp; 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (exp_diff >= 0) 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (exp_diff > 24) // B is too small to contribute 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return packed_a; 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shift_b = exp_diff; 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com exp = exp_a; 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com exp_diff = -exp_diff; 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (exp_diff > 24) // A is too small to contribute 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return packed_b; 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shift_a = exp_diff; 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com exp = exp_b; 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int value_a = get_signed_value(packed_a) >> shift_a; 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int value_b = get_signed_value(packed_b) >> shift_b; 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkFloat::SetShift(value_a + value_b, exp - EXP_BIAS); 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 159bf0001d0472d727266762c5967ec0d919a6df083reed@google.comstatic inline int32_t mul24(int32_t a, int32_t b) { 160bf0001d0472d727266762c5967ec0d919a6df083reed@google.com int64_t tmp = (sk_64_mul(a, b) + (1 << 23)) >> 24; 161bf0001d0472d727266762c5967ec0d919a6df083reed@google.com return sk_64_asS32(tmp); 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::Mul(int32_t packed_a, int32_t packed_b) 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (packed_a == 0 || packed_b == 0) 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int exp_a = get_unsigned_exp(packed_a); 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int exp_b = get_unsigned_exp(packed_b); 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int value_a = get_signed_value(packed_a); 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int value_b = get_signed_value(packed_b); 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkFloat::SetShift(mul24(value_a, value_b), exp_a + exp_b - 2*EXP_BIAS + 24); 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::MulInt(int32_t packed, int n) 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return Mul(packed, SetShift(n, 0)); 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::Div(int32_t packed_n, int32_t packed_d) 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(packed_d != 0); 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (packed_n == 0) 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int exp_n = get_unsigned_exp(packed_n); 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int exp_d = get_unsigned_exp(packed_d); 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int value_n = get_signed_value(packed_n); 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int value_d = get_signed_value(packed_d); 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkFloat::SetShift(SkDivBits(value_n, value_d, 24), exp_n - exp_d - 24); 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::DivInt(int32_t packed, int n) 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return Div(packed, SetShift(n, 0)); 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::Invert(int32_t packed) 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return Div(packed, SetShift(1, 0)); 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::Sqrt(int32_t packed) 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (packed < 0) 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 2130c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("can't sqrt a negative number"); 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int exp = get_unsigned_exp(packed); 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int value = get_unsigned_value(packed); 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int nexp = exp - EXP_BIAS; 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int root = SkSqrtBits(value << (nexp & 1), 26); 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com nexp >>= 1; 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkFloat::SetShift(root, nexp - 11); 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined _WIN32 && _MSC_VER >= 1300 // disable warning : unreachable code 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( push ) 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( disable : 4702 ) 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkFloat::CubeRoot(int32_t packed) 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_throw(); 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined _WIN32 && _MSC_VER >= 1300 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( pop ) 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline int32_t clear_high_bit(int32_t n) 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return ((uint32_t)(n << 1)) >> 1; 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline int int_sign(int32_t a, int32_t b) 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return a > b ? 1 : (a < b ? -1 : 0); 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkFloat::Cmp(int32_t packed_a, int32_t packed_b) 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com packed_a = SkApplySign(clear_high_bit(packed_a), SkExtractSign(packed_a)); 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com packed_b = SkApplySign(clear_high_bit(packed_b), SkExtractSign(packed_b)); 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return int_sign(packed_a, packed_b); 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////////// 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////////// 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRandom.h" 2657886ad3de1aa523d5c71f1fa9f355dfcb2412d1dreed@google.com#include "SkFloatingPoint.h" 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkFloat::UnitTest() 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 269385afd8b7127b5578d6f272e6b9e7080c2afd229robertphillips@google.com#if 0 // def SK_SUPPORT_UNITTEST 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFloat a, b, c, d; 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int n; 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a.setZero(); 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n = a.getInt(); 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(n == 0); 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com b.setInt(5); 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n = b.getInt(); 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(n == 5); 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.setInt(-3); 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n = c.getInt(); 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(n == -3); 2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com d.setAdd(c, b); 286fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkDebugf("SkFloat: %d + %d = %d\n", c.getInt(), b.getInt(), d.getInt()); 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 288e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.org SkRandom rand; 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int i; 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (i = 0; i < 1000; i++) 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com float fa, fb; 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int aa = rand.nextS() >> 14; 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int bb = rand.nextS() >> 14; 2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a.setInt(aa); 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com b.setInt(bb); 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(a.getInt() == aa); 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(b.getInt() == bb); 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.setAdd(a, b); 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int cc = c.getInt(); 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(cc == aa + bb); 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.setSub(a, b); 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cc = c.getInt(); 3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(cc == aa - bb); 3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa >>= 5; 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bb >>= 5; 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a.setInt(aa); 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com b.setInt(bb); 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.setMul(a, b); 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cc = c.getInt(); 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(cc == aa * bb); 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ///////////////////////////////////// 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa = rand.nextS() >> 11; 3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a.setFixed(aa); 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cc = a.getFixed(); 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(aa == cc); 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bb = rand.nextS() >> 11; 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com b.setFixed(bb); 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cc = b.getFixed(); 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(bb == cc); 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cc = SkFixedMul(aa, bb); 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.setMul(a, b); 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed dd = c.getFixed(); 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int diff = cc - dd; 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(SkAbs32(diff) <= 1); 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fa = (float)aa / 65536.0f; 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fb = (float)bb / 65536.0f; 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a.assertEquals(fa); 3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com b.assertEquals(fb); 3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fa = a.getFloat(); 3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fb = b.getFloat(); 3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.assertEquals(fa * fb, 1); 3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.setDiv(a, b); 3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cc = SkFixedDiv(aa, bb); 3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dd = c.getFixed(); 3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com diff = cc - dd; 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(SkAbs32(diff) <= 3); 3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.assertEquals(fa / fb, 1); 3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((aa == bb) == (a == b)); 3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((aa != bb) == (a != b)); 3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((aa < bb) == (a < b)); 3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((aa <= bb) == (a <= b)); 3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((aa > bb) == (a > b)); 3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((aa >= bb) == (a >= b)); 3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (aa < 0) 3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa = -aa; 3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fa = -fa; 3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a.setFixed(aa); 3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.setSqrt(a); 3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cc = SkFixedSqrt(aa); 3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dd = c.getFixed(); 3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(dd == cc); 3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.assertEquals(sk_float_sqrt(fa), 2); 3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // cuberoot 3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0 3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a.setInt(1); 3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a.cubeRoot(); 3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a.assertEquals(1.0f, 0); 3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a.setInt(8); 3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a.cubeRoot(); 3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a.assertEquals(2.0f, 0); 3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a.setInt(27); 3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a.cubeRoot(); 3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a.assertEquals(3.0f, 0); 3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 388