18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 The Android Open Source Project 38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 84b163ed2c22facbe8891616874ae07ba7827d9c9reed@google.com#include "SkMathPriv.h" 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFloatBits.h" 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFloatingPoint.h" 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalar.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 138f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.comconst uint32_t gIEEENotANumber = 0x7FFFFFFF; 148f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.comconst uint32_t gIEEEInfinity = 0x7F800000; 158f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.comconst uint32_t gIEEENegativeInfinity = 0xFF800000; 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define sub_shift(zeros, x, n) \ 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com zeros -= n; \ 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x >>= n 20fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCLZ_portable(uint32_t x) { 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (x == 0) { 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 32; 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int zeros = 31; 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (x & 0xFFFF0000) { 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sub_shift(zeros, x, 16); 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (x & 0xFF00) { 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sub_shift(zeros, x, 8); 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (x & 0xF0) { 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sub_shift(zeros, x, 4); 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (x & 0xC) { 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sub_shift(zeros, x, 2); 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (x & 0x2) { 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sub_shift(zeros, x, 1); 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return zeros; 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 460e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.comSkFixed SkFixedMul_portable(SkFixed a, SkFixed b) { 471915fd09f3b60eb907f5ab155e8379b589e2bae1reed@google.com#if defined(SkLONGLONG) 4801c41a556e0ef0ae2338a1b5ae110a501e1ed0a8reed@google.com return static_cast<SkFixed>((int64_t)a * b >> 16); 490e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com#else 500e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com int sa = SkExtractSign(a); 510e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com int sb = SkExtractSign(b); 520e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com // now make them positive 530e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com a = SkApplySign(a, sa); 540e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com b = SkApplySign(b, sb); 550e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com 560e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com uint32_t ah = a >> 16; 570e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com uint32_t al = a & 0xFFFF; 580e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com uint32_t bh = b >> 16; 590e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com uint32_t bl = b & 0xFFFF; 600e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com 610e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com uint32_t R = ah * b + al * bh + (al * bl >> 16); 620e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com 630e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com return SkApplySign(R, sa ^ sb); 640e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com#endif 650e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com} 660e6e8cc627242cc7e301401cfe112ba98a008101robertphillips@google.com 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define DIVBITS_ITER(n) \ 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case n: \ 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((numer = (numer << 1) - denom) >= 0) \ 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result |= 1 << (n - 1); else numer += denom 73fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkDivBits(int32_t numer, int32_t denom, int shift_bias) { 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(denom != 0); 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (numer == 0) { 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 79fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // make numer and denom positive, and sign hold the resulting sign 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int32_t sign = SkExtractSign(numer ^ denom); 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com numer = SkAbs32(numer); 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com denom = SkAbs32(denom); 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int nbits = SkCLZ(numer) - 1; 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int dbits = SkCLZ(denom) - 1; 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int bits = shift_bias - nbits + dbits; 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bits < 0) { // answer will underflow 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bits > 31) { // answer will overflow 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkApplySign(SK_MaxS32, sign); 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com denom <<= dbits; 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com numer <<= nbits; 98fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed result = 0; 100fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // do the first one 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((numer -= denom) >= 0) { 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result = 1; 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com numer += denom; 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 107fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Now fall into our switch statement if there are more bits to compute 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bits > 0) { 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // make room for the rest of the answer bits 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result <<= bits; 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (bits) { 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DIVBITS_ITER(31); DIVBITS_ITER(30); DIVBITS_ITER(29); 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DIVBITS_ITER(28); DIVBITS_ITER(27); DIVBITS_ITER(26); 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DIVBITS_ITER(25); DIVBITS_ITER(24); DIVBITS_ITER(23); 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DIVBITS_ITER(22); DIVBITS_ITER(21); DIVBITS_ITER(20); 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DIVBITS_ITER(19); DIVBITS_ITER(18); DIVBITS_ITER(17); 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DIVBITS_ITER(16); DIVBITS_ITER(15); DIVBITS_ITER(14); 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DIVBITS_ITER(13); DIVBITS_ITER(12); DIVBITS_ITER(11); 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DIVBITS_ITER(10); DIVBITS_ITER( 9); DIVBITS_ITER( 8); 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DIVBITS_ITER( 7); DIVBITS_ITER( 6); DIVBITS_ITER( 5); 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DIVBITS_ITER( 4); DIVBITS_ITER( 3); DIVBITS_ITER( 2); 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // we merge these last two together, makes GCC make better ARM 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DIVBITS_ITER( 1); 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (result < 0) { 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result = SK_MaxS32; 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkApplySign(result, sign); 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* www.worldserver.com/turk/computergraphics/FixedSqrt.pdf 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkSqrtBits(int32_t x, int count) { 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(x >= 0 && count > 0 && (unsigned)count <= 30); 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t root = 0; 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t remHi = 0; 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t remLo = x; 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com root <<= 1; 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com remHi = (remHi<<2) | (remLo>>30); 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com remLo <<= 2; 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t testDiv = (root << 1) + 1; 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (remHi >= testDiv) { 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com remHi -= testDiv; 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com root++; 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--count >= 0); 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return root; 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comfloat SkScalarSinCos(float radians, float* cosValue) { 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com float sinValue = sk_float_sin(radians); 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (cosValue) { 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *cosValue = sk_float_cos(radians); 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkScalarNearlyZero(*cosValue)) { 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *cosValue = 0; 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkScalarNearlyZero(sinValue)) { 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sinValue = 0; 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return sinValue; 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define INTERP_SINTABLE 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define BUILD_TABLE_AT_RUNTIMEx 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define kTableSize 256 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef BUILD_TABLE_AT_RUNTIME 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static uint16_t gSkSinTable[kTableSize]; 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void build_sintable(uint16_t table[]) { 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < kTableSize; i++) { 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com double rad = i * 3.141592653589793 / (2*kTableSize); 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com double val = sin(rad); 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int ival = (int)(val * SK_Fixed1); 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com table[i] = SkToU16(ival); 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #include "SkSinTable.h" 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_Fract1024SizeOver2PI 0x28BE60 /* floatToFract(1024 / 2PI) */ 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef INTERP_SINTABLE 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkFixed interp_table(const uint16_t table[], int index, int partial255) { 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)index < kTableSize); 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)partial255 <= 255); 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed lower = table[index]; 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed upper = (index == kTableSize - 1) ? SK_Fixed1 : table[index + 1]; 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(lower < upper); 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(lower >= 0); 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(upper <= SK_Fixed1); 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com partial255 += (partial255 >> 7); 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return lower + ((upper - lower) * partial255 >> 8); 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValuePtr) { 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(SK_ARRAY_COUNT(gSkSinTable) == kTableSize); 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef BUILD_TABLE_AT_RUNTIME 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static bool gFirstTime = true; 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (gFirstTime) { 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com build_sintable(gSinTable); 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com gFirstTime = false; 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // make radians positive 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed sinValue, cosValue; 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int32_t cosSign = 0; 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int32_t sinSign = SkExtractSign(radians); 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com radians = SkApplySign(radians, sinSign); 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // scale it to 0...1023 ... 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef INTERP_SINTABLE 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com radians = SkMulDiv(radians, 2 * kTableSize * 256, SK_FixedPI); 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int findex = radians & (kTableSize * 256 - 1); 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = findex >> 8; 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int partial = findex & 255; 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sinValue = interp_table(gSkSinTable, index, partial); 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com findex = kTableSize * 256 - findex - 1; 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com index = findex >> 8; 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com partial = findex & 255; 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cosValue = interp_table(gSkSinTable, index, partial); 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int quad = ((unsigned)radians / (kTableSize * 256)) & 3; 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com radians = SkMulDiv(radians, 2 * kTableSize, SK_FixedPI); 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = radians & (kTableSize - 1); 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index == 0) { 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sinValue = 0; 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cosValue = SK_Fixed1; 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sinValue = gSkSinTable[index]; 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cosValue = gSkSinTable[kTableSize - index]; 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int quad = ((unsigned)radians / kTableSize) & 3; 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (quad & 1) { 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTSwap<SkFixed>(sinValue, cosValue); 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (quad & 2) { 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sinSign = ~sinSign; 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (((quad - 1) & 2) == 0) { 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cosSign = ~cosSign; 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // restore the sign for negative angles 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sinValue = SkApplySign(sinValue, sinSign); 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cosValue = SkApplySign(cosValue, cosSign); 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (1) { 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed sin2 = SkFixedMul(sinValue, sinValue); 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed cos2 = SkFixedMul(cosValue, cosValue); 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int diff = cos2 + sin2 - SK_Fixed1; 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(SkAbs32(diff) <= 7); 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (cosValuePtr) { 2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *cosValuePtr = cosValue; 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return sinValue; 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 290