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