github.com/afumu/libc@v0.0.6/musl/src/internal/libm.h (about) 1 #ifndef _LIBM_H 2 #define _LIBM_H 3 4 #include <stdint.h> 5 #include <float.h> 6 #include <math.h> 7 #include <endian.h> 8 #include "fp_arch.h" 9 10 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 11 #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN 12 union ldshape { 13 long double f; 14 struct { 15 uint64_t m; 16 uint16_t se; 17 } i; 18 }; 19 #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN 20 /* This is the m68k variant of 80-bit long double, and this definition only works 21 * on archs where the alignment requirement of uint64_t is <= 4. */ 22 union ldshape { 23 long double f; 24 struct { 25 uint16_t se; 26 uint16_t pad; 27 uint64_t m; 28 } i; 29 }; 30 #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN 31 union ldshape { 32 long double f; 33 struct { 34 uint64_t lo; 35 uint32_t mid; 36 uint16_t top; 37 uint16_t se; 38 } i; 39 struct { 40 uint64_t lo; 41 uint64_t hi; 42 } i2; 43 }; 44 #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN 45 union ldshape { 46 long double f; 47 struct { 48 uint16_t se; 49 uint16_t top; 50 uint32_t mid; 51 uint64_t lo; 52 } i; 53 struct { 54 uint64_t hi; 55 uint64_t lo; 56 } i2; 57 }; 58 #else 59 #error Unsupported long double representation 60 #endif 61 62 /* Support non-nearest rounding mode. */ 63 #define WANT_ROUNDING 1 64 /* Support signaling NaNs. */ 65 #define WANT_SNAN 0 66 67 #if WANT_SNAN 68 #error SNaN is unsupported 69 #else 70 #define issignalingf_inline(x) 0 71 #define issignaling_inline(x) 0 72 #endif 73 74 #ifndef TOINT_INTRINSICS 75 #define TOINT_INTRINSICS 0 76 #endif 77 78 #if TOINT_INTRINSICS 79 /* Round x to nearest int in all rounding modes, ties have to be rounded 80 consistently with converttoint so the results match. If the result 81 would be outside of [-2^31, 2^31-1] then the semantics is unspecified. */ 82 static double_t roundtoint(double_t); 83 84 /* Convert x to nearest int in all rounding modes, ties have to be rounded 85 consistently with roundtoint. If the result is not representible in an 86 int32_t then the semantics is unspecified. */ 87 static int32_t converttoint(double_t); 88 #endif 89 90 /* Helps static branch prediction so hot path can be better optimized. */ 91 #ifdef __GNUC__ 92 #define predict_true(x) __builtin_expect(!!(x), 1) 93 #define predict_false(x) __builtin_expect(x, 0) 94 #else 95 #define predict_true(x) (x) 96 #define predict_false(x) (x) 97 #endif 98 99 /* Evaluate an expression as the specified type. With standard excess 100 precision handling a type cast or assignment is enough (with 101 -ffloat-store an assignment is required, in old compilers argument 102 passing and return statement may not drop excess precision). */ 103 104 static inline float eval_as_float(float x) 105 { 106 float y = x; 107 return y; 108 } 109 110 static inline double eval_as_double(double x) 111 { 112 double y = x; 113 return y; 114 } 115 116 /* fp_barrier returns its input, but limits code transformations 117 as if it had a side-effect (e.g. observable io) and returned 118 an arbitrary value. */ 119 120 #ifndef fp_barrierf 121 #define fp_barrierf fp_barrierf 122 static inline float fp_barrierf(float x) 123 { 124 volatile float y = x; 125 return y; 126 } 127 #endif 128 129 #ifndef fp_barrier 130 #define fp_barrier fp_barrier 131 static inline double fp_barrier(double x) 132 { 133 volatile double y = x; 134 return y; 135 } 136 #endif 137 138 #ifndef fp_barrierl 139 #define fp_barrierl fp_barrierl 140 static inline long double fp_barrierl(long double x) 141 { 142 volatile long double y = x; 143 return y; 144 } 145 #endif 146 147 /* fp_force_eval ensures that the input value is computed when that's 148 otherwise unused. To prevent the constant folding of the input 149 expression, an additional fp_barrier may be needed or a compilation 150 mode that does so (e.g. -frounding-math in gcc). Then it can be 151 used to evaluate an expression for its fenv side-effects only. */ 152 153 #ifndef fp_force_evalf 154 #define fp_force_evalf fp_force_evalf 155 static inline void fp_force_evalf(float x) 156 { 157 volatile float y; 158 y = x; 159 } 160 #endif 161 162 #ifndef fp_force_eval 163 #define fp_force_eval fp_force_eval 164 static inline void fp_force_eval(double x) 165 { 166 volatile double y; 167 y = x; 168 } 169 #endif 170 171 #ifndef fp_force_evall 172 #define fp_force_evall fp_force_evall 173 static inline void fp_force_evall(long double x) 174 { 175 volatile long double y; 176 y = x; 177 } 178 #endif 179 180 #define FORCE_EVAL(x) do { \ 181 if (sizeof(x) == sizeof(float)) { \ 182 fp_force_evalf(x); \ 183 } else if (sizeof(x) == sizeof(double)) { \ 184 fp_force_eval(x); \ 185 } else { \ 186 fp_force_evall(x); \ 187 } \ 188 } while(0) 189 190 #define asuint(f) ((union{float _f; uint32_t _i;}){f})._i 191 #define asfloat(i) ((union{uint32_t _i; float _f;}){i})._f 192 #define asuint64(f) ((union{double _f; uint64_t _i;}){f})._i 193 #define asdouble(i) ((union{uint64_t _i; double _f;}){i})._f 194 195 #define EXTRACT_WORDS(hi,lo,d) \ 196 do { \ 197 uint64_t __u = asuint64(d); \ 198 (hi) = __u >> 32; \ 199 (lo) = (uint32_t)__u; \ 200 } while (0) 201 202 #define GET_HIGH_WORD(hi,d) \ 203 do { \ 204 (hi) = asuint64(d) >> 32; \ 205 } while (0) 206 207 #define GET_LOW_WORD(lo,d) \ 208 do { \ 209 (lo) = (uint32_t)asuint64(d); \ 210 } while (0) 211 212 #define INSERT_WORDS(d,hi,lo) \ 213 do { \ 214 (d) = asdouble(((uint64_t)(hi)<<32) | (uint32_t)(lo)); \ 215 } while (0) 216 217 #define SET_HIGH_WORD(d,hi) \ 218 INSERT_WORDS(d, hi, (uint32_t)asuint64(d)) 219 220 #define SET_LOW_WORD(d,lo) \ 221 INSERT_WORDS(d, asuint64(d)>>32, lo) 222 223 #define GET_FLOAT_WORD(w,d) \ 224 do { \ 225 (w) = asuint(d); \ 226 } while (0) 227 228 #define SET_FLOAT_WORD(d,w) \ 229 do { \ 230 (d) = asfloat(w); \ 231 } while (0) 232 233 hidden int __rem_pio2_large(double*,double*,int,int,int); 234 235 hidden int __rem_pio2(double,double*); 236 hidden double __sin(double,double,int); 237 hidden double __cos(double,double); 238 hidden double __tan(double,double,int); 239 hidden double __expo2(double,double); 240 241 hidden int __rem_pio2f(float,double*); 242 hidden float __sindf(double); 243 hidden float __cosdf(double); 244 hidden float __tandf(double,int); 245 hidden float __expo2f(float,float); 246 247 hidden int __rem_pio2l(long double, long double *); 248 hidden long double __sinl(long double, long double, int); 249 hidden long double __cosl(long double, long double); 250 hidden long double __tanl(long double, long double, int); 251 252 hidden long double __polevll(long double, const long double *, int); 253 hidden long double __p1evll(long double, const long double *, int); 254 255 extern int __signgam; 256 hidden double __lgamma_r(double, int *); 257 hidden float __lgammaf_r(float, int *); 258 259 /* error handling functions */ 260 hidden float __math_xflowf(uint32_t, float); 261 hidden float __math_uflowf(uint32_t); 262 hidden float __math_oflowf(uint32_t); 263 hidden float __math_divzerof(uint32_t); 264 hidden float __math_invalidf(float); 265 hidden double __math_xflow(uint32_t, double); 266 hidden double __math_uflow(uint32_t); 267 hidden double __math_oflow(uint32_t); 268 hidden double __math_divzero(uint32_t); 269 hidden double __math_invalid(double); 270 271 #endif