
/* @(#)fdlibm.h 5.1 93/09/24 */
/*
 * ====================================================
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
 *
 * Developed at SunPro, a Sun Microsystems, Inc. business.
 * Permission to use, copy, modify, and distribute this
 * software is freely granted, provided that this notice
 * is preserved.
 * ====================================================
 */

#ifndef _FDLIBM_H_
#define _FDLIBM_H_

/* REDHAT LOCAL: Include files.  */
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif
#include <math.h>
#include <sys/types.h>
#include <machine/ieeefp.h>
#include <fenv.h>
#include "math_config.h"

/* Most routines need to check whether a float is finite, infinite, or not a
   number, and many need to know whether the result of an operation will
   overflow.  These conditions depend on whether the largest exponent is
   used for NaNs & infinities, or whether it's used for finite numbers.  The
   macros below wrap up that kind of information:

   FLT_UWORD_IS_FINITE(X)
        True if a positive float with bitmask X is finite.

   FLT_UWORD_IS_NAN(X)
        True if a positive float with bitmask X is not a number.

   FLT_UWORD_IS_INFINITE(X)
        True if a positive float with bitmask X is +infinity.

   FLT_UWORD_MAX
        The bitmask of FLT_MAX.

   FLT_UWORD_HALF_MAX
        The bitmask of FLT_MAX/2.

   FLT_UWORD_EXP_MAX
        The bitmask of the largest finite exponent (129 if the largest
        exponent is used for finite numbers, 128 otherwise).

   FLT_UWORD_LOG_MAX
        The bitmask of log(FLT_MAX), rounded down.  This value is the largest
        input that can be passed to exp() without producing overflow.

   FLT_UWORD_LOG_2MAX
        The bitmask of log(2*FLT_MAX), rounded down.  This value is the
        largest input than can be passed to cosh() without producing
        overflow.

   FLT_LARGEST_EXP
        The largest biased exponent that can be used for finite numbers
        (255 if the largest exponent is used for finite numbers, 254
        otherwise) */

#ifdef _FLT_LARGEST_EXPONENT_IS_NORMAL
#define FLT_UWORD_IS_FINITE(x)   1
#define FLT_UWORD_IS_NAN(x)      0
#define FLT_UWORD_IS_INFINITE(x) 0
#define FLT_UWORD_MAX            0x7fffffff
#define FLT_UWORD_EXP_MAX        0x43010000
#define FLT_UWORD_LOG_MAX        0x42b2d4fc
#define FLT_UWORD_LOG_2MAX       0x42b437e0
#define HUGE                     ((float)0X1.FFFFFEP128)
#else
#define FLT_UWORD_IS_FINITE(x)   ((x) < 0x7f800000L)
#define FLT_UWORD_IS_NAN(x)      ((x) > 0x7f800000L)
#define FLT_UWORD_IS_INFINITE(x) ((x) == 0x7f800000L)
#define FLT_UWORD_MAX            0x7f7fffffL
#define FLT_UWORD_EXP_MAX        0x43000000
#define FLT_UWORD_LOG_MAX        0x42b17217
#define FLT_UWORD_LOG_2MAX       0x42b2d4fc
#define HUGE                     ((float)3.40282346638528860e+38)
#endif
#define FLT_UWORD_HALF_MAX (FLT_UWORD_MAX - (1L << 23))
#define FLT_LARGEST_EXP    (FLT_UWORD_MAX >> 23)

/* rounding mode tests; nearest if not set. Assumes hardware
 * without rounding mode support uses nearest
 */

/* If there are rounding modes other than FE_TONEAREST defined, then
 * add code to check which is active
 */
#if (defined(FE_UPWARD) + defined(FE_DOWNWARD) + defined(FE_TOWARDZERO)) >= 1
#define FE_DECL_ROUND(v) int v = fegetround()
#define __is_nearest(r)  ((r) == FE_TONEAREST)
#else
#define FE_DECL_ROUND(v)
#define __is_nearest(r) 1
#endif

#ifdef FE_UPWARD
#define __is_upward(r) ((r) == FE_UPWARD)
#else
#define __is_upward(r) 0
#endif

#ifdef FE_DOWNWARD
#define __is_downward(r) ((r) == FE_DOWNWARD)
#else
#define __is_downward(r) 0
#endif

#ifdef FE_TOWARDZERO
#define __is_towardzero(r) ((r) == FE_TOWARDZERO)
#else
#define __is_towardzero(r) 0
#endif

