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

       1                 : 
       2                 : /*
       3                 :  * Copyright 2006 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 "SkCordic.h"
      11                 : #include "SkMath.h"
      12                 : #include "Sk64.h"
      13                 : 
      14                 : // 0x20000000 equals pi / 4
      15                 : const int32_t kATanDegrees[] = { 0x20000000,
      16                 :     0x12E4051D, 0x9FB385B, 0x51111D4, 0x28B0D43, 0x145D7E1, 0xA2F61E, 0x517C55,
      17                 :     0x28BE53, 0x145F2E, 0xA2F98, 0x517CC, 0x28BE6, 0x145F3, 0xA2F9, 0x517C,
      18                 :     0x28BE, 0x145F, 0xA2F, 0x517, 0x28B, 0x145, 0xA2, 0x51, 0x28, 0x14,
      19                 :     0xA, 0x5, 0x2, 0x1 };
      20                 : 
      21                 : const int32_t kFixedInvGain1 = 0x18bde0bb;  // 0.607252935
      22                 : 
      23               0 : static void SkCircularRotation(int32_t* x0, int32_t* y0, int32_t* z0) 
      24                 : {
      25               0 :     int32_t t = 0;
      26               0 :     int32_t x = *x0;
      27               0 :     int32_t y = *y0;
      28               0 :     int32_t z = *z0;
      29               0 :     const int32_t* tanPtr = kATanDegrees;
      30               0 :    do {
      31               0 :         int32_t x1 = y >> t;
      32               0 :         int32_t y1 = x >> t;
      33               0 :         int32_t tan = *tanPtr++;    
      34               0 :         if (z >= 0) {
      35               0 :             x -= x1;
      36               0 :             y += y1;
      37               0 :             z -= tan;
      38                 :         } else {
      39               0 :             x += x1;
      40               0 :             y -= y1;
      41               0 :             z += tan;
      42                 :         }
      43                 :    } while (++t < 16); // 30);
      44               0 :     *x0 = x;
      45               0 :     *y0 = y;
      46               0 :     *z0 = z;
      47               0 : }
      48                 : 
      49               0 : SkFixed SkCordicSinCos(SkFixed radians, SkFixed* cosp)
      50                 : {
      51               0 :     int32_t scaledRadians = radians * 0x28be;   // scale radians to 65536 / PI()
      52               0 :     int quadrant = scaledRadians >> 30;
      53               0 :     quadrant += 1;
      54               0 :     if (quadrant & 2) 
      55               0 :         scaledRadians = -scaledRadians + 0x80000000;
      56                 :     /* |a| <= 90 degrees as a 1.31 number */
      57               0 :     SkFixed sin = 0;
      58               0 :     SkFixed cos = kFixedInvGain1;
      59               0 :     SkCircularRotation(&cos, &sin, &scaledRadians);
      60                 :     Sk64 scaled;
      61               0 :     scaled.setMul(sin, 0x6488d);
      62               0 :     sin = scaled.fHi;
      63               0 :     scaled.setMul(cos, 0x6488d);
      64               0 :     if (quadrant & 2)
      65               0 :         scaled.fHi = - scaled.fHi;
      66               0 :     *cosp = scaled.fHi;
      67               0 :     return sin;
      68                 : }
      69                 : 
      70               0 : SkFixed SkCordicTan(SkFixed a) 
      71                 : {
      72                 :     int32_t cos;
      73               0 :     int32_t sin = SkCordicSinCos(a, &cos);
      74               0 :     return SkFixedDiv(sin, cos);
      75                 : }
      76                 : 
      77               0 : static int32_t SkCircularVector(int32_t* y0, int32_t* x0, int32_t vecMode) 
      78                 : {
      79               0 :     int32_t x = *x0;
      80               0 :     int32_t y = *y0;
      81               0 :     int32_t z = 0;
      82               0 :     int32_t t = 0;
      83               0 :     const int32_t* tanPtr = kATanDegrees;
      84               0 :    do {
      85               0 :         int32_t x1 = y >> t;
      86               0 :         int32_t y1 = x >> t;
      87               0 :         int32_t tan = *tanPtr++;    
      88               0 :         if (y < vecMode) {
      89               0 :             x -= x1;
      90               0 :             y += y1;
      91               0 :             z -= tan;
      92                 :         } else {
      93               0 :             x += x1;
      94               0 :             y -= y1;
      95               0 :             z += tan;
      96                 :         }
      97                 :    } while (++t < 16);  // 30
      98                 :     Sk64 scaled;
      99               0 :     scaled.setMul(z, 0x6488d); // scale back into the SkScalar space (0x100000000/0x28be)
     100               0 :    return scaled.fHi;
     101                 : }
     102                 : 
     103               0 : SkFixed SkCordicASin(SkFixed a) {
     104               0 :     int32_t sign = SkExtractSign(a);
     105               0 :     int32_t z = SkFixedAbs(a);
     106               0 :     if (z >= SK_Fixed1)
     107               0 :         return SkApplySign(SK_FixedPI>>1, sign);
     108               0 :     int32_t x = kFixedInvGain1;
     109               0 :     int32_t y = 0;
     110               0 :     z *= 0x28be;
     111               0 :     z = SkCircularVector(&y, &x, z);
     112               0 :     z = SkApplySign(z, ~sign);
     113               0 :     return z;
     114                 : }
     115                 : 
     116               0 : SkFixed SkCordicACos(SkFixed a) {
     117               0 :     int32_t z = SkCordicASin(a);
     118               0 :     z = (SK_FixedPI>>1) - z;
     119               0 :     return z;
     120                 : }
     121                 : 
     122               0 : SkFixed SkCordicATan2(SkFixed y, SkFixed x) {
     123               0 :     if ((x | y) == 0)
     124               0 :         return 0;
     125               0 :     int32_t xsign = SkExtractSign(x);
     126               0 :     x = SkFixedAbs(x);
     127               0 :     int32_t result = SkCircularVector(&y, &x, 0);
     128               0 :     if (xsign) {
     129               0 :         int32_t rsign = SkExtractSign(result);
     130               0 :         if (y == 0)
     131               0 :             rsign = 0;
     132               0 :         SkFixed pi = SkApplySign(SK_FixedPI, rsign);
     133               0 :         result = pi - result;
     134                 :     }
     135               0 :     return result;
     136                 : }
     137                 : 
     138                 : const int32_t kATanHDegrees[] = { 
     139                 :     0x1661788D, 0xA680D61, 0x51EA6FC, 0x28CBFDD, 0x1460E34,
     140                 :     0xA2FCE8, 0x517D2E, 0x28BE6E, 0x145F32,
     141                 :     0xA2F98, 0x517CC, 0x28BE6, 0x145F3, 0xA2F9, 0x517C,
     142                 :     0x28BE, 0x145F, 0xA2F, 0x517, 0x28B, 0x145, 0xA2, 0x51, 0x28, 0x14,
     143                 :     0xA, 0x5, 0x2, 0x1 };
     144                 : 
     145                 : const int32_t kFixedInvGain2 = 0x31330AAA;  // 1.207534495
     146                 : 
     147               0 : static void SkHyperbolic(int32_t* x0, int32_t* y0, int32_t* z0, int mode) 
     148                 : {
     149               0 :     int32_t t = 1;
     150               0 :     int32_t x = *x0;
     151               0 :     int32_t y = *y0;
     152               0 :     int32_t z = *z0;
     153               0 :     const int32_t* tanPtr = kATanHDegrees;
     154               0 :     int k = -3;
     155               0 :     do {
     156               0 :         int32_t x1 = y >> t;
     157               0 :         int32_t y1 = x >> t;
     158               0 :         int32_t tan = *tanPtr++;    
     159               0 :         int count = 2 + (k >> 31);
     160               0 :         if (++k == 1)
     161               0 :             k = -2;
     162               0 :         do {
     163               0 :             if (((y >> 31) & mode) | ~((z >> 31) | mode)) {
     164               0 :                 x += x1;
     165               0 :                 y += y1;
     166               0 :                 z -= tan;
     167                 :             } else {
     168               0 :                 x -= x1;
     169               0 :                 y -= y1;
     170               0 :                 z += tan;
     171                 :             }
     172                 :         } while (--count);
     173                 :     } while (++t < 30);
     174               0 :     *x0 = x;
     175               0 :     *y0 = y;
     176               0 :     *z0 = z;
     177               0 : }
     178                 : 
     179               0 : SkFixed SkCordicLog(SkFixed a) {
     180               0 :     a *= 0x28be;
     181               0 :     int32_t x = a + 0x28BE60DB; // 1.0
     182               0 :     int32_t y = a - 0x28BE60DB;
     183               0 :     int32_t z = 0;
     184               0 :     SkHyperbolic(&x, &y, &z, -1);
     185                 :     Sk64 scaled;
     186               0 :     scaled.setMul(z, 0x6488d);
     187               0 :     z = scaled.fHi;
     188               0 :     return z << 1;
     189                 : }
     190                 : 
     191               0 : SkFixed SkCordicExp(SkFixed a) {
     192               0 :     int32_t cosh = kFixedInvGain2;
     193               0 :     int32_t sinh = 0;
     194               0 :     SkHyperbolic(&cosh, &sinh, &a, 0);
     195               0 :     return cosh + sinh;
     196                 : }
     197                 : 
     198                 : #ifdef SK_DEBUG
     199                 : 
     200                 : #ifdef SK_CAN_USE_FLOAT
     201                 :     #include "SkFloatingPoint.h"
     202                 : #endif
     203                 : 
     204               0 : void SkCordic_UnitTest()
     205                 : {
     206                 : #if defined(SK_SUPPORT_UNITTEST) && defined(SK_CAN_USE_FLOAT)
     207                 :     float val;
     208                 :     for (float angle = -720; angle < 720; angle += 30) {
     209                 :         float radian = angle * 3.1415925358f / 180.0f;
     210                 :         SkFixed f_angle = (int) (radian * 65536.0f);
     211                 :     // sincos
     212                 :         float sine = sinf(radian);
     213                 :         float cosine = cosf(radian);
     214                 :         SkFixed f_cosine;
     215                 :         SkFixed f_sine = SkCordicSinCos(f_angle, &f_cosine);
     216                 :         float sine2 = (float) f_sine / 65536.0f;
     217                 :         float cosine2 = (float) f_cosine / 65536.0f;
     218                 :         float error = fabsf(sine - sine2);
     219                 :         if (error > 0.001)
     220                 :             SkDebugf("sin error : angle = %g ; sin = %g ; cordic = %g\n", angle, sine, sine2);
     221                 :         error = fabsf(cosine - cosine2);
     222                 :         if (error > 0.001)
     223                 :             SkDebugf("cos error : angle = %g ; cos = %g ; cordic = %g\n", angle, cosine, cosine2);
     224                 :     // tan
     225                 :         float _tan = tanf(radian);
     226                 :         SkFixed f_tan = SkCordicTan(f_angle);
     227                 :         float tan2 = (float) f_tan / 65536.0f;
     228                 :         error = fabsf(_tan - tan2);
     229                 :         if (error > 0.05 && fabsf(_tan) < 1e6)
     230                 :             SkDebugf("tan error : angle = %g ; tan = %g ; cordic = %g\n", angle, _tan, tan2);
     231                 :     }
     232                 :     for (val = -1; val <= 1; val += .1f) {
     233                 :         SkFixed f_val = (int) (val * 65536.0f);
     234                 :     // asin
     235                 :         float arcsine = asinf(val);
     236                 :         SkFixed f_arcsine = SkCordicASin(f_val);
     237                 :         float arcsine2 = (float) f_arcsine / 65536.0f;
     238                 :         float error = fabsf(arcsine - arcsine2);
     239                 :         if (error > 0.001)
     240                 :             SkDebugf("asin error : val = %g ; asin = %g ; cordic = %g\n", val, arcsine, arcsine2);
     241                 :     }
     242                 : #if 1
     243                 :     for (val = -1; val <= 1; val += .1f) {
     244                 : #else
     245                 :     val = .5; {
     246                 : #endif
     247                 :         SkFixed f_val = (int) (val * 65536.0f);
     248                 :     // acos
     249                 :         float arccos = acosf(val);
     250                 :         SkFixed f_arccos = SkCordicACos(f_val);
     251                 :         float arccos2 = (float) f_arccos / 65536.0f;
     252                 :         float error = fabsf(arccos - arccos2);
     253                 :         if (error > 0.001)
     254                 :             SkDebugf("acos error : val = %g ; acos = %g ; cordic = %g\n", val, arccos, arccos2);
     255                 :     }
     256                 :     // atan2
     257                 : #if 1
     258                 :     for (val = -1000; val <= 1000; val += 500.f) {
     259                 :         for (float val2 = -1000; val2 <= 1000; val2 += 500.f) {
     260                 : #else
     261                 :             val = 0; {
     262                 :             float val2 = -1000; {
     263                 : #endif
     264                 :             SkFixed f_val = (int) (val * 65536.0f);
     265                 :             SkFixed f_val2 = (int) (val2 * 65536.0f);
     266                 :             float arctan = atan2f(val, val2);
     267                 :             SkFixed f_arctan = SkCordicATan2(f_val, f_val2);
     268                 :             float arctan2 = (float) f_arctan / 65536.0f;
     269                 :             float error = fabsf(arctan - arctan2);
     270                 :             if (error > 0.001)
     271                 :                 SkDebugf("atan2 error : val = %g ; val2 = %g ; atan2 = %g ; cordic = %g\n", val, val2, arctan, arctan2);
     272                 :         }
     273                 :     }
     274                 :     // log
     275                 : #if 1
     276                 :     for (val = 0.125f; val <= 8.f; val *= 2.0f) {
     277                 : #else
     278                 :     val = .5; {
     279                 : #endif
     280                 :         SkFixed f_val = (int) (val * 65536.0f);
     281                 :     // acos
     282                 :         float log = logf(val);
     283                 :         SkFixed f_log = SkCordicLog(f_val);
     284                 :         float log2 = (float) f_log / 65536.0f;
     285                 :         float error = fabsf(log - log2);
     286                 :         if (error > 0.001)
     287                 :             SkDebugf("log error : val = %g ; log = %g ; cordic = %g\n", val, log, log2);
     288                 :     }
     289                 :     // exp
     290                 : #endif
     291               0 : }
     292                 : 
     293                 : #endif

Generated by: LCOV version 1.7