Files
cKit/Foundation/c_float.h
T
2026-08-29 00:53:40 +08:00

165 lines
4.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#ifndef INCLUDED_C_FLOAT_H
#define INCLUDED_C_FLOAT_H
#ifndef INCLUDED_FLOAT_H
#define INCLUDED_FLOAT_H
#include <float.h>
#endif /*INCLUDED_FLOAT_H*/
#ifndef INCLUDED_STDINT_H
#define INCLUDED_STDINT_H
#include <stdint.h>
#endif /*INCLUDED_STDINT_H*/
#ifndef INCLUDED_MATH_H
#define INCLUDED_MATH_H
#include <math.h>
#endif /*INCLUDED_MATH_H*/
#ifndef INCLUDED_C_COMPILER_H
#include <c_Compiler.h>
#endif /*INCLUDED_C_COMPILER_H*/
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
typedef union {
float f;
uint32_t u;
struct {
uint32_t sign: 1;
uint32_t exponent: 8;
uint32_t mantissa: 23;
}IEEE754;
}c_Float_t;
typedef union {
double d;
uint64_t u;
struct {
uint64_t sign: 1;
uint64_t exponent: 11;
uint64_t mantissa: 52;
};
}c_Double_t;
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
C_STATIC_FORCE_INLINE
int c_float_is_eq(const float a, const float b) {
return fabsf(a - b) < FLT_EPSILON;
}
C_STATIC_FORCE_INLINE
int c_float_is_gt(const float a, const float b) {
return (a - b) > FLT_EPSILON;
}
C_STATIC_FORCE_INLINE
int c_float_is_ge(const float a, const float b) {
return (a - b) >= -FLT_EPSILON;
}
C_STATIC_FORCE_INLINE
int c_float_cmp_safe(const float fa, const float fb) {
int nan_a = isnan(fa);
int nan_b = isnan(fb);
if (C_UNLIKELY(nan_a || nan_b)) {
if (nan_a && nan_b) return 0;
if (nan_a) return 1;
return -1;
}
if (fa < fb) return -1;
if (fa > fb) return 1;
return 0;
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* double */
C_STATIC_FORCE_INLINE
int c_double_is_eq(const double a, const double b) {
return fabs(a - b) < DBL_EPSILON;
}
C_STATIC_FORCE_INLINE
int c_double_is_gt(const double a, const double b) {
return (a - b) > DBL_EPSILON;
}
C_STATIC_FORCE_INLINE
int c_double_is_ge(const double a, const double b) {
return (a - b) >= -DBL_EPSILON;
}
C_STATIC_FORCE_INLINE
int c_double_cmp_safe(const double da, const double db) {
int nan_a = isnan(da);
int nan_b = isnan(db);
/* --- 1. 处理 NaN 的极端分支 --- */
/* 采用 C_UNLIKELY 优化,因为大部分待排数据中 NaN 是极少数,提示 CPU 预读正常分支 */
if (C_UNLIKELY(nan_a || nan_b)) {
if (nan_a && nan_b) return 0; /* 两个都是 NaN,视为相等 */
if (nan_a) return 1; /* a 是 NaNb 是正常数,视为 a > b(NaN排到最后) */
return -1; /* a 是正常数,b 是 NaN,视为 a < b */
}
/* --- 2. 正常数值的三向比较分支 --- */
if (da < db) return -1;
if (da > db) return 1;
return 0;
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
C_STATIC_FORCE_INLINE
int c_float_ptr_cmp_safe(const void* a, const void* b) {
float fa = *(const float*)a;
float fb = *(const float*)b;
int nan_a = isnan(fa);
int nan_b = isnan(fb);
if (C_UNLIKELY(nan_a || nan_b)) {
if (nan_a && nan_b) return 0;
if (nan_a) return 1;
return -1;
}
if (fa < fb) return -1;
if (fa > fb) return 1;
return 0;
}
C_STATIC_FORCE_INLINE
int c_double_ptr_cmp_safe(const void* a, const void* b) {
double da = *(const double*)a;
double db = *(const double*)b;
int nan_a = isnan(da);
int nan_b = isnan(db);
/* --- 1. 处理 NaN 的极端分支 --- */
/* 采用 C_UNLIKELY 优化,因为大部分待排数据中 NaN 是极少数,提示 CPU 预读正常分支 */
if (C_UNLIKELY(nan_a || nan_b)) {
if (nan_a && nan_b) return 0; /* 两个都是 NaN,视为相等 */
if (nan_a) return 1; /* a 是 NaNb 是正常数,视为 a > b(NaN排到最后) */
return -1; /* a 是正常数,b 是 NaN,视为 a < b */
}
/* --- 2. 正常数值的三向比较分支 --- */
if (da < db) return -1;
if (da > db) return 1;
return 0;
}
#endif /*INCLUDED_C_FLOAT_H*/