From e896ec021506e25d4c0fe5e94c93beb99814484d Mon Sep 17 00:00:00 2001 From: Okladnoj Date: Thu, 30 Jul 2026 16:09:42 +0300 Subject: [PATCH 1/7] refactor(wwmath): Remove redundant Acos/Asin/Atan/Atan2/Sqrt _Legacy wrappers These five _Legacy wrappers are bit-identical to their non-Legacy siblings in every math mode (verified exhaustively and independently), so route all callers to the siblings and drop the wrappers. Force float binding where a call site passed a double literal or double expression, to keep the original single-precision behaviour and avoid selecting the true-double overload. EulerAnglesClass::From_Matrix switches sy/cy to float as part of this: Matrix3D elements are float, and passing double sy/cy to WWMath::Atan2 produced mixed (double, float) argument lists that matched neither the float nor the double overload once the wrappers were gone, causing error C2666. Kept: Fabsf/Sinf/Cosf/Inv_Sqrt _Legacy, which differ under retail (x87 asm, bit twiddle, NaN handling) and must stay to preserve RETAIL_COMPATIBLE_CRC. --- .../GameClient/CameraShakeSystem.cpp | 2 +- .../Source/W3DDevice/GameClient/W3DView.cpp | 12 ++-- .../Source/WWVegas/WW3D2/shattersystem.cpp | 2 +- .../Source/WWVegas/WW3D2/texproject.cpp | 4 +- .../Source/WWVegas/WWAudio/SoundPseudo3D.cpp | 2 +- .../Source/WWVegas/WWMath/colmathline.cpp | 2 +- .../Libraries/Source/WWVegas/WWMath/euler.cpp | 24 +++---- .../Libraries/Source/WWVegas/WWMath/matrix3.h | 6 +- .../Source/WWVegas/WWMath/matrix3d.cpp | 8 +-- Core/Libraries/Source/WWVegas/WWMath/quat.cpp | 12 ++-- Core/Libraries/Source/WWVegas/WWMath/quat.h | 2 +- .../Libraries/Source/WWVegas/WWMath/vector2.h | 4 +- .../Libraries/Source/WWVegas/WWMath/vector3.h | 2 +- .../Libraries/Source/WWVegas/WWMath/vector4.h | 2 +- .../Source/WWVegas/WWMath/vehiclecurve.cpp | 10 +-- Core/Libraries/Source/WWVegas/WWMath/wwmath.h | 64 +------------------ .../W3DDevice/GameClient/W3DRoadBuffer.cpp | 2 +- .../Libraries/Source/WWVegas/WW3D2/camera.cpp | 4 +- .../W3DDevice/GameClient/W3DRoadBuffer.cpp | 2 +- .../Libraries/Source/WWVegas/WW3D2/camera.cpp | 4 +- 20 files changed, 55 insertions(+), 115 deletions(-) diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/CameraShakeSystem.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/CameraShakeSystem.cpp index 2d5e398ea94..195ffdbd762 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/CameraShakeSystem.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/CameraShakeSystem.cpp @@ -159,7 +159,7 @@ void CameraShakeSystemClass::CameraShakerClass::Compute_Rotations(const Vector3 ** omega(t) = start_omega + (end_omega - start_omega) * t ** phi = random(0..start_omega) */ - float intensity = Intensity * (1.0f - WWMath::Sqrt_Legacy(len2) / Radius) * (1.0f - ElapsedTime / Duration); + float intensity = Intensity * (1.0f - WWMath::Sqrt(len2) / Radius) * (1.0f - ElapsedTime / Duration); for (int i=0; i<3; i++) { float omega = Omega[i] + (END_OMEGA - Omega[i]) * ElapsedTime; (*set_angles)[i] += AXIS_ROTATION[i] * intensity * WWMath::Sinf_Legacy(omega * ElapsedTime + Phi[i]); diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DView.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DView.cpp index 6cb1bcac357..ef30417eb14 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DView.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DView.cpp @@ -2779,7 +2779,7 @@ void W3DView::rotateCameraTowardPosition(const Coord3D *pLoc, Int milliseconds, Vector2 dir(pLoc->x-curPos.x, pLoc->y-curPos.y); const Real dirLength = dir.Length(); if (dirLength<0.1f) return; - Real angle = WWMath::Acos_Legacy(dir.X/dirLength); + Real angle = WWMath::Acos(dir.X/dirLength); if (dir.Y<0.0f) { angle = -angle; } @@ -2922,7 +2922,7 @@ void W3DView::cameraModLookToward(Coord3D *pLoc) Vector2 dir(pLoc->x-result.x, pLoc->y-result.y); const Real dirLength = dir.Length(); if (dirLength<0.1f) continue; - Real angle = WWMath::Acos_Legacy(dir.X/dirLength); + Real angle = WWMath::Acos(dir.X/dirLength); if (dir.Y<0.0f) { angle = -angle; } @@ -3003,7 +3003,7 @@ void W3DView::cameraModFinalLookToward(Coord3D *pLoc) Vector2 dir(pLoc->x-result.x, pLoc->y-result.y); const Real dirLength = dir.Length(); if (dirLength<0.1f) continue; - Real angle = WWMath::Acos_Legacy(dir.X/dirLength); + Real angle = WWMath::Acos(dir.X/dirLength); if (dir.Y<0.0f) { angle = -angle; } @@ -3184,7 +3184,7 @@ void W3DView::setupWaypointPath(Bool orient) m_mcwpInfo.waySegLength[i] = dirLength; m_mcwpInfo.totalDistance += m_mcwpInfo.waySegLength[i]; if (orient && dirLength >= 0.1f) { - angle = WWMath::Acos_Legacy(dir.X/dirLength); + angle = WWMath::Acos(dir.X/dirLength); if (dir.Y<0.0f) { angle = -angle; } @@ -3260,7 +3260,7 @@ static Real makeQuadraticS(Real t) tPrime = 0.5 * (2*t*2*t); } else { tPrime = (t-0.5)*2; - tPrime = WWMath::Sqrt_Legacy(tPrime); + tPrime = WWMath::Sqrt(tPrime); tPrime = 0.5 + 0.5*(tPrime); } return tPrime*0.5 + t*0.5; @@ -3294,7 +3294,7 @@ void W3DView::rotateCameraOneFrame() const Real dirLength = dir.Length(); if (dirLength>=0.1f) { - Real angle = WWMath::Acos_Legacy(dir.X/dirLength); + Real angle = WWMath::Acos(dir.X/dirLength); if (dir.Y<0.0f) { angle = -angle; } diff --git a/Core/Libraries/Source/WWVegas/WW3D2/shattersystem.cpp b/Core/Libraries/Source/WWVegas/WW3D2/shattersystem.cpp index dde6e35f8c4..5a78a5f1273 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/shattersystem.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/shattersystem.cpp @@ -450,7 +450,7 @@ void PolygonClass::Compute_Plane() ay /= (double)NumVerts; az /= (double)NumVerts; - double len = WWMath::Sqrt_Legacy(nx*nx + ny*ny + nz*nz); + double len = WWMath::Sqrt((float)(nx*nx + ny*ny + nz*nz)); nx /= len; ny /= len; nz /= len; diff --git a/Core/Libraries/Source/WWVegas/WW3D2/texproject.cpp b/Core/Libraries/Source/WWVegas/WW3D2/texproject.cpp index 3e8745abc1e..0d8de7c376f 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/texproject.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/texproject.cpp @@ -960,8 +960,8 @@ bool TexProjectClass::Compute_Perspective_Projection float tan_hfov2 = WWMath::Fabsf_Legacy(box.Extent.X / (box.Center.Z + box.Extent.Z)); float tan_vfov2 = WWMath::Fabsf_Legacy(box.Extent.Y / (box.Center.Z + box.Extent.Z)); - float hfov = 2.0f * WWMath::Atan_Legacy(tan_hfov2); - float vfov = 2.0f * WWMath::Atan_Legacy(tan_vfov2); + float hfov = 2.0f * WWMath::Atan(tan_hfov2); + float vfov = 2.0f * WWMath::Atan(tan_vfov2); /* ** Plug in the results. diff --git a/Core/Libraries/Source/WWVegas/WWAudio/SoundPseudo3D.cpp b/Core/Libraries/Source/WWVegas/WWAudio/SoundPseudo3D.cpp index 17aefcc701c..3805659b907 100644 --- a/Core/Libraries/Source/WWVegas/WWAudio/SoundPseudo3D.cpp +++ b/Core/Libraries/Source/WWVegas/WWAudio/SoundPseudo3D.cpp @@ -213,7 +213,7 @@ SoundPseudo3DClass::Update_Pseudo_Pan () // // Calculate a normalized pan from 0 (hard left) to 1.0F (hard right) // - float angle = WWMath::Atan2_Legacy (rel_sound_pos.Y, rel_sound_pos.X); + float angle = WWMath::Atan2 (rel_sound_pos.Y, rel_sound_pos.X); float pan = -WWMath::Fast_Sin (angle); pan = (pan / 2.0F) + 0.5F; diff --git a/Core/Libraries/Source/WWVegas/WWMath/colmathline.cpp b/Core/Libraries/Source/WWVegas/WWMath/colmathline.cpp index 43be3a73a99..726adee7e86 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/colmathline.cpp +++ b/Core/Libraries/Source/WWVegas/WWMath/colmathline.cpp @@ -253,7 +253,7 @@ bool CollisionMath::Collide(const LineSegClass & line,const SphereClass & sphere if (disc < 0.0f) { return false; } else { - float d = WWMath::Sqrt_Legacy(disc); + float d = WWMath::Sqrt(disc); float frac = (clen - d) / line.Get_Length(); if (frac<0.0f) frac = (clen + d) / line.Get_Length(); diff --git a/Core/Libraries/Source/WWVegas/WWMath/euler.cpp b/Core/Libraries/Source/WWVegas/WWMath/euler.cpp index 9685ec39705..15d27779e84 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/euler.cpp +++ b/Core/Libraries/Source/WWVegas/WWMath/euler.cpp @@ -180,35 +180,35 @@ void EulerAnglesClass::From_Matrix(const Matrix3D & M, int order) _euler_unpack_order(order,i,j,k,h,n,s,f); if (s == EULER_REPEAT_YES) { - double sy = WWMath::Sqrt(M[i][j]*M[i][j] + M[i][k]*M[i][k]); + float sy = WWMath::Sqrt(M[i][j]*M[i][j] + M[i][k]*M[i][k]); if (sy > 16*FLT_EPSILON) { - Angle[0] = WWMath::Atan2_Legacy(M[i][j],M[i][k]); - Angle[1] = WWMath::Atan2_Legacy(sy,M[i][i]); - Angle[2] = WWMath::Atan2_Legacy(M[j][i],-M[k][i]); + Angle[0] = WWMath::Atan2(M[i][j],M[i][k]); + Angle[1] = WWMath::Atan2(sy,M[i][i]); + Angle[2] = WWMath::Atan2(M[j][i],-M[k][i]); } else { - Angle[0] = WWMath::Atan2_Legacy(-M[j][k],M[j][j]); - Angle[1] = WWMath::Atan2_Legacy(sy,M[i][i]); + Angle[0] = WWMath::Atan2(-M[j][k],M[j][j]); + Angle[1] = WWMath::Atan2(sy,M[i][i]); Angle[2] = 0.0; } } else { - double cy = WWMath::Sqrt(M[i][i]*M[i][i] + M[j][i]*M[j][i]); + float cy = WWMath::Sqrt(M[i][i]*M[i][i] + M[j][i]*M[j][i]); if (cy > 16*FLT_EPSILON) { - Angle[0] = WWMath::Atan2_Legacy(M[k][j],M[k][k]); - Angle[1] = WWMath::Atan2_Legacy(-M[k][i],cy); - Angle[2] = WWMath::Atan2_Legacy(M[j][i],M[i][i]); + Angle[0] = WWMath::Atan2(M[k][j],M[k][k]); + Angle[1] = WWMath::Atan2(-M[k][i],cy); + Angle[2] = WWMath::Atan2(M[j][i],M[i][i]); } else { - Angle[0] = WWMath::Atan2_Legacy(-M[j][k],M[j][j]); - Angle[1] = WWMath::Atan2_Legacy(-M[k][i],cy); + Angle[0] = WWMath::Atan2(-M[j][k],M[j][j]); + Angle[1] = WWMath::Atan2(-M[k][i],cy); Angle[2] = 0; } } diff --git a/Core/Libraries/Source/WWVegas/WWMath/matrix3.h b/Core/Libraries/Source/WWVegas/WWMath/matrix3.h index 004923f700f..379053fb5e9 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/matrix3.h +++ b/Core/Libraries/Source/WWVegas/WWMath/matrix3.h @@ -589,7 +589,7 @@ WWINLINE Matrix3x3& Matrix3x3::operator /= (float d) WWINLINE float Matrix3x3::Get_X_Rotation() const { Vector3 v = (*this) * Vector3(0.0,1.0,0.0); - return WWMath::Atan2_Legacy(v[2], v[1]); + return WWMath::Atan2(v[2], v[1]); } /*********************************************************************************************** @@ -607,7 +607,7 @@ WWINLINE float Matrix3x3::Get_X_Rotation() const WWINLINE float Matrix3x3::Get_Y_Rotation() const { Vector3 v = (*this) * Vector3(0.0,0.0,1.0); - return WWMath::Atan2_Legacy(v[0],v[2]); + return WWMath::Atan2(v[0],v[2]); } /*********************************************************************************************** @@ -625,7 +625,7 @@ WWINLINE float Matrix3x3::Get_Y_Rotation() const WWINLINE float Matrix3x3::Get_Z_Rotation() const { Vector3 v = (*this) * Vector3(1.0,0.0,0.0); - return WWMath::Atan2_Legacy(v[1],v[0]); + return WWMath::Atan2(v[1],v[0]); } WWINLINE Vector3 Matrix3x3::Get_X_Vector() const diff --git a/Core/Libraries/Source/WWVegas/WWMath/matrix3d.cpp b/Core/Libraries/Source/WWVegas/WWMath/matrix3d.cpp index 1bb6b74abeb..517ab181522 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/matrix3d.cpp +++ b/Core/Libraries/Source/WWVegas/WWMath/matrix3d.cpp @@ -248,7 +248,7 @@ void Matrix3D::Set_Rotation(const Quaternion & q) *=============================================================================================*/ float Matrix3D::Get_X_Rotation() const { - return WWMath::Atan2_Legacy(Row[2][1], Row[1][1]); + return WWMath::Atan2(Row[2][1], Row[1][1]); } @@ -266,7 +266,7 @@ float Matrix3D::Get_X_Rotation() const *=============================================================================================*/ float Matrix3D::Get_Y_Rotation() const { - return WWMath::Atan2_Legacy(Row[0][2], Row[2][2]); + return WWMath::Atan2(Row[0][2], Row[2][2]); } @@ -284,7 +284,7 @@ float Matrix3D::Get_Y_Rotation() const *=============================================================================================*/ float Matrix3D::Get_Z_Rotation() const { - return WWMath::Atan2_Legacy(Row[1][0], Row[0][0]); + return WWMath::Atan2(Row[1][0], Row[0][0]); } @@ -372,7 +372,7 @@ void Matrix3D::Look_At_Dir(const Vector3 &pos, const Vector3 &dir, float roll) float dz = dir.Z; // length of projection onto XY plane - float len2 = (float)WWMath::Sqrt_Legacy(dx*dx + dy*dy); + float len2 = WWMath::Sqrt(dx*dx + dy*dy); // pitch sinp = dz; diff --git a/Core/Libraries/Source/WWVegas/WWMath/quat.cpp b/Core/Libraries/Source/WWVegas/WWMath/quat.cpp index cc119ac72d6..31d6a47b1c3 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/quat.cpp +++ b/Core/Libraries/Source/WWVegas/WWMath/quat.cpp @@ -200,7 +200,7 @@ Quaternion Trackball(float x0, float y0, float x1, float y1, float sphsize) // Avoid problems with out of control values if (t > 1.0f) t = 1.0f; if (t < -1.0f) t = -1.0f; - phi = 2.0f * WWMath::Asin_Legacy(t); + phi = 2.0f * WWMath::Asin(t); return Axis_To_Quat(a, phi); } @@ -324,7 +324,7 @@ void __cdecl Fast_Slerp(Quaternion& res, const Quaternion & p,const Quaternion & // ---------------------------------------------------------------------------- // normal slerp! // else { -// theta = WWMath::Acos_Legacy(cos_t); +// theta = WWMath::Acos(cos_t); // sin_t = WWMath::Sinf_Legacy(theta); // oo_sin_t = 1.0 / sin_t; // beta = WWMath::Sinf_Legacy(theta - alpha*theta) * oo_sin_t; @@ -512,7 +512,7 @@ void Slerp(Quaternion& res, const Quaternion & p,const Quaternion & q,float alph } else { // normal slerp! - theta = WWMath::Acos_Legacy(cos_t); + theta = WWMath::Acos(cos_t); float sin_t = WWMath::Sinf_Legacy(theta); oo_sin_t = 1.0f / sin_t; beta = WWMath::Sinf_Legacy(theta - alpha*theta) * oo_sin_t; @@ -567,7 +567,7 @@ void Slerp_Setup(const Quaternion & p,const Quaternion & q,SlerpInfoStruct * sle } else { slerpinfo->Linear = false; - slerpinfo->Theta = WWMath::Acos_Legacy(cos_t); + slerpinfo->Theta = WWMath::Acos(cos_t); slerpinfo->SinT = WWMath::Sinf_Legacy(slerpinfo->Theta); } @@ -868,10 +868,10 @@ float project_to_sphere(float r, float x, float y) { const float SQRT2 = 1.41421356f; float t, z; - float d = WWMath::Sqrt_Legacy(x * x + y * y); + float d = WWMath::Sqrt(x * x + y * y); if (d < r * (SQRT2/(2.0f))) // inside sphere - z = WWMath::Sqrt_Legacy(r * r - d * d); + z = WWMath::Sqrt(r * r - d * d); else { // on hyperbola t = r / SQRT2; z = t * t / d; diff --git a/Core/Libraries/Source/WWVegas/WWMath/quat.h b/Core/Libraries/Source/WWVegas/WWMath/quat.h index 805225a8c86..a1c6d36f75d 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/quat.h +++ b/Core/Libraries/Source/WWVegas/WWMath/quat.h @@ -87,7 +87,7 @@ class Quaternion WWINLINE float Length2() const { return (X*X + Y*Y + Z*Z + W*W); } // Magnitude of the quaternion - WWINLINE float Length() const { return WWMath::Sqrt_Legacy(Length2()); } + WWINLINE float Length() const { return WWMath::Sqrt(Length2()); } // Make the quaternion unit length void Normalize(); diff --git a/Core/Libraries/Source/WWVegas/WWMath/vector2.h b/Core/Libraries/Source/WWVegas/WWMath/vector2.h index a7d110e58d2..3db367dedb2 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/vector2.h +++ b/Core/Libraries/Source/WWVegas/WWMath/vector2.h @@ -356,7 +356,7 @@ WWINLINE Vector2 Normalize(const Vector2 & vec) *========================================================================*/ WWINLINE float Vector2::Length() const { - return (float)WWMath::Sqrt_Legacy(Length2()); + return WWMath::Sqrt(Length2()); } /************************************************************************** @@ -638,7 +638,7 @@ WWINLINE float Distance(float x1, float y1, float x2, float y2) float x_diff = x1 - x2; float y_diff = y1 - y2; - return (WWMath::Sqrt_Legacy((x_diff * x_diff) + (y_diff * y_diff))); + return (WWMath::Sqrt((x_diff * x_diff) + (y_diff * y_diff))); } diff --git a/Core/Libraries/Source/WWVegas/WWMath/vector3.h b/Core/Libraries/Source/WWVegas/WWMath/vector3.h index 3e058579cba..f558c340813 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/vector3.h +++ b/Core/Libraries/Source/WWVegas/WWMath/vector3.h @@ -452,7 +452,7 @@ WWINLINE Vector3 Normalize(const Vector3 & vec) *========================================================================*/ WWINLINE float Vector3::Length() const { - return WWMath::Sqrt_Legacy(Length2()); + return WWMath::Sqrt(Length2()); } /************************************************************************** diff --git a/Core/Libraries/Source/WWVegas/WWMath/vector4.h b/Core/Libraries/Source/WWVegas/WWMath/vector4.h index 18764bebad3..21601bc4f25 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/vector4.h +++ b/Core/Libraries/Source/WWVegas/WWMath/vector4.h @@ -303,7 +303,7 @@ WWINLINE Vector4 Normalize(const Vector4 & vec) *========================================================================*/ WWINLINE float Vector4::Length() const { - return WWMath::Sqrt_Legacy(Length2()); + return WWMath::Sqrt(Length2()); } /************************************************************************** diff --git a/Core/Libraries/Source/WWVegas/WWMath/vehiclecurve.cpp b/Core/Libraries/Source/WWVegas/WWMath/vehiclecurve.cpp index cb52599cb09..cd6ba177417 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/vehiclecurve.cpp +++ b/Core/Libraries/Source/WWVegas/WWMath/vehiclecurve.cpp @@ -102,8 +102,8 @@ Find_Tangent // Determine the offset angle (from the line between the point and center) // where the 2 tangent points lie. // - float angle_offset = WWMath::Acos_Legacy (radius / dist); - float base_angle = WWMath::Atan2_Legacy (delta_x, -delta_y); + float angle_offset = WWMath::Acos (radius / dist); + float base_angle = WWMath::Atan2 (delta_x, -delta_y); base_angle = WWMath::Wrap (base_angle, 0, DEG_TO_RADF (360)); // @@ -185,10 +185,10 @@ Find_Turn_Arc // the point halfway between the angles formed by the (prev-curr) and // (next-curr) vectors. // - float angle1 = ::WWMath::Atan2_Legacy ((prev_pt.Y - curr_pt.Y), prev_pt.X - curr_pt.X); + float angle1 = ::WWMath::Atan2 ((prev_pt.Y - curr_pt.Y), prev_pt.X - curr_pt.X); angle1 = WWMath::Wrap (angle1, 0, DEG_TO_RADF (360)); - float angle2 = ::WWMath::Atan2_Legacy ((next_pt.Y - curr_pt.Y), next_pt.X - curr_pt.X); + float angle2 = ::WWMath::Atan2 ((next_pt.Y - curr_pt.Y), next_pt.X - curr_pt.X); angle2 = WWMath::Wrap (angle2, 0, DEG_TO_RADF (360)); float avg_angle = (angle1 + angle2) * 0.5F; @@ -252,7 +252,7 @@ Find_Tangents // // Find the angle where the current position lies on the turn arc // - (*point_angle) = ::WWMath::Atan2_Legacy (curr_pt.X - arc_center.X, -(curr_pt.Y - arc_center.Y)); + (*point_angle) = ::WWMath::Atan2 (curr_pt.X - arc_center.X, -(curr_pt.Y - arc_center.Y)); (*point_angle) = WWMath::Wrap ((*point_angle), 0, DEG_TO_RADF (360)); // diff --git a/Core/Libraries/Source/WWVegas/WWMath/wwmath.h b/Core/Libraries/Source/WWVegas/WWMath/wwmath.h index c83cfaa8eff..a8789788931 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/wwmath.h +++ b/Core/Libraries/Source/WWVegas/WWMath/wwmath.h @@ -105,7 +105,6 @@ static void Shutdown(); static WWINLINE double Pow(double x, double y); static WWINLINE float Powf(float x, float y); static WWINLINE double Sqr(float x); -static WWINLINE float Sqrt_Legacy(float val); static WWINLINE float Sqrt(float x); static WWINLINE float Sqrt(int x); static WWINLINE double Sqrt(double x); @@ -116,19 +115,15 @@ 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 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 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 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 float Atan2(float x, float y); static WWINLINE double Atan2(double x, double y); static WWINLINE float Atan2f(float x, float y); @@ -247,25 +242,6 @@ WWINLINE float WWMath::Powf(float x, float y) #endif } -WWINLINE float WWMath::Sqrt_Legacy(float val) -{ -#if USE_DETERMINISTIC_MATH - return gm_sqrtf(val); - -#elif defined(_MSC_VER) && defined(_M_IX86) - float retval; - __asm { - fld [val] - fsqrt - fstp [retval] - } - return retval; - -#else - return (float)sqrt((double)val); -#endif -} - WWINLINE float WWMath::Sqrt(float x) { #if USE_DETERMINISTIC_MATH @@ -376,7 +352,7 @@ WWINLINE float WWMath::Fast_Acos(float val) { // Near -1 and +1, the table becomes too inaccurate if (Fabsf_Legacy(val) > 0.975f) { - return Acos_Legacy(val); + return Acos(val); } val*=float(ARC_TABLE_SIZE/2); @@ -400,7 +376,7 @@ WWINLINE float WWMath::Fast_Asin(float val) { // Near -1 and +1, the table becomes too inaccurate if (Fabsf_Legacy(val) > 0.975f) { - return Asin_Legacy(val); + return Asin(val); } val*=float(ARC_TABLE_SIZE/2); @@ -420,15 +396,6 @@ WWINLINE float WWMath::Fast_Asin(float val) return (1.0f - frac) * _FastAsinTable[idx0] + frac * _FastAsinTable[idx1]; } -WWINLINE float WWMath::Acos_Legacy(float val) -{ -#if USE_DETERMINISTIC_MATH - return gm_acosf(val); -#else - return (float)acos((double)val); -#endif -} - WWINLINE float WWMath::Acos(float x) { #if USE_DETERMINISTIC_MATH @@ -456,15 +423,6 @@ WWINLINE float WWMath::Acosf(float x) #endif } -WWINLINE float WWMath::Asin_Legacy(float val) -{ -#if USE_DETERMINISTIC_MATH - return gm_asinf(val); -#else - return (float)asin((double)val); -#endif -} - WWINLINE float WWMath::Asin(float x) { #if USE_DETERMINISTIC_MATH @@ -491,15 +449,6 @@ WWINLINE float WWMath::Asinf(float x) #endif } -WWINLINE float WWMath::Atan_Legacy(float x) -{ -#if USE_DETERMINISTIC_MATH - return gm_atanf(x); -#else - return (float)atan((double)x); -#endif -} - WWINLINE float WWMath::Atan(float x) { #if USE_DETERMINISTIC_MATH @@ -527,15 +476,6 @@ WWINLINE float WWMath::Atanf(float x) #endif } -WWINLINE float WWMath::Atan2_Legacy(float x, float y) -{ -#if USE_DETERMINISTIC_MATH - return gm_atan2f(x, y); -#else - return (float)atan2((double)x, (double)y); -#endif -} - WWINLINE float WWMath::Atan2(float x, float y) { #if USE_DETERMINISTIC_MATH diff --git a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DRoadBuffer.cpp b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DRoadBuffer.cpp index c4c855f9eae..a4f1125b659 100644 --- a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DRoadBuffer.cpp +++ b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DRoadBuffer.cpp @@ -2872,7 +2872,7 @@ void W3DRoadBuffer::insertCurveSegmentAt(Int ndx1, Int ndx2) line1.Set(Vector3(pr1->X, pr1->Y, 0), Vector3(pr2->X, pr2->Y, 0)); line2.Set(Vector3(pr3->X, pr3->Y, 0), Vector3(pr4->X, pr4->Y, 0)); } - Real angle = WWMath::Acos_Legacy(curSin); + Real angle = WWMath::Acos(curSin); Real count = angle / (PI/6.0f); // number of 30 degree steps. if (count<0.9 || m_roads[ndx1].m_pt1.isAngled) { miter(ndx1, ndx2); diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/camera.cpp b/Generals/Code/Libraries/Source/WWVegas/WW3D2/camera.cpp index 572ecdcccb0..376495b2aac 100644 --- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/camera.cpp +++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/camera.cpp @@ -769,13 +769,13 @@ void CameraClass::Get_Clip_Planes(float & znear,float & zfar) const float CameraClass::Get_Horizontal_FOV() const { float width = ViewPlane.Max.X - ViewPlane.Min.X; - return 2*WWMath::Atan2_Legacy(width,2.0); + return 2*WWMath::Atan2(width,2.0f); } float CameraClass::Get_Vertical_FOV() const { float height = ViewPlane.Max.Y - ViewPlane.Min.Y; - return 2*WWMath::Atan2_Legacy(height,2.0); + return 2*WWMath::Atan2(height,2.0f); } float CameraClass::Get_Aspect_Ratio() const diff --git a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DRoadBuffer.cpp b/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DRoadBuffer.cpp index 76fe703e725..15c3d347d76 100644 --- a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DRoadBuffer.cpp +++ b/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DRoadBuffer.cpp @@ -2896,7 +2896,7 @@ void W3DRoadBuffer::insertCurveSegmentAt(Int ndx1, Int ndx2) line1.Set(Vector3(pr1->X, pr1->Y, 0), Vector3(pr2->X, pr2->Y, 0)); line2.Set(Vector3(pr3->X, pr3->Y, 0), Vector3(pr4->X, pr4->Y, 0)); } - Real angle = WWMath::Acos_Legacy(curSin); + Real angle = WWMath::Acos(curSin); Real count = angle / (PI/6.0f); // number of 30 degree steps. if (count<0.9 || m_roads[ndx1].m_pt1.isAngled) { miter(ndx1, ndx2); diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/camera.cpp b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/camera.cpp index 3144c5114c3..4cc1f37aaab 100644 --- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/camera.cpp +++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/camera.cpp @@ -769,13 +769,13 @@ void CameraClass::Get_Clip_Planes(float & znear,float & zfar) const float CameraClass::Get_Horizontal_FOV() const { float width = ViewPlane.Max.X - ViewPlane.Min.X; - return 2*WWMath::Atan2_Legacy(width,2.0); + return 2*WWMath::Atan2(width,2.0f); } float CameraClass::Get_Vertical_FOV() const { float height = ViewPlane.Max.Y - ViewPlane.Min.Y; - return 2*WWMath::Atan2_Legacy(height,2.0); + return 2*WWMath::Atan2(height,2.0f); } float CameraClass::Get_Aspect_Ratio() const From 59a90354d23a517e0cee174981e9afdc7acdb70e Mon Sep 17 00:00:00 2001 From: Okladnoj Date: Fri, 31 Jul 2026 16:25:17 +0300 Subject: [PATCH 2/7] refactor(wwmath): Remove Sqrt(int) overload, cast int call sites to float TheSuperHackers @refactor Okladnoj Sqrt(int) collapsed to the same numeric result as Sqrt(float): in DET it already truncated the argument to float (gm_sqrtf((float)x)); in RETAIL it returned (float)sqrt((double)x). After removal an int argument would be ambiguous between Sqrt(float)/Sqrt(double), so the pathfinding call sites in AIPathfind (Int dx,dy cell deltas) get an explicit (float) cast. This preserves CRC bit-for-bit in both modes: DET is identical, RETAIL is identical because the int magnitudes (dx*dx+dy*dy of cell coordinates) are far below 2^24 and thus exactly representable in float. --- Core/GameEngine/Source/GameLogic/AI/AIPathfind.cpp | 6 +++--- Core/Libraries/Source/WWVegas/WWMath/wwmath.h | 10 ---------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/Core/GameEngine/Source/GameLogic/AI/AIPathfind.cpp b/Core/GameEngine/Source/GameLogic/AI/AIPathfind.cpp index b5170cc840a..8db761f7b60 100644 --- a/Core/GameEngine/Source/GameLogic/AI/AIPathfind.cpp +++ b/Core/GameEngine/Source/GameLogic/AI/AIPathfind.cpp @@ -2070,7 +2070,7 @@ UnsignedInt PathfindCell::costToGoal( PathfindCell *goal ) Int dy = m_info->m_pos.y - goal->getYIndex(); #define NO_REAL_DIST #ifdef REAL_DIST - Int cost = COST_ORTHOGONAL*WWMath::Sqrt(dx*dx + dy*dy); + Int cost = COST_ORTHOGONAL*WWMath::Sqrt((float)(dx*dx + dy*dy)); #else if (dx<0) dx = -dx; if (dy<0) dy = -dy; @@ -2096,7 +2096,7 @@ UnsignedInt PathfindCell::costToHierGoal( PathfindCell *goal ) } Int dx = m_info->m_pos.x - goal->getXIndex(); Int dy = m_info->m_pos.y - goal->getYIndex(); - Int cost = REAL_TO_INT_FLOOR(COST_ORTHOGONAL*WWMath::Sqrt(dx*dx + dy*dy) + 0.5f); + Int cost = REAL_TO_INT_FLOOR(COST_ORTHOGONAL*WWMath::Sqrt((float)(dx*dx + dy*dy)) + 0.5f); return cost; } @@ -6444,7 +6444,7 @@ Int Pathfinder::examineNeighboringCells(PathfindCell *parentCell, PathfindCell * } else { dx = newCellCoord.x - goalCell->getXIndex(); dy = newCellCoord.y - goalCell->getYIndex(); - costRemaining = COST_ORTHOGONAL*WWMath::Sqrt(dx*dx + dy*dy); + costRemaining = COST_ORTHOGONAL*WWMath::Sqrt((float)(dx*dx + dy*dy)); costRemaining -= attackDistance/2; if (costRemaining<0) costRemaining=0; diff --git a/Core/Libraries/Source/WWVegas/WWMath/wwmath.h b/Core/Libraries/Source/WWVegas/WWMath/wwmath.h index a8789788931..099deaa58e8 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/wwmath.h +++ b/Core/Libraries/Source/WWVegas/WWMath/wwmath.h @@ -106,7 +106,6 @@ static WWINLINE double Pow(double x, double y); static WWINLINE float Powf(float x, float y); static WWINLINE double Sqr(float 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); @@ -251,15 +250,6 @@ WWINLINE float WWMath::Sqrt(float 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 From 72c5c287bce7c96da40bb57cb7e328b8330b0e2a Mon Sep 17 00:00:00 2001 From: Okladnoj Date: Fri, 31 Jul 2026 16:25:17 +0300 Subject: [PATCH 3/7] refactor(w3d): Route W3DMouse cursor angle through WWMath::Atan2 TheSuperHackers @refactor Okladnoj Finish the constant-only WWMath conversion in W3DMouse::draw() (WWMATH_HALF_PI) by also routing the scroll-cursor angle through WWMath::Atan2 instead of the raw libm atan2, per review consensus (either all operations through WWMath or revert the constant). Cursor rendering is not part of the simulation CRC. --- .../GameEngineDevice/Source/W3DDevice/GameClient/W3DMouse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DMouse.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DMouse.cpp index c30c4cd0a18..e71887c051e 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DMouse.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DMouse.cpp @@ -567,7 +567,7 @@ void W3DMouse::draw() { offset = TheInGameUI->getScrollAmount(); offset.normalize(); - Real theta = atan2(-offset.y, offset.x); + Real theta = WWMath::Atan2(-offset.y, offset.x); theta -= (Real)WWMATH_HALF_PI; tm.Rotate_Z(theta); } @@ -671,7 +671,7 @@ void W3DMouse::setCursorDirection(MouseCursor cursor) if (offset.x || offset.y) { offset.normalize(); - Real theta = atan2(offset.y, offset.x); + Real theta = WWMath::Atan2(offset.y, offset.x); theta = fmod(theta+WWMATH_TWO_PI,WWMATH_TWO_PI); Int numDirections=m_cursorInfo[m_currentCursor].numDirections; //Figure out which of our predrawn cursor orientations best matches the From d92e73afeb314bf72bc533d1b5ed1364cb30205c Mon Sep 17 00:00:00 2001 From: Okladnoj Date: Mon, 3 Aug 2026 11:28:05 +0300 Subject: [PATCH 4/7] refactor(wwmath): Call sqrtf directly in Sqrt(float) non-deterministic branch TheSuperHackers @refactor Okladnoj Finish the Sqrt consolidation per review: the non-deterministic branch of Sqrt(float) now calls sqrtf(x) directly instead of (float)Sqrt((double)x), dropping the float->double->float round-trip left over from the old Sqrt_Legacy removal. CRC is preserved bit-for-bit: sqrtf(x) == (float)sqrt((double)x) == x87 fsqrt across all 2^31 non-negative float encodings (VC6, MSVC x86/x64; 0 divergences), and double rounding is harmless for sqrt. The deterministic branch (gm_sqrtf) is unchanged. --- Core/Libraries/Source/WWVegas/WWMath/wwmath.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Libraries/Source/WWVegas/WWMath/wwmath.h b/Core/Libraries/Source/WWVegas/WWMath/wwmath.h index 099deaa58e8..83c9e87d15b 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/wwmath.h +++ b/Core/Libraries/Source/WWVegas/WWMath/wwmath.h @@ -246,7 +246,7 @@ WWINLINE float WWMath::Sqrt(float x) #if USE_DETERMINISTIC_MATH return gm_sqrtf(x); #else - return (float)Sqrt((double)x); + return sqrtf(x); #endif } From 28b6fd731db50e9b325b416b468bd1835628b780 Mon Sep 17 00:00:00 2001 From: Okladnoj Date: Mon, 3 Aug 2026 13:59:04 +0300 Subject: [PATCH 5/7] style(wwmath): Align function declarations and constant macros --- Core/Libraries/Source/WWVegas/WWMath/wwmath.h | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WWMath/wwmath.h b/Core/Libraries/Source/WWVegas/WWMath/wwmath.h index 83c9e87d15b..1e738b851f8 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/wwmath.h +++ b/Core/Libraries/Source/WWVegas/WWMath/wwmath.h @@ -52,12 +52,12 @@ #define WWMATH_EPSILON 0.0001f #define WWMATH_EPSILON2 WWMATH_EPSILON * WWMATH_EPSILON #define WWMATH_HALF_PI 1.570796327f -#define WWMATH_PI 3.141592654f -#define WWMATH_TWO_PI 6.283185308f +#define WWMATH_PI 3.141592654f +#define WWMATH_TWO_PI 6.283185308f #define WWMATH_FLOAT_MAX (FLT_MAX) #define WWMATH_FLOAT_MIN (FLT_MIN) -#define WWMATH_SQRT2 1.414213562f -#define WWMATH_SQRT3 1.732050808f +#define WWMATH_SQRT2 1.414213562f +#define WWMATH_SQRT3 1.732050808f #define WWMATH_OOSQRT2 0.707106781f #define WWMATH_OOSQRT3 0.577350269f @@ -99,14 +99,14 @@ class WWMath // Initialization and Shutdown. Other math sub-systems which require initialization and // shutdown processing will be handled in these functions -static void Init(); -static void Shutdown(); +static void Init(); +static void Shutdown(); static WWINLINE double Pow(double x, double y); static WWINLINE float Powf(float x, float y); static WWINLINE double Sqr(float x); static WWINLINE float Sqrt(float x); - static WWINLINE double Sqrt(double 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); @@ -115,16 +115,16 @@ 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(float x); - static WWINLINE double Acos(double x); +static WWINLINE double Acos(double x); static WWINLINE float Acosf(float x); static WWINLINE float Asin(float x); - static WWINLINE double Asin(double x); +static WWINLINE double Asin(double x); static WWINLINE float Asinf(float x); static WWINLINE float Atan(float x); - static WWINLINE double Atan(double x); +static WWINLINE double Atan(double x); static WWINLINE float Atanf(float x); static WWINLINE float Atan2(float x, float y); - static WWINLINE double Atan2(double x, double y); +static WWINLINE double Atan2(double x, double y); static WWINLINE float Atan2f(float x, float y); static WWINLINE float Fast_Cos(float val); @@ -132,18 +132,18 @@ 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 float Cos(float val); - static WWINLINE double Cos(double val); +static WWINLINE double Cos(double val); static WWINLINE float Cosf(float val); static WWINLINE float Cosf_Legacy(float 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); +// 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 float Tan(float x); - static WWINLINE double Tan(double x); +static WWINLINE double Tan(double x); static WWINLINE float Tanf(float x); static WWINLINE double Cosh(double x); @@ -154,7 +154,7 @@ static WWINLINE double Tanh(double x); static WWINLINE float Tanhf(float x); static WWINLINE float Fabs(float x); - static WWINLINE double Fabs(double x); +static WWINLINE double Fabs(double x); static WWINLINE float Fabsf(float x); static WWINLINE float Fabsf_Legacy(float val); @@ -172,45 +172,45 @@ static WWINLINE float Log10f(float x); static WWINLINE double Log(double x); static WWINLINE float Logf(float x); -static WWINLINE bool Fast_Is_Float_Positive(const float & val); -static WWINLINE bool Is_Power_Of_2(const unsigned int val); +static WWINLINE bool Fast_Is_Float_Positive(const float & val); +static WWINLINE bool Is_Power_Of_2(const unsigned int val); -static float Random_Float(); +static float Random_Float(); -static WWINLINE float Random_Float(float min,float max); -static WWINLINE float Clamp(float val, float min = 0.0f, float max = 1.0f); +static WWINLINE float Random_Float(float min,float max); +static WWINLINE float Clamp(float val, float min = 0.0f, float max = 1.0f); static WWINLINE double Clamp(double val, double min = 0.0f, double max = 1.0f); -static WWINLINE int Clamp_Int(int val, int min_val, int max_val); -static WWINLINE float Wrap(float val, float min = 0.0f, float max = 1.0f); +static WWINLINE int Clamp_Int(int val, int min_val, int max_val); +static WWINLINE float Wrap(float val, float min = 0.0f, float max = 1.0f); static WWINLINE double Wrap(double val, double min = 0.0f, double max = 1.0f); -static WWINLINE float Min(float a, float b); -static WWINLINE float Max(float a, float b); +static WWINLINE float Min(float a, float b); +static WWINLINE float Max(float a, float b); // Linearly interpolates between a and b using parameter t in [0, 1]. // t = 0 returns a, t = 1 returns b, values in between return a proportionate blend. -static WWINLINE float Lerp(float a, float b, float t); +static WWINLINE float Lerp(float a, float b, float t); static WWINLINE double Lerp(double a, double b, float t); // Computes the interpolation parameter t such that v = Lerp(a, b, t). // Returns where v lies between a and b as a ratio, typically in [0, 1]. -static WWINLINE float Inverse_Lerp(float a, float b, float v); +static WWINLINE float Inverse_Lerp(float a, float b, float v); static WWINLINE double Inverse_Lerp(double a, double b, float v); -static WWINLINE bool Is_Valid_Float(float x); -static WWINLINE bool Is_Valid_Double(double x); +static WWINLINE bool Is_Valid_Float(float x); +static WWINLINE bool Is_Valid_Double(double x); -static WWINLINE int Float_To_Int_Chop(float f); -static WWINLINE int Float_To_Int_Floor(float f); -static WWINLINE long Float_To_Long(float f); -static WWINLINE long Float_To_Long(double f); -static WWINLINE int Float_As_Int(const float f) { return *((int*)&f); } -static WWINLINE unsigned char Unit_Float_To_Byte(float f) { return (unsigned char)(f*255.0f); } -static WWINLINE float Byte_To_Unit_Float(unsigned char byte) { return ((float)byte) / 255.0f; } +static WWINLINE int Float_To_Int_Chop(float f); +static WWINLINE int Float_To_Int_Floor(float f); +static WWINLINE long Float_To_Long(float f); +static WWINLINE long Float_To_Long(double f); +static WWINLINE int Float_As_Int(const float f) { return *((int*)&f); } +static WWINLINE unsigned char Unit_Float_To_Byte(float f) { return (unsigned char)(f*255.0f); } +static WWINLINE float Byte_To_Unit_Float(unsigned char byte) { return ((float)byte) / 255.0f; } -static WWINLINE float Normalize_Angle(float angle); // Normalizes the angle to the range -PI..PI +static WWINLINE float Normalize_Angle(float angle); // Normalizes the angle to the range -PI..PI -static WWINLINE float Div_Safe(float dividend, float divisor, float fallback = 0.0f); -static WWINLINE double Div_Safe(double dividend, double divisor, double fallback = 0.0); +static WWINLINE float Div_Safe(float dividend, float divisor, float fallback = 0.0f); +static WWINLINE double Div_Safe(double dividend, double divisor, double fallback = 0.0); }; From b9d0e7690bad24457864b4dfdde457bde5064ed6 Mon Sep 17 00:00:00 2001 From: Okladnoj Date: Tue, 11 Aug 2026 23:29:30 +0300 Subject: [PATCH 6/7] refactor(wwmath): Drop WWMath::Sqr and route squaring back through WWMath::Pow Sqr was introduced only to avoid gm_pow, but it is not a wrapper around an existing engine function: retail squares via pow(x, 2), so a dedicated Sqr adds a new API where routing the original call through WWMath::Pow is enough. Restore WWMath::Pow(expr, 2) at every former Sqr call site in PartitionManager, POWTruckAIUpdate and BuildAssistant across both engines, and remove Sqr. Pow itself now squares through gm_powf under deterministic math: gm_pow runs on x87 under _PC_24 on the 32-bit Windows build and diverges from macOS ARM64, while gm_powf is cross-platform bit-identical. The retail path keeps pow(double) and is unaffected. Existing x*x expressions and the sqr() helper in BaseType.h are left untouched. --- Core/Libraries/Source/WWVegas/WWMath/wwmath.h | 12 +----------- .../Source/Common/System/BuildAssistant.cpp | 2 +- .../Source/GameLogic/Object/PartitionManager.cpp | 8 ++++---- .../Object/Update/AIUpdate/POWTruckAIUpdate.cpp | 2 +- .../Source/Common/System/BuildAssistant.cpp | 2 +- .../Source/GameLogic/Object/PartitionManager.cpp | 8 ++++---- .../Object/Update/AIUpdate/POWTruckAIUpdate.cpp | 2 +- 7 files changed, 13 insertions(+), 23 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WWMath/wwmath.h b/Core/Libraries/Source/WWVegas/WWMath/wwmath.h index 1e738b851f8..1266609f3c3 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/wwmath.h +++ b/Core/Libraries/Source/WWVegas/WWMath/wwmath.h @@ -104,7 +104,6 @@ static void Shutdown(); static WWINLINE double Pow(double x, double y); static WWINLINE float Powf(float x, float y); -static WWINLINE double Sqr(float x); static WWINLINE float Sqrt(float x); static WWINLINE double Sqrt(double x); static WWINLINE float Sqrtf(float x); @@ -217,21 +216,12 @@ static WWINLINE double Div_Safe(double dividend, double divisor, double fallback WWINLINE double WWMath::Pow(double x, double y) { #if USE_DETERMINISTIC_MATH - return gm_pow(x, y); + return (double)gm_powf((float)x, (float)y); // gm_pow diverges on x87, gm_powf is bit-identical #else return pow(x, y); #endif } -WWINLINE double WWMath::Sqr(float x) -{ -#if USE_DETERMINISTIC_MATH - return (double)(x * x); -#else - return Pow((double)x, 2.0); -#endif -} - WWINLINE float WWMath::Powf(float x, float y) { #if USE_DETERMINISTIC_MATH diff --git a/Generals/Code/GameEngine/Source/Common/System/BuildAssistant.cpp b/Generals/Code/GameEngine/Source/Common/System/BuildAssistant.cpp index bbfdbb45808..944d639315c 100644 --- a/Generals/Code/GameEngine/Source/Common/System/BuildAssistant.cpp +++ b/Generals/Code/GameEngine/Source/Common/System/BuildAssistant.cpp @@ -1405,7 +1405,7 @@ Bool BuildAssistant::moveObjectsForConstruction( const ThingTemplate *whatToBuil Bool anyUnmovables = false; MemoryPoolObjectHolder hold( iter ); - Real radius = WWMath::Sqrt(WWMath::Sqr(gi.getMajorRadius()) + WWMath::Sqr(gi.getMinorRadius())); + Real radius = WWMath::Sqrt(WWMath::Pow(gi.getMajorRadius(), 2) + WWMath::Pow(gi.getMinorRadius(), 2)); radius *= 1.4f; // Fudge the distance, for( Object *them = iter->first(); them; them = iter->next() ) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp index bc8aa91145d..15640b424e2 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp @@ -5732,7 +5732,7 @@ void hLineAddThreat(Int x1, Int x2, Int y, void *threatValueParms) if (x < 0 || x >= ThePartitionManager->m_cellCountX) continue; - distance = WWMath::Sqrt( WWMath::Sqr(x - parms->xCenter) + WWMath::Sqr(y - parms->yCenter) ); + distance = WWMath::Sqrt( WWMath::Pow(x - parms->xCenter, 2) + WWMath::Pow(y - parms->yCenter, 2) ); mulVal = 1 - distance / parms->radius; if (mulVal < 0.0f) mulVal = 0.0f; @@ -5760,7 +5760,7 @@ void hLineRemoveThreat(Int x1, Int x2, Int y, void *threatValueParms) if (x < 0 || x >= ThePartitionManager->m_cellCountX) continue; - distance = WWMath::Sqrt( WWMath::Sqr(x - parms->xCenter) + WWMath::Sqr(y - parms->yCenter) ); + distance = WWMath::Sqrt( WWMath::Pow(x - parms->xCenter, 2) + WWMath::Pow(y - parms->yCenter, 2) ); mulVal = 1 - distance / parms->radius; if (mulVal < 0.0f) mulVal = 0.0f; @@ -5788,7 +5788,7 @@ void hLineAddValue(Int x1, Int x2, Int y, void *threatValueParms) if (x < 0 || x >= ThePartitionManager->m_cellCountX) continue; - distance = WWMath::Sqrt( WWMath::Sqr(x - parms->xCenter) + WWMath::Sqr(y - parms->yCenter) ); + distance = WWMath::Sqrt( WWMath::Pow(x - parms->xCenter, 2) + WWMath::Pow(y - parms->yCenter, 2) ); mulVal = 1 - distance / parms->radius; if (mulVal < 0.0f) mulVal = 0.0f; @@ -5816,7 +5816,7 @@ void hLineRemoveValue(Int x1, Int x2, Int y, void *threatValueParms) if (x < 0 || x >= ThePartitionManager->m_cellCountX) continue; - distance = WWMath::Sqrt( WWMath::Sqr(x - parms->xCenter) + WWMath::Sqr(y - parms->yCenter) ); + distance = WWMath::Sqrt( WWMath::Pow(x - parms->xCenter, 2) + WWMath::Pow(y - parms->yCenter, 2) ); mulVal = 1 - distance / parms->radius; if (mulVal < 0.0f) mulVal = 0.0f; diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/POWTruckAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/POWTruckAIUpdate.cpp index 01f0ea410ca..52333f5c8b5 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/POWTruckAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/POWTruckAIUpdate.cpp @@ -480,7 +480,7 @@ void POWTruckAIUpdate::updateCollectingTarget() { // are we close enough to tell them to start moving to us - Real distSq = WWMath::Sqr( us->getGeometryInfo().getBoundingSphereRadius() * 2.0f ); + Real distSq = WWMath::Pow( us->getGeometryInfo().getBoundingSphereRadius() * 2.0f, 2 ); if( ThePartitionManager->getDistanceSquared( us, target, FROM_CENTER_2D ) <= distSq ) { diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp index 4cadf12855c..54dd7c3ee6f 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp @@ -1435,7 +1435,7 @@ Bool BuildAssistant::moveObjectsForConstruction( const ThingTemplate *whatToBuil Bool anyUnmovables = false; MemoryPoolObjectHolder hold( iter ); - Real radius = WWMath::Sqrt(WWMath::Sqr(gi.getMajorRadius()) + WWMath::Sqr(gi.getMinorRadius())); + Real radius = WWMath::Sqrt(WWMath::Pow(gi.getMajorRadius(), 2) + WWMath::Pow(gi.getMinorRadius(), 2)); radius *= 1.4f; // Fudge the distance, for( Object *them = iter->first(); them; them = iter->next() ) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp index 787bc6a57fe..90774238c1a 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp @@ -5774,7 +5774,7 @@ void hLineAddThreat(Int x1, Int x2, Int y, void *threatValueParms) if (x < 0 || x >= ThePartitionManager->m_cellCountX) continue; - distance = WWMath::Sqrt( WWMath::Sqr(x - parms->xCenter) + WWMath::Sqr(y - parms->yCenter) ); + distance = WWMath::Sqrt( WWMath::Pow(x - parms->xCenter, 2) + WWMath::Pow(y - parms->yCenter, 2) ); mulVal = 1 - distance / parms->radius; if (mulVal < 0.0f) mulVal = 0.0f; @@ -5802,7 +5802,7 @@ void hLineRemoveThreat(Int x1, Int x2, Int y, void *threatValueParms) if (x < 0 || x >= ThePartitionManager->m_cellCountX) continue; - distance = WWMath::Sqrt( WWMath::Sqr(x - parms->xCenter) + WWMath::Sqr(y - parms->yCenter) ); + distance = WWMath::Sqrt( WWMath::Pow(x - parms->xCenter, 2) + WWMath::Pow(y - parms->yCenter, 2) ); mulVal = 1 - distance / parms->radius; if (mulVal < 0.0f) mulVal = 0.0f; @@ -5830,7 +5830,7 @@ void hLineAddValue(Int x1, Int x2, Int y, void *threatValueParms) if (x < 0 || x >= ThePartitionManager->m_cellCountX) continue; - distance = WWMath::Sqrt( WWMath::Sqr(x - parms->xCenter) + WWMath::Sqr(y - parms->yCenter) ); + distance = WWMath::Sqrt( WWMath::Pow(x - parms->xCenter, 2) + WWMath::Pow(y - parms->yCenter, 2) ); mulVal = 1 - distance / parms->radius; if (mulVal < 0.0f) mulVal = 0.0f; @@ -5858,7 +5858,7 @@ void hLineRemoveValue(Int x1, Int x2, Int y, void *threatValueParms) if (x < 0 || x >= ThePartitionManager->m_cellCountX) continue; - distance = WWMath::Sqrt( WWMath::Sqr(x - parms->xCenter) + WWMath::Sqr(y - parms->yCenter) ); + distance = WWMath::Sqrt( WWMath::Pow(x - parms->xCenter, 2) + WWMath::Pow(y - parms->yCenter, 2) ); mulVal = 1 - distance / parms->radius; if (mulVal < 0.0f) mulVal = 0.0f; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/POWTruckAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/POWTruckAIUpdate.cpp index adcc2472719..b4ef88d8bed 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/POWTruckAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/POWTruckAIUpdate.cpp @@ -480,7 +480,7 @@ void POWTruckAIUpdate::updateCollectingTarget() { // are we close enough to tell them to start moving to us - Real distSq = WWMath::Sqr( us->getGeometryInfo().getBoundingSphereRadius() * 2.0f ); + Real distSq = WWMath::Pow( us->getGeometryInfo().getBoundingSphereRadius() * 2.0f, 2 ); if( ThePartitionManager->getDistanceSquared( us, target, FROM_CENTER_2D ) <= distSq ) { From dec57e53d1e50fbd9d8532f8158b549154fc4a83 Mon Sep 17 00:00:00 2001 From: Okladnoj Date: Tue, 11 Aug 2026 23:29:44 +0300 Subject: [PATCH 7/7] revert(wwlib): Restore Point.h to its upstream state Routing TPoint2D/TPoint3D Length and Normalize through WWMath::Sqrt is what forced wwmath.h into Point.h in the first place, and that include is what the qualified-path build fix was patching. Point.h is consumed only by rendering code (metalmap, dazzle), never by the simulation, so it needs no deterministic math. Restore the original sqrt calls and drop the include along with them. --- Core/Libraries/Source/WWVegas/WWLib/Point.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WWLib/Point.h b/Core/Libraries/Source/WWVegas/WWLib/Point.h index bde3fbf100b..78a9f8c7ea9 100644 --- a/Core/Libraries/Source/WWVegas/WWLib/Point.h +++ b/Core/Libraries/Source/WWVegas/WWLib/Point.h @@ -36,8 +36,6 @@ #pragma once -#include "wwmath.h" - template class TRect; /* @@ -78,9 +76,9 @@ class TPoint2D { TPoint2D const operator - () const {return(TPoint2D(-X, -Y));} // Vector support functions. - T Length() const {return(T(WWMath::Sqrt(X*X + Y*Y)));} + T Length() const {return(T(sqrt(X*X + Y*Y)));} TPoint2D const Normalize() const { - double len = WWMath::Sqrt(X*X + Y*Y); + double len = sqrt(X*X + Y*Y); if (len != 0.0) { return(TPoint2D((T)((double)X / len), (T)((double)Y / len))); } else { @@ -165,9 +163,9 @@ class TPoint3D : public TPoint2D { TPoint3D const operator - () const {return(TPoint3D(-X, -Y, -Z));} // Vector support functions. - T Length() const {return(T(WWMath::Sqrt(X*X + Y*Y + Z*Z)));} + T Length() const {return(T(sqrt(X*X + Y*Y + Z*Z)));} TPoint3D const Normalize() const { - double len = WWMath::Sqrt(X*X + Y*Y + Z*Z); + double len = sqrt(X*X + Y*Y + Z*Z); if (len != 0.0) { return(TPoint3D(X / len, Y / len, Z / len)); } else {