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
34extern "C" GLfixed gglFloatToFixed(float f) __attribute__((const));
35
36// ----------------------------------------------------------------------------
37namespace android {
38
39namespace 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
47inline bool     cmpf(GLfloat a, GLfloat b) CONST;
48inline bool     isZerof(GLfloat) CONST;
49inline bool     isOnef(GLfloat) CONST;
50
51inline int      isZeroOrNegativef(GLfloat) CONST;
52
53inline int      exponent(GLfloat) CONST;
54inline int32_t  mantissa(GLfloat) CONST;
55inline GLfloat  clampToZerof(GLfloat) CONST;
56inline GLfloat  reciprocalf(GLfloat) CONST;
57inline GLfloat  rsqrtf(GLfloat) CONST;
58inline GLfloat  sqrf(GLfloat) CONST;
59inline GLfloat  addExpf(GLfloat v, int e) CONST;
60inline GLfloat  mul2f(GLfloat v) CONST;
61inline GLfloat  div2f(GLfloat v) CONST;
62inline 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
75inline float fastexpf(float y) __attribute__((const));
76
77inline 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
100bool 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
114bool 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
127bool isOnef(GLfloat v) {
128    return cmpf(v, 1.0f);
129}
130
131int 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
144int exponent(GLfloat v) {
145    union {
146        float    f;
147        uint32_t i;
148    };
149    f = v;
150    return ((i << 1) >> 24) - 127;
151}
152
153int32_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
166GLfloat 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
180GLfloat reciprocalf(GLfloat v) {
181    // XXX: do better
182    return 1.0f / v;
183}
184
185GLfloat rsqrtf(GLfloat v) {
186    // XXX: do better
187    return 1.0f / sqrtf(v);
188}
189
190GLfloat sqrf(GLfloat v) {
191    // XXX: do better
192    return v*v;
193}
194
195GLfloat 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
207GLfloat mul2f(GLfloat v) {
208#if DEBUG_USE_FLOATS
209    return v*2;
210#else
211    return addExpf(v, 1);
212#endif
213}
214
215GLfloat div2f(GLfloat v) {
216#if DEBUG_USE_FLOATS
217    return v*0.5f;
218#else
219    return addExpf(v, -1);
220#endif
221}
222
223GLfloat  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