Skip to content

Commit 121e30a

Browse files
committed
feat: Add float overloads to WWMath to ensure deterministic single-precision math results
1 parent a75b7c1 commit 121e30a

1 file changed

Lines changed: 82 additions & 0 deletions

File tree

  • Core/Libraries/Source/WWVegas/WWMath

Core/Libraries/Source/WWVegas/WWMath/wwmath.h

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <math.h>
4141
#include <float.h>
4242
#include <assert.h>
43+
#include "Lib/BaseDefines.h"
4344

4445
#if USE_DETERMINISTIC_MATH
4546
#include "gmath.h"
@@ -139,6 +140,21 @@ static WWINLINE float Sinf_Legacy(float val);
139140
static WWINLINE double Tan(double x);
140141
static WWINLINE float Tanf(float x);
141142

143+
// ── FLOAT OVERLOADS FOR DETERMINISTIC MATH ──
144+
// Prevent automatic compiler promotion of float arguments to double-precision variants.
145+
// Single-precision math in GameMath (gm_*f) is guaranteed to be cross-platform bit-identical,
146+
// whereas double-precision math (gm_*) can diverge by 1 ULP due to FPU precision differences (x87 vs NEON).
147+
// Example fact: at Frame 1 on Akas Magic, Object 312 ROTATE dy=446C04C6 dx=C3A4DDB0 had:
148+
// WWMath::Atan2(float, float) -> resolved to double Atan2 -> gm_atan2(double, double)
149+
// resulting in Mac: 3FF4128C vs Win: 3FF4128B (1 ULP mismatch).
150+
static WWINLINE float Sin(float val);
151+
static WWINLINE float Cos(float val);
152+
static WWINLINE float Tan(float x);
153+
static WWINLINE float Atan(float x);
154+
static WWINLINE float Atan2(float x, float y);
155+
static WWINLINE float Asin(float x);
156+
static WWINLINE float Acos(float x);
157+
142158
static WWINLINE double Cosh(double x);
143159
static WWINLINE float Coshf(float x);
144160
static WWINLINE double Sinh(double x);
@@ -484,6 +500,72 @@ WWINLINE float WWMath::Atan2f(float x, float y)
484500
#endif
485501
}
486502

503+
// ── FLOAT OVERLOADS FOR DETERMINISTIC MATH ──
504+
// Inline implementations routing float calls directly to Single-precision GameMath functions.
505+
506+
WWINLINE float WWMath::Sin(float val)
507+
{
508+
#if USE_DETERMINISTIC_MATH
509+
return gm_sinf(val);
510+
#else
511+
return sinf(val);
512+
#endif
513+
}
514+
515+
WWINLINE float WWMath::Cos(float val)
516+
{
517+
#if USE_DETERMINISTIC_MATH
518+
return gm_cosf(val);
519+
#else
520+
return cosf(val);
521+
#endif
522+
}
523+
524+
WWINLINE float WWMath::Tan(float x)
525+
{
526+
#if USE_DETERMINISTIC_MATH
527+
return gm_tanf(x);
528+
#else
529+
return tanf(x);
530+
#endif
531+
}
532+
533+
WWINLINE float WWMath::Atan(float x)
534+
{
535+
#if USE_DETERMINISTIC_MATH
536+
return gm_atanf(x);
537+
#else
538+
return atanf(x);
539+
#endif
540+
}
541+
542+
WWINLINE float WWMath::Atan2(float x, float y)
543+
{
544+
#if USE_DETERMINISTIC_MATH
545+
return gm_atan2f(x, y);
546+
#else
547+
return atan2f(x, y);
548+
#endif
549+
}
550+
551+
WWINLINE float WWMath::Asin(float x)
552+
{
553+
#if USE_DETERMINISTIC_MATH
554+
return gm_asinf(x);
555+
#else
556+
return asinf(x);
557+
#endif
558+
}
559+
560+
WWINLINE float WWMath::Acos(float x)
561+
{
562+
#if USE_DETERMINISTIC_MATH
563+
return gm_acosf(x);
564+
#else
565+
return acosf(x);
566+
#endif
567+
}
568+
487569
WWINLINE float WWMath::Fast_Cos(float val)
488570
{
489571
val+=(WWMATH_PI * 0.5f);

0 commit comments

Comments
 (0)