11#define WRAPPER_FUNC(x) __wrap_ ## x
12#define WRAPPER_FUNC_NAME(x) __wrap_##x
18float fix2float(int32_t m,
int e);
21_Pragma(
"GCC diagnostic push")
22_Pragma("GCC diagnostic ignored \"-Wconversion\"")
23_Pragma("GCC diagnostic ignored \"-Wsign-conversion\"")
28#define FPINF ( HUGE_VALF)
29#define FMINF (-HUGE_VALF)
30#define NANF ((float)NAN)
34#define PI 3.14159265358979323846
35#define LOG2 0.69314718055994530941
37#define LOG10 2.30258509299404568401
38#define LOG2E 1.44269504088896340737
39#define LOG10E 0.43429448190325182765
40#define ONETHIRD 0.33333333333333333333
42#define PIf 3.14159265358979323846f
43#define LOG2f 0.69314718055994530941f
44#define LOG2Ef 1.44269504088896340737f
45#define LOG10Ef 0.43429448190325182765f
46#define ONETHIRDf 0.33333333333333333333f
48#define FUNPACK(x,e,m) e=((x)>>23)&0xff,m=((x)&0x007fffff)|0x00800000
49#define FUNPACKS(x,s,e,m) s=((x)>>31),FUNPACK((x),(e),(m))
56static inline float ui322float(ui32 ix) {
62static inline ui32 float2ui32(
float f) {
68static inline bool fisnan(
float x) {
69 ui32 ix=float2ui32(x);
70 return ix * 2 > 0xff000000u;
73#if PICO_FLOAT_PROPAGATE_NANS
74#define check_nan_f1(x) if (fisnan((x))) return (x)
75#define check_nan_f2(x,y) if (fisnan((x))) return (x); else if (fisnan((y))) return (y);
77#define check_nan_f1(x) ((void)0)
78#define check_nan_f2(x,y) ((void)0)
81static inline int fgetsignexp(
float x) {
82 ui32 ix=float2ui32(x);
83 return (ix>>23)&0x1ff;
86static inline int fgetexp(
float x) {
87 ui32 ix=float2ui32(x);
91static inline float fldexp(
float x,
int de) {
92 ui32 ix=float2ui32(x),iy;
95 if(e==0||e==0xff)
return x;
97 if(e<=0) iy=ix&0x80000000;
98 else if(e>=0xff) iy=(ix&0x80000000)|0x7f800000ULL;
99 else iy=ix+((ui32)de<<23);
100 return ui322float(iy);
103float WRAPPER_FUNC(ldexpf)(
float x,
int de) {
105 return fldexp(x, de);
108static inline float fcopysign(
float x,
float y) {
109 ui32 ix=float2ui32(x),iy=float2ui32(y);
110 ix=((ix&0x7fffffff)|(iy&0x80000000));
111 return ui322float(ix);
114float WRAPPER_FUNC(copysignf)(
float x,
float y) {
116 return fcopysign(x, y);
119static inline int fiszero(
float x) {
return fgetexp (x)==0; }
120static inline int fispzero(
float x) {
return fgetsignexp(x)==0; }
121static inline int fismzero(
float x) {
return fgetsignexp(x)==0x100; }
122static inline int fisinf(
float x) {
return fgetexp (x)==0xff; }
123static inline int fispinf(
float x) {
return fgetsignexp(x)==0xff; }
124static inline int fisminf(
float x) {
return fgetsignexp(x)==0x1ff; }
126static inline int fisint(
float x) {
127 ui32 ix=float2ui32(x),m;
139static inline int fisoddint(
float x) {
140 ui32 ix=float2ui32(x),m;
152static inline int fisstrictneg(
float x) {
153 ui32 ix=float2ui32(x);
154 if(fiszero(x))
return 0;
158static inline int fisneg(
float x) {
159 ui32 ix=float2ui32(x);
163static inline float fneg(
float x) {
164 ui32 ix=float2ui32(x);
166 return ui322float(ix);
169static inline int fispo2(
float x) {
170 ui32 ix=float2ui32(x);
171 if(fiszero(x))
return 0;
172 if(fisinf(x))
return 0;
177static inline float fnan_or(
float x) {
178#if PICO_FLOAT_PROPAGATE_NANS
185float WRAPPER_FUNC(truncf)(
float x) {
187 ui32 ix=float2ui32(x),m;
192 return ui322float(ix);
198 return ui322float(ix);
201float WRAPPER_FUNC(roundf)(
float x) {
203 ui32 ix=float2ui32(x),m;
208 return ui322float(ix);
213 return ui322float(ix);
221 return ui322float(ix);
224float WRAPPER_FUNC(floorf)(
float x) {
226 ui32 ix=float2ui32(x),m;
230 return ui322float(ix);
234 if(fisneg(x))
return -1;
242 return ui322float(ix);
245float WRAPPER_FUNC(ceilf)(
float x) {
247 ui32 ix=float2ui32(x),m;
251 return ui322float(ix);
255 if(fisneg(x))
return MZERO;
261 if(!fisneg(x)) ix+=m;
263 return ui322float(ix);
266float WRAPPER_FUNC(asinf)(
float x) {
270 if(fisstrictneg(u))
return fnan_or(FPINF);
271 return atan2f(x,sqrtf(u));
274float WRAPPER_FUNC(acosf)(
float x) {
278 if(fisstrictneg(u))
return fnan_or(FPINF);
279 return atan2f(sqrtf(u),x);
282float WRAPPER_FUNC(atanf)(
float x) {
284 if(fispinf(x))
return (
float)( PIf/2);
285 if(fisminf(x))
return (
float)(-PIf/2);
286 return atan2f(x,1.0f);
289float WRAPPER_FUNC(sinhf)(
float x) {
291 return fldexp((expf(x)-expf(fneg(x))),-1);
294float WRAPPER_FUNC(coshf)(
float x) {
296 return fldexp((expf(x)+expf(fneg(x))),-1);
299float WRAPPER_FUNC(tanhf)(
float x) {
305 if(!fisneg(x))
return 1;
309 return (u-1.0f)/(u+1.0f);
312float WRAPPER_FUNC(asinhf)(
float x) {
317 if(!fisneg(x))
return logf( x )+LOG2f;
318 else return fneg(logf(fneg(x))+LOG2f);
320 if(x>0)
return (
float)log(sqrt((
double)x*(
double)x+1.0)+(
double)x);
321 else return fneg((
float)log(sqrt((
double)x*(
double)x+1.0)-(
double)x));
324float WRAPPER_FUNC(acoshf)(
float x) {
327 if(fisneg(x)) x=fneg(x);
329 if(e>=16+0x7f)
return logf(x)+LOG2f;
330 return (
float)log(sqrt(((
double)x+1.0)*((
double)x-1.0))+(
double)x);
333float WRAPPER_FUNC(atanhf)(
float x) {
335 return fldexp(logf((1.0f+x)/(1.0f-x)),-1);
338float WRAPPER_FUNC(exp2f)(
float x) { check_nan_f1(x);
return (
float)exp((
double)x*LOG2); }
339float WRAPPER_FUNC(log2f)(
float x) { check_nan_f1(x);
return logf(x)*LOG2Ef; }
340float WRAPPER_FUNC(exp10f)(
float x) { check_nan_f1(x);
return (
float)exp((
double)x*LOG10); }
341float WRAPPER_FUNC(log10f)(
float x) { check_nan_f1(x);
return logf(x)*LOG10Ef; }
343float WRAPPER_FUNC(expm1f)(
float x) { check_nan_f1(x);
return (
float)(exp((
double)x)-1); }
344float WRAPPER_FUNC(log1pf)(
float x) { check_nan_f1(x);
return (
float)(log(1+(
double)x)); }
345float WRAPPER_FUNC(fmaf)(
float x,
float y,
float z) {
348 return (
float)((double)x*(double)y+(double)z);
352static inline float fpow_1(
float x,
float y) {
353 return (
float)exp(log((
double)x)*(
double)y);
356static float fpow_int2(
float x,
int y) {
366static inline float fpowint_1(
float x,
int y) {
367 if(y<0) x=1.0f/x,y=-y;
368 return fpow_int2(x,y);
372static float fpowint_0(
float x,
int y) {
375 if(fisoddint(y))
return fneg(fpowint_0(fneg(x),y));
376 else return fpowint_0(fneg(x),y);
386 if(y>=-32&&y<=32)
return fpowint_1(x,y);
390float WRAPPER_FUNC(powintf)(
float x,
int y) {
391 _Pragma(
"GCC diagnostic push")
392 _Pragma("GCC diagnostic ignored \"-Wfloat-equal\"")
393 if(x==1.0f||y==0) return 1;
399 if((y&1))
return fcopysign(FPINF,x);
402 _Pragma(
"GCC diagnostic pop")
410 if((y&1))
return FMINF;
413 if((y&1))
return MZERO;
416 return fpowint_0(x,y);
420static float fpow_0(
float x,
float y) {
423 if(fisoddint(y))
return fneg(fpow_0(fneg(x),y));
424 else return fpow_0(fneg(x),y);
435 if(p>=-32&&p<=32)
return fpowint_1(x,p);
439float WRAPPER_FUNC(powf)(
float x,
float y) {
440 _Pragma(
"GCC diagnostic push")
441 _Pragma("GCC diagnostic ignored \"-Wfloat-equal\"")
442 if(x==1.0f||fiszero(y)) return 1;
444 if(x==-1.0f&&fisinf(y)) return 1;
445 _Pragma("GCC diagnostic pop")
448 if(fisoddint(y))
return x;
451 if(fisoddint(y))
return fcopysign(FPINF,x);
455 if(fisneg(y))
return 0;
460 if(fisoddint(y))
return FMINF;
463 if(fisoddint(y))
return MZERO;
467 if(fgetexp(x)<0x7f)
return PZERO;
471 if(fgetexp(x)<0x7f)
return FPINF;
474 if(fisint(y))
return fpow_0(x,y);
475 if(fisneg(x))
return FPINF;
479float WRAPPER_FUNC(hypotf)(
float x,
float y) {
482 ex=fgetexp(x); ey=fgetexp(y);
483 if(ex>=0x7f+50||ey>=0x7f+50) {
484 x=fldexp(x,-70),y=fldexp(y,-70);
485 return fldexp(sqrtf(x*x+y*y), 70);
487 else if(ex<=0x7f-50&&ey<=0x7f-50) {
488 x=fldexp(x, 70),y=fldexp(y, 70);
489 return fldexp(sqrtf(x*x+y*y),-70);
491 return sqrtf(x*x+y*y);
494float WRAPPER_FUNC(cbrtf)(
float x) {
497 if(fisneg(x))
return fneg(cbrtf(fneg(x)));
498 if(fiszero(x))
return fcopysign(PZERO,x);
500 e=(e*0x5555+0x8000)>>16;
502 x=expf(logf(x)*ONETHIRDf);
508static i32 frem_0(i32 mx,i32 my,
int e,
int*pquo) {
511 r=0xffffffffU/(ui32)(my>>7);
516 q=((q>>(29-s))+1)>>1;
521 if(mx>=my) mx-=my,quo++;
522 if(mx>=my) mx-=my,quo++;
523 if(mx<0) mx+=my,quo--;
524 if(mx<0) mx+=my,quo--;
529float WRAPPER_FUNC(fmodf)(
float x,
float y) {
531 ui32 ix=float2ui32(x),iy=float2ui32(y);
534 FUNPACKS(ix,sx,ex,mx);
537 return fnan_or(FPINF);
539 if(ey==0)
return FPINF;
541 if(!fisneg(x))
return PZERO;
545 mx=frem_0(mx,my,ex-ey,0);
547 return fix2float(mx,0x7f-ey+23);
550float WRAPPER_FUNC(remquof)(
float x,
float y,
int*quo) {
552 ui32 ix=float2ui32(x),iy=float2ui32(y);
555 FUNPACKS(ix,sx,ex,mx);
556 FUNPACKS(iy,sy,ey,my);
558 if(ex==0xff)
return FPINF;
559 if(ey==0)
return FPINF;
560 if(ex==0)
return PZERO;
561 if(ey==0xff)
return x;
562 if(ex<ey-1)
return x;
578 mx=frem_0(mx,my,ex-ey,&q);
579 if(mx+mx>my || (mx+mx==my&&(q&1)) ) {
586 return fix2float(mx,0x7f-ey+23);
589float WRAPPER_FUNC(dremf)(
float x,
float y) { check_nan_f2(x,y);
return remquof(x,y,0); }
591float WRAPPER_FUNC(remainderf)(
float x,
float y) { check_nan_f2(x,y);
return remquof(x,y,0); }
593_Pragma(
"GCC diagnostic pop")