text: /*
   * ====================================================
   * 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.
   * ====================================================
   */
  
  /*
   * from: @(#)fdlibm.h 5.1 93/09/24
   * $NetBSD: math_private.h,v 1.16 2010/09/16 20:39:50 drochner Exp $
   */
  
  #ifndef _MATH_PRIVATE_H_
  #define _MATH_PRIVATE_H_
  
  #include <sys/types.h>
  
  /* The original fdlibm 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.  */
  
  /* A union which permits us to convert between a double and two 32 bit
     ints.  */
  
  /*
   * The ARM ports are little endian except for the FPA word order which is
   * big endian.
   */
  
  #if BYTE_ORDER == BIG_ENDIAN
  
  typedef union
  {
    double value;
    struct
    {
      u_int32_t msw;
      u_int32_t lsw;
    } parts;
    struct
    {
      u_int64_t w;
    } xparts;
  } ieee_double_shape_type;
  
  #endif
  
  #if BYTE_ORDER == LITTLE_ENDIAN
  
  typedef union
  {
    double value;
    struct
    {
      u_int32_t lsw;
      u_int32_t msw;
    } parts;
    struct
    {
      u_int64_t w;
    } xparts;
  } 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.value = (d);						\
    (ix0) = ew_u.parts.msw;					\
    (ix1) = ew_u.parts.lsw;					\
  } while (/*CONSTCOND*/0)
  
  /*
   * Get a 64-bit int from a double.
   * Origin: FreeBSD msun/src/math_private.h
   */
  #define EXTRACT_WORD64(ix,d)					\
  do {								\
    ieee_double_shape_type ew_u;					\
    ew_u.value = (d);						\
    (ix) = ew_u.xparts.w;						\
  } 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.value = (d);						\
    (i) = gh_u.parts.msw;						\
  } while (/*CONSTCOND*/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.value = (d);						\
    (i) = gl_u.parts.lsw;						\
  } while (/*CONSTCOND*/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) = iw_u.value;						\
  } while (/*CONSTCOND*/0)
  
  /*
   * Set a double from a 64-bit int.
   * Origin: FreeBSD msun/src/math_private.h
   */
  #define INSERT_WORD64(d,ix)					\
  do {								\
    ieee_double_shape_type iw_u;					\
    iw_u.xparts.w = (ix);						\
    (d) = iw_u.value;						\
  } 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.value = (d);						\
    sh_u.parts.msw = (v);						\
    (d) = sh_u.value;						\
  } while (/*CONSTCOND*/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.value = (d);						\
    sl_u.parts.lsw = (v);						\
    (d) = sl_u.value;						\
  } while (/*CONSTCOND*/0)
  
  /* A union which permits us to convert between a float and a 32 bit
     int.  */
  
  typedef union
  {
    float value;
    u_int32_t word;
  } ieee_float_shape_type;
  
  /* Get a 32 bit int from a float.  */
  
  #define GET_FLOAT_WORD(i,d)					\
  do {								\
    ieee_float_shape_type gf_u;					\
    gf_u.value = (d);						\
    (i) = gf_u.word;						\
  } while (/*CONSTCOND*/0)
  
  /* Set a float from a 32 bit int.  */
  
  #define SET_FLOAT_WORD(d,i)					\
  do {								\
    ieee_float_shape_type sf_u;					\
    sf_u.word = (i);						\
    (d) = sf_u.value;						\
  } while (/*CONSTCOND*/0)
  
  /*
   * Get expsign as a 16 bit int from a long double.
   * Origin: FreeBSD msun/src/math_private.h
   */
  
  #define	GET_LDBL_EXPSIGN(i,d)					\
  do {								\
    union IEEEl2bits ge_u;					\
    ge_u.e = (d);							\
    (i) = ge_u.xbits.expsign;					\
  } while (/*CONSTCOND*/0)
  
  /*
   * Set expsign of a long double from a 16 bit int.
   */
  
  #define	SET_LDBL_EXPSIGN(d,v)					\
  do {								\
    union IEEEl2bits se_u;					\
    se_u.e = (d);							\
    se_u.xbits.expsign = (v);					\
    (d) = se_u.e;							\
  } while (/*CONSTCOND*/0)
  
  /*
   * Attempt to get strict C99 semantics for assignment with non-C99 compilers.
   */
  #if FLT_EVAL_METHOD == 0 || __GNUC__ == 0
  #define	STRICT_ASSIGN(type, lval, rval)	((lval) = (rval))
  #else
  #define	STRICT_ASSIGN(type, lval, rval) do {	\
  	volatile type __lval;			\
  						\
  	if (sizeof(type) >= sizeof(double))	\
  		(lval) = (rval);		\
  	else {					\
  		__lval = (rval);		\
  		(lval) = __lval;		\
  	}					\
  } while (/*CONSTCOND*/0)
  #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])
  
  /*
   * Inline functions that can be used to construct complex values.
   *
   * The C99 standard intends x+I*y to be used for this, but x+I*y is
   * currently unusable in general since gcc introduces many overflow,
   * underflow, sign and efficiency bugs by rewriting I*y as
   * (0.0+I)*(y+0.0*I) and laboriously computing the full complex product.
   * In particular, I*Inf is corrupted to NaN+I*Inf, and I*-0 is corrupted
   * to -0.0+I*0.0.
   */
  static __inline float complex
  cpackf(float x, float y)
  {
  	float_complex fc;
  
  	REAL_PART(fc) = x;
  	IMAG_PART(fc) = y;
  	return (fc.z);
  }
  
  static __inline double complex
  cpack(double x, double y)
  {
  	double_complex dc;
  
  	REAL_PART(dc) = x;
  	IMAG_PART(dc) = y;
  	return (dc.z);
  }
  
  static __inline long double complex
  cpackl(long double x, long double y)
  {
  	long_double_complex ldc;
  
  	REAL_PART(ldc) = x;
  	IMAG_PART(ldc) = y;
  	return (ldc.z);
  }
  
  #endif	/* _COMPLEX_H */
  
  __BEGIN_DECLS
  #pragma GCC visibility push(hidden)
  
  /* fdlibm kernel function */
  int	__kernel_rem_pio2(double*,double*,int,int,int);
  
  /* double precision kernel functions */
  int	__libm_rem_pio2(double, double*);
  double	__kernel_sin(double, double, int);
  double	__kernel_cos(double, double);
  double	__kernel_tan(double, double, int);
  
  /* float precision kernel functions */
  int	__libm_rem_pio2f(float,double*);
  float	__kernel_sindf(double);
  float	__kernel_cosdf(double);
  float	__kernel_tandf(double, int);
  
  /* long double precision kernel functions */
  long double __kernel_sinl(long double, long double, int);
  long double __kernel_cosl(long double, long double);
  long double __kernel_tanl(long double, long double, int);
  
  #pragma GCC visibility pop
  __END_DECLS
  
  #endif /* _MATH_PRIVATE_H_ */
  