Files
2026-09-07 21:22:01 +08:00

153 lines
4.8 KiB
C

#ifndef INCLUDED_C_FLOAT_H
#define INCLUDED_C_FLOAT_H
#ifndef INCLUDED_C_TYPES_H
#include <c_Types.h>
#endif /*INCLUDED_C_TYPES_H*/
#ifndef INCLUDED_MATH_H
#define INCLUDED_MATH_H
#include <math.h>
#endif /*INCLUDED_MATH_H*/
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
/* Complete IEEE 754 Standard Width Type Definition Constraints [1] */
typedef float c_float_t;
typedef double c_double_t;
/* ================================================================================================================== */
/* 32-bit Single Precision IEEE 754 Bitfields Layout [1] */
typedef struct {
uint32_t sign : 1; /* Bit 31: Sign [1] */
uint32_t exponent : 8; /* Bits 30-23: Biased Exponent [1] */
uint32_t mantissa : 23; /* Bits 22-0: Fractional Significand [1] */
} c_IEEE754_Float_Layout_t;
typedef union {
c_float_t value;
uint32_t bits;
c_IEEE754_Float_Layout_t layout;
} c_Float_Cast_t;
/* ================================================================================================================== */
/* 64-bit Double Precision IEEE 754 Bitfields Layout [1] */
typedef struct {
#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
uint64_t sign : 1; /* Bit 63 [1] */
uint64_t exponent : 11; /* Bits 62-52 [1] */
uint64_t mantissa : 52; /* Bits 51-0 [1] */
#else
/* Little Endian Bitfield Ordering Layout Configuration */
uint64_t mantissa : 52; /* Bits 0-51 [1] */
uint64_t exponent : 11; /* Bits 52-62 [1] */
uint64_t sign : 1; /* Bit 63 [1] */
#endif
} c_IEEE754_Double_Layout_t;
typedef union {
c_double_t value;
uint64_t bits;
c_IEEE754_Double_Layout_t layout;
} c_Double_Cast_t;
/* ================================================================================================================== */
/* Core Inline Bit-Level Inspection Queries */
C_STATIC_FORCE_INLINE
uint32_t c_Float_ToBits(c_float_t f) {
c_Float_Cast_t cast;
cast.value = f;
return cast.bits;
}
C_STATIC_FORCE_INLINE
c_float_t c_Float_FromBits(uint32_t bits) {
c_Float_Cast_t cast;
cast.bits = bits;
return cast.value;
}
C_STATIC_FORCE_INLINE
uint64_t c_Double_ToBits(c_double_t d) {
c_Double_Cast_t cast;
cast.value = d;
return cast.bits;
}
C_STATIC_FORCE_INLINE
c_double_t c_Double_FromBits(uint64_t bits) {
c_Double_Cast_t cast;
cast.bits = bits;
return cast.value;
}
C_STATIC_FORCE_INLINE
bool c_Float_IsNaN(c_float_t f) {
c_Float_Cast_t cast;
cast.value = f;
/* IEEE 754 rule: Exponent is all 1s, Mantissa is non-zero [1] */
return (cast.layout.exponent == 0xFF) && (cast.layout.mantissa != 0);
}
C_STATIC_FORCE_INLINE
bool c_Double_IsNaN(c_double_t d) {
c_Double_Cast_t cast;
cast.value = d;
/* IEEE 754 rule: Exponent is all 1s (0x7FF), Mantissa is non-zero [1] */
return (cast.layout.exponent == 0x7FF) && (cast.layout.mantissa != 0);
}
/* ================================================================================================================== */
/* Generic Callback Comparators (Perfect for Heaps & Sort Engines) */
/**
* @brief Standard generic min-heap comparator for single-precision c_float_t elements.
* @return < 0 if a < b, 0 if a == b, > 0 if a > b
*/
C_STATIC_FORCE_INLINE int c_Compare_FloatMin(const void* a, const void* b, void* args) {
c_float_t val_a = *(const c_float_t*)a;
c_float_t val_b = *(const c_float_t*)b;
(void)args;
return (val_a > val_b) - (val_a < val_b); /* Highly optimized branchless pattern */
}
/**
* @brief Standard generic min-heap comparator for double-precision c_double_t elements.
* @return < 0 if a < b, 0 if a == b, > 0 if a > b
*/
C_STATIC_FORCE_INLINE int c_Compare_DoubleMin(const void* a, const void* b, void* args) {
c_double_t val_a = *(const c_double_t*)a;
c_double_t val_b = *(const c_double_t*)b;
(void)args;
return (val_a > val_b) - (val_a < val_b);
}
/* ================================================================================================================== */
/* Epsilon Tolerant Mathematical Assertions */
/**
* @brief Checks if two single-precision floats are practically equal under an epsilon boundary.
*/
C_STATIC_FORCE_INLINE bool c_Float_AlmostEquals(c_float_t a, c_float_t b, c_float_t epsilon) {
/* If exactly equal (or both are positive/negative infinity), shortcut out */
if (a == b) return true;
return fabs(a - b) <= epsilon;
}
/**
* @brief Checks if two double-precision floats are practically equal under an epsilon boundary.
*/
C_STATIC_FORCE_INLINE bool c_Double_AlmostEquals(c_double_t a, c_double_t b, c_double_t epsilon) {
if (a == b) return true;
return fabs(a - b) <= epsilon;
}
#endif /*INCLUDED_C_FLOAT_H*/