LCOV - app.info - gfx/skia/src/core/SkCordic.cpp

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-07-07 | 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