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