1 /* libs/opengles/fp.h
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #ifndef ANDROID_OPENGLES_FP_H
19 #define ANDROID_OPENGLES_FP_H
20
21 #include <stdint.h>
22 #include <stddef.h>
23 #include <sys/types.h>
24 #include <math.h>
25
26 #include <private/pixelflinger/ggl_context.h>
27
28 #include <GLES/gl.h>
29
30 #define DEBUG_USE_FLOATS 0
31
32 // ----------------------------------------------------------------------------
33
34 extern "C" GLfixed gglFloatToFixed(float f) __attribute__((const));
35
36 // ----------------------------------------------------------------------------
37 namespace android {
38
39 namespace gl {
40
41 GLfloat fixedToFloat(GLfixed) CONST;
42
43 void sincosf(GLfloat angle, GLfloat* s, GLfloat* c);
44 float sinef(GLfloat x) CONST;
45 float cosinef(GLfloat x) CONST;
46
47 inline bool cmpf(GLfloat a, GLfloat b) CONST;
48 inline bool isZerof(GLfloat) CONST;
49 inline bool isOnef(GLfloat) CONST;
50
51 inline int isZeroOrNegativef(GLfloat) CONST;
52
53 inline int exponent(GLfloat) CONST;
54 inline int32_t mantissa(GLfloat) CONST;
55 inline GLfloat clampToZerof(GLfloat) CONST;
56 inline GLfloat reciprocalf(GLfloat) CONST;
57 inline GLfloat rsqrtf(GLfloat) CONST;
58 inline GLfloat sqrf(GLfloat) CONST;
59 inline GLfloat addExpf(GLfloat v, int e) CONST;
60 inline GLfloat mul2f(GLfloat v) CONST;
61 inline GLfloat div2f(GLfloat v) CONST;
62 inline GLfloat absf(GLfloat v) CONST;
63
64
65 /*
66 * float fastexpf(float) : a fast approximation of expf(x)
67 * give somewhat accurate results for -88 <= x <= 88
68 *
69 * exp(x) = 2^(x/ln(2))
70 * we use the properties of float encoding
71 * to get a fast 2^ and linear interpolation
72 *
73 */
74
75 inline float fastexpf(float y) __attribute__((const));
76
fastexpf(float y)77 inline float fastexpf(float y)
78 {
79 union {
80 float r;
81 int32_t i;
82 } u;
83
84 // 127*ln(2) = 88
85 if (y < -88.0f) {
86 u.r = 0.0f;
87 } else if (y > 88.0f) {
88 u.r = INFINITY;
89 } else {
90 const float kOneOverLogTwo = (1L<<23) / M_LN2;
91 const int32_t kExponentBias = 127L<<23;
92 const int32_t e = int32_t(y*kOneOverLogTwo);
93 u.i = e + kExponentBias;
94 }
95
96 return u.r;
97 }
98
99
cmpf(GLfloat a,GLfloat b)100 bool cmpf(GLfloat a, GLfloat b) {
101 #if DEBUG_USE_FLOATS
102 return a == b;
103 #else
104 union {
105 float f;
106 uint32_t i;
107 } ua, ub;
108 ua.f = a;
109 ub.f = b;
110 return ua.i == ub.i;
111 #endif
112 }
113
isZerof(GLfloat v)114 bool isZerof(GLfloat v) {
115 #if DEBUG_USE_FLOATS
116 return v == 0;
117 #else
118 union {
119 float f;
120 int32_t i;
121 };
122 f = v;
123 return (i<<1) == 0;
124 #endif
125 }
126
isOnef(GLfloat v)127 bool isOnef(GLfloat v) {
128 return cmpf(v, 1.0f);
129 }
130
isZeroOrNegativef(GLfloat v)131 int isZeroOrNegativef(GLfloat v) {
132 #if DEBUG_USE_FLOATS
133 return v <= 0;
134 #else
135 union {
136 float f;
137 int32_t i;
138 };
139 f = v;
140 return isZerof(v) | (i>>31);
141 #endif
142 }
143
exponent(GLfloat v)144 int exponent(GLfloat v) {
145 union {
146 float f;
147 uint32_t i;
148 };
149 f = v;
150 return ((i << 1) >> 24) - 127;
151 }
152
mantissa(GLfloat v)153 int32_t mantissa(GLfloat v) {
154 union {
155 float f;
156 uint32_t i;
157 };
158 f = v;
159 if (!(i&0x7F800000)) return 0;
160 const int s = i >> 31;
161 i |= (1L<<23);
162 i &= ~0xFF000000;
163 return s ? -i : i;
164 }
165
clampToZerof(GLfloat v)166 GLfloat clampToZerof(GLfloat v) {
167 #if DEBUG_USE_FLOATS
168 return v<0 ? 0 : (v>1 ? 1 : v);
169 #else
170 union {
171 float f;
172 int32_t i;
173 };
174 f = v;
175 i &= ~(i>>31);
176 return f;
177 #endif
178 }
179
reciprocalf(GLfloat v)180 GLfloat reciprocalf(GLfloat v) {
181 // XXX: do better
182 return 1.0f / v;
183 }
184
rsqrtf(GLfloat v)185 GLfloat rsqrtf(GLfloat v) {
186 // XXX: do better
187 return 1.0f / sqrtf(v);
188 }
189
sqrf(GLfloat v)190 GLfloat sqrf(GLfloat v) {
191 // XXX: do better
192 return v*v;
193 }
194
addExpf(GLfloat v,int e)195 GLfloat addExpf(GLfloat v, int e) {
196 union {
197 float f;
198 int32_t i;
199 };
200 f = v;
201 if (i<<1) { // XXX: deal with over/underflow
202 i += int32_t(e)<<23;
203 }
204 return f;
205 }
206
mul2f(GLfloat v)207 GLfloat mul2f(GLfloat v) {
208 #if DEBUG_USE_FLOATS
209 return v*2;
210 #else
211 return addExpf(v, 1);
212 #endif
213 }
214
div2f(GLfloat v)215 GLfloat div2f(GLfloat v) {
216 #if DEBUG_USE_FLOATS
217 return v*0.5f;
218 #else
219 return addExpf(v, -1);
220 #endif
221 }
222
absf(GLfloat v)223 GLfloat absf(GLfloat v) {
224 #if DEBUG_USE_FLOATS
225 return v<0 ? -v : v;
226 #else
227 union {
228 float f;
229 int32_t i;
230 };
231 f = v;
232 i &= ~0x80000000;
233 return f;
234 #endif
235 }
236
237 }; // namespace gl
238
239 // ----------------------------------------------------------------------------
240 }; // namespace android
241
242 #endif // ANDROID_OPENGLES_FP_H
243
244