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