From 599cf790258c5a17c09e1eff74e9eb93a433d696 Mon Sep 17 00:00:00 2001 From: Okladnoj Date: Sun, 21 Jun 2026 14:27:53 +0300 Subject: [PATCH 1/2] feat(math): Add deterministic float math overloads alongside their double counterparts --- Core/Libraries/Source/WWVegas/WWMath/wwmath.h | 124 ++++++++++++++++-- 1 file changed, 113 insertions(+), 11 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WWMath/wwmath.h b/Core/Libraries/Source/WWVegas/WWMath/wwmath.h index f901488f7b7..5ccc4ed9b80 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/wwmath.h +++ b/Core/Libraries/Source/WWVegas/WWMath/wwmath.h @@ -40,6 +40,7 @@ #include #include #include +#include "Lib/BaseDefines.h" #if USE_DETERMINISTIC_MATH #include "gmath.h" @@ -79,7 +80,6 @@ #define DEG_TO_RADF(x) (((float)x)*WWMATH_PI/180.0f) #endif - const int ARC_TABLE_SIZE=1024; const int SIN_TABLE_SIZE=1024; extern float _FastAcosTable[ARC_TABLE_SIZE]; @@ -105,7 +105,9 @@ static void Shutdown(); static WWINLINE double Pow(double x, double y); static WWINLINE float Powf(float x, float y); static WWINLINE float Sqrt_Legacy(float val); -static WWINLINE double Sqrt(double x); +static WWINLINE float Sqrt(float x); + static WWINLINE float Sqrt(int x); + static WWINLINE double Sqrt(double x); static WWINLINE float Sqrtf(float x); static WWINLINE float Inv_Sqrt_Legacy(float a); static WWINLINE double Inv_Sqrt(double x); @@ -114,29 +116,39 @@ static WWINLINE float Inv_Sqrtf(float x); static WWINLINE float Fast_Acos(float val); static WWINLINE float Fast_Asin(float val); static WWINLINE float Acos_Legacy(float val); -static WWINLINE double Acos(double x); +static WWINLINE float Acos(float x); + static WWINLINE double Acos(double x); static WWINLINE float Acosf(float x); static WWINLINE float Asin_Legacy(float val); -static WWINLINE double Asin(double x); +static WWINLINE float Asin(float x); + static WWINLINE double Asin(double x); static WWINLINE float Asinf(float x); static WWINLINE float Atan_Legacy(float x); -static WWINLINE double Atan(double x); +static WWINLINE float Atan(float x); + static WWINLINE double Atan(double x); static WWINLINE float Atanf(float x); static WWINLINE float Atan2_Legacy(float x, float y); -static WWINLINE double Atan2(double x, double y); +static WWINLINE float Atan2(float x, float y); + static WWINLINE double Atan2(double x, double y); static WWINLINE float Atan2f(float x, float y); static WWINLINE float Fast_Cos(float val); static WWINLINE float Fast_Inv_Cos(float val); static WWINLINE float Fast_Sin(float val); static WWINLINE float Fast_Inv_Sin(float val); -static WWINLINE double Cos(double val); +static WWINLINE float Cos(float val); + static WWINLINE double Cos(double val); static WWINLINE float Cosf(float val); static WWINLINE float Cosf_Legacy(float val); -static WWINLINE double Sin(double val); +// Prevent automatic compiler promotion of float arguments to double-precision variants. + // Single-precision math in GameMath (gm_*f) is guaranteed to be cross-platform bit-identical, + // whereas double-precision math (gm_*) can diverge by 1 ULP due to FPU precision differences (x87 vs NEON). + static WWINLINE float Sin(float val); + static WWINLINE double Sin(double val); static WWINLINE float Sinf(float val); static WWINLINE float Sinf_Legacy(float val); -static WWINLINE double Tan(double x); +static WWINLINE float Tan(float x); + static WWINLINE double Tan(double x); static WWINLINE float Tanf(float x); static WWINLINE double Cosh(double x); @@ -146,7 +158,8 @@ static WWINLINE float Sinhf(float x); static WWINLINE double Tanh(double x); static WWINLINE float Tanhf(float x); -static WWINLINE double Fabs(double x); +static WWINLINE float Fabs(float x); + static WWINLINE double Fabs(double x); static WWINLINE float Fabsf(float x); static WWINLINE float Fabsf_Legacy(float val); @@ -203,7 +216,6 @@ static WWINLINE float Normalize_Angle(float angle); // Normalizes the angle to t }; - WWINLINE double WWMath::Pow(double x, double y) { #if USE_DETERMINISTIC_MATH @@ -241,6 +253,24 @@ WWINLINE float WWMath::Sqrt_Legacy(float val) #endif } +WWINLINE float WWMath::Sqrt(float x) +{ +#if USE_DETERMINISTIC_MATH + return gm_sqrtf(x); +#else + return (float)Sqrt((double)x); +#endif +} + +WWINLINE float WWMath::Sqrt(int x) +{ +#if USE_DETERMINISTIC_MATH + return gm_sqrtf((float)x); +#else + return (float)Sqrt((double)x); +#endif +} + WWINLINE double WWMath::Sqrt(double x) { #if USE_DETERMINISTIC_MATH @@ -386,6 +416,15 @@ WWINLINE float WWMath::Acos_Legacy(float val) #endif } +WWINLINE float WWMath::Acos(float x) +{ +#if USE_DETERMINISTIC_MATH + return gm_acosf(x); +#else + return (float)Acos((double)x); +#endif +} + WWINLINE double WWMath::Acos(double x) { #if USE_DETERMINISTIC_MATH @@ -413,6 +452,15 @@ WWINLINE float WWMath::Asin_Legacy(float val) #endif } +WWINLINE float WWMath::Asin(float x) +{ +#if USE_DETERMINISTIC_MATH + return gm_asinf(x); +#else + return (float)Asin((double)x); +#endif +} + WWINLINE double WWMath::Asin(double x) { #if USE_DETERMINISTIC_MATH @@ -439,6 +487,15 @@ WWINLINE float WWMath::Atan_Legacy(float x) #endif } +WWINLINE float WWMath::Atan(float x) +{ +#if USE_DETERMINISTIC_MATH + return gm_atanf(x); +#else + return (float)Atan((double)x); +#endif +} + WWINLINE double WWMath::Atan(double x) { #if USE_DETERMINISTIC_MATH @@ -466,6 +523,15 @@ WWINLINE float WWMath::Atan2_Legacy(float x, float y) #endif } +WWINLINE float WWMath::Atan2(float x, float y) +{ +#if USE_DETERMINISTIC_MATH + return gm_atan2f(x, y); +#else + return (float)Atan2((double)x, (double)y); +#endif +} + WWINLINE double WWMath::Atan2(double x, double y) { #if USE_DETERMINISTIC_MATH @@ -561,6 +627,15 @@ WWINLINE float WWMath::Fast_Inv_Sin(float val) #endif } +WWINLINE float WWMath::Cos(float val) +{ +#if USE_DETERMINISTIC_MATH + return gm_cosf(val); +#else + return (float)Cos((double)val); +#endif +} + WWINLINE double WWMath::Cos(double val) { #if USE_DETERMINISTIC_MATH @@ -598,6 +673,15 @@ WWINLINE float WWMath::Cosf_Legacy(float val) #endif } +WWINLINE float WWMath::Sin(float val) +{ +#if USE_DETERMINISTIC_MATH + return gm_sinf(val); +#else + return (float)Sin((double)val); +#endif +} + WWINLINE double WWMath::Sin(double val) { #if USE_DETERMINISTIC_MATH @@ -635,6 +719,15 @@ WWINLINE float WWMath::Sinf_Legacy(float val) #endif } +WWINLINE float WWMath::Tan(float x) +{ +#if USE_DETERMINISTIC_MATH + return gm_tanf(x); +#else + return (float)Tan((double)x); +#endif +} + WWINLINE double WWMath::Tan(double x) { #if USE_DETERMINISTIC_MATH @@ -707,6 +800,15 @@ WWINLINE float WWMath::Tanhf(float x) #endif } +WWINLINE float WWMath::Fabs(float x) +{ +#if USE_DETERMINISTIC_MATH + return gm_fabsf(x); +#else + return (float)Fabs((double)x); +#endif +} + WWINLINE double WWMath::Fabs(double x) { #if USE_DETERMINISTIC_MATH From 4f745252c149bced8b4e229224dd7ba593994722 Mon Sep 17 00:00:00 2001 From: Okladnoj Date: Sun, 21 Jun 2026 14:27:53 +0300 Subject: [PATCH 2/2] fix(core): Use unsigned __int64 to support VC6 compiler in BitFlags.h --- Generals/Code/GameEngine/Include/Common/BitFlags.h | 8 ++++---- GeneralsMD/Code/GameEngine/Include/Common/BitFlags.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Generals/Code/GameEngine/Include/Common/BitFlags.h b/Generals/Code/GameEngine/Include/Common/BitFlags.h index f0e91b7c99a..3ef1f19d290 100644 --- a/Generals/Code/GameEngine/Include/Common/BitFlags.h +++ b/Generals/Code/GameEngine/Include/Common/BitFlags.h @@ -309,19 +309,19 @@ class BitFlags for (int chunk = numChunks - 1; chunk >= 0; --chunk) { - unsigned long long val = 0; + UnsignedInt64 val = 0; for (int bit = 0; bit < 64 && (chunk * 64 + bit) < NUMBITS; ++bit) { if (m_bits.test(chunk * 64 + bit)) - val |= (unsigned long long)(1) << bit; + val |= (UnsignedInt64)(1) << bit; } if (val != 0 || chunk == 0 || printedAny) { if (printedAny) - snprintf(chunkBuf, sizeof(chunkBuf), "%016llX", val); + snprintf(chunkBuf, sizeof(chunkBuf), "%016I64X", val); else - snprintf(chunkBuf, sizeof(chunkBuf), "%llX", val); + snprintf(chunkBuf, sizeof(chunkBuf), "%I64X", val); result.concat(chunkBuf); printedAny = true; diff --git a/GeneralsMD/Code/GameEngine/Include/Common/BitFlags.h b/GeneralsMD/Code/GameEngine/Include/Common/BitFlags.h index 9b6a10d8dbd..f0ef44aeae6 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/BitFlags.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/BitFlags.h @@ -309,19 +309,19 @@ class BitFlags for (int chunk = numChunks - 1; chunk >= 0; --chunk) { - unsigned long long val = 0; + UnsignedInt64 val = 0; for (int bit = 0; bit < 64 && (chunk * 64 + bit) < NUMBITS; ++bit) { if (m_bits.test(chunk * 64 + bit)) - val |= (unsigned long long)(1) << bit; + val |= (UnsignedInt64)(1) << bit; } if (val != 0 || chunk == 0 || printedAny) { if (printedAny) - snprintf(chunkBuf, sizeof(chunkBuf), "%016llX", val); + snprintf(chunkBuf, sizeof(chunkBuf), "%016I64X", val); else - snprintf(chunkBuf, sizeof(chunkBuf), "%llX", val); + snprintf(chunkBuf, sizeof(chunkBuf), "%I64X", val); result.concat(chunkBuf); printedAny = true;