/* 
 *     Copyright (c) 2020, NVIDIA CORPORATION.  All rights reserved.
 *
 * NVIDIA CORPORATION and its licensors retain all intellectual property
 * and proprietary rights in and to this software, related documentation
 * and any modifications thereto.  Any use, reproduction, disclosure or
 * distribution of this software and related documentation without an express
 * license agreement from NVIDIA CORPORATION is strictly prohibited.
 *
 */

#include_next <math.h>

#if !defined(_PGI_CMATH_INCLUDE_IN_PROGRESS) && !defined(_PGI_MATH_H_INCLUDE)

#define _PGI_MATH_H_INCLUDE

#if defined(__cplusplus) && __cplusplus >= 201103L && __GNUC__ < 6

/* In <math.h> in GCC 4.x and 5.x, the eight functions below are defined as
   macros only (with no backing function behind them) in both C and C++ modes.
   This can cause problems in C++ where code can expect ::fpclassify to be the
   name of a function.  When this situation arises, undefine the macro and
   define inline functions at global scope that simply forward to the
   corresponding built-in function.  But only do this when not being included
   from <cmath>.  When <cmath> is included, the user doesn't necessarily want
   the declarations at global scope, and having those can cause overload
   failures. */

#undef fpclassify
#undef isnormal
#undef isgreater
#undef isgreaterequal
#undef isless
#undef islessequal
#undef islessgreater
#undef isunordered

inline int fpclassify(float __x) {
  return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL,
                              FP_ZERO, __x);
}
inline int fpclassify(double __x) {
  return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL,
                              FP_ZERO, __x);
}
inline int fpclassify(long double __x) {
  return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL,
                              FP_ZERO, __x);
}
inline int isnormal(float __x) {
  return __builtin_isnormal(__x);
}
inline int isnormal(double __x) {
  return __builtin_isnormal(__x);
}
inline int isnormal(long double __x) {
  return __builtin_isnormal(__x);
}
inline int isgreater(double __x, double __y) {
  return __builtin_isgreater(__x, __y);
}
inline int isgreaterequal(double __x, double __y) {
  return __builtin_isgreaterequal(__x, __y);
}
inline int isless(double __x, double __y) {
  return __builtin_isless(__x, __y);
}
inline int islessequal(double __x, double __y) {
  return __builtin_islessequal(__x, __y);
}
inline int islessgreater(double __x, double __y) {
  return __builtin_islessgreater(__x, __y);
}
inline int isunordered(double __x, double __y) {
  return __builtin_isunordered(__x, __y);
}

#endif
#endif

#ifndef _PGI_MATH_LIBM_PRAGMAS
#define _PGI_MATH_LIBM_PRAGMAS
/* #pragma libm marks these routines for special handling in
   OpenACC and OpenMP regions */
#pragma libm (acosf, acoshf, asinf, asinhf, atanhf, atan2f)
#pragma libm (cbrtf, ceilf, copysignf, cosf, coshf)
#pragma libm (erff, erfcf, expf, exp2f, exp10f, expm1f)
#pragma libm (fabsf, floorf, fmaf, fminf, fmaxf)
#pragma libm (ilogbf)
#pragma libm (ldexpf, lgammaf, llrintf, llroundf, logbf, log1pf, logf, log2f, log10f, lrintf, lroundf)
#pragma libm (modff)
#pragma libm (nanf, nearbyintf, nextafterf)
#pragma libm (powf)
#pragma libm (remainderf, remquof, rintf, roundf, rsqrtf)
#pragma libm (scalblnf, scalbnf, sinf, sinhf, sqrtf)
#pragma libm (tanf, tanhf, tgammaf, truncf)
#pragma libm (abs, acos, acosh, asin, asinh, atanh, atan2)
#pragma libm (cbrt, ceil, copysign, cos, cosh)
#pragma libm (erf, erfc, exp, exp2, exp10, expm1)
#pragma libm (fabs, floor, fma, fmin, fmax)
#pragma libm (ilogb, isinf, isfinite, isnan)
#pragma libm (ldexp, lgamma, llrint, llround, logb, log1p, log, log2, log10, lrint, lround)
#pragma libm (modf)
#pragma libm (nan, nearbyint, nextafter)
#pragma libm (pow)
#pragma libm (remainder, remquo, rint, round, rsqrt)
#pragma libm (scalbln, scalbn, sin, sinh, sqrt)
#pragma libm (tan, tanh, tgamma, trunc)
#pragma libm (llabs)
#pragma libm (cyl_bessel_i0f,cyl_bessel_i1f)
#pragma libm (erfcinvf,erfcxf,erfinvf)
#pragma libm (erfcinv,erfcx,erfinv)
#pragma libm (fdim,fdimf)
#pragma libm (normf,norm3df,norm4df,normcdff,normcdfinvf)
#pragma libm (norm,norm3d,norm4d,normcdf,normcdfinv)
#pragma libm (rnormf,rnorm3df,rnorm4df,rhypotf,rcbrtf)
#pragma libm (rnorm,rnorm3d,rnorm4d,rhypot,rcbrt)
#pragma libm (ynf,y1f,y0f)
#pragma libm (yn,y1,y0)
#pragma libm (jnf,j1f,j0f)
#pragma libm (jn,j1,j0)
#endif
