From d50e743e0e534833aa5645234915c76e04307338 Mon Sep 17 00:00:00 2001 From: Graham Sanderson Date: Tue, 12 Oct 2021 09:07:36 -0500 Subject: [PATCH] make type punning of floating point/int in float_math and double_math use union to avoid warnings (#600) --- src/rp2_common/pico_double/double_math.c | 77 ++++++++++++++---------- src/rp2_common/pico_float/float_math.c | 77 ++++++++++++++---------- 2 files changed, 90 insertions(+), 64 deletions(-) diff --git a/src/rp2_common/pico_double/double_math.c b/src/rp2_common/pico_double/double_math.c index c6db8c1..6c35ded 100644 --- a/src/rp2_common/pico_double/double_math.c +++ b/src/rp2_common/pico_double/double_math.c @@ -41,11 +41,25 @@ typedef int64_t i64; #define DUNPACK(x,e,m) e=((x)>>52)&0x7ff,m=((x)&0x000fffffffffffffULL)|0x0010000000000000ULL #define DUNPACKS(x,s,e,m) s=((x)>>63),DUNPACK((x),(e),(m)) -_Pragma("GCC diagnostic push") -_Pragma("GCC diagnostic ignored \"-Wstrict-aliasing\"") +typedef union { + double d; + ui64 ix; +} double_ui64; + +static inline double ui642double(ui64 ix) { + double_ui64 tmp; + tmp.ix = ix; + return tmp.d; +} + +static inline ui64 double2ui64(double d) { + double_ui64 tmp; + tmp.d = d; + return tmp.ix; +} static inline bool disnan(double x) { - ui64 ix=*(ui64*)&x; + ui64 ix= double2ui64(x); // checks the top bit of the low 32 bit of the NAN, but it I think that is ok return ((uint32_t)(ix >> 31)) > 0xffe00000u; } @@ -59,17 +73,17 @@ static inline bool disnan(double x) { #endif static inline int dgetsignexp(double x) { - ui64 ix=*(ui64*)&x; + ui64 ix=double2ui64(x); return (ix>>52)&0xfff; } static inline int dgetexp(double x) { - ui64 ix=*(ui64*)&x; + ui64 ix=double2ui64(x); return (ix>>52)&0x7ff; } static inline double dldexp(double x,int de) { - ui64 ix=*(ui64*)&x,iy; + ui64 ix=double2ui64(x),iy; int e; e=dgetexp(x); if(e==0||e==0x7ff) return x; @@ -77,7 +91,7 @@ static inline double dldexp(double x,int de) { if(e<=0) iy=ix&0x8000000000000000ULL; // signed zero for underflow else if(e>=0x7ff) iy=(ix&0x8000000000000000ULL)|0x7ff0000000000000ULL; // signed infinity on overflow else iy=ix+((ui64)de<<52); - return *(double*)&iy; + return ui642double(iy); } double WRAPPER_FUNC(ldexp)(double x, int de) { @@ -87,9 +101,9 @@ double WRAPPER_FUNC(ldexp)(double x, int de) { static inline double dcopysign(double x,double y) { - ui64 ix=*(ui64*)&x,iy=*(ui64*)&y; + ui64 ix=double2ui64(x),iy=double2ui64(y); ix=((ix&0x7fffffffffffffffULL)|(iy&0x8000000000000000ULL)); - return *(double*)&ix; + return ui642double(ix); } double WRAPPER_FUNC(copysign)(double x, double y) { @@ -104,7 +118,7 @@ static inline int dispinf(double x) { return dgetsignexp(x)==0x7ff; } static inline int disminf(double x) { return dgetsignexp(x)==0xfff; } static inline int disint(double x) { - ui64 ix=*(ui64*)&x,m; + ui64 ix=double2ui64(x),m; int e=dgetexp(x); if(e==0) return 1; // 0 is an integer e-=0x3ff; // remove exponent bias @@ -117,7 +131,7 @@ static inline int disint(double x) { } static inline int disoddint(double x) { - ui64 ix=*(ui64*)&x,m; + ui64 ix=double2ui64(x),m; int e=dgetexp(x); e-=0x3ff; // remove exponent bias if(e<0) return 0; // |x|<1; 0 is not odd @@ -130,24 +144,24 @@ static inline int disoddint(double x) { } static inline int disstrictneg(double x) { - ui64 ix=*(ui64*)&x; + ui64 ix=double2ui64(x); if(diszero(x)) return 0; return ix>>63; } static inline int disneg(double x) { - ui64 ix=*(ui64*)&x; + ui64 ix=double2ui64(x); return ix>>63; } static inline double dneg(double x) { - ui64 ix=*(ui64*)&x; + ui64 ix=double2ui64(x); ix^=0x8000000000000000ULL; - return *(double*)&ix; + return ui642double(ix); } static inline int dispo2(double x) { - ui64 ix=*(ui64*)&x; + ui64 ix=double2ui64(x); if(diszero(x)) return 0; if(disinf(x)) return 0; ix&=0x000fffffffffffffULL; @@ -164,33 +178,33 @@ static inline double dnan_or(double x) { double WRAPPER_FUNC(trunc)(double x) { check_nan_d1(x); - ui64 ix=*(ui64*)&x,m; + ui64 ix=double2ui64(x),m; int e=dgetexp(x); e-=0x3ff; // remove exponent bias if(e<0) { // |x|<1 ix&=0x8000000000000000ULL; - return *(double*)&ix; + return ui642double(ix); } e=52-e; // bit position in mantissa with significance 1 if(e<=0) return x; // |x| large, so must be an integer m=(1ULL<>23)&0xff,m=((x)&0x007fffff)|0x00800000 #define FUNPACKS(x,s,e,m) s=((x)>>31),FUNPACK((x),(e),(m)) -_Pragma("GCC diagnostic push") -_Pragma("GCC diagnostic ignored \"-Wstrict-aliasing\"") +typedef union { + float f; + ui32 ix; +} float_ui32; + +static inline float ui322float(ui32 ix) { + float_ui32 tmp; + tmp.ix = ix; + return tmp.f; +} + +static inline ui32 float2ui32(float f) { + float_ui32 tmp; + tmp.f = f; + return tmp.ix; +} static inline bool fisnan(float x) { - ui32 ix=*(ui32*)&x; + ui32 ix=float2ui32(x); return ix * 2 > 0xff000000u; } @@ -56,17 +70,17 @@ static inline bool fisnan(float x) { #endif static inline int fgetsignexp(float x) { - ui32 ix=*(ui32*)&x; + ui32 ix=float2ui32(x); return (ix>>23)&0x1ff; } static inline int fgetexp(float x) { - ui32 ix=*(ui32*)&x; + ui32 ix=float2ui32(x); return (ix>>23)&0xff; } static inline float fldexp(float x,int de) { - ui32 ix=*(ui32*)&x,iy; + ui32 ix=float2ui32(x),iy; int e; e=fgetexp(x); if(e==0||e==0xff) return x; @@ -74,7 +88,7 @@ static inline float fldexp(float x,int de) { if(e<=0) iy=ix&0x80000000; // signed zero for underflow else if(e>=0xff) iy=(ix&0x80000000)|0x7f800000ULL; // signed infinity on overflow else iy=ix+((ui32)de<<23); - return *(float*)&iy; + return ui322float(iy); } float WRAPPER_FUNC(ldexpf)(float x, int de) { @@ -83,9 +97,9 @@ float WRAPPER_FUNC(ldexpf)(float x, int de) { } static inline float fcopysign(float x,float y) { - ui32 ix=*(ui32*)&x,iy=*(ui32*)&y; + ui32 ix=float2ui32(x),iy=float2ui32(y); ix=((ix&0x7fffffff)|(iy&0x80000000)); - return *(float*)&ix; + return ui322float(ix); } float WRAPPER_FUNC(copysignf)(float x, float y) { @@ -101,7 +115,7 @@ static inline int fispinf(float x) { return fgetsignexp(x)==0xff; } static inline int fisminf(float x) { return fgetsignexp(x)==0x1ff; } static inline int fisint(float x) { - ui32 ix=*(ui32*)&x,m; + ui32 ix=float2ui32(x),m; int e=fgetexp(x); if(e==0) return 1; // 0 is an integer e-=0x7f; // remove exponent bias @@ -114,7 +128,7 @@ static inline int fisint(float x) { } static inline int fisoddint(float x) { - ui32 ix=*(ui32*)&x,m; + ui32 ix=float2ui32(x),m; int e=fgetexp(x); e-=0x7f; // remove exponent bias if(e<0) return 0; // |x|<1; 0 is not odd @@ -127,24 +141,24 @@ static inline int fisoddint(float x) { } static inline int fisstrictneg(float x) { - ui32 ix=*(ui32*)&x; + ui32 ix=float2ui32(x); if(fiszero(x)) return 0; return ix>>31; } static inline int fisneg(float x) { - ui32 ix=*(ui32*)&x; + ui32 ix=float2ui32(x); return ix>>31; } static inline float fneg(float x) { - ui32 ix=*(ui32*)&x; + ui32 ix=float2ui32(x); ix^=0x80000000; - return *(float*)&ix; + return ui322float(ix); } static inline int fispo2(float x) { - ui32 ix=*(ui32*)&x; + ui32 ix=float2ui32(x); if(fiszero(x)) return 0; if(fisinf(x)) return 0; ix&=0x007fffff; @@ -161,33 +175,33 @@ static inline float fnan_or(float x) { float WRAPPER_FUNC(truncf)(float x) { check_nan_f1(x); - ui32 ix=*(ui32*)&x,m; + ui32 ix=float2ui32(x),m; int e=fgetexp(x); e-=0x7f; // remove exponent bias if(e<0) { // |x|<1 ix&=0x80000000; - return *(float*)&ix; + return ui322float(ix); } e=23-e; // bit position in mantissa with significance 1 if(e<=0) return x; // |x| large, so must be an integer m=(1<