std1.0.0-beta-7 SafeC docs
// SafeC Standard Library — Math
// Integer utilities are pure const functions eligible for compile-time evaluation.
// Float/double utilities wrap the corresponding <math.h> functions.
// safeguard: link unix -lm
#pragma once
#include <std/math.h>

// ── Explicit extern declarations for libm functions ───────────────────────────
// '#include <math.h>' isn't usable here: the system header's macro-heavy,
// attribute-laden declarations aren't something this compiler's preprocessor
// re-parses, so nothing was ever actually declared — every call below was
// silently unresolved. Declare the exact symbols this file calls instead,
// same as mem.sc/str.sc do for libc.
namespace std {

extern float  fabsf(float x);
extern float  sqrtf(float x);
extern float  cbrtf(float x);
extern float  floorf(float x);
extern float  ceilf(float x);
extern float  roundf(float x);
extern float  truncf(float x);
extern float  powf(float base, float exp);
extern float  expf(float x);
extern float  exp2f(float x);
extern float  logf(float x);
extern float  log2f(float x);
extern float  log10f(float x);
extern float  sinf(float x);
extern float  cosf(float x);
extern float  tanf(float x);
extern float  asinf(float x);
extern float  acosf(float x);
extern float  atanf(float x);
extern float  atan2f(float y, float x);
extern float  sinhf(float x);
extern float  coshf(float x);
extern float  tanhf(float x);
extern float  hypotf(float x, float y);
extern float  fmodf(float x, float y);
extern float  copysignf(float mag, float sgn);
extern float  fmaf(float a, float b, float c);

extern double fabs(double x);
extern double sqrt(double x);
extern double cbrt(double x);
extern double floor(double x);
extern double ceil(double x);
extern double round(double x);
extern double trunc(double x);
extern double pow(double base, double exp);
extern double exp(double x);
extern double exp2(double x);
extern double log(double x);
extern double log2(double x);
extern double log10(double x);
extern double sin(double x);
extern double cos(double x);
extern double tan(double x);
extern double asin(double x);
extern double acos(double x);
extern double atan(double x);
extern double atan2(double y, double x);
extern double sinh(double x);
extern double cosh(double x);
extern double tanh(double x);
extern double hypot(double x, double y);
extern double fmod(double x, double y);
extern double copysign(double mag, double sgn);
extern double fma(double a, double b, double c);

// ── Constants ─────────────────────────────────────────────────────────────────

inline const double PI_D()    { return 3.141592653589793238462643383; }
inline const double E_D()     { return 2.718281828459045235360287471; }
inline const double LN2_D()   { return 0.693147180559945309417232121; }
inline const double LN10_D()  { return 2.302585092994045684017991455; }
inline const double SQRT2_D() { return 1.414213562373095048801688724; }
inline const double INF_D()   { unsafe { return (double)(1.0 / 0.0); } }

const float  PI_F()    { return (float)3.14159265358979323846; }
const float  E_F()     { return (float)2.71828182845904523536; }
const float  SQRT2_F() { return (float)1.41421356237309504880; }

// ── Integer ───────────────────────────────────────────────────────────────────

inline const int abs_int(int x) {
    return x < 0 ? -x : x;
}

inline const long long abs_ll(long long x) {
    return x < 0 ? -x : x;
}

inline const int min_int(int a, int b) {
    return a < b ? a : b;
}

inline const int max_int(int a, int b) {
    return a > b ? a : b;
}

inline const long long min_ll(long long a, long long b) {
    return a < b ? a : b;
}

inline const long long max_ll(long long a, long long b) {
    return a > b ? a : b;
}

inline const int clamp_int(int v, int lo, int hi) {
    return v < lo ? lo : (v > hi ? hi : v);
}

inline const long long clamp_ll(long long v, long long lo, long long hi) {
    return v < lo ? lo : (v > hi ? hi : v);
}

// ── Single-precision float ────────────────────────────────────────────────────
// MSVC's UCRT import libraries reliably export the double-precision libm
// functions below (fabs, sqrt, ...) but not their 'f'-suffixed single-
// precision counterparts (fabsf, sqrtf, ...) as real linkable symbols --
// those are meant to be resolved through <math.h>'s intrinsic/inline
// substitution, which this file can't use (see the file-header comment on
// why math.h itself isn't included). Confirmed directly: a minimal
// 'extern float fabsf(float); fabsf(-3.5f);' fails to link on Windows
// (LNK2019, unresolved external), while the identical program calling
// 'extern double fabs(double)' links and runs fine. So on Windows, route
// every '_f' wrapper through the double-precision CRT function instead
// (cast in, call, cast back) — everywhere else, xxxf() links normally, no
// reason to pay the float->double->float round trip there.
#ifdef _WIN32
inline float abs_f(float x)                      { unsafe { return (float)fabs((double)x); } }
inline float sqrt_f(float x)                     { unsafe { return (float)sqrt((double)x); } }
inline float cbrt_f(float x)                     { unsafe { return (float)cbrt((double)x); } }
inline float floor_f(float x)                    { unsafe { return (float)floor((double)x); } }
inline float ceil_f(float x)                     { unsafe { return (float)ceil((double)x); } }
inline float round_f(float x)                    { unsafe { return (float)round((double)x); } }
inline float trunc_f(float x)                    { unsafe { return (float)trunc((double)x); } }
inline float pow_f(float base, float exp)        { unsafe { return (float)pow((double)base, (double)exp); } }
inline float exp_f(float x)                      { unsafe { return (float)exp((double)x); } }
inline float exp2_f(float x)                     { unsafe { return (float)exp2((double)x); } }
inline float log_f(float x)                      { unsafe { return (float)log((double)x); } }
inline float log2_f(float x)                     { unsafe { return (float)log2((double)x); } }
inline float log10_f(float x)                    { unsafe { return (float)log10((double)x); } }
inline float sin_f(float x)                      { unsafe { return (float)sin((double)x); } }
inline float cos_f(float x)                      { unsafe { return (float)cos((double)x); } }
inline float tan_f(float x)                      { unsafe { return (float)tan((double)x); } }
inline float asin_f(float x)                     { unsafe { return (float)asin((double)x); } }
inline float acos_f(float x)                     { unsafe { return (float)acos((double)x); } }
inline float atan_f(float x)                     { unsafe { return (float)atan((double)x); } }
inline float atan2_f(float y, float x)           { unsafe { return (float)atan2((double)y, (double)x); } }
inline float sinh_f(float x)                     { unsafe { return (float)sinh((double)x); } }
inline float cosh_f(float x)                     { unsafe { return (float)cosh((double)x); } }
inline float tanh_f(float x)                     { unsafe { return (float)tanh((double)x); } }
inline float hypot_f(float x, float y)           { unsafe { return (float)hypot((double)x, (double)y); } }
inline float fmod_f(float x, float y)            { unsafe { return (float)fmod((double)x, (double)y); } }
inline float copysign_f(float mag, float sgn)    { unsafe { return (float)copysign((double)mag, (double)sgn); } }
inline float fma_f(float a, float b, float c)    { unsafe { return (float)fma((double)a, (double)b, (double)c); } }
#else
inline float abs_f(float x)                      { unsafe { return fabsf(x); } }
inline float sqrt_f(float x)                     { unsafe { return sqrtf(x); } }
inline float cbrt_f(float x)                     { unsafe { return cbrtf(x); } }
inline float floor_f(float x)                    { unsafe { return floorf(x); } }
inline float ceil_f(float x)                     { unsafe { return ceilf(x); } }
inline float round_f(float x)                    { unsafe { return roundf(x); } }
inline float trunc_f(float x)                    { unsafe { return truncf(x); } }
inline float pow_f(float base, float exp)        { unsafe { return powf(base, exp); } }
inline float exp_f(float x)                      { unsafe { return expf(x); } }
inline float exp2_f(float x)                     { unsafe { return exp2f(x); } }
inline float log_f(float x)                      { unsafe { return logf(x); } }
inline float log2_f(float x)                     { unsafe { return log2f(x); } }
inline float log10_f(float x)                    { unsafe { return log10f(x); } }
inline float sin_f(float x)                      { unsafe { return sinf(x); } }
inline float cos_f(float x)                      { unsafe { return cosf(x); } }
inline float tan_f(float x)                      { unsafe { return tanf(x); } }
inline float asin_f(float x)                     { unsafe { return asinf(x); } }
inline float acos_f(float x)                     { unsafe { return acosf(x); } }
inline float atan_f(float x)                     { unsafe { return atanf(x); } }
inline float atan2_f(float y, float x)           { unsafe { return atan2f(y, x); } }
inline float sinh_f(float x)                     { unsafe { return sinhf(x); } }
inline float cosh_f(float x)                     { unsafe { return coshf(x); } }
inline float tanh_f(float x)                     { unsafe { return tanhf(x); } }
inline float hypot_f(float x, float y)           { unsafe { return hypotf(x, y); } }
inline float fmod_f(float x, float y)            { unsafe { return fmodf(x, y); } }
inline float copysign_f(float mag, float sgn)    { unsafe { return copysignf(mag, sgn); } }
inline float fma_f(float a, float b, float c)    { unsafe { return fmaf(a, b, c); } }
#endif

inline const float min_f(float a, float b)             { return a < b ? a : b; }
inline const float max_f(float a, float b)             { return a > b ? a : b; }
inline const float clamp_f(float v, float lo, float hi){ return v < lo ? lo : (v > hi ? hi : v); }

// IEEE 754: NaN is the only value not equal to itself.
inline const int isnan_f(float x)    { return x != x; }
// IEEE 754: inf * 2 == inf (and != 0), finite * 2 != itself.
inline const int isinf_f(float x)    { return x != (float)0 && x + x == x; }
// Finite iff neither NaN nor inf.
inline const int isfinite_f(float x) { return !isnan_f(x) && !isinf_f(x); }

// ── Double-precision double ───────────────────────────────────────────────────

inline double abs_d(double x)                        { unsafe { return fabs(x); } }
inline double sqrt_d(double x)                       { unsafe { return sqrt(x); } }
inline double cbrt_d(double x)                       { unsafe { return cbrt(x); } }
inline double floor_d(double x)                      { unsafe { return floor(x); } }
inline double ceil_d(double x)                       { unsafe { return ceil(x); } }
inline double round_d(double x)                      { unsafe { return round(x); } }
inline double trunc_d(double x)                      { unsafe { return trunc(x); } }
inline double pow_d(double base, double exp)         { unsafe { return pow(base, exp); } }
inline double exp_d(double x)                        { unsafe { return exp(x); } }
inline double exp2_d(double x)                       { unsafe { return exp2(x); } }
inline double log_d(double x)                        { unsafe { return log(x); } }
inline double log2_d(double x)                       { unsafe { return log2(x); } }
inline double log10_d(double x)                      { unsafe { return log10(x); } }
inline double sin_d(double x)                        { unsafe { return sin(x); } }
inline double cos_d(double x)                        { unsafe { return cos(x); } }
inline double tan_d(double x)                        { unsafe { return tan(x); } }
inline double asin_d(double x)                       { unsafe { return asin(x); } }
inline double acos_d(double x)                       { unsafe { return acos(x); } }
inline double atan_d(double x)                       { unsafe { return atan(x); } }
inline double atan2_d(double y, double x)            { unsafe { return atan2(y, x); } }
inline double sinh_d(double x)                       { unsafe { return sinh(x); } }
inline double cosh_d(double x)                       { unsafe { return cosh(x); } }
inline double tanh_d(double x)                       { unsafe { return tanh(x); } }
inline double hypot_d(double x, double y)            { unsafe { return hypot(x, y); } }
inline double fmod_d(double x, double y)             { unsafe { return fmod(x, y); } }
inline double copysign_d(double mag, double sgn)     { unsafe { return copysign(mag, sgn); } }
inline double fma_d(double a, double b, double c)    { unsafe { return fma(a, b, c); } }

inline const double min_d(double a, double b)              { return a < b ? a : b; }
inline const double max_d(double a, double b)              { return a > b ? a : b; }
inline const double clamp_d(double v, double lo, double hi){ return v < lo ? lo : (v > hi ? hi : v); }

inline const int isnan_d(double x)    { return x != x; }
inline const int isinf_d(double x)    { return x != 0.0 && x + x == x; }
inline const int isfinite_d(double x) { return !isnan_d(x) && !isinf_d(x); }

} // namespace std