libdragon
fmath.h
Go to the documentation of this file.
1
58#ifndef __LIBDRAGON_FMATH_H
59#define __LIBDRAGON_FMATH_H
60
61#include <math.h>
62#include <string.h>
63#include <stdint.h>
64
65#ifdef __cplusplus
66extern "C" {
67#endif
68
73#define BITCAST_F2I(f) ({ int32_t i; memcpy(&i, &f, 4); i; })
74
79#define BITCAST_I2F(i) ({ float f; memcpy(&f, &i, 4); f; })
80
86static inline float fm_truncf(float x) {
87 /* Notice that trunc.w.s is also emitted by the compiler when casting a
88 * float to int, but in this case we want a floating point result anyway,
89 * so it's useless to go back and forth a GPR. */
90 float yint, y;
91 __asm ("trunc.w.s %0,%1" : "=f"(yint) : "f"(x));
92 __asm ("cvt.s.w %0,%1" : "=f"(y) : "f"(yint));
93 return y;
94}
95
101static inline float fm_ceilf(float x) {
102 float yint, y;
103 __asm ("ceil.w.s %0,%1" : "=f"(yint) : "f"(x));
104 __asm ("cvt.s.w %0,%1" : "=f"(y) : "f"(yint));
105 return y;
106}
107
113static inline float fm_floorf(float x) {
114 float y = fm_truncf(x);
115 // After truncation, correct the negative numbers
116 if (x < 0) y -= 1.0f;
117 return y;
118}
119
127static inline float fm_fmodf(float x, float y) {
128 return x - fm_floorf(x * (1.0f / y)) * y;
129}
130
145float fm_sinf(float x);
146
168float fm_sinf_approx(float x, int approx);
169
176float fm_cosf(float x);
177
188void fm_sincosf(float x, float *sin, float *cos);
189
200float fm_atan2f(float y, float x);
201
202#ifdef LIBDRAGON_FAST_MATH
203 #define truncf(x) fm_truncf(x)
204 #define floorf(x) fm_floorf(x)
205 #define ceilf(x) fm_ceilf(x)
206
207 // The following macros contain a special-case: when called with constant
208 // arguments, they fall back to the standard math.h version. This allows
209 // the compiler to compute an accurate result at compile time.
210 // For instance, if we find `sinf(sqrtf(2.0f))` in the source code,
211 // we expect that to be resolved at compile-time with the maximum accuracy,
212 // so it's important to generate code that calls the standard C function
213 // which is then intrinsified by the compiler.
214 #define fmodf(x, y) ((__builtin_constant_p(x) && __builtin_constant_p(y)) ? fmodf(x,y) : fm_fmodf(x,y))
215 #define sinf(x) (__builtin_constant_p(x) ? sinf(x) : fm_sinf(x))
216 #define cosf(x) (__builtin_constant_p(x) ? cosf(x) : fm_cosf(x))
217 #define sincosf(x,s,c) (__builtin_constant_p(x) ? sincosf(x,s,c) : fm_sincosf(x,s,c))
218 #define atan2f(y, x) ((__builtin_constant_p(x) && __builtin_constant_p(y)) ? atan2f(y, x) : fm_atan2f(y, x))
219#endif
220
221#ifdef __cplusplus
222}
223#endif
224
225#endif
226
float fm_cosf(float x)
Faster version of cosf.
Definition: fmath.c:52
float fm_atan2f(float y, float x)
Faster version of atan2f.
Definition: fmath.c:67
float fm_sinf(float x)
Faster version of sinf.
Definition: fmath.c:48
float fm_sinf_approx(float x, int approx)
Faster version of sinf, with tunable approximation level.
Definition: fmath.c:39
void fm_sincosf(float x, float *sin, float *cos)
Faster version of sincosf.
Definition: fmath.c:56