|
40 | 40 | #include <math.h> |
41 | 41 | #include <float.h> |
42 | 42 | #include <assert.h> |
| 43 | +#include "Lib/BaseDefines.h" |
43 | 44 |
|
44 | 45 | #if USE_DETERMINISTIC_MATH |
45 | 46 | #include "gmath.h" |
@@ -139,6 +140,21 @@ static WWINLINE float Sinf_Legacy(float val); |
139 | 140 | static WWINLINE double Tan(double x); |
140 | 141 | static WWINLINE float Tanf(float x); |
141 | 142 |
|
| 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 | + |
142 | 158 | static WWINLINE double Cosh(double x); |
143 | 159 | static WWINLINE float Coshf(float x); |
144 | 160 | static WWINLINE double Sinh(double x); |
@@ -484,6 +500,72 @@ WWINLINE float WWMath::Atan2f(float x, float y) |
484 | 500 | #endif |
485 | 501 | } |
486 | 502 |
|
| 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 | + |
487 | 569 | WWINLINE float WWMath::Fast_Cos(float val) |
488 | 570 | { |
489 | 571 | val+=(WWMATH_PI * 0.5f); |
|
0 commit comments