/* Many routines check for zero and subnormal numbers.  Such things depend
   on whether the target supports denormals or not:

   FLT_UWORD_IS_ZERO(X)
        True if a positive float with bitmask X is +0.	Without denormals,
        any float with a zero exponent is a +0 representation.	With
        denormals, the only +0 representation is a 0 bitmask.

   FLT_UWORD_IS_SUBNORMAL(X)
        True if a non-zero positive float with bitmask X is subnormal.
        (Routines should check for zeros first.)

   FLT_UWORD_MIN
        The bitmask of the smallest float above +0.  Call this number
        REAL_FLT_MIN...

   FLT_UWORD_EXP_MIN
        The bitmask of the float representation of REAL_FLT_MIN's exponent.

   FLT_UWORD_LOG_MIN
        The bitmask of |log(REAL_FLT_MIN)|, rounding down.

   FLT_SMALLEST_EXP
        REAL_FLT_MIN's exponent - EXP_BIAS (1 if denormals are not supported,
        -22 if they are).
*/

#ifdef _FLT_NO_DENORMALS
#define FLT_UWORD_IS_ZERO(x)      ((x) < 0x00800000L)
#define FLT_UWORD_IS_SUBNORMAL(x) 0
#define FLT_UWORD_MIN             0x00800000
#define FLT_UWORD_EXP_MIN         0x42fc0000
#define FLT_UWORD_LOG_MIN         0x42aeac50
#define FLT_SMALLEST_EXP          1
#else
#define FLT_UWORD_IS_ZERO(x)      ((x) == 0)
#define FLT_UWORD_IS_SUBNORMAL(x) ((x) < 0x00800000L)
#define FLT_UWORD_MIN             0x00000001
#define FLT_UWORD_EXP_MIN         0x43160000
#define FLT_UWORD_LOG_MIN         0x42cff1b5
#define FLT_SMALLEST_EXP          -22
#endif

/*
 * set X_TLOSS = pi*2**52, which is possibly defined in <values.h>
 * (one may replace the following line by "#include <values.h>")
 */

#define X_TLOSS 1.41484755040568800000e+16

#ifdef _NEED_FLOAT64
extern __int32_t __rem_pio2(__float64, __float64 *);

/* fdlibm kernel function */
extern __float64 __kernel_sin(__float64, __float64, int);
extern __float64 __kernel_cos(__float64, __float64);
extern __float64 __kernel_tan(__float64, __float64, int);
extern int       __kernel_rem_pio2(__float64 *, __float64 *, int, int, int, const __int32_t *);
#endif

extern int   __rem_pio2f(float, float *);

/* float versions of fdlibm kernel functions */
extern float __kernel_sinf(float, float, int);
extern float __kernel_cosf(float, float);
extern float __kernel_tanf(float, float, int);

/* The original code used statements like
        n0 = ((*(int*)&one)>>29)^1;		* index of high word *
        ix0 = *(n0+(int*)&x);			* high word of x *
        ix1 = *((1-n0)+(int*)&x);		* low word of x *
   to dig two 32 bit words out of the 64 bit IEEE floating point
   value.  That is non-ANSI, and, moreover, the gcc instruction
   scheduler gets it wrong.  We instead use the following macros.
   Unlike the original code, we determine the endianness at compile
   time, not at run time; I don't see much benefit to selecting
   endianness at run time.  */

#ifndef __IEEE_BIG_ENDIAN
#ifndef __IEEE_LITTLE_ENDIAN
#error Must define endianness
#endif
#endif

/* A union which permits us to convert between a double and two 32 bit
   ints.  */

#ifdef __IEEE_BIG_ENDIAN

typedef union {
    uint64_t bits;
    struct {
        __uint32_t msw;
        __uint32_t lsw;
    } parts;
} ieee_double_shape_type;

#endif

#ifdef __IEEE_LITTLE_ENDIAN

typedef union {
    uint64_t bits;
    struct {
        __uint32_t lsw;
        __uint32_t msw;
    } parts;
} ieee_double_shape_type;

#endif

/* Get two 32 bit ints from a double.  */

#define EXTRACT_WORDS(ix0, ix1, d)   \
    do {                             \
        ieee_double_shape_type ew_u; \
        ew_u.bits = asuint64(d);     \
        (ix0) = ew_u.parts.msw;      \
        (ix1) = ew_u.parts.lsw;      \
    } while (0)

/* Get the more significant 32 bit int from a double.  */

#define GET_HIGH_WORD(i, d)          \
    do {                             \
        ieee_double_shape_type gh_u; \
        gh_u.bits = asuint64(d);     \
        (i) = gh_u.parts.msw;        \
    } while (0)

/* Get the less significant 32 bit int from a double.  */

#define GET_LOW_WORD(i, d)           \
    do {                             \
        ieee_double_shape_type gl_u; \
        gl_u.bits = asuint64(d);     \
        (i) = gl_u.parts.lsw;        \
    } while (0)

/* Set a double from two 32 bit ints.  */

#define INSERT_WORDS(d, ix0, ix1)    \
    do {                             \
        ieee_double_shape_type iw_u; \
        iw_u.parts.msw = (ix0);      \
        iw_u.parts.lsw = (ix1);      \
        (d) = asfloat64(iw_u.bits);  \
    } while (0)

