1570af302Sopenharmony_ci#ifndef _LIBM_H 2570af302Sopenharmony_ci#define _LIBM_H 3570af302Sopenharmony_ci 4570af302Sopenharmony_ci#include <stdint.h> 5570af302Sopenharmony_ci#include <float.h> 6570af302Sopenharmony_ci#include <math.h> 7570af302Sopenharmony_ci#include <endian.h> 8570af302Sopenharmony_ci#include "../include/features.h" 9570af302Sopenharmony_ci 10570af302Sopenharmony_ci 11570af302Sopenharmony_ci#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 12570af302Sopenharmony_ci#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN 13570af302Sopenharmony_ciunion ldshape { 14570af302Sopenharmony_ci long double f; 15570af302Sopenharmony_ci struct { 16570af302Sopenharmony_ci uint64_t m; 17570af302Sopenharmony_ci uint16_t se; 18570af302Sopenharmony_ci } i; 19570af302Sopenharmony_ci}; 20570af302Sopenharmony_ci#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN 21570af302Sopenharmony_ci/* This is the m68k variant of 80-bit long double, and this definition only works 22570af302Sopenharmony_ci * on archs where the alignment requirement of uint64_t is <= 4. */ 23570af302Sopenharmony_ciunion ldshape { 24570af302Sopenharmony_ci long double f; 25570af302Sopenharmony_ci struct { 26570af302Sopenharmony_ci uint16_t se; 27570af302Sopenharmony_ci uint16_t pad; 28570af302Sopenharmony_ci uint64_t m; 29570af302Sopenharmony_ci } i; 30570af302Sopenharmony_ci}; 31570af302Sopenharmony_ci#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN 32570af302Sopenharmony_ciunion ldshape { 33570af302Sopenharmony_ci long double f; 34570af302Sopenharmony_ci struct { 35570af302Sopenharmony_ci uint64_t lo; 36570af302Sopenharmony_ci uint32_t mid; 37570af302Sopenharmony_ci uint16_t top; 38570af302Sopenharmony_ci uint16_t se; 39570af302Sopenharmony_ci } i; 40570af302Sopenharmony_ci struct { 41570af302Sopenharmony_ci uint64_t lo; 42570af302Sopenharmony_ci uint64_t hi; 43570af302Sopenharmony_ci } i2; 44570af302Sopenharmony_ci}; 45570af302Sopenharmony_ci#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN 46570af302Sopenharmony_ciunion ldshape { 47570af302Sopenharmony_ci long double f; 48570af302Sopenharmony_ci struct { 49570af302Sopenharmony_ci uint16_t se; 50570af302Sopenharmony_ci uint16_t top; 51570af302Sopenharmony_ci uint32_t mid; 52570af302Sopenharmony_ci uint64_t lo; 53570af302Sopenharmony_ci } i; 54570af302Sopenharmony_ci struct { 55570af302Sopenharmony_ci uint64_t hi; 56570af302Sopenharmony_ci uint64_t lo; 57570af302Sopenharmony_ci } i2; 58570af302Sopenharmony_ci}; 59570af302Sopenharmony_ci#else 60570af302Sopenharmony_ci#error Unsupported long double representation 61570af302Sopenharmony_ci#endif 62570af302Sopenharmony_ci 63570af302Sopenharmony_ci/* Support non-nearest rounding mode. */ 64570af302Sopenharmony_ci#define WANT_ROUNDING 1 65570af302Sopenharmony_ci/* Support signaling NaNs. */ 66570af302Sopenharmony_ci#define WANT_SNAN 0 67570af302Sopenharmony_ci 68570af302Sopenharmony_ci#if WANT_SNAN 69570af302Sopenharmony_ci#error SNaN is unsupported 70570af302Sopenharmony_ci#else 71570af302Sopenharmony_ci#define issignalingf_inline(x) 0 72570af302Sopenharmony_ci#define issignaling_inline(x) 0 73570af302Sopenharmony_ci#endif 74570af302Sopenharmony_ci 75570af302Sopenharmony_ci#ifndef TOINT_INTRINSICS 76570af302Sopenharmony_ci#define TOINT_INTRINSICS 0 77570af302Sopenharmony_ci#endif 78570af302Sopenharmony_ci 79570af302Sopenharmony_ci#if TOINT_INTRINSICS 80570af302Sopenharmony_ci/* Round x to nearest int in all rounding modes, ties have to be rounded 81570af302Sopenharmony_ci consistently with converttoint so the results match. If the result 82570af302Sopenharmony_ci would be outside of [-2^31, 2^31-1] then the semantics is unspecified. */ 83570af302Sopenharmony_cistatic double_t roundtoint(double_t); 84570af302Sopenharmony_ci 85570af302Sopenharmony_ci/* Convert x to nearest int in all rounding modes, ties have to be rounded 86570af302Sopenharmony_ci consistently with roundtoint. If the result is not representible in an 87570af302Sopenharmony_ci int32_t then the semantics is unspecified. */ 88570af302Sopenharmony_cistatic int32_t converttoint(double_t); 89570af302Sopenharmony_ci#endif 90570af302Sopenharmony_ci 91570af302Sopenharmony_ci/* Helps static branch prediction so hot path can be better optimized. */ 92570af302Sopenharmony_ci#ifdef __GNUC__ 93570af302Sopenharmony_ci#define predict_true(x) __builtin_expect(!!(x), 1) 94570af302Sopenharmony_ci#define predict_false(x) __builtin_expect(x, 0) 95570af302Sopenharmony_ci#else 96570af302Sopenharmony_ci#define predict_true(x) (x) 97570af302Sopenharmony_ci#define predict_false(x) (x) 98570af302Sopenharmony_ci#endif 99570af302Sopenharmony_ci 100570af302Sopenharmony_ci/* Evaluate an expression as the specified type. With standard excess 101570af302Sopenharmony_ci precision handling a type cast or assignment is enough (with 102570af302Sopenharmony_ci -ffloat-store an assignment is required, in old compilers argument 103570af302Sopenharmony_ci passing and return statement may not drop excess precision). */ 104570af302Sopenharmony_ci 105570af302Sopenharmony_cistatic inline float eval_as_float(float x) 106570af302Sopenharmony_ci{ 107570af302Sopenharmony_ci float y = x; 108570af302Sopenharmony_ci return y; 109570af302Sopenharmony_ci} 110570af302Sopenharmony_ci 111570af302Sopenharmony_cistatic inline double eval_as_double(double x) 112570af302Sopenharmony_ci{ 113570af302Sopenharmony_ci double y = x; 114570af302Sopenharmony_ci return y; 115570af302Sopenharmony_ci} 116570af302Sopenharmony_ci 117570af302Sopenharmony_ci/* fp_barrier returns its input, but limits code transformations 118570af302Sopenharmony_ci as if it had a side-effect (e.g. observable io) and returned 119570af302Sopenharmony_ci an arbitrary value. */ 120570af302Sopenharmony_ci 121570af302Sopenharmony_ci#ifndef fp_barrierf 122570af302Sopenharmony_ci#define fp_barrierf fp_barrierf 123570af302Sopenharmony_cistatic inline float fp_barrierf(float x) 124570af302Sopenharmony_ci{ 125570af302Sopenharmony_ci volatile float y = x; 126570af302Sopenharmony_ci return y; 127570af302Sopenharmony_ci} 128570af302Sopenharmony_ci#endif 129570af302Sopenharmony_ci 130570af302Sopenharmony_ci#ifndef fp_barrier 131570af302Sopenharmony_ci#define fp_barrier fp_barrier 132570af302Sopenharmony_cistatic inline double fp_barrier(double x) 133570af302Sopenharmony_ci{ 134570af302Sopenharmony_ci volatile double y = x; 135570af302Sopenharmony_ci return y; 136570af302Sopenharmony_ci} 137570af302Sopenharmony_ci#endif 138570af302Sopenharmony_ci 139570af302Sopenharmony_ci#ifndef fp_barrierl 140570af302Sopenharmony_ci#define fp_barrierl fp_barrierl 141570af302Sopenharmony_cistatic inline long double fp_barrierl(long double x) 142570af302Sopenharmony_ci{ 143570af302Sopenharmony_ci volatile long double y = x; 144570af302Sopenharmony_ci return y; 145570af302Sopenharmony_ci} 146570af302Sopenharmony_ci#endif 147570af302Sopenharmony_ci 148570af302Sopenharmony_ci/* fp_force_eval ensures that the input value is computed when that's 149570af302Sopenharmony_ci otherwise unused. To prevent the constant folding of the input 150570af302Sopenharmony_ci expression, an additional fp_barrier may be needed or a compilation 151570af302Sopenharmony_ci mode that does so (e.g. -frounding-math in gcc). Then it can be 152570af302Sopenharmony_ci used to evaluate an expression for its fenv side-effects only. */ 153570af302Sopenharmony_ci 154570af302Sopenharmony_ci#ifndef fp_force_evalf 155570af302Sopenharmony_ci#define fp_force_evalf fp_force_evalf 156570af302Sopenharmony_cistatic inline void fp_force_evalf(float x) 157570af302Sopenharmony_ci{ 158570af302Sopenharmony_ci volatile float y; 159570af302Sopenharmony_ci y = x; 160570af302Sopenharmony_ci} 161570af302Sopenharmony_ci#endif 162570af302Sopenharmony_ci 163570af302Sopenharmony_ci#ifndef fp_force_eval 164570af302Sopenharmony_ci#define fp_force_eval fp_force_eval 165570af302Sopenharmony_cistatic inline void fp_force_eval(double x) 166570af302Sopenharmony_ci{ 167570af302Sopenharmony_ci volatile double y; 168570af302Sopenharmony_ci y = x; 169570af302Sopenharmony_ci} 170570af302Sopenharmony_ci#endif 171570af302Sopenharmony_ci 172570af302Sopenharmony_ci#ifndef fp_force_evall 173570af302Sopenharmony_ci#define fp_force_evall fp_force_evall 174570af302Sopenharmony_cistatic inline void fp_force_evall(long double x) 175570af302Sopenharmony_ci{ 176570af302Sopenharmony_ci volatile long double y; 177570af302Sopenharmony_ci y = x; 178570af302Sopenharmony_ci} 179570af302Sopenharmony_ci#endif 180570af302Sopenharmony_ci 181570af302Sopenharmony_ci#define FORCE_EVAL(x) do { \ 182570af302Sopenharmony_ci if (sizeof(x) == sizeof(float)) { \ 183570af302Sopenharmony_ci fp_force_evalf(x); \ 184570af302Sopenharmony_ci } else if (sizeof(x) == sizeof(double)) { \ 185570af302Sopenharmony_ci fp_force_eval(x); \ 186570af302Sopenharmony_ci } else { \ 187570af302Sopenharmony_ci fp_force_evall(x); \ 188570af302Sopenharmony_ci } \ 189570af302Sopenharmony_ci} while(0) 190570af302Sopenharmony_ci 191570af302Sopenharmony_ci#define asuint(f) ((union{float _f; uint32_t _i;}){f})._i 192570af302Sopenharmony_ci#define asfloat(i) ((union{uint32_t _i; float _f;}){i})._f 193570af302Sopenharmony_ci#define asuint64(f) ((union{double _f; uint64_t _i;}){f})._i 194570af302Sopenharmony_ci#define asdouble(i) ((union{uint64_t _i; double _f;}){i})._f 195570af302Sopenharmony_ci 196570af302Sopenharmony_ci#define EXTRACT_WORDS(hi,lo,d) \ 197570af302Sopenharmony_cido { \ 198570af302Sopenharmony_ci uint64_t __u = asuint64(d); \ 199570af302Sopenharmony_ci (hi) = __u >> 32; \ 200570af302Sopenharmony_ci (lo) = (uint32_t)__u; \ 201570af302Sopenharmony_ci} while (0) 202570af302Sopenharmony_ci 203570af302Sopenharmony_ci#define GET_HIGH_WORD(hi,d) \ 204570af302Sopenharmony_cido { \ 205570af302Sopenharmony_ci (hi) = asuint64(d) >> 32; \ 206570af302Sopenharmony_ci} while (0) 207570af302Sopenharmony_ci 208570af302Sopenharmony_ci#define GET_LOW_WORD(lo,d) \ 209570af302Sopenharmony_cido { \ 210570af302Sopenharmony_ci (lo) = (uint32_t)asuint64(d); \ 211570af302Sopenharmony_ci} while (0) 212570af302Sopenharmony_ci 213570af302Sopenharmony_ci#define INSERT_WORDS(d,hi,lo) \ 214570af302Sopenharmony_cido { \ 215570af302Sopenharmony_ci (d) = asdouble(((uint64_t)(hi)<<32) | (uint32_t)(lo)); \ 216570af302Sopenharmony_ci} while (0) 217570af302Sopenharmony_ci 218570af302Sopenharmony_ci#define SET_HIGH_WORD(d,hi) \ 219570af302Sopenharmony_ci INSERT_WORDS(d, hi, (uint32_t)asuint64(d)) 220570af302Sopenharmony_ci 221570af302Sopenharmony_ci#define SET_LOW_WORD(d,lo) \ 222570af302Sopenharmony_ci INSERT_WORDS(d, asuint64(d)>>32, lo) 223570af302Sopenharmony_ci 224570af302Sopenharmony_ci#define GET_FLOAT_WORD(w,d) \ 225570af302Sopenharmony_cido { \ 226570af302Sopenharmony_ci (w) = asuint(d); \ 227570af302Sopenharmony_ci} while (0) 228570af302Sopenharmony_ci 229570af302Sopenharmony_ci#define SET_FLOAT_WORD(d,w) \ 230570af302Sopenharmony_cido { \ 231570af302Sopenharmony_ci (d) = asfloat(w); \ 232570af302Sopenharmony_ci} while (0) 233570af302Sopenharmony_ci 234570af302Sopenharmony_cihidden int __rem_pio2_large(double*,double*,int,int,int); 235570af302Sopenharmony_ci 236570af302Sopenharmony_cihidden int __rem_pio2(double,double*); 237570af302Sopenharmony_cihidden double __sin(double,double,int); 238570af302Sopenharmony_cihidden double __cos(double,double); 239570af302Sopenharmony_cihidden double __tan(double,double,int); 240570af302Sopenharmony_cihidden double __expo2(double); 241570af302Sopenharmony_ci 242570af302Sopenharmony_cihidden int __rem_pio2f(float,double*); 243570af302Sopenharmony_cihidden float __sindf(double); 244570af302Sopenharmony_cihidden float __cosdf(double); 245570af302Sopenharmony_cihidden float __tandf(double,int); 246570af302Sopenharmony_cihidden float __expo2f(float); 247570af302Sopenharmony_ci 248570af302Sopenharmony_cihidden int __rem_pio2l(long double, long double *); 249570af302Sopenharmony_cihidden long double __sinl(long double, long double, int); 250570af302Sopenharmony_cihidden long double __cosl(long double, long double); 251570af302Sopenharmony_cihidden long double __tanl(long double, long double, int); 252570af302Sopenharmony_ci 253570af302Sopenharmony_cihidden long double __polevll(long double, const long double *, int); 254570af302Sopenharmony_cihidden long double __p1evll(long double, const long double *, int); 255570af302Sopenharmony_ci 256570af302Sopenharmony_ciextern int __signgam; 257570af302Sopenharmony_cihidden double __lgamma_r(double, int *); 258570af302Sopenharmony_cihidden float __lgammaf_r(float, int *); 259570af302Sopenharmony_ci 260570af302Sopenharmony_ci/* error handling functions */ 261570af302Sopenharmony_cihidden float __math_xflowf(uint32_t, float); 262570af302Sopenharmony_cihidden float __math_uflowf(uint32_t); 263570af302Sopenharmony_cihidden float __math_oflowf(uint32_t); 264570af302Sopenharmony_cihidden float __math_divzerof(uint32_t); 265570af302Sopenharmony_cihidden float __math_invalidf(float); 266570af302Sopenharmony_cihidden double __math_xflow(uint32_t, double); 267570af302Sopenharmony_cihidden double __math_uflow(uint32_t); 268570af302Sopenharmony_cihidden double __math_oflow(uint32_t); 269570af302Sopenharmony_cihidden double __math_divzero(uint32_t); 270570af302Sopenharmony_cihidden double __math_invalid(double); 271570af302Sopenharmony_ci 272570af302Sopenharmony_ci#endif 273