211 lines
8.0 KiB
C
211 lines
8.0 KiB
C
/*
|
|
File: math.h
|
|
Author: Taylor Robbins
|
|
Date: 08\28\2025
|
|
*/
|
|
|
|
#ifndef _MATH_H
|
|
#define _MATH_H
|
|
|
|
//NOTE: clang was shadowing our intrinsics implementations (like floor, ceil, scalbnf, sqrt, etc.) with it's builtin ones,
|
|
// we've decided to route through our functions using macros and functions prefixed with _.
|
|
// Even if they route to builtins at the end of the day, this gives us the ability
|
|
// to test our implementation and the control to route these however we want.
|
|
|
|
// +--------------------------------------------------------------+
|
|
// | Defines |
|
|
// +--------------------------------------------------------------+
|
|
#define NAN __builtin_nanf("")
|
|
#define INFINITY __builtin_inff()
|
|
|
|
#define FP_NAN 0
|
|
#define FP_INFINITE 1
|
|
#define FP_ZERO 2
|
|
#define FP_SUBNORMAL 3
|
|
#define FP_NORMAL 4
|
|
|
|
#define M_E 2.7182818284590452354 // e
|
|
#define M_LOG2E 1.4426950408889634074 // log_2 e
|
|
#define M_LOG10E 0.43429448190325182765 // log_10 e
|
|
#define M_LN2 0.69314718055994530942 // log_e 2
|
|
#define M_LN10 2.30258509299404568402 // log_e 10
|
|
#define M_PI 3.14159265358979323846 // pi
|
|
#define M_PI_2 1.57079632679489661923 // pi/2
|
|
#define M_PI_4 0.78539816339744830962 // pi/4
|
|
#define M_1_PI 0.31830988618379067154 // 1/pi
|
|
#define M_2_PI 0.63661977236758134308 // 2/pi
|
|
#define M_2_SQRTPI 1.12837916709551257390 // 2/sqrt(pi)
|
|
#define M_SQRT2 1.41421356237309504880 // sqrt(2)
|
|
#define M_SQRT1_2 0.70710678118654752440 // 1/sqrt(2)
|
|
|
|
// +--------------------------------------------------------------+
|
|
// | Macros |
|
|
// +--------------------------------------------------------------+
|
|
#define isinf(value) (sizeof(value) == sizeof(float) \
|
|
? (__FLOAT_BITS((float)value) & 0x7fffffff) == 0x7f800000 \
|
|
: (__DOUBLE_BITS((double)value) & -1ULL>>1) == 0x7ffULL<<52 \
|
|
)
|
|
|
|
#define isnan(value) (sizeof(value) == sizeof(float) \
|
|
? (__FLOAT_BITS((float)value) & 0x7fffffff) > 0x7f800000 \
|
|
: (__DOUBLE_BITS((double)value) & -1ULL>>1) > 0x7ffULL<<52 \
|
|
)
|
|
|
|
#define signbit(value) (sizeof(value) == sizeof(float) \
|
|
? (int)(__FLOAT_BITS((float)value)>>31) \
|
|
: (int)(__DOUBLE_BITS((double)value)>>63) \
|
|
)
|
|
|
|
#define isnormal(value) (sizeof(value) == sizeof(float) \
|
|
? ((__FLOAT_BITS(value)+0x00800000) & 0x7fffffff) >= 0x01000000 \
|
|
: ((__DOUBLE_BITS(value)+(1ULL<<52)) & -1ULL>>1) >= 1ULL<<53 \
|
|
)
|
|
|
|
#define fpclassify(value) (sizeof(value) == sizeof(float) \
|
|
? __fpclassifyf(value) \
|
|
: __fpclassify(value) \
|
|
)
|
|
|
|
#define FORCE_EVAL(value) do { \
|
|
if (sizeof(value) == sizeof(float)) { fp_force_evalf(value); } \
|
|
else { fp_force_eval(value); } \
|
|
} while(0)
|
|
|
|
#define asuint(value) ((union { float _value; uint32_t _integer; }){ value })._integer
|
|
#define asfloat(value) ((union { uint32_t _value; float _float; }){ value })._float
|
|
#define asuint64(value) ((union { double _value; uint64_t _integer; }){ value })._integer
|
|
#define asdouble(value) ((union { uint64_t _value; double _double; }){ value })._double
|
|
|
|
#define EXTRACT_WORDS(highWord, lowWord, value) do { uint64_t __u = asuint64(value); (highWord) = (__u >> 32); (lowWord) = (uint32_t)__u; } while (0)
|
|
#define INSERT_WORDS(doubleVar, highWord, lowWord) do { (doubleVar) = asdouble(((uint64_t)(highWord)<<32) | (uint32_t)(lowWord)); } while (0)
|
|
#define GET_HIGH_WORD(wordVar, value) do { (wordVar) = asuint64(value) >> 32; } while (0)
|
|
#define GET_LOW_WORD(wordVar, value) do { (wordVar) = (uint32_t)asuint64(value); } while (0)
|
|
#define SET_HIGH_WORD(doubleVar, wordValue) INSERT_WORDS(doubleVar, wordValue, (uint32_t)asuint64(doubleVar))
|
|
#define SET_LOW_WORD(doubleVar, wordValue) INSERT_WORDS(doubleVar, asuint64(doubleVar)>>32, wordValue)
|
|
#define GET_FLOAT_WORD(wordVar, value) do { (wordVar) = asuint(value); } while (0)
|
|
#define SET_FLOAT_WORD(floatVar, value) do { (floatVar) = asfloat(value); } while (0)
|
|
|
|
// Helps static branch prediction so hot path can be better optimized.
|
|
#define predict_true(condition) __builtin_expect(!!(condition), 1)
|
|
#define predict_false(condition) __builtin_expect(condition, 0)
|
|
|
|
MAYBE_START_EXTERN_C
|
|
|
|
// +--------------------------------------------------------------+
|
|
// | Builtin Functions |
|
|
// +--------------------------------------------------------------+
|
|
#define copysignf(magnitude, sign) __builtin_copysignf((magnitude), (sign)) //results in f32.copysign instruction
|
|
#define copysign(magnitude, sign) __builtin_copysign((magnitude), (sign)) //results in f64.copysign instruction
|
|
#define fabsf(value) __builtin_fabsf(value) //results in f32.abs instruction
|
|
#define fabs(value) __builtin_fabs(value) //results in f64.abs instruction
|
|
#define floorf(value) __builtin_floorf(value) //results in f32.floor instruction
|
|
#define floor(value) __builtin_floor(value) //results in f64.floor instruction
|
|
#define ceilf(value) __builtin_ceilf(value) //results in f32.ceil instruction
|
|
#define ceil(value) __builtin_ceil(value) //results in f64.ceil instruction
|
|
|
|
// +--------------------------------------------------------------+
|
|
// | Helper Functions |
|
|
// +--------------------------------------------------------------+
|
|
int __fpclassifyf(float value);
|
|
int __fpclassify(double value);
|
|
|
|
unsigned __FLOAT_BITS(float value);
|
|
unsigned long long __DOUBLE_BITS(double value);
|
|
|
|
void fp_force_evalf(float value);
|
|
void fp_force_eval(double value);
|
|
|
|
float __math_invalidf(float value);
|
|
double __math_invalid(double value);
|
|
|
|
float eval_as_float(float x);
|
|
double eval_as_double(double x);
|
|
|
|
float __math_divzerof(uint32_t sign);
|
|
double __math_divzero(uint32_t sign);
|
|
|
|
// Top 16 bits of a double.
|
|
uint32_t top16(double x);
|
|
// Top 12 bits of a double (sign and exponent bits).
|
|
uint32_t top12(double value);
|
|
uint32_t top12f(float x);
|
|
|
|
float fp_barrierf(float x);
|
|
double fp_barrier(double x);
|
|
|
|
// +--------------------------------------------------------------+
|
|
// | Functions |
|
|
// +--------------------------------------------------------------+
|
|
// TODO: long double fabsl(long double value);
|
|
// TODO: long double fmodl(long double numer, long double denom);
|
|
|
|
float fminf(float value1, float value2);
|
|
double fmin(double value1, double value2);
|
|
float fmaxf(float value1, float value2);
|
|
double fmax(double value1, double value2);
|
|
|
|
float fmodf(float numer, float denom);
|
|
double fmod(double numer, double denom);
|
|
|
|
float roundf(float value);
|
|
double round(double value);
|
|
|
|
float _scalbnf(float value, int power);
|
|
double _scalbn(double value, int power);
|
|
// TODO: long double _scalbnl(long double value, int power);
|
|
#define scalbnf(value, power) _scalbnf(value, power)
|
|
#define scalbn(value, power) _scalbn(value, power)
|
|
|
|
float sqrtf(float value);
|
|
double sqrt(double value);
|
|
|
|
float _cbrtf(float value);
|
|
double _cbrt(double value);
|
|
#define cbrtf(value) _cbrtf(value)
|
|
#define cbrt(value) _cbrt(value)
|
|
|
|
float sinf(float value);
|
|
double sin(double value);
|
|
|
|
float cosf(float value);
|
|
double cos(double value);
|
|
|
|
float tanf(float value);
|
|
double tan(double value);
|
|
|
|
float asinf(float value);
|
|
double asin(double value);
|
|
|
|
float acosf(float value);
|
|
double acos(double value);
|
|
|
|
float atanf(float value);
|
|
double atan(double value);
|
|
|
|
float atan2f(float numer, float denom);
|
|
double atan2(double numer, double denom);
|
|
|
|
float powf(float value, float exponent);
|
|
double pow(double value, double exponent);
|
|
|
|
float logf(float value);
|
|
double log(double value);
|
|
|
|
float log2f(float value);
|
|
double log2(double value);
|
|
|
|
float log10f(float value);
|
|
double log10(double x);
|
|
|
|
float ldexpf(float value, int exponent);
|
|
double ldexp(double value, int exponent);
|
|
|
|
float expf(float value);
|
|
double exp(double value);
|
|
|
|
// TODO: long double copysignl(long double magnitude, long double sign);
|
|
|
|
MAYBE_END_EXTERN_C
|
|
|
|
#endif // _MATH_H
|