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