/* Set the more significant 32 bits of a double from an int.  */

#define SET_HIGH_WORD(d, v)          \
    do {                             \
        ieee_double_shape_type sh_u; \
        sh_u.bits = asuint64(d);     \
        sh_u.parts.msw = (v);        \
        (d) = asfloat64(sh_u.bits);  \
    } while (0)

/* Set the less significant 32 bits of a double from an int.  */

#define SET_LOW_WORD(d, v)           \
    do {                             \
        ieee_double_shape_type sl_u; \
        sl_u.bits = asuint64(d);     \
        sl_u.parts.lsw = (v);        \
        (d) = asfloat64(sl_u.bits);  \
    } while (0)

/* A union which permits us to convert between a float and a 32 bit
   int.  */

/* Get a 32 bit int from a float.  */

#define GET_FLOAT_WORD(i, d) ((i) = asuint(d))

/* Set a float from a 32 bit int.  */

#define SET_FLOAT_WORD(d, i) ((d) = asfloat(i))

/* Macros to avoid undefined behaviour that can arise if the amount
   of a shift is exactly equal to the size of the shifted operand.  */

#define SAFE_LEFT_SHIFT(op, amt)  (((amt) < (int)(8 * sizeof(op))) ? ((op) << (amt)) : 0)

#define SAFE_RIGHT_SHIFT(op, amt) (((amt) < (int)(8 * sizeof(op))) ? ((op) >> (amt)) : 0)

int __undefined_shift_size(int x, int s);

/*
 * Shift left of negative integers is UB. Cast to unsigned, shift,
 * cast back.
 *
 * Shift right of negative integers is ID. When we want arithmetic
 * shifts, we use the shift operator directly when the sanitizer is
 * disabled because the alternative is a whole lotta code.
 */
#define lsl(__x, __s)                                                                       \
    ((sizeof(__x) == sizeof(char))        ? (__typeof(__x))((unsigned char)(__x) << (__s))  \
         : (sizeof(__x) == sizeof(short)) ? (__typeof(__x))((unsigned short)(__x) << (__s)) \
         : (sizeof(__x) == sizeof(int))   ? (__typeof(__x))((unsigned int)(__x) << (__s))   \
         : (sizeof(__x) == sizeof(long))  ? (__typeof(__x))((unsigned long)(__x) << (__s))  \
         : (sizeof(__x) == sizeof(long long))                                               \
         ? (__typeof(__x))((unsigned long long)(__x) << (__s))                              \
         : __undefined_shift_size(__x, __s))

#if defined(__has_feature) && __has_feature(undefined_behavior_sanitizer)

/*
 * Compute arithmetic right shift. For negative values, flip the bits,
 * shift and flip back. Otherwise, just shift. Thanks to Per Vognsen
 * for this version which both gcc and clang both currently optimize
 * to a single asr instruction in small tests.
 */
#define __asr(t, n)                         \
    static inline t __asr_##n(t x, int s)   \
    {                                       \
        return x < 0 ? ~(~x >> s) : x >> s; \
    }

__asr(signed char, signed_char) __asr(short, short) __asr(int, int) __asr(long, long)
    __asr(long long, long_long)

#define asr(__x, __s)                                                                      \
    ((sizeof(__x) == sizeof(char))            ? (__typeof(__x))__asr_signed_char(__x, __s) \
         : (sizeof(__x) == sizeof(short))     ? (__typeof(__x))__asr_short(__x, __s)       \
         : (sizeof(__x) == sizeof(int))       ? (__typeof(__x))__asr_int(__x, __s)         \
         : (sizeof(__x) == sizeof(long))      ? (__typeof(__x))__asr_long(__x, __s)        \
         : (sizeof(__x) == sizeof(long long)) ? (__typeof(__x))__asr_long_long(__x, __s)   \
                                              : __undefined_shift_size(__x, __s))
#else
#define asr(__x, __s) ((__x) >> (__s))
#endif

#ifdef _COMPLEX_H

    /*
     * Quoting from ISO/IEC 9899:TC2:
     *
     * 6.2.5.13 Types
     * Each complex type has the same representation and alignment requirements as
     * an array type containing exactly two elements of the corresponding real type;
     * the first element is equal to the real part, and the second element to the
     * imaginary part, of the complex number.
     */
    typedef union {
    float complex z;
    float         parts[2];
} float_complex;

typedef union {
    double complex z;
    double         parts[2];
} double_complex;

typedef union {
    long double complex z;
    long double         parts[2];
} long_double_complex;

#define REAL_PART(z) ((z).parts[0])
#define IMAG_PART(z) ((z).parts[1])

#endif /* _COMPLEX_H */

#endif /* _FDLIBM_H_ */
