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 
SkCLZ_portable(uint32_t x)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 
SkDivBits(int32_t numer,int32_t denom,int shift_bias)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 */
SkSqrtBits(int32_t x,int count)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 
SkScalarSinCos(float radians,float * cosValue)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