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