LCOV - code coverage report
Current view: directory - gfx/skia/src/core - SkMath.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 231 0 0.0 %
Date: 2012-06-02 Functions: 21 0 0.0 %

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

Generated by: LCOV version 1.7