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 yint, y;
116 __asm ("floor.w.s %0,%1" : "=f"(yint) : "f"(x));
117 __asm ("cvt.s.w %0,%1" : "=f"(y) : "f"(yint));
118 return y;
119}
120
131static inline float fm_fmodf(float x, float y) {
132 return x - fm_truncf(x * (1.0f / y)) * y;
133}
134
141static inline float fm_wrapf(float x, float y) {
142 return x - fm_floorf(x * (1.0f / y)) * y;
143}
144
159float fm_sinf(float x);
160
182float fm_sinf_approx(float x, int approx);
183
190float fm_cosf(float x);
191
202void fm_sincosf(float x, float *sin, float *cos);
203
214float fm_atan2f(float y, float x);
215
216#ifdef LIBDRAGON_FAST_MATH
217 #define truncf(x) fm_truncf(x)
218 #define floorf(x) fm_floorf(x)
219 #define ceilf(x) fm_ceilf(x)
220
221 // The following macros contain a special-case: when called with constant
222 // arguments, they fall back to the standard math.h version. This allows
223 // the compiler to compute an accurate result at compile time.
224 // For instance, if we find `sinf(sqrtf(2.0f))` in the source code,
225 // we expect that to be resolved at compile-time with the maximum accuracy,
226 // so it's important to generate code that calls the standard C function
227 // which is then intrinsified by the compiler.
228 #define fmodf(x, y) ((__builtin_constant_p(x) && __builtin_constant_p(y)) ? fmodf(x,y) : fm_fmodf(x,y))
229 #define sinf(x) (__builtin_constant_p(x) ? sinf(x) : fm_sinf(x))
230 #define cosf(x) (__builtin_constant_p(x) ? cosf(x) : fm_cosf(x))
231 #define sincosf(x,s,c) (__builtin_constant_p(x) ? sincosf(x,s,c) : fm_sincosf(x,s,c))
232 #define atan2f(y, x) ((__builtin_constant_p(x) && __builtin_constant_p(y)) ? atan2f(y, x) : fm_atan2f(y, x))
233#endif
234
235#ifdef __cplusplus
236}
237#endif
238
239#endif
240
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