1bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/* 2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2008 The Android Open Source Project 3bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com * 4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file. 6bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 7bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 81b03b2b8c46cc230a5f78a5617526d35da9fb29ereed@google.com#include "SkMathPriv.h" 9bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkCordic.h" 10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkFloatBits.h" 11bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkFloatingPoint.h" 12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "Sk64.h" 13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkScalar.h" 14bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 15bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_SCALAR_IS_FLOAT 16bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const uint32_t gIEEENotANumber = 0x7FFFFFFF; 17bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const uint32_t gIEEEInfinity = 0x7F800000; 18e7fbdcafc5488d4c766599d8e4e6b71dee466553bsalomon@google.com const uint32_t gIEEENegativeInfinity = 0xFF800000; 19bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 20bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 21bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define sub_shift(zeros, x, n) \ 22bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com zeros -= n; \ 23bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com x >>= n 24935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 25bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint SkCLZ_portable(uint32_t x) { 26bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (x == 0) { 27bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return 32; 28bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 29bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 30bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int zeros = 31; 31bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (x & 0xFFFF0000) { 32bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sub_shift(zeros, x, 16); 33bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 34bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (x & 0xFF00) { 35bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sub_shift(zeros, x, 8); 36bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 37bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (x & 0xF0) { 38bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sub_shift(zeros, x, 4); 39bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 40bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (x & 0xC) { 41bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sub_shift(zeros, x, 2); 42bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 43bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (x & 0x2) { 44bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sub_shift(zeros, x, 1); 45bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return zeros; 48bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 49bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 50bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkMulDiv(int32_t numer1, int32_t numer2, int32_t denom) { 51bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(denom); 52bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 53bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Sk64 tmp; 54bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp.setMul(numer1, numer2); 55bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp.div(denom, Sk64::kTrunc_DivOption); 56bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return tmp.get32(); 57bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 59bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkMulShift(int32_t a, int32_t b, unsigned shift) { 60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int sign = SkExtractSign(a ^ b); 61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 62bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (shift > 63) { 63bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return sign; 64bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 65bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 66bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a = SkAbs32(a); 67bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com b = SkAbs32(b); 68bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 69bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t ah = a >> 16; 70bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t al = a & 0xFFFF; 71bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t bh = b >> 16; 72bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t bl = b & 0xFFFF; 73bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 74bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t A = ah * bh; 75bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t B = ah * bl + al * bh; 76bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t C = al * bl; 77bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 78bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /* [ A ] 79bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com [ B ] 80bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com [ C ] 81bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 82bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t lo = C + (B << 16); 83bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int32_t hi = A + (B >> 16) + (lo < C); 84bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 85bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (sign < 0) { 86bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com hi = -hi - Sk32ToBool(lo); 87bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com lo = 0 - lo; 88bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 90bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (shift == 0) { 91bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUGx 92bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(((int32_t)lo >> 31) == hi); 93bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 94bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return lo; 95bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else if (shift >= 32) { 96bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return hi >> (shift - 32); 97bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 98bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUGx 99bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int32_t tmp = hi >> shift; 100bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(tmp == 0 || tmp == -1); 101bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 102bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // we want (hi << (32 - shift)) | (lo >> shift) but rounded 103bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int roundBit = (lo >> (shift - 1)) & 1; 104bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return ((hi << (32 - shift)) | (lo >> shift)) + roundBit; 105bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 106bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 107bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 108bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkFixed SkFixedMul_portable(SkFixed a, SkFixed b) { 109bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#if 0 110bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Sk64 tmp; 111bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp.setMul(a, b); 113bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp.shiftRight(16); 114bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return tmp.fLo; 115bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#elif defined(SkLONGLONG) 116e5dd6cd1e1addbc58df3d0f55655448140490002reed@android.com return static_cast<SkFixed>((SkLONGLONG)a * b >> 16); 117bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#else 118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int sa = SkExtractSign(a); 119bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int sb = SkExtractSign(b); 120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // now make them positive 121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a = SkApplySign(a, sa); 122bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com b = SkApplySign(b, sb); 123bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t ah = a >> 16; 125bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t al = a & 0xFFFF; 126bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t bh = b >> 16; 127bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t bl = b & 0xFFFF; 128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t R = ah * b + al * bh + (al * bl >> 16); 130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 131bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkApplySign(R, sa ^ sb); 132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 135bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkFract SkFractMul_portable(SkFract a, SkFract b) { 136bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#if 0 137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Sk64 tmp; 138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp.setMul(a, b); 139bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return tmp.getFract(); 140bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#elif defined(SkLONGLONG) 141e5dd6cd1e1addbc58df3d0f55655448140490002reed@android.com return static_cast<SkFract>((SkLONGLONG)a * b >> 30); 142bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#else 143bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int sa = SkExtractSign(a); 144bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int sb = SkExtractSign(b); 145bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // now make them positive 146bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a = SkApplySign(a, sa); 147bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com b = SkApplySign(b, sb); 148bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 149bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t ah = a >> 16; 150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t al = a & 0xFFFF; 151bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t bh = b >> 16; 152bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t bl = b & 0xFFFF; 153bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 154bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t A = ah * bh; 155bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t B = ah * bl + al * bh; 156bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t C = al * bl; 157bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 158bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /* [ A ] 159bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com [ B ] 160bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com [ C ] 161bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 162bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t Lo = C + (B << 16); 163bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t Hi = A + (B >>16) + (Lo < C); 164bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 165bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((Hi >> 29) == 0); // else overflow 166bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 167bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int32_t R = (Hi << 2) + (Lo >> 30); 168bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 169bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkApplySign(R, sa ^ sb); 170bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 171bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 172bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 173bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint SkFixedMulCommon(SkFixed a, int b, int bias) { 174bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // this function only works if b is 16bits 175bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(b == (int16_t)b); 176bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(b >= 0); 177bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 178bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int sa = SkExtractSign(a); 179bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a = SkApplySign(a, sa); 180bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t ah = a >> 16; 181bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t al = a & 0xFFFF; 182bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t R = ah * b + ((al * b + bias) >> 16); 183bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkApplySign(R, sa); 184bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 185bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 186bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUGx 187bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com #define TEST_FASTINVERT 188bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 189bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 190bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkFixed SkFixedFastInvert(SkFixed x) { 191bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/* Adapted (stolen) from gglRecip() 192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com*/ 193bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 194bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (x == SK_Fixed1) { 195bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SK_Fixed1; 196bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 197bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 198bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int sign = SkExtractSign(x); 199bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t a = SkApplySign(x, sign); 200bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 201bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (a <= 2) { 202bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkApplySign(SK_MaxS32, sign); 203bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 204bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 205bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef TEST_FASTINVERT 206bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkFixed orig = a; 207bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t slow = SkFixedDiv(SK_Fixed1, a); 208bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 209bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 210bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // normalize a 211bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int lz = SkCLZ(a); 212bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a = a << lz >> 16; 213bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 214935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com // compute 1/a approximation (0.5 <= a < 1.0) 215bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t r = 0x17400 - a; // (2.90625 (~2.914) - 2*a) >> 1 216bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 217bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // Newton-Raphson iteration: 218bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // x = r*(2 - a*r) = ((r/2)*(1 - a*r/2))*4 219bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com r = ( (0x10000 - ((a*r)>>16)) * r ) >> 15; 220bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com r = ( (0x10000 - ((a*r)>>16)) * r ) >> (30 - lz); 221bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 222bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef TEST_FASTINVERT 223bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDebugf("SkFixedFastInvert(%x %g) = %x %g Slow[%x %g]\n", 224bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com orig, orig/65536., 225bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com r, r/65536., 226bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com slow, slow/65536.); 227bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 228bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 229bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkApplySign(r, sign); 230bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 231bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 232bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 233bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 234bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define DIVBITS_ITER(n) \ 235bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case n: \ 236bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if ((numer = (numer << 1) - denom) >= 0) \ 237bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com result |= 1 << (n - 1); else numer += denom 238935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 239bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkDivBits(int32_t numer, int32_t denom, int shift_bias) { 240bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(denom != 0); 241bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (numer == 0) { 242bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return 0; 243bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 244935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 245bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // make numer and denom positive, and sign hold the resulting sign 246bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int32_t sign = SkExtractSign(numer ^ denom); 247bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com numer = SkAbs32(numer); 248bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com denom = SkAbs32(denom); 249bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 250bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int nbits = SkCLZ(numer) - 1; 251bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int dbits = SkCLZ(denom) - 1; 252bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int bits = shift_bias - nbits + dbits; 253bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 254bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (bits < 0) { // answer will underflow 255bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return 0; 256bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 257bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (bits > 31) { // answer will overflow 258bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkApplySign(SK_MaxS32, sign); 259bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 260bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 261bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com denom <<= dbits; 262bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com numer <<= nbits; 263935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 264bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkFixed result = 0; 265935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 266bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // do the first one 267bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if ((numer -= denom) >= 0) { 268bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com result = 1; 269bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 270bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com numer += denom; 271bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 272935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 273bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // Now fall into our switch statement if there are more bits to compute 274bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (bits > 0) { 275bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // make room for the rest of the answer bits 276bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com result <<= bits; 277bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com switch (bits) { 278bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com DIVBITS_ITER(31); DIVBITS_ITER(30); DIVBITS_ITER(29); 279bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com DIVBITS_ITER(28); DIVBITS_ITER(27); DIVBITS_ITER(26); 280bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com DIVBITS_ITER(25); DIVBITS_ITER(24); DIVBITS_ITER(23); 281bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com DIVBITS_ITER(22); DIVBITS_ITER(21); DIVBITS_ITER(20); 282bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com DIVBITS_ITER(19); DIVBITS_ITER(18); DIVBITS_ITER(17); 283bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com DIVBITS_ITER(16); DIVBITS_ITER(15); DIVBITS_ITER(14); 284bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com DIVBITS_ITER(13); DIVBITS_ITER(12); DIVBITS_ITER(11); 285bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com DIVBITS_ITER(10); DIVBITS_ITER( 9); DIVBITS_ITER( 8); 286bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com DIVBITS_ITER( 7); DIVBITS_ITER( 6); DIVBITS_ITER( 5); 287bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com DIVBITS_ITER( 4); DIVBITS_ITER( 3); DIVBITS_ITER( 2); 288bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // we merge these last two together, makes GCC make better ARM 289bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com default: 290bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com DIVBITS_ITER( 1); 291bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 292bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 293bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 294bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (result < 0) { 295bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com result = SK_MaxS32; 296bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 297bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkApplySign(result, sign); 298bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 299bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 300bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/* mod(float numer, float denom) seems to always return the sign 301bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com of the numer, so that's what we do too 302bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com*/ 303bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkFixed SkFixedMod(SkFixed numer, SkFixed denom) { 304bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int sn = SkExtractSign(numer); 305bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int sd = SkExtractSign(denom); 306bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 307bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com numer = SkApplySign(numer, sn); 308bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com denom = SkApplySign(denom, sd); 309935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (numer < denom) { 311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkApplySign(numer, sn); 312bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else if (numer == denom) { 313bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return 0; 314bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 315bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkFixed div = SkFixedDiv(numer, denom); 316bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkApplySign(SkFixedMul(denom, div & 0xFFFF), sn); 317bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 318bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 319bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 320bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/* www.worldserver.com/turk/computergraphics/FixedSqrt.pdf 321bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com*/ 322bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkSqrtBits(int32_t x, int count) { 323bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(x >= 0 && count > 0 && (unsigned)count <= 30); 324bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 325bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t root = 0; 326bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t remHi = 0; 327bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t remLo = x; 328bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 329bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com do { 330bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com root <<= 1; 331bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 332bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com remHi = (remHi<<2) | (remLo>>30); 333bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com remLo <<= 2; 334bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 335bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t testDiv = (root << 1) + 1; 336bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (remHi >= testDiv) { 337bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com remHi -= testDiv; 338bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com root++; 339bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 340bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } while (--count >= 0); 341bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 342bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return root; 343bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 344bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 345bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint32_t SkCubeRootBits(int32_t value, int bits) { 346bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(bits > 0); 347bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 348bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int sign = SkExtractSign(value); 349bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com value = SkApplySign(value, sign); 350bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 351bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t root = 0; 352bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t curr = (uint32_t)value >> 30; 353bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com value <<= 2; 354bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 355bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com do { 356bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com root <<= 1; 357bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t guess = root * root + root; 358bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com guess = (guess << 1) + guess; // guess *= 3 359bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (guess < curr) { 360bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com curr -= guess + 1; 361bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com root |= 1; 362bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 363bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com curr = (curr << 3) | ((uint32_t)value >> 29); 364bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com value <<= 3; 365bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } while (--bits); 366bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 367bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkApplySign(root, sign); 368bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 369bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 370bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkFixed SkFixedMean(SkFixed a, SkFixed b) { 371bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Sk64 tmp; 372935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 373bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp.setMul(a, b); 374bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return tmp.getSqrt(); 375bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 376bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 377bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 378bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 379bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_SCALAR_IS_FLOAT 380bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comfloat SkScalarSinCos(float radians, float* cosValue) { 381bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com float sinValue = sk_float_sin(radians); 382bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 383bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (cosValue) { 384bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *cosValue = sk_float_cos(radians); 385bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (SkScalarNearlyZero(*cosValue)) { 386bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *cosValue = 0; 387bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 388bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 389bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 390bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (SkScalarNearlyZero(sinValue)) { 391bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sinValue = 0; 392bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 393bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return sinValue; 394bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 395bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 396bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 397bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define INTERP_SINTABLE 398bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define BUILD_TABLE_AT_RUNTIMEx 399bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 400bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define kTableSize 256 401bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 402bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef BUILD_TABLE_AT_RUNTIME 403bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com static uint16_t gSkSinTable[kTableSize]; 404bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 405bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com static void build_sintable(uint16_t table[]) { 406bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com for (int i = 0; i < kTableSize; i++) { 407bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com double rad = i * 3.141592653589793 / (2*kTableSize); 408bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com double val = sin(rad); 409bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int ival = (int)(val * SK_Fixed1); 410bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com table[i] = SkToU16(ival); 411bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 412bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 413bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#else 414bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com #include "SkSinTable.h" 415bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 416bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 417bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define SK_Fract1024SizeOver2PI 0x28BE60 /* floatToFract(1024 / 2PI) */ 418bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 419bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef INTERP_SINTABLE 420bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic SkFixed interp_table(const uint16_t table[], int index, int partial255) { 421bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((unsigned)index < kTableSize); 422bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((unsigned)partial255 <= 255); 423bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 424bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkFixed lower = table[index]; 425bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkFixed upper = (index == kTableSize - 1) ? SK_Fixed1 : table[index + 1]; 426bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 427bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(lower < upper); 428bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(lower >= 0); 429bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(upper <= SK_Fixed1); 430bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 431bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com partial255 += (partial255 >> 7); 432bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return lower + ((upper - lower) * partial255 >> 8); 433bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 434bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 435bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 436bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValuePtr) { 437bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(SK_ARRAY_COUNT(gSkSinTable) == kTableSize); 438bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 439bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef BUILD_TABLE_AT_RUNTIME 440bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com static bool gFirstTime = true; 441bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (gFirstTime) { 442bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com build_sintable(gSinTable); 443bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com gFirstTime = false; 444bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 445bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 446bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 447bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // make radians positive 448bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkFixed sinValue, cosValue; 449bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int32_t cosSign = 0; 450bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int32_t sinSign = SkExtractSign(radians); 451bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com radians = SkApplySign(radians, sinSign); 452bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // scale it to 0...1023 ... 453bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 454bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef INTERP_SINTABLE 455bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com radians = SkMulDiv(radians, 2 * kTableSize * 256, SK_FixedPI); 456bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int findex = radians & (kTableSize * 256 - 1); 457bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int index = findex >> 8; 458bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int partial = findex & 255; 459bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sinValue = interp_table(gSkSinTable, index, partial); 460bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 461bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com findex = kTableSize * 256 - findex - 1; 462bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com index = findex >> 8; 463bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com partial = findex & 255; 464bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cosValue = interp_table(gSkSinTable, index, partial); 465bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 466bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int quad = ((unsigned)radians / (kTableSize * 256)) & 3; 467bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#else 468bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com radians = SkMulDiv(radians, 2 * kTableSize, SK_FixedPI); 469bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int index = radians & (kTableSize - 1); 470bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 471bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (index == 0) { 472bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sinValue = 0; 473bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cosValue = SK_Fixed1; 474bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 475bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sinValue = gSkSinTable[index]; 476bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cosValue = gSkSinTable[kTableSize - index]; 477bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 478bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int quad = ((unsigned)radians / kTableSize) & 3; 479bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 480bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 481bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (quad & 1) { 482bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkTSwap<SkFixed>(sinValue, cosValue); 483bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 484bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (quad & 2) { 485bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sinSign = ~sinSign; 486bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 487bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (((quad - 1) & 2) == 0) { 488bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cosSign = ~cosSign; 489bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 490bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 491bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // restore the sign for negative angles 492bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sinValue = SkApplySign(sinValue, sinSign); 493bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cosValue = SkApplySign(cosValue, cosSign); 494bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 495bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG 496bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (1) { 497bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkFixed sin2 = SkFixedMul(sinValue, sinValue); 498bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkFixed cos2 = SkFixedMul(cosValue, cosValue); 499bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int diff = cos2 + sin2 - SK_Fixed1; 500bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(SkAbs32(diff) <= 7); 501bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 502bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 503bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 504bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (cosValuePtr) { 505bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *cosValuePtr = cosValue; 506bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 507bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return sinValue; 508bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 509bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 510bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 511bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 512bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkFixed SkFixedTan(SkFixed radians) { return SkCordicTan(radians); } 513bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkFixed SkFixedASin(SkFixed x) { return SkCordicASin(x); } 514bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkFixed SkFixedACos(SkFixed x) { return SkCordicACos(x); } 515bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkFixed SkFixedATan2(SkFixed y, SkFixed x) { return SkCordicATan2(y, x); } 516bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkFixed SkFixedExp(SkFixed x) { return SkCordicExp(x); } 517bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkFixed SkFixedLog(SkFixed x) { return SkCordicLog(x); } 518