| /* libs/opengles/fp.h |
| ** |
| ** Copyright 2006, The Android Open Source Project |
| ** |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| */ |
| |
| #ifndef ANDROID_OPENGLES_FP_H |
| #define ANDROID_OPENGLES_FP_H |
| |
| #include <stdint.h> |
| #include <stddef.h> |
| #include <sys/types.h> |
| #include <math.h> |
| |
| #include <private/pixelflinger/ggl_context.h> |
| |
| #include <GLES/gl.h> |
| |
| #define DEBUG_USE_FLOATS 0 |
| |
| // ---------------------------------------------------------------------------- |
| |
| extern "C" GLfixed gglFloatToFixed(float f) __attribute__((const)); |
| |
| // ---------------------------------------------------------------------------- |
| namespace android { |
| |
| namespace gl { |
| |
| GLfloat fixedToFloat(GLfixed) CONST; |
| |
| void sincosf(GLfloat angle, GLfloat* s, GLfloat* c); |
| float sinef(GLfloat x) CONST; |
| float cosinef(GLfloat x) CONST; |
| |
| inline bool cmpf(GLfloat a, GLfloat b) CONST; |
| inline bool isZerof(GLfloat) CONST; |
| inline bool isOnef(GLfloat) CONST; |
| |
| inline int isZeroOrNegativef(GLfloat) CONST; |
| |
| inline int exponent(GLfloat) CONST; |
| inline int32_t mantissa(GLfloat) CONST; |
| inline GLfloat clampToZerof(GLfloat) CONST; |
| inline GLfloat reciprocalf(GLfloat) CONST; |
| inline GLfloat rsqrtf(GLfloat) CONST; |
| inline GLfloat sqrf(GLfloat) CONST; |
| inline GLfloat addExpf(GLfloat v, int e) CONST; |
| inline GLfloat mul2f(GLfloat v) CONST; |
| inline GLfloat div2f(GLfloat v) CONST; |
| inline GLfloat absf(GLfloat v) CONST; |
| |
| |
| /* |
| * float fastexpf(float) : a fast approximation of expf(x) |
| * give somewhat accurate results for -88 <= x <= 88 |
| * |
| * exp(x) = 2^(x/ln(2)) |
| * we use the properties of float encoding |
| * to get a fast 2^ and linear interpolation |
| * |
| */ |
| |
| inline float fastexpf(float y) __attribute__((const)); |
| |
| inline float fastexpf(float y) |
| { |
| union { |
| float r; |
| int32_t i; |
| } u; |
| |
| // 127*ln(2) = 88 |
| if (y < -88.0f) { |
| u.r = 0.0f; |
| } else if (y > 88.0f) { |
| u.r = INFINITY; |
| } else { |
| const float kOneOverLogTwo = (1L<<23) / M_LN2; |
| const int32_t kExponentBias = 127L<<23; |
| const int32_t e = int32_t(y*kOneOverLogTwo); |
| u.i = e + kExponentBias; |
| } |
| |
| return u.r; |
| } |
| |
| |
| bool cmpf(GLfloat a, GLfloat b) { |
| #if DEBUG_USE_FLOATS |
| return a == b; |
| #else |
| union { |
| float f; |
| uint32_t i; |
| } ua, ub; |
| ua.f = a; |
| ub.f = b; |
| return ua.i == ub.i; |
| #endif |
| } |
| |
| bool isZerof(GLfloat v) { |
| #if DEBUG_USE_FLOATS |
| return v == 0; |
| #else |
| union { |
| float f; |
| int32_t i; |
| }; |
| f = v; |
| return (i<<1) == 0; |
| #endif |
| } |
| |
| bool isOnef(GLfloat v) { |
| return cmpf(v, 1.0f); |
| } |
| |
| int isZeroOrNegativef(GLfloat v) { |
| #if DEBUG_USE_FLOATS |
| return v <= 0; |
| #else |
| union { |
| float f; |
| int32_t i; |
| }; |
| f = v; |
| return isZerof(v) | (i>>31); |
| #endif |
| } |
| |
| int exponent(GLfloat v) { |
| union { |
| float f; |
| uint32_t i; |
| }; |
| f = v; |
| return ((i << 1) >> 24) - 127; |
| } |
| |
| int32_t mantissa(GLfloat v) { |
| union { |
| float f; |
| uint32_t i; |
| }; |
| f = v; |
| if (!(i&0x7F800000)) return 0; |
| const int s = i >> 31; |
| i |= (1L<<23); |
| i &= ~0xFF000000; |
| return s ? -i : i; |
| } |
| |
| GLfloat clampToZerof(GLfloat v) { |
| #if DEBUG_USE_FLOATS |
| return v<0 ? 0 : (v>1 ? 1 : v); |
| #else |
| union { |
| float f; |
| int32_t i; |
| }; |
| f = v; |
| i &= ~(i>>31); |
| return f; |
| #endif |
| } |
| |
| GLfloat reciprocalf(GLfloat v) { |
| // XXX: do better |
| return 1.0f / v; |
| } |
| |
| GLfloat rsqrtf(GLfloat v) { |
| // XXX: do better |
| return 1.0f / sqrtf(v); |
| } |
| |
| GLfloat sqrf(GLfloat v) { |
| // XXX: do better |
| return v*v; |
| } |
| |
| GLfloat addExpf(GLfloat v, int e) { |
| union { |
| float f; |
| int32_t i; |
| }; |
| f = v; |
| if (i<<1) { // XXX: deal with over/underflow |
| i += int32_t(e)<<23; |
| } |
| return f; |
| } |
| |
| GLfloat mul2f(GLfloat v) { |
| #if DEBUG_USE_FLOATS |
| return v*2; |
| #else |
| return addExpf(v, 1); |
| #endif |
| } |
| |
| GLfloat div2f(GLfloat v) { |
| #if DEBUG_USE_FLOATS |
| return v*0.5f; |
| #else |
| return addExpf(v, -1); |
| #endif |
| } |
| |
| GLfloat absf(GLfloat v) { |
| #if DEBUG_USE_FLOATS |
| return v<0 ? -v : v; |
| #else |
| union { |
| float f; |
| int32_t i; |
| }; |
| f = v; |
| i &= ~0x80000000; |
| return f; |
| #endif |
| } |
| |
| }; // namespace gl |
| |
| // ---------------------------------------------------------------------------- |
| }; // namespace android |
| |
| #endif // ANDROID_OPENGLES_FP_H |
| |