// <cmath> — C++ shim over the W65816 runtime's <math.h>.
//
// llvm-mos clang++ on this target has no system C++ stdlib.  ETL's
// format.h reaches for <cmath> when ETL_USING_FORMAT_FLOATING_POINT=1,
// and ordinary user C++ code expects std::sqrt / std::sin / etc. to
// resolve.  This header pulls in the existing extern-C-wrapped <math.h>
// and exports `std::` aliases for the libc functions.
//
// HUGE_VAL / INFINITY / NAN are macros (per the C standard); they are
// inherited as-is from <math.h>.  `std::HUGE_VAL_v` is provided as a
// constexpr alias since macros can't live inside namespaces.
//
// Per the C++ standard, isnan/isinf/isfinite/signbit/fpclassify must be
// functions when <cmath> is in scope (not C-style type-generic macros).
// We #undef the <math.h> macros and re-declare them as inline functions
// in namespace std and at global scope.

#ifndef _W65816_CXX_CMATH
#define _W65816_CXX_CMATH

#include <math.h>

// Drop the C-style classification macros so they can be re-declared as
// proper C++ functions below.
#undef isnan
#undef isinf
#undef isfinite
#undef signbit

inline bool isnan(double x) { return ::__isnan_d(x) != 0; }
inline bool isinf(double x) { return ::__isinf_d(x) != 0; }
inline bool isfinite(double x) { return ::__isfinite_d(x) != 0; }
inline bool signbit(double x) { return ::__signbit_d(x) != 0; }

namespace std {

// ---- Special-value alias (HUGE_VAL is a macro from <math.h>) -------
constexpr double HUGE_VAL_v = HUGE_VAL;

// ---- Classification (function form per C++ <cmath>) ----------------
inline bool isnan(double x) { return ::__isnan_d(x) != 0; }
inline bool isinf(double x) { return ::__isinf_d(x) != 0; }
inline bool isfinite(double x) { return ::__isfinite_d(x) != 0; }
inline bool signbit(double x) { return ::__signbit_d(x) != 0; }

// ---- Absolute / sign -------------------------------------------------
using ::fabs;
using ::fabsf;
using ::copysign;
using ::copysignf;

// ---- Rounding --------------------------------------------------------
using ::floor;
using ::floorf;
using ::ceil;
using ::ceilf;
using ::trunc;
using ::truncf;
using ::round;
using ::roundf;

// ---- Min / max / positive difference --------------------------------
using ::fmax;
using ::fmin;
using ::fdim;
using ::fmaxf;
using ::fminf;
using ::fdimf;

// ---- Mod / remainder -------------------------------------------------
using ::fmod;
using ::fmodf;
using ::remainder;
using ::remainderf;

// ---- FP decomposition ------------------------------------------------
using ::ldexp;
using ::ldexpf;
using ::frexp;
using ::frexpf;
using ::modf;
using ::modff;

// ---- Power / root ----------------------------------------------------
using ::sqrt;
using ::sqrtf;
using ::cbrt;
using ::cbrtf;
using ::pow;
using ::powf;
using ::hypot;
using ::hypotf;

// ---- Exponential / log ----------------------------------------------
using ::exp;
using ::expf;
using ::exp2;
using ::exp2f;
using ::expm1;
using ::expm1f;
using ::log;
using ::logf;
using ::log10;
using ::log10f;
using ::log2;
using ::log2f;
using ::log1p;
using ::log1pf;

// ---- Trigonometric --------------------------------------------------
using ::sin;
using ::sinf;
using ::cos;
using ::cosf;
using ::tan;
using ::tanf;
using ::atan;
using ::atanf;
using ::atan2;
using ::atan2f;
using ::asin;
using ::asinf;
using ::acos;
using ::acosf;

// ---- Hyperbolic -----------------------------------------------------
using ::sinh;
using ::sinhf;
using ::cosh;
using ::coshf;
using ::tanh;
using ::tanhf;
using ::asinh;
using ::asinhf;
using ::acosh;
using ::acoshf;
using ::atanh;
using ::atanhf;

// ---- Fused multiply-add ---------------------------------------------
using ::fma;
using ::fmaf;

// ---- NaN payload helpers --------------------------------------------
using ::nan;
using ::nanf;

// ---- Rounding to FP integer -----------------------------------------
using ::rint;
using ::rintf;
using ::nearbyint;
using ::nearbyintf;

// ---- Rounding to integer --------------------------------------------
using ::lround;
using ::lroundf;
using ::lrint;
using ::lrintf;

// ---- Scaling --------------------------------------------------------
using ::scalbn;
using ::scalbnf;
using ::scalbln;
using ::scalblnf;

// ---- Classification (function form) ---------------------------------
using ::fpclassify;

}  // namespace std

#endif  // _W65816_CXX_CMATH
