Skip to content

Remove streflop#369

Open
andy5995 wants to merge 4 commits intodevelopfrom
remove-streflop
Open

Remove streflop#369
andy5995 wants to merge 4 commits intodevelopfrom
remove-streflop

Conversation

@andy5995
Copy link
Copy Markdown
Collaborator

No description provided.

andy5995 and others added 4 commits March 21, 2026 19:32
…ndency

Root cause of OOS in network games
-----------------------------------
IEEE 754 mandates bit-identical results only for the five basic operations
(+, -, *, /, sqrt).  Transcendental functions (atan2, sin, cos, …) may
differ by 1-2 ULPs between libm implementations on Linux, macOS, and
Windows.  The four streflop::atan2 calls in unit.cpp produced float values
that were written into logSynchData() checkpoints; even a 1-ULP difference
caused "Game out of synch" errors between cross-platform clients.

Fix: deterministic_math.h
--------------------------
New header source/shared_lib/include/platform/common/deterministic_math.h
provides deterministicAtan2Deg(float y, float x).  It uses only IEEE 754
basic arithmetic (+, -, *, /) on doubles, so its output is bit-identical on
all conforming platforms.  Algorithm:

  1. Range-reduce |y|/|x| to t in [0, tan(pi/12)] using the identity
       atan(x) = pi/6 + atan((x*sqrt(3)-1)/(sqrt(3)+x))  for x in (tan(pi/12),1]
       atan(x) = pi/2 - atan(1/x)                         for x > 1
  2. Evaluate atan(t) via a 6-term Taylor series.
     Maximum error for |t| <= tan(pi/12): < 4e-11 rad (~5e-9 degrees),
     well within the truncateDecimal(6) applied by callers.
  3. Restore quadrant, convert to degrees in double, return as float.

unit.cpp: replace 4 atan2 call sites
--------------------------------------
calculateXZRotation()  (terrain slope, lines ~953/964)
setTargetPos()         (move command target, line ~1487) -- directly logged
updateTarget()         (combat facing, line ~3926)

All four #ifdef USE_STREFLOP / streflop::atan2 / #else / atan2 / #endif
blocks are replaced with a single deterministicAtan2Deg() call.
radToDeg() is no longer needed; the new function returns degrees directly.

Other streflop uses: collapse trivial #ifdef blocks
-----------------------------------------------------
The remaining streflop uses (fabs in tileset.cpp / map.cpp, floor in
unit_updater.cpp / map.cpp) are inherently deterministic: fabs is a
single-bit operation and floor of sqrt (an IEEE 754 exact operation) of
integer inputs is deterministic.  The #ifdef USE_STREFLOP blocks that
already had identical #else branches are collapsed to the standard-library
form, removing dead preprocessor noise.

CMakeLists.txt: disable streflop by default
--------------------------------------------
WANT_USE_STREFLOP default changed from ON to OFF.  Streflop may still be
enabled explicitly, but is no longer required for multiplayer sync
correctness.  The old "Out of synchs may occur" warning is replaced with a
note describing the deterministic replacement.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
streflop is no longer needed: the four atan2 calls that affected
sync-logged game state now use deterministicAtan2Deg() (previous
commit), and the remaining streflop uses (fabs, floor, sqrt) are
inherently deterministic under IEEE 754.

Source file cleanup
-------------------
Every #ifdef USE_STREFLOP / streflop:: / #else / stdlib / #endif block
is collapsed to the stdlib branch:

  unit_updater.cpp   - floor() for range checks
  map_preview.cpp    - sqrtf() distance, fabs() gradient
  particle.cpp       - fabsf/sinf/cosf/sqrtf/fmod/cos/sin/atan2
                       (all rendering-only, no sync impact)
  vec.h              - std::sqrt() in Vec2/Vec3::length()
  main.cpp           - remove STREFLOP mode/enabled log prints
  math_wrapper.h     - unconditional #include <cmath>

lua_script.cpp: remove Lua_STREFLOP_Wrapper class and all ~25
instances. The class toggled streflop precision around Lua calls to
avoid FPU state corruption; with streflop gone it is a no-op.

platform_main.h
---------------
  - Remove --disable-streflop-checks CLI arg and GAME_ARG enum value
  - Remove the SSE capability runtime check (was only needed to
    validate streflop's SSE mode requirement)
  - Remove streflop_init<streflop::Simple>() startup call

CMakeLists.txt
--------------
  - Remove WANT_USE_STREFLOP and FORCE_STREFLOP_SOFTWRAPPER options
  - Remove the STREFLOP_SSE/X87/SOFT detection and ADD_DEFINITIONS block

source/shared_lib/CMakeLists.txt
---------------------------------
  - Remove pkg_search_module(STREFLOP …) discovery
  - Remove ADD_SUBDIRECTORY(sources/streflop) and link step
  - Remove ${STREFLOP_PROPERTIES} from compile flags
  - Remove ${MG_STREFLOP} from Windows link libraries

Deleted files
-------------
  source/shared_lib/sources/streflop/         (~70 .cpp files)
  source/shared_lib/include/streflop/         (~20 .h files)
  source/shared_lib/include/platform/common/streflop_cond.h
  source/tests/shared_lib/streflop/           (OOS regression test)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant