Skip to content

fix(ENG-RELEASE-WINDOWS): M_PI is POSIX, not C++ — and the grep that found it undercounted both ways (#720) - #732

Merged
localai-bot merged 2 commits into
mainfrom
row/FIX-MSVC-M-PI
Aug 14, 2026
Merged

fix(ENG-RELEASE-WINDOWS): M_PI is POSIX, not C++ — and the grep that found it undercounted both ways (#720)#732
localai-bot merged 2 commits into
mainfrom
row/FIX-MSVC-M-PI

Conversation

@localai-bot

Copy link
Copy Markdown
Collaborator

Closes #720.

M_PI is a POSIX extension, not standard C++. MSVC's <cmath> defines it only
when _USE_MATH_DEFINES precedes the include, so windows-msvc-cpu and
windows-msvc-vulkan hard-error C2065 at ltx2.cpp on every open PR. This
replaces every M_PI under src/ and tests/ with std::numbers::pi_v<double>
— the C++20 spelling this repo already uses at mla_attention.cpp:82,
deepseek_v4.cpp:602, minimax_h3_video_vae.cpp:258 and vocoder1d.cpp:35.

_USE_MATH_DEFINES was rejected: it is order-dependent across transitive
includes, and it re-declares the POSIX extension rather than removing the
dependency on it. No fifth spelling of pi is introduced (cf. #687).

Spec: .agents/specs/windows-msvc-m-pi.md.
This is the second of the two stacked Windows defects; the first is #664 / PR #677.

The TU list, and why the issue title undercounts both ways

git grep -l M_PI -- src include returns three files. Measurement disagrees
with that in both directions:

TU M_PI uses Own #define guard? Actually breaks MSVC?
src/.../ltx2.cpp 3 no yes — the C2065s in the CI log
tests/vllm/models/test_vocoder1d.cpp 2 no yes — never named anywhere
src/.../ltx2_audio_vae.cpp 4 yes no
src/.../ltx2_video_vae.cpp 0 yes (dead) no

The two VAEs carry #ifndef M_PI / #define M_PI 3.14159265358979323846 and
compile fine under MSVC — they are two extra hand-rolled spellings of pi, and
the video one's guard has zero uses. Meanwhile test_vocoder1d.cpp is a genuine
hard break that git grep -- src include never looked at and no CI log ever
named, because the library build stops at ltx2.cpp first. All four are fixed.

RED — an already-committed, already-failing test

No checker semantics change. tests/scripts/test_check_windows_portability.py's
test_real_tree_uses_portable_windows_allocation_and_math already asserts
that nothing under src/ or tests/ contains \bM_PI\b, and it was already
failing at the base SHA naming all four files:

AssertionError: Lists differ: ['src/vllm/model_executor/models/ltx2.cpp'...] != []
- ['src/vllm/model_executor/models/ltx2.cpp',
-  'src/vllm/model_executor/models/ltx2_video_vae.cpp',
-  'src/vllm/model_executor/models/ltx2_audio_vae.cpp',
-  'tests/vllm/models/test_vocoder1d.cpp']
Ran 71 tests   FAILED (failures=2)

That suite runs in no workflow (#646, #680), which is how the assertion went
unheld while the LTX-2.5 lane landed on top of it. GREEN is the same 71 cases
with failures 2 → 1; the survivor is
test_real_unsupported_tier_helper_is_structurally_scoped, pre-existing and
owned by #680 (captured failing on the pristine base before any edit).

The MSVC diagnostic also reproduces on Linux. -U_GNU_SOURCE -D_ISOC99_SOURCE
removes glibc's M_PI from <cmath>, recreating MSVC's header condition, and
g++ then reports the same line and column as the hosted MSVC log:

ltx2.cpp:72:58: error: 'M_PI' was not declared in this scope
ltx2.cpp:557:69: error: 'M_PI' was not declared in this scope
ltx2.cpp:572:76: error: 'M_PI' was not declared in this scope
test_vocoder1d.cpp:106:21 / 121:21   <- no MSVC log had reached these

It emits nothing for the two VAEs, confirming their guards by measurement rather
than by reading. This is g++/glibc, not MSVC — the hosted jobs remain the
authoritative compiler gate.

No golden moved — asserted three ways, not assumed

  1. Bit identity. M_PI, std::numbers::pi_v<double> and the hand-rolled
    3.14159265358979323846 are the same double, 400921fb54442d18; the three
    derived quantities (sqrt(2/pi) as float, pi/2 as float and as double) are
    bit-equal.
  2. Pure token substitution. A token-sequence comparison over all four files
    (41,191 tokens, both pi spellings unified) reports no difference beyond the
    added <numbers> includes and the two removed defines — so no operator
    order, cast or operand moved.
  3. Before/after goldens. Seven suites, identical in both arms: 185 cases,
    17,378 assertions, all passing
    .
suite before after
test_vocoder1d 10 / 58 10 / 58
test_ltx2 35 / 2435 35 / 2435
test_ltx2_vae 36 / 3039 36 / 3039
test_ltx2_device 15 / 523 15 / 523
test_ltx2_loader 26 / 4826 26 / 4826
test_ltx2_text_encoder 26 / 4115 26 / 4115
test_ltx2_pipeline 37 / 2382 37 / 2382

Mutation

Every mutation was restored from the index and verified by sha256sum -c, never
by git status. Compile status is printed beside each result, because a
mutation that fails to build reads as a passing test.

  • Revert the constant to M_PI in ltx2.cppM1_BUILD_EXIT=0, i.e. it
    still builds clean on Linux, while the portability gate goes red and the
    MSVC probe reproduces the error. That is the whole shape of this bug: the
    Linux build is structurally blind to it.
  • Perturb pi to 3.14159M2_BUILD_EXIT=0, and 60 assertions red in
    test_ltx2 plus 5 in test_ltx2_pipeline. So arm 3 above is not a vacuous
    green. (test_ltx2_vae stays green under this mutation — it does not reach
    these sites, and its unchanged result is therefore evidence of nothing.)
  • Restructure the expression — the token-equivalence instrument correctly
    goes red, so arm 2 is not vacuous either.

Gate

Owed

Native windows-msvc-cpu and windows-msvc-vulkan on this head are the
authoritative /W4 /WX validation. Linux cannot substitute for the MSVC
compiler gate. Note these jobs are PR-only, so they cannot go green on this
branch until #677 lands too — the two defects are stacked.

🤖 Generated with Claude Code

mudler added 2 commits August 14, 2026 10:22
…found it undercounted both ways (#720)

`M_PI` is a POSIX extension. MSVC's `<cmath>` defines it only when
`_USE_MATH_DEFINES` precedes the include, so `windows-msvc-cpu` and
`windows-msvc-vulkan` hard-error C2065 at `ltx2.cpp` on every open PR. This
replaces every `M_PI` in `src/` and `tests/` with `std::numbers::pi_v<double>`,
the C++20 spelling already used at four sites here.

`_USE_MATH_DEFINES` was rejected: it is order-dependent across transitive
includes and re-declares the extension instead of removing the dependency.

THE INTAKE'S "THREE TUs" IS WRONG IN BOTH DIRECTIONS, and measurement rather
than `git grep -l` is what separates them. `ltx2_audio_vae.cpp` and
`ltx2_video_vae.cpp` carry their own `#ifndef M_PI` guard and compile fine under
MSVC — they are two extra spellings of pi (#687's disease), and the video one
has ZERO uses, so its define is dead. Meanwhile
`tests/vllm/models/test_vocoder1d.cpp` has two unguarded uses and IS a hard
break: `git grep -- src include` never looked at `tests/`, and the CI log never
named it because the library build stops at `ltx2.cpp` first.

RED is a test that was ALREADY COMMITTED AND ALREADY FAILING.
`test_check_windows_portability.py`'s
`test_real_tree_uses_portable_windows_allocation_and_math` asserts no `\bM_PI\b`
under `src/` or `tests/`, and named all four files at the base SHA. No checker
semantics change here. That suite runs in no workflow (#646, #680), which is how
the assertion went unheld while the LTX-2.5 lane landed on top of it.

The MSVC condition also reproduces on Linux: `-U_GNU_SOURCE -D_ISOC99_SOURCE`
removes glibc's `M_PI` from `<cmath>`, and g++ then reports `ltx2.cpp` 72:58,
557:69, 572:76 — the same line AND column as the hosted MSVC log — plus
`test_vocoder1d.cpp` 106:21 and 121:21, which no MSVC log had reached yet. It
reports nothing for the two VAEs, confirming their guards by measurement.

VALUE IDENTITY IS ASSERTED, NOT ASSUMED, three ways. `M_PI`,
`std::numbers::pi_v<double>` and the hand-rolled `3.14159265358979323846` are
the same double, `400921fb54442d18`. A token-sequence comparison over all four
files (41,191 tokens, both pi spellings unified) reports pure token
substitution: the only deltas are the added `<numbers>` includes and the two
removed defines, so no operator order, cast or operand moved. The seven LTX-2.5
and vocoder golden suites report identical counts before and after — 185 cases,
17,378 assertions, all green in both arms.

That third arm is not vacuous: perturbing pi to `3.14159` builds clean and reds
60 assertions in `test_ltx2` and 5 in `test_ltx2_pipeline`. Reverting the
constant to `M_PI` still BUILDS CLEAN on Linux (exit 0) while re-reding the
portability gate and the MSVC probe — which is the whole shape of this bug: the
Linux build is structurally blind to it.

Full ctest 440/441. The one failure, `test_op_parity`, throws the identical
`json.exception.type_error.302` at the base SHA and is not from this change.
`ctest -N` is 441 against the 429 last recorded; this diff touches no
`CMakeLists.txt` and registers no test, so the drift is main's.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [Claude Code]
FOLLOWING_AGENTS_PROTOCOL

main advanced five commits (indextts2 S2Mel/talker, MUSIC3 records) while this
row was gating. Merged rather than rebased; `docs/FEATURES.md` was co-edited by
both sides and auto-merged with this row's scoped line-30 amendment intact.

Re-gated on the merged tree, because a clean merge is not a built merge: no
`M_PI` survives in `src/`, `include/` or `tests/`; the token-equivalence proof
still reports pure substitution across all four files; the portability suite is
71 cases / 1 pre-existing failure (#680); full build exit 0 with no ENOSPC; and
ctest is 442/443 with only the pre-existing `test_op_parity` throw.

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [Claude Code]
localai-bot added a commit that referenced this pull request Aug 14, 2026
…s with POSIX stat

FOLLOWING_AGENTS_PROTOCOL

`src/vllm/multimodal/video_engine.cpp` reached Windows with unguarded POSIX
`stat` -- `:21` `#include <sys/stat.h>`, `:57-60` `IsDir`, `:62-65` `Exists` --
which `check-windows-portability.py:1675-1688` flags under `full_source_posix`,
i.e. every scanned source and not only the platform-boundary set. It reddened
`windows-msvc-cpu` and `windows-msvc-vulkan` on EVERY open pull request in the
repository, across five unrelated lanes. It hid because those jobs are
`skipped` on `main` pushes (#584), so a green main carried no information.

Repaired at the SOURCE, never the checker: `IsDir`/`Exists` now take the
`std::error_code` <filesystem> overloads through a file-local path helper,
preserving `::stat`'s return-false-for-an-uninspectable-path behaviour that the
THROWING overloads would have turned into a `filesystem_error` escaping a
registry query. The helper adopts `fs_io.cpp:31`'s spelling byte-for-byte and
deliberately NOT `minimax_h3_sharded.cpp:55`'s, which throws on malformed UTF-8
under _WIN32 -- that would reintroduce on Windows the exception this removes on
POSIX. The wider divergence is #687.

RED first, and the honest RED is worth recording: a missing-path test would
have passed with and without the guarantee, because ENOENT does not throw. The
real probe is a 300-character path component (ENAMETOOLONG).

Reviewed PASS by a fresh reviewer who reproduced the premise from another
lane's CI log, confirmed by sha256 that the checker was untouched, and REJECTED
the implementer's probe for the one surviving mutation -- "fails to refute is
not unreachability" -- then established unreachability from the library
mechanism instead: `IsDir` is TU-local with one call site gated by `Exists`,
and libstdc++ implements both via `f(status(p))`, so `exists()` can only return
true when the stat already succeeded.

Operator gate at the merged tree: WINPORT_EXIT=0, BUILD_EXIT=0, 0 errors,
0 ENOSPC, REGISTERED=444, test_video_engine 12 cases / 260 assertions exit 0.
Two ctest failures both attributed by measurement, not assumption:
`test_op_parity` is #737 (a null in the Music3 golden added today -- proven by
moving that one golden aside: 10/10 pass, assertions 70 -> 123), and
`test_openai_conformance` is a load artifact at load average 115 that passes
alone, exit 0, 48 assertions.

This does NOT turn the Windows lane green on its own. Two independent defects
were stacked; with this one gone the build reaches `M_PI`, which MSVC does not
define -- #720, fixed by #732.

Closes #664.

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5[1m] [claude-code]
@localai-bot
localai-bot merged commit 0011bed into main Aug 14, 2026
12 of 18 checks passed
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.

M_PI is not defined by MSVC — three LTX-2.5 TUs fail the Windows build, revealed once #664's POSIX defect was fixed

2 participants