Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2008 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkMathPriv.h"
      9 #include "SkFloatBits.h"
     10 #include "SkFloatingPoint.h"
     11 #include "SkScalar.h"
     12 
     13 const uint32_t gIEEENotANumber = 0x7FFFFFFF;
     14 const uint32_t gIEEEInfinity = 0x7F800000;
     15 const uint32_t gIEEENegativeInfinity = 0xFF800000;
     16 
     17 #define sub_shift(zeros, x, n)  \
     18     zeros -= n;                 \
     19     x >>= n
     20 
     21 int SkCLZ_portable(uint32_t x) {
     22     if (x == 0) {
     23         return 32;
     24     }
     25 
     26     int zeros = 31;
     27     if (x & 0xFFFF0000) {
     28         sub_shift(zeros, x, 16);
     29     }
     30     if (x & 0xFF00) {
     31         sub_shift(zeros, x, 8);
     32     }
     33     if (x & 0xF0) {
     34         sub_shift(zeros, x, 4);
     35     }
     36     if (x & 0xC) {
     37         sub_shift(zeros, x, 2);
     38     }
     39     if (x & 0x2) {
     40         sub_shift(zeros, x, 1);
     41     }
     42 
     43     return zeros;
     44 }
     45 
     46 ///////////////////////////////////////////////////////////////////////////////
     47 
     48 #define DIVBITS_ITER(n)                                 \
     49     case n:                                             \
     50         if ((numer = (numer << 1) - denom) >= 0)        \
     51             result |= 1 << (n - 1); else numer += denom
     52 
     53 int32_t SkDivBits(int32_t numer, int32_t denom, int shift_bias) {
     54     SkASSERT(denom != 0);
     55     if (numer == 0) {
     56         return 0;
     57     }
     58 
     59     // make numer and denom positive, and sign hold the resulting sign
     60     int32_t sign = SkExtractSign(numer ^ denom);
     61     numer = SkAbs32(numer);
     62     denom = SkAbs32(denom);
     63 
     64     int nbits = SkCLZ(numer) - 1;
     65     int dbits = SkCLZ(denom) - 1;
     66     int bits = shift_bias - nbits + dbits;
     67 
     68     if (bits < 0) {  // answer will underflow
     69         return 0;
     70     }
     71     if (bits > 31) {  // answer will overflow
     72         return SkApplySign(SK_MaxS32, sign);
     73     }
     74 
     75     denom <<= dbits;
     76     numer <<= nbits;
     77 
     78     SkFixed result = 0;
     79 
     80     // do the first one
     81     if ((numer -= denom) >= 0) {
     82         result = 1;
     83     } else {
     84         numer += denom;
     85     }
     86 
     87     // Now fall into our switch statement if there are more bits to compute
     88     if (bits > 0) {
     89         // make room for the rest of the answer bits
     90         result <<= bits;
     91         switch (bits) {
     92             DIVBITS_ITER(31); DIVBITS_ITER(30); DIVBITS_ITER(29);
     93             DIVBITS_ITER(28); DIVBITS_ITER(27); DIVBITS_ITER(26);
     94             DIVBITS_ITER(25); DIVBITS_ITER(24); DIVBITS_ITER(23);
     95             DIVBITS_ITER(22); DIVBITS_ITER(21); DIVBITS_ITER(20);
     96             DIVBITS_ITER(19); DIVBITS_ITER(18); DIVBITS_ITER(17);
     97             DIVBITS_ITER(16); DIVBITS_ITER(15); DIVBITS_ITER(14);
     98             DIVBITS_ITER(13); DIVBITS_ITER(12); DIVBITS_ITER(11);
     99             DIVBITS_ITER(10); DIVBITS_ITER( 9); DIVBITS_ITER( 8);
    100             DIVBITS_ITER( 7); DIVBITS_ITER( 6); DIVBITS_ITER( 5);
    101             DIVBITS_ITER( 4); DIVBITS_ITER( 3); DIVBITS_ITER( 2);
    102             // we merge these last two together, makes GCC make better ARM
    103             default:
    104             DIVBITS_ITER( 1);
    105         }
    106     }
    107 
    108     if (result < 0) {
    109         result = SK_MaxS32;
    110     }
    111     return SkApplySign(result, sign);
    112 }
    113 
    114 /* www.worldserver.com/turk/computergraphics/FixedSqrt.pdf
    115 */
    116 int32_t SkSqrtBits(int32_t x, int count) {
    117     SkASSERT(x >= 0 && count > 0 && (unsigned)count <= 30);
    118 
    119     uint32_t    root = 0;
    120     uint32_t    remHi = 0;
    121     uint32_t    remLo = x;
    122 
    123     do {
    124         root <<= 1;
    125 
    126         remHi = (remHi<<2) | (remLo>>30);
    127         remLo <<= 2;
    128 
    129         uint32_t testDiv = (root << 1) + 1;
    130         if (remHi >= testDiv) {
    131             remHi -= testDiv;
    132             root++;
    133         }
    134     } while (--count >= 0);
    135 
    136     return root;
    137 }
    138 
    139 ///////////////////////////////////////////////////////////////////////////////
    140 
    141 float SkScalarSinCos(float radians, float* cosValue) {
    142     float sinValue = sk_float_sin(radians);
    143 
    144     if (cosValue) {
    145         *cosValue = sk_float_cos(radians);
    146         if (SkScalarNearlyZero(*cosValue)) {
    147             *cosValue = 0;
    148         }
    149     }
    150 
    151     if (SkScalarNearlyZero(sinValue)) {
    152         sinValue = 0;
    153     }
    154     return sinValue;
    155 }
